Merge "Use consistent naming for sharing broadcaster's identity"
diff --git a/ApiDocs.bp b/ApiDocs.bp
index a46ecce..90b6603 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -422,26 +422,27 @@
         "$(location merge_zips) $(out) $(location :ds-docs-java{.docs.zip}) $(genDir)/ds-docs-kt-moved.zip",
 }
 
-java_genrule {
-    name: "ds-docs-switched",
-    tools: [
-        "switcher4",
-        "soong_zip",
-    ],
-    srcs: [
-        ":ds-docs-java{.docs.zip}",
-        ":ds-docs-kt{.docs.zip}",
-    ],
-    out: ["ds-docs-switched.zip"],
-    dist: {
-        targets: ["docs"],
-    },
-    cmd: "unzip -q $(location :ds-docs-java{.docs.zip}) -d $(genDir) && " +
-        "unzip -q $(location :ds-docs-kt{.docs.zip}) -d $(genDir)/en/reference/kotlin && " +
-        "SWITCHER=$$(cd $$(dirname $(location switcher4)) && pwd)/$$(basename $(location switcher4)) && " +
-        "(cd $(genDir)/en/reference && $$SWITCHER --work platform) > /dev/null && " +
-        "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)",
-}
+// Disable doc generation until Doclava is migrated to JDK 17 (b/240421555).
+// java_genrule {
+//     name: "ds-docs-switched",
+//     tools: [
+//         "switcher4",
+//         "soong_zip",
+//     ],
+//     srcs: [
+//         ":ds-docs-java{.docs.zip}",
+//         ":ds-docs-kt{.docs.zip}",
+//     ],
+//     out: ["ds-docs-switched.zip"],
+//     dist: {
+//         targets: ["docs"],
+//     },
+//     cmd: "unzip -q $(location :ds-docs-java{.docs.zip}) -d $(genDir) && " +
+//         "unzip -q $(location :ds-docs-kt{.docs.zip}) -d $(genDir)/en/reference/kotlin && " +
+//         "SWITCHER=$$(cd $$(dirname $(location switcher4)) && pwd)/$$(basename $(location switcher4)) && " +
+//         "(cd $(genDir)/en/reference && $$SWITCHER --work platform) > /dev/null && " +
+//         "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)",
+// }
 
 droiddoc {
     name: "ds-static-docs",
diff --git a/PERFORMANCE_OWNERS b/PERFORMANCE_OWNERS
new file mode 100644
index 0000000..9452ea3
--- /dev/null
+++ b/PERFORMANCE_OWNERS
@@ -0,0 +1,5 @@
+timmurray@google.com
+edgararriaga@google.com
+dualli@google.com
+carmenjackson@google.com
+philipcuadra@google.com
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a48ce0c..9610f2c 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -198,5 +198,30 @@
        }
      ]
    }
+ ],
+ "auto-features-postsubmit": [
+   // Test tag for automotive feature targets. These are only running in postsubmit.
+   // This tag is used in targeted test features testing to limit resource use.
+   // TODO(b/256932212): this tag to be removed once the above is no longer in use.
+   {
+     "name": "FrameworksMockingServicesTests",
+     "options": [
+       {
+         "include-filter": "com.android.server.pm.UserVisibilityMediatorSUSDTest"
+       },
+       {
+         "include-filter": "com.android.server.pm.UserVisibilityMediatorMUMDTest"
+       },
+       {
+         "include-filter": "com.android.server.pm.UserVisibilityMediatorMUPANDTest"
+       },
+       {
+         "exclude-annotation": "androidx.test.filters.FlakyTest"
+       },
+       {
+         "exclude-annotation": "org.junit.Ignore"
+       }
+     ]
+   }
  ]
 }
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index b71d596..051dde0 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -271,34 +271,110 @@
 
     /**
      * Tests starting an uninitialized user, with wait times in between iterations.
-     * Measures the time until the ProgressListener callback.
+     *
+     * The first iteration will take longer due to the process of setting policy permissions for
+     * a new user.
      */
     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
-    public void startUser_realistic() throws RemoteException {
+    public void startUser_uninitializedUser() throws RemoteException {
+        startUser_measuresAfterFirstIterations(/* numberOfIterationsToSkip */0);
+    }
+
+    /**
+     * Tests the second iteration of start user that has a problem that it takes too long to run, a
+     * bug has been created (b/266574680) and after investigating or fix this problem,
+     * this test can be removed.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void startUser_startedOnceBefore() throws RemoteException {
+        startUser_measuresAfterFirstIterations(/* numberOfIterationsToSkip */1);
+    }
+
+    /**
+     * Tests a specific iteration of the start user process.
+     * Measures the time until ACTION_USER_STARTED is received.
+     * @param numberOfIterationsToSkip number of iterations that must be skipped in the preStartUser
+     *                                 method.
+     */
+    private void startUser_measuresAfterFirstIterations(int numberOfIterationsToSkip)
+            throws RemoteException {
+        /**
+         * Run start user and stop for the next iteration, measures time while mRunner.keepRunning()
+         * return true.
+         */
         while (mRunner.keepRunning()) {
             mRunner.pauseTiming();
+
             final int userId = createUserNoFlags();
-            final ProgressWaiter waiter = new ProgressWaiter();
+
+            preStartUser(userId, numberOfIterationsToSkip);
 
             waitForBroadcastIdle();
-            mRunner.resumeTiming();
-            Log.i(TAG, "Starting timer");
+            waitCoolDownPeriod();
 
-            final boolean success = mIam.startUserInBackgroundWithListener(userId, waiter)
-                    && waiter.waitForFinish(TIMEOUT_IN_SECOND * 1000);
+            runThenWaitForBroadcasts(userId, () -> {
+                mRunner.resumeTiming();
+                Log.i(TAG, "Starting timer");
+
+                mIam.startUserInBackground(userId);
+            }, Intent.ACTION_USER_STARTED);
 
             mRunner.pauseTiming();
             Log.i(TAG, "Stopping timer");
 
-            assertTrue("Error: could not start user " + userId, success);
-
             removeUser(userId);
-            waitCoolDownPeriod();
             mRunner.resumeTimingForNextIteration();
         }
     }
 
     /**
+     * Tests starting an initialized user, with wait times in between iterations stopping between
+     * iterations,this test will skip the first two iterations and only measure the next ones.
+     *
+     * The first iteration will take longer due to the process of setting policy permissions for
+     * a new user.
+     *
+     * The second iteration takes longer than expected and has a bug (b/266574680) to investigate
+     * it.
+     *
+     * The next iterations take the expected time to start a user.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void startUser_startedTwiceBefore() throws RemoteException {
+        final int userId = createUserNoFlags();
+
+        //TODO(b/266681181) Reduce iteration number by 1 after investigation and possible fix.
+        preStartUser(userId, /* numberOfIterations */2);
+
+        /**
+         * Run start user and stop for the next iteration, measures time while mRunner.keepRunning()
+         * return true.
+         */
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+
+            waitForBroadcastIdle();
+            waitCoolDownPeriod();
+
+            runThenWaitForBroadcasts(userId, () -> {
+                mRunner.resumeTiming();
+                Log.i(TAG, "Starting timer");
+
+                mIam.startUserInBackground(userId);
+            }, Intent.ACTION_USER_STARTED);
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+
+            stopUser(userId, /* force */true);
+            mRunner.resumeTimingForNextIteration();
+        }
+
+        removeUser(userId);
+    }
+
+
+    /**
      * Tests starting & unlocking an uninitialized user.
      * Measures the time until unlock listener is triggered and user is unlocked.
      */
@@ -321,6 +397,46 @@
     }
 
     /**
+     * Tests starting & unlocking an initialized user, stopping the user at the end simulating real
+     * usage where the user is not removed after created and initialized.
+     * Measures the time until unlock listener is triggered and user is unlocked.
+     * This test will skip the first two iterations and only measure the next ones.
+     *
+     * The first iteration will take longer due to the process of setting policy permissions for a
+     * new user.
+     *
+     * The second iteration takes longer than expected and has a bug (b/266574680) to investigate
+     * it.
+     *
+     * The next iterations take the expected time to start a user.
+     */
+    @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
+    public void startAndUnlockUser_startedTwiceBefore() throws RemoteException {
+        final int userId = createUserNoFlags();
+
+        //TODO(b/266681181) Reduce iteration number by 1 after investigation and possible fix.
+        preStartUser(userId, /* numberOfIterations */2);
+
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+
+            waitCoolDownPeriod();
+            mRunner.resumeTiming();
+            Log.i(TAG, "Starting timer");
+
+            // Waits for UserState.mUnlockProgress.finish().
+            startUserInBackgroundAndWaitForUnlock(userId);
+
+            mRunner.pauseTiming();
+            Log.i(TAG, "Stopping timer");
+            stopUser(userId, /* force */true);
+            mRunner.resumeTimingForNextIteration();
+        }
+
+        removeUser(userId);
+    }
+
+    /**
      * Tests starting & unlocking an uninitialized user.
      * Measures the time until unlock listener is triggered and user is unlocked.
      */
@@ -404,28 +520,36 @@
         }
     }
 
-    /** Tests switching to a previously-started, but no-longer-running, user with wait
-     * times between iterations */
+    /**
+     * Tests switching to a previously-started, but no-longer-running, user with wait
+     * times between iterations
+     **/
     @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS)
     public void switchUser_stopped_realistic() throws RemoteException {
-        final int startUser = ActivityManager.getCurrentUser();
-        final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ true);
+        final int currentUserId = ActivityManager.getCurrentUser();
+        final int userId = initializeNewUserAndSwitchBack(/* stopNewUser */ true);
+
+        /**
+         * Skip the second iteration of start user process that is taking a long time to finish.
+         */
+        preStartUser(userId, /* numberOfIterations */1);
+
         while (mRunner.keepRunning()) {
             mRunner.pauseTiming();
             waitCoolDownPeriod();
             Log.d(TAG, "Starting timer");
             mRunner.resumeTiming();
 
-            switchUser(testUser);
+            switchUser(userId);
 
             mRunner.pauseTiming();
             Log.d(TAG, "Stopping timer");
-            switchUserNoCheck(startUser);
-            stopUserAfterWaitingForBroadcastIdle(testUser, true);
-            attestFalse("Failed to stop user " + testUser, mAm.isUserRunning(testUser));
+            switchUserNoCheck(currentUserId);
+            stopUserAfterWaitingForBroadcastIdle(userId, /* force */true);
+            attestFalse("Failed to stop user " + userId, mAm.isUserRunning(userId));
             mRunner.resumeTimingForNextIteration();
         }
-        removeUser(testUser);
+        removeUser(userId);
     }
 
     /** Tests switching to a previously-started, but no-longer-running, user with wait
@@ -1378,6 +1502,24 @@
         }
     }
 
+    /**
+     * Start the user and stop after that, will repeat numberOfIterations times.
+     * Make sure the user is started before proceeding with the test.
+     * @param userId identifier of the user that will be started.
+     * @param numberOfIterations number of iterations that must be skipped.
+     */
+    private void preStartUser(int userId, int numberOfIterations) throws RemoteException {
+        for (int i = 0; i < numberOfIterations; i++) {
+            final ProgressWaiter preWaiter = new ProgressWaiter();
+
+            final boolean preStartComplete = mIam.startUserInBackgroundWithListener(userId,
+                    preWaiter) && preWaiter.waitForFinish(TIMEOUT_IN_SECOND * 1000);
+            stopUserAfterWaitingForBroadcastIdle(userId, /* force */true);
+
+            assertTrue("Pre start was not performed for user" + userId, preStartComplete);
+        }
+    }
+
     private void fail(@NonNull String message) {
         Log.e(TAG, "Test failed on iteration #" + mRunner.getIteration() + ": " + message);
         mRunner.markAsFailed(new AssertionError(message));
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
index 7ed4d35..3103fcf 100644
--- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java
+++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
@@ -36,7 +36,9 @@
 import android.os.HandlerExecutor;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.os.WorkSource;
 import android.text.TextUtils;
 import android.util.Log;
@@ -90,6 +92,14 @@
 public class AlarmManager {
     private static final String TAG = "AlarmManager";
 
+    /**
+     * Prefix used by {{@link #makeTag(long, WorkSource)}} to make a tag on behalf of the caller
+     * when the {@link #set(int, long, long, long, OnAlarmListener, Handler, WorkSource)} API is
+     * used. This prefix is a unique sequence of characters to differentiate with other tags that
+     * apps may provide to other APIs that accept a listener callback.
+     */
+    private static final String GENERATED_TAG_PREFIX = "$android.alarm.generated";
+
     /** @hide */
     @IntDef(prefix = { "RTC", "ELAPSED" }, value = {
             RTC_WAKEUP,
@@ -667,7 +677,7 @@
      * than supplying a PendingIntent to be sent when the alarm time is reached, this variant
      * supplies an {@link OnAlarmListener} instance that will be invoked at that time.
      * <p>
-     * The OnAlarmListener {@link OnAlarmListener#onAlarm() onAlarm()} method will be
+     * The OnAlarmListener's {@link OnAlarmListener#onAlarm() onAlarm()} method will be
      * invoked via the specified target Executor.
      *
      * <p>
@@ -912,6 +922,24 @@
     }
 
     /**
+     * This is only used to make an identifying tag for the deprecated
+     * {@link #set(int, long, long, long, OnAlarmListener, Handler, WorkSource)} API which doesn't
+     * accept a tag. For all other APIs, the tag provided by the app is used, even if it is
+     * {@code null}.
+     */
+    private static String makeTag(long triggerMillis, WorkSource ws) {
+        final StringBuilder tagBuilder = new StringBuilder(GENERATED_TAG_PREFIX);
+
+        tagBuilder.append(":");
+        final int attributionUid =
+                (ws == null || ws.isEmpty()) ? Process.myUid() : ws.getAttributionUid();
+        tagBuilder.append(UserHandle.formatUid(attributionUid));
+        tagBuilder.append(":");
+        tagBuilder.append(triggerMillis);
+        return tagBuilder.toString();
+    }
+
+    /**
      * Direct callback version of {@link #set(int, long, long, long, PendingIntent, WorkSource)}.
      * Note that repeating alarms must use the PendingIntent variant, not an OnAlarmListener.
      * <p>
@@ -919,15 +947,26 @@
      * invoked via the specified target Handler, or on the application's main looper
      * if {@code null} is passed as the {@code targetHandler} parameter.
      *
+     * <p>The behavior of this API when {@code windowMillis < 0} is undefined.
+     *
+     * @deprecated Better alternative APIs exist for setting an alarm with this method:
+     * <ul>
+     *     <li>For alarms with {@code windowMillis > 0}, use
+     *     {@link #setWindow(int, long, long, String, Executor, WorkSource, OnAlarmListener)}</li>
+     *     <li>For alarms with {@code windowMillis = 0}, use
+     *     {@link #setExact(int, long, String, Executor, WorkSource, OnAlarmListener)}</li>
+     * </ul>
+     *
      * @hide
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void set(@AlarmType int type, long triggerAtMillis, long windowMillis,
             long intervalMillis, @NonNull OnAlarmListener listener, @Nullable Handler targetHandler,
             @Nullable WorkSource workSource) {
-        setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, null, listener, null,
-                targetHandler, workSource, null);
+        setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, null, listener,
+                makeTag(triggerAtMillis, workSource), targetHandler, workSource, null);
     }
 
     /**
diff --git a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
index 5d67c96..50a7a19 100644
--- a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
+++ b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
@@ -230,9 +230,10 @@
             android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
             android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
     @Override
-    public void stopUserVisibleJobsForUser(@NonNull String packageName, int userId) {
+    public void notePendingUserRequestedAppStop(@NonNull String packageName, int userId,
+            @Nullable String debugReason) {
         try {
-            mBinder.stopUserVisibleJobsForUser(packageName, userId);
+            mBinder.notePendingUserRequestedAppStop(packageName, userId, debugReason);
         } catch (RemoteException e) {
         }
     }
diff --git a/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl b/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
index a1f1954..1ea0c5b 100644
--- a/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
+++ b/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
@@ -48,5 +48,5 @@
     @EnforcePermission(allOf={"MANAGE_ACTIVITY_TASKS", "INTERACT_ACROSS_USERS_FULL"})
     void unregisterUserVisibleJobObserver(in IUserVisibleJobObserver observer);
     @EnforcePermission(allOf={"MANAGE_ACTIVITY_TASKS", "INTERACT_ACROSS_USERS_FULL"})
-    void stopUserVisibleJobsForUser(String packageName, int userId);
+    void notePendingUserRequestedAppStop(String packageName, int userId, String debugReason);
 }
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index e0fffb4..d4110a3 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -1897,7 +1897,11 @@
          * <p>
          * All user-initiated jobs must have an associated notification, set via
          * {@link JobService#setNotification(JobParameters, int, Notification, int)}, and will be
-         * shown in the Task Manager when running.
+         * shown in the Task Manager when running. These jobs cannot be rescheduled by the app
+         * if the user stops the job via system provided affordance (such as the Task Manager).
+         * Thus, it is best practice and recommended to provide action buttons in the
+         * associated notification to allow the user to stop the job gracefully
+         * and allow for rescheduling.
          *
          * <p>
          * If the app doesn't hold the {@link android.Manifest.permission#RUN_LONG_JOBS} permission
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
index 4aec484..3ba5c31 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
@@ -515,5 +515,6 @@
             android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
             android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
     @SuppressWarnings("HiddenAbstractMethod")
-    public abstract void stopUserVisibleJobsForUser(@NonNull String packageName, int userId);
+    public abstract void notePendingUserRequestedAppStop(@NonNull String packageName, int userId,
+            @Nullable String debugReason);
 }
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobService.java b/apex/jobscheduler/framework/java/android/app/job/JobService.java
index 1a205d0..2ab4324 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobService.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobService.java
@@ -156,6 +156,12 @@
      * a future idle maintenance window.
      * </p>
      *
+     * <p class="note">
+     * Any {@link JobInfo.Builder#setUserInitiated(boolean) user-initiated job}
+     * cannot be rescheduled when the user has asked to stop the app
+     * via a system provided affordance (such as the Task Manager).
+     * In such situations, the value of {@code wantsReschedule} is always treated as {@code false}.
+     *
      * @param params The parameters identifying this job, as supplied to
      *               the job in the {@link #onStartJob(JobParameters)} callback.
      * @param wantsReschedule {@code true} if this job should be rescheduled according
@@ -220,6 +226,12 @@
      * Once this method returns (or times out), the system releases the wakelock that it is holding
      * on behalf of the job.</p>
      *
+     * <p class="note">
+     * Any {@link JobInfo.Builder#setUserInitiated(boolean) user-initiated job}
+     * cannot be rescheduled when stopped by the user via a system provided affordance (such as
+     * the Task Manager). In such situations, the returned value from this method call is always
+     * treated as {@code false}.
+     *
      * <p class="caution"><strong>Note:</strong> When a job is stopped and rescheduled via this
      * method call, the deadline constraint is excluded from the rescheduled job's constraint set.
      * The rescheduled job will run again once all remaining constraints are satisfied.
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index d7163d8..5599e54 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -1933,8 +1933,9 @@
                     Intent.FLAG_RECEIVER_REGISTERED_ONLY
                             | Intent.FLAG_RECEIVER_FOREGROUND
                             | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
-            mTimeTickOptions = BroadcastOptions
-                    .makeRemovingMatchingFilter(new IntentFilter(Intent.ACTION_TIME_TICK))
+            mTimeTickOptions = BroadcastOptions.makeBasic()
+                    .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+                    .setDeferUntilActive(true)
                     .toBundle();
             mTimeTickTrigger = new IAlarmListener.Stub() {
                 @Override
@@ -4252,8 +4253,8 @@
                     }
                 }
                 // And send a TIME_TICK right now, since it is important to get the UI updated.
-                mHandler.post(() ->
-                        getContext().sendBroadcastAsUser(mTimeTickIntent, UserHandle.ALL));
+                mHandler.post(() -> getContext().sendBroadcastAsUser(mTimeTickIntent,
+                        UserHandle.ALL, null, mTimeTickOptions));
             } else {
                 mNonInteractiveStartTime = nowELAPSED;
             }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
index 62d97358..a474cc8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -1282,17 +1282,20 @@
     }
 
     @GuardedBy("mLock")
-    void stopUserVisibleJobsLocked(int userId, @NonNull String packageName,
-            @JobParameters.StopReason int reason, int internalReasonCode) {
+    void markJobsForUserStopLocked(int userId, @NonNull String packageName,
+            @Nullable String debugReason) {
         for (int i = mActiveServices.size() - 1; i >= 0; --i) {
             final JobServiceContext jsc = mActiveServices.get(i);
             final JobStatus jobStatus = jsc.getRunningJobLocked();
 
-            if (jobStatus != null && userId == jobStatus.getSourceUserId()
-                    && jobStatus.getSourcePackageName().equals(packageName)
-                    && jobStatus.isUserVisibleJob()) {
-                jsc.cancelExecutingJobLocked(reason, internalReasonCode,
-                        JobParameters.getInternalReasonCodeDescription(internalReasonCode));
+            // Normally, we handle jobs primarily using the source package and userId,
+            // however, user-visible jobs are shown as coming from the calling app, so we
+            // need to operate on the jobs from that perspective here.
+            if (jobStatus != null && userId == jobStatus.getUserId()
+                    && jobStatus.getServiceComponent().getPackageName().equals(packageName)) {
+                jsc.markForProcessDeathLocked(JobParameters.STOP_REASON_USER,
+                        JobParameters.INTERNAL_STOP_REASON_USER_UI_STOP,
+                        debugReason);
             }
         }
     }
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 e8fcdd2..fce75a2 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1701,16 +1701,15 @@
     }
 
     @VisibleForTesting
-    void stopUserVisibleJobsInternal(@NonNull String packageName, int userId) {
+    void notePendingUserRequestedAppStopInternal(@NonNull String packageName, int userId,
+            @Nullable String debugReason) {
         final int packageUid = mLocalPM.getPackageUid(packageName, 0, userId);
         if (packageUid < 0) {
             Slog.wtf(TAG, "Asked to stop jobs of an unknown package");
             return;
         }
         synchronized (mLock) {
-            mConcurrencyManager.stopUserVisibleJobsLocked(userId, packageName,
-                    JobParameters.STOP_REASON_USER,
-                    JobParameters.INTERNAL_STOP_REASON_USER_UI_STOP);
+            mConcurrencyManager.markJobsForUserStopLocked(userId, packageName, debugReason);
             final ArraySet<JobStatus> jobs = mJobs.getJobsByUid(packageUid);
             for (int i = jobs.size() - 1; i >= 0; i--) {
                 final JobStatus job = jobs.valueAt(i);
@@ -2387,12 +2386,25 @@
      *
      * @param failureToReschedule Provided job status that we will reschedule.
      * @return A newly instantiated JobStatus with the same constraints as the last job except
-     * with adjusted timing constraints.
+     * with adjusted timing constraints, or {@code null} if the job shouldn't be rescheduled for
+     * some policy reason.
      * @see #maybeQueueReadyJobsForExecutionLocked
      */
+    @Nullable
     @VisibleForTesting
     JobStatus getRescheduleJobForFailureLocked(JobStatus failureToReschedule,
             @JobParameters.StopReason int stopReason, int internalStopReason) {
+        if (internalStopReason == JobParameters.INTERNAL_STOP_REASON_USER_UI_STOP
+                && failureToReschedule.isUserVisibleJob()) {
+            // If a user stops an app via Task Manager and the job was user-visible, then assume
+            // the user wanted to stop that task and not let it run in the future. It's in the
+            // app's best interests to provide action buttons in their notification to avoid this
+            // scenario.
+            Slog.i(TAG,
+                    "Dropping " + failureToReschedule.toShortString() + " because of user stop");
+            return null;
+        }
+
         final long elapsedNowMillis = sElapsedRealtimeClock.millis();
         final JobInfo job = failureToReschedule.getJob();
 
@@ -4225,12 +4237,13 @@
 
         @Override
         @EnforcePermission(allOf = {MANAGE_ACTIVITY_TASKS, INTERACT_ACROSS_USERS_FULL})
-        public void stopUserVisibleJobsForUser(@NonNull String packageName, int userId) {
-            super.stopUserVisibleJobsForUser_enforcePermission();
+        public void notePendingUserRequestedAppStop(@NonNull String packageName, int userId,
+                @Nullable String debugReason) {
+            super.notePendingUserRequestedAppStop_enforcePermission();
             if (packageName == null) {
                 throw new NullPointerException("packageName");
             }
-            JobSchedulerService.this.stopUserVisibleJobsInternal(packageName, userId);
+            notePendingUserRequestedAppStopInternal(packageName, userId, debugReason);
         }
     }
 
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 911744f..cc9e517 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -190,6 +190,14 @@
 
     private Network mPendingNetworkChange;
 
+    /**
+     * The reason this job is marked for death. If it's not marked for death,
+     * then the value should be {@link JobParameters#STOP_REASON_UNDEFINED}.
+     */
+    private int mDeathMarkStopReason = JobParameters.STOP_REASON_UNDEFINED;
+    private int mDeathMarkInternalStopReason;
+    private String mDeathMarkDebugReason;
+
     // Debugging: reason this job was last stopped.
     public String mStoppedReason;
 
@@ -452,6 +460,7 @@
             mStoppedReason = null;
             mStoppedTime = 0;
             job.startedAsExpeditedJob = job.shouldTreatAsExpeditedJob();
+            job.startedAsUserInitiatedJob = job.shouldTreatAsUserInitiatedJob();
             return true;
         }
     }
@@ -502,6 +511,34 @@
         doCancelLocked(reason, internalStopReason, debugReason);
     }
 
+    /**
+     * Called when an app's process is about to be killed and we want to update the job's stop
+     * reasons without telling the job it's going to be stopped.
+     */
+    @GuardedBy("mLock")
+    void markForProcessDeathLocked(@JobParameters.StopReason int reason,
+            int internalStopReason, @NonNull String debugReason) {
+        if (mVerb == VERB_FINISHED) {
+            if (DEBUG) {
+                Slog.d(TAG, "Too late to mark for death (verb=" + mVerb + "), ignoring.");
+            }
+            return;
+        }
+        if (DEBUG) {
+            Slog.d(TAG,
+                    "Marking " + mRunningJob.toShortString() + " for death because "
+                            + reason + ":" + debugReason);
+        }
+        mDeathMarkStopReason = reason;
+        mDeathMarkInternalStopReason = internalStopReason;
+        mDeathMarkDebugReason = debugReason;
+        if (mParams.getStopReason() == JobParameters.STOP_REASON_UNDEFINED) {
+            // Only set the stop reason if we're not already trying to stop the job for some
+            // other reason in case that other stop is successful before the process dies.
+            mParams.setStopReason(reason, internalStopReason, debugReason);
+        }
+    }
+
     int getPreferredUid() {
         return mPreferredUid;
     }
@@ -648,7 +685,7 @@
                             "last work dequeued");
                     // This will finish the job.
                     doCallbackLocked(false, "last work dequeued");
-                } else {
+                } else if (work != null) {
                     // Delivery count has been updated, so persist JobWorkItem change.
                     mService.mJobs.touchJob(mRunningJob);
                 }
@@ -754,6 +791,12 @@
     @Override
     public void onServiceDisconnected(ComponentName name) {
         synchronized (mLock) {
+            if (mDeathMarkStopReason != JobParameters.STOP_REASON_UNDEFINED) {
+                // Service "unexpectedly" disconnected, but we knew the process was going to die.
+                // Use that as the stop reason for logging/debugging purposes.
+                mParams.setStopReason(
+                        mDeathMarkStopReason, mDeathMarkInternalStopReason, mDeathMarkDebugReason);
+            }
             closeAndCleanupJobLocked(true /* needsReschedule */, "unexpectedly disconnected");
         }
     }
@@ -1182,29 +1225,51 @@
      * we want to clean up internally.
      */
     @GuardedBy("mLock")
-    private void closeAndCleanupJobLocked(boolean reschedule, @Nullable String reason) {
+    private void closeAndCleanupJobLocked(boolean reschedule, @Nullable String loggingDebugReason) {
         final JobStatus completedJob;
         if (mVerb == VERB_FINISHED) {
             return;
         }
         if (DEBUG) {
             Slog.d(TAG, "Cleaning up " + mRunningJob.toShortString()
-                    + " reschedule=" + reschedule + " reason=" + reason);
+                    + " reschedule=" + reschedule + " reason=" + loggingDebugReason);
         }
-        applyStoppedReasonLocked(reason);
+        applyStoppedReasonLocked(loggingDebugReason);
         completedJob = mRunningJob;
-        final int internalStopReason = mParams.getInternalStopReasonCode();
-        final int stopReason = mParams.getStopReason();
+        // Use the JobParameters stop reasons for logging and metric purposes,
+        // but if the job was marked for death, use that reason for rescheduling purposes.
+        // The discrepancy could happen if a job ends up stopping for some reason
+        // in the time between the job being marked and the process actually dying.
+        // Since the job stopped for another reason, we want to log the actual stop reason
+        // for the sake of accurate metrics and debugging,
+        // but we should use the death mark reasons when determining reschedule policy.
+        final int loggingStopReason = mParams.getStopReason();
+        final int loggingInternalStopReason = mParams.getInternalStopReasonCode();
+        final int reschedulingStopReason, reschedulingInternalStopReason;
+        if (mDeathMarkStopReason != JobParameters.STOP_REASON_UNDEFINED) {
+            if (DEBUG) {
+                Slog.d(TAG, "Job marked for death because of "
+                        + JobParameters.getInternalReasonCodeDescription(
+                                mDeathMarkInternalStopReason)
+                        + ": " + mDeathMarkDebugReason);
+            }
+            reschedulingStopReason = mDeathMarkStopReason;
+            reschedulingInternalStopReason = mDeathMarkInternalStopReason;
+        } else {
+            reschedulingStopReason = loggingStopReason;
+            reschedulingInternalStopReason = loggingInternalStopReason;
+        }
         mPreviousJobHadSuccessfulFinish =
-                (internalStopReason == JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
+                (loggingInternalStopReason == JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
         if (!mPreviousJobHadSuccessfulFinish) {
             mLastUnsuccessfulFinishElapsed = sElapsedRealtimeClock.millis();
         }
-        mJobPackageTracker.noteInactive(completedJob, internalStopReason, reason);
+        mJobPackageTracker.noteInactive(completedJob,
+                loggingInternalStopReason, loggingDebugReason);
         FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED,
                 completedJob.getSourceUid(), null, completedJob.getBatteryName(),
                 FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED,
-                internalStopReason, completedJob.getStandbyBucket(), completedJob.getJobId(),
+                loggingInternalStopReason, completedJob.getStandbyBucket(), completedJob.getJobId(),
                 completedJob.hasChargingConstraint(),
                 completedJob.hasBatteryNotLowConstraint(),
                 completedJob.hasStorageNotLowConstraint(),
@@ -1215,7 +1280,7 @@
                 completedJob.hasContentTriggerConstraint(),
                 completedJob.isRequestedExpeditedJob(),
                 completedJob.startedAsExpeditedJob,
-                stopReason,
+                loggingStopReason,
                 completedJob.getJob().isPrefetch(),
                 completedJob.getJob().getPriority(),
                 completedJob.getEffectivePriority(),
@@ -1235,11 +1300,11 @@
         }
         try {
             mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), mRunningJob.getSourceUid(),
-                    internalStopReason);
+                    loggingInternalStopReason);
         } catch (RemoteException e) {
             // Whatever.
         }
-        if (mParams.getStopReason() == JobParameters.STOP_REASON_TIMEOUT) {
+        if (loggingStopReason == JobParameters.STOP_REASON_TIMEOUT) {
             mEconomyManagerInternal.noteInstantaneousEvent(
                     mRunningJob.getSourceUserId(), mRunningJob.getSourcePackageName(),
                     JobSchedulerEconomicPolicy.ACTION_JOB_TIMEOUT,
@@ -1260,6 +1325,9 @@
         mCancelled = false;
         service = null;
         mAvailable = true;
+        mDeathMarkStopReason = JobParameters.STOP_REASON_UNDEFINED;
+        mDeathMarkInternalStopReason = 0;
+        mDeathMarkDebugReason = null;
         mPendingStopReason = JobParameters.STOP_REASON_UNDEFINED;
         mPendingInternalStopReason = 0;
         mPendingDebugStopReason = null;
@@ -1268,8 +1336,8 @@
         if (completedJob.isUserVisibleJob()) {
             mService.informObserversOfUserVisibleJobChange(this, completedJob, false);
         }
-        mCompletedListener.onJobCompletedLocked(completedJob, stopReason, internalStopReason,
-                reschedule);
+        mCompletedListener.onJobCompletedLocked(completedJob,
+                reschedulingStopReason, reschedulingInternalStopReason, reschedule);
         mJobConcurrencyManager.onJobCompletedLocked(this, completedJob, workType);
     }
 
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index b87dec1..f18b11e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -434,7 +434,7 @@
         final UidStats uidStats =
                 getUidStats(jobStatus.getSourceUid(), jobStatus.getSourcePackageName(), true);
 
-        if (jobStatus.shouldTreatAsExpeditedJob() && jobStatus.shouldTreatAsUserInitiatedJob()) {
+        if (jobStatus.shouldTreatAsExpeditedJob() || jobStatus.shouldTreatAsUserInitiatedJob()) {
             if (!jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY)) {
                 // Don't request a direct hole through any of the firewalls. Instead, mark the
                 // constraint as satisfied if the network is available, and the job will get
@@ -444,7 +444,9 @@
             }
             // Don't need to update constraint here if the network goes away. We'll do that as part
             // of regular processing when we're notified about the drop.
-        } else if (jobStatus.isRequestedExpeditedJob()
+        } else if (((jobStatus.isRequestedExpeditedJob() && !jobStatus.shouldTreatAsExpeditedJob())
+                || (jobStatus.getJob().isUserInitiated()
+                        && !jobStatus.shouldTreatAsUserInitiatedJob()))
                 && jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY)) {
             // Make sure we don't accidentally keep the constraint as satisfied if the job went
             // from being expedited-ready to not-expeditable.
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 ce33a8e..1971a11 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
@@ -402,6 +402,11 @@
      * running. This isn't copied over when a job is rescheduled.
      */
     public boolean startedAsExpeditedJob = false;
+    /**
+     * Whether or not this particular JobStatus instance was treated as a user-initiated job
+     * when it started running. This isn't copied over when a job is rescheduled.
+     */
+    public boolean startedAsUserInitiatedJob = false;
 
     public boolean startedWithImmediacyPrivilege = false;
 
@@ -1407,7 +1412,7 @@
      * @return true if this is a job whose execution should be made visible to the user.
      */
     public boolean isUserVisibleJob() {
-        return shouldTreatAsUserInitiatedJob();
+        return shouldTreatAsUserInitiatedJob() || startedAsUserInitiatedJob;
     }
 
     /**
@@ -2568,6 +2573,13 @@
             pw.print(startedAsExpeditedJob);
             pw.println(")");
         }
+        if ((getFlags() & JobInfo.FLAG_USER_INITIATED) != 0) {
+            pw.print("userInitiatedApproved: ");
+            pw.print(shouldTreatAsUserInitiatedJob());
+            pw.print(" (started as UIJ: ");
+            pw.print(startedAsUserInitiatedJob);
+            pw.println(")");
+        }
         pw.decreaseIndent();
 
         if (changedAuthorities != null) {
diff --git a/core/api/current.txt b/core/api/current.txt
index b0d5e06..ed81918 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -121,6 +121,7 @@
     field public static final String INTERACT_ACROSS_PROFILES = "android.permission.INTERACT_ACROSS_PROFILES";
     field public static final String INTERNET = "android.permission.INTERNET";
     field public static final String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
+    field public static final String LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE = "android.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE";
     field public static final String LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK = "android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK";
     field public static final String LOADER_USAGE_STATS = "android.permission.LOADER_USAGE_STATS";
     field public static final String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
@@ -1988,17 +1989,17 @@
     field public static final int system_primary_container_light;
     field public static final int system_primary_dark;
     field public static final int system_primary_fixed_dark;
+    field public static final int system_primary_fixed_darker_dark;
     field public static final int system_primary_fixed_darker_light;
     field public static final int system_primary_fixed_light;
-    field public static final int system_primary_fixeder_dark;
     field public static final int system_primary_light;
     field public static final int system_secondary_container_dark;
     field public static final int system_secondary_container_light;
     field public static final int system_secondary_dark;
     field public static final int system_secondary_fixed_dark;
+    field public static final int system_secondary_fixed_darker_dark;
     field public static final int system_secondary_fixed_darker_light;
     field public static final int system_secondary_fixed_light;
-    field public static final int system_secondary_fixeder_dark;
     field public static final int system_secondary_light;
     field public static final int system_surface_bright_dark;
     field public static final int system_surface_bright_light;
@@ -2022,9 +2023,9 @@
     field public static final int system_tertiary_container_light;
     field public static final int system_tertiary_dark;
     field public static final int system_tertiary_fixed_dark;
+    field public static final int system_tertiary_fixed_darker_dark;
     field public static final int system_tertiary_fixed_darker_light;
     field public static final int system_tertiary_fixed_light;
-    field public static final int system_tertiary_fixeder_dark;
     field public static final int system_tertiary_light;
     field public static final int system_text_hint_inverse_dark;
     field public static final int system_text_hint_inverse_light;
@@ -3538,6 +3539,7 @@
     method public float getCenterY();
     method public int getMode();
     method public float getScale();
+    method public boolean isActivated();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.MagnificationConfig> CREATOR;
     field public static final int MAGNIFICATION_MODE_DEFAULT = 0; // 0x0
@@ -3548,6 +3550,7 @@
   public static final class MagnificationConfig.Builder {
     ctor public MagnificationConfig.Builder();
     method @NonNull public android.accessibilityservice.MagnificationConfig build();
+    method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setActivated(boolean);
     method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setCenterX(float);
     method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setCenterY(float);
     method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setMode(int);
@@ -4754,6 +4757,7 @@
     method public int getLaunchDisplayId();
     method public boolean getLockTaskMode();
     method public int getPendingIntentBackgroundActivityStartMode();
+    method public int getPendingIntentCreatorBackgroundActivityStartMode();
     method public int getSplashScreenStyle();
     method @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed();
     method public boolean isShareIdentityEnabled();
@@ -4774,6 +4778,7 @@
     method public android.app.ActivityOptions setLockTaskEnabled(boolean);
     method @Deprecated public void setPendingIntentBackgroundActivityLaunchAllowed(boolean);
     method @NonNull public android.app.ActivityOptions setPendingIntentBackgroundActivityStartMode(int);
+    method @NonNull public android.app.ActivityOptions setPendingIntentCreatorBackgroundActivityStartMode(int);
     method @NonNull public android.app.ActivityOptions setShareIdentityEnabled(boolean);
     method @NonNull public android.app.ActivityOptions setSplashScreenStyle(int);
     method public android.os.Bundle toBundle();
@@ -5148,6 +5153,8 @@
     field public static final int REASON_INITIALIZATION_FAILURE = 7; // 0x7
     field public static final int REASON_LOW_MEMORY = 3; // 0x3
     field public static final int REASON_OTHER = 13; // 0xd
+    field public static final int REASON_PACKAGE_STATE_CHANGE = 15; // 0xf
+    field public static final int REASON_PACKAGE_UPDATED = 16; // 0x10
     field public static final int REASON_PERMISSION_CHANGE = 8; // 0x8
     field public static final int REASON_SIGNALED = 2; // 0x2
     field public static final int REASON_UNKNOWN = 0; // 0x0
@@ -6710,6 +6717,7 @@
     method public boolean areNotificationsEnabled();
     method public boolean areNotificationsPaused();
     method public boolean canNotifyAsPackage(@NonNull String);
+    method public boolean canSendFullScreenIntent();
     method public void cancel(int);
     method public void cancel(@Nullable String, int);
     method public void cancelAll();
@@ -7195,6 +7203,7 @@
   }
 
   public class StatusBarManager {
+    method @RequiresPermission(android.Manifest.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE) public boolean canLaunchCaptureContentActivityForNote(@NonNull android.app.Activity);
     method public void requestAddTileService(@NonNull android.content.ComponentName, @NonNull CharSequence, @NonNull android.graphics.drawable.Icon, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     field public static final int TILE_ADD_REQUEST_ERROR_APP_NOT_IN_FOREGROUND = 1004; // 0x3ec
     field public static final int TILE_ADD_REQUEST_ERROR_BAD_COMPONENT = 1002; // 0x3ea
@@ -7273,6 +7282,7 @@
     method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
     method public android.os.ParcelFileDescriptor executeShellCommand(String);
     method @NonNull public android.os.ParcelFileDescriptor[] executeShellCommandRw(@NonNull String);
+    method @NonNull public android.os.ParcelFileDescriptor[] executeShellCommandRwe(@NonNull String);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
     method public android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
@@ -10709,6 +10719,7 @@
     field public static final String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
     field public static final String ACTION_INSTALL_FAILURE = "android.intent.action.INSTALL_FAILURE";
     field @Deprecated public static final String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
+    field @RequiresPermission(android.Manifest.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE) public static final String ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE = "android.intent.action.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE";
     field public static final String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
     field public static final String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
     field public static final String ACTION_MAIN = "android.intent.action.MAIN";
@@ -10802,6 +10813,11 @@
     field public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
     field @Deprecated public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
     field public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
+    field public static final int CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN = 4; // 0x4
+    field public static final int CAPTURE_CONTENT_FOR_NOTE_FAILED = 1; // 0x1
+    field public static final int CAPTURE_CONTENT_FOR_NOTE_SUCCESS = 0; // 0x0
+    field public static final int CAPTURE_CONTENT_FOR_NOTE_USER_CANCELED = 2; // 0x2
+    field public static final int CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED = 3; // 0x3
     field public static final String CATEGORY_ACCESSIBILITY_SHORTCUT_TARGET = "android.intent.category.ACCESSIBILITY_SHORTCUT_TARGET";
     field public static final String CATEGORY_ALTERNATIVE = "android.intent.category.ALTERNATIVE";
     field public static final String CATEGORY_APP_BROWSER = "android.intent.category.APP_BROWSER";
@@ -10857,12 +10873,14 @@
     field public static final String EXTRA_AUTO_LAUNCH_SINGLE_CHOICE = "android.intent.extra.AUTO_LAUNCH_SINGLE_CHOICE";
     field public static final String EXTRA_BCC = "android.intent.extra.BCC";
     field public static final String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
+    field public static final String EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE = "android.intent.extra.CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE";
     field public static final String EXTRA_CC = "android.intent.extra.CC";
     field @Deprecated public static final String EXTRA_CHANGED_COMPONENT_NAME = "android.intent.extra.changed_component_name";
     field public static final String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list";
     field public static final String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
     field public static final String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
     field public static final String EXTRA_CHOOSER_CUSTOM_ACTIONS = "android.intent.extra.CHOOSER_CUSTOM_ACTIONS";
+    field public static final String EXTRA_CHOOSER_MODIFY_SHARE_ACTION = "android.intent.extra.CHOOSER_MODIFY_SHARE_ACTION";
     field public static final String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
     field public static final String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
     field public static final String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
@@ -12105,11 +12123,11 @@
 
   public static final class PackageInstaller.InstallConstraints implements android.os.Parcelable {
     method public int describeContents();
-    method public boolean isRequireAppNotForeground();
-    method public boolean isRequireAppNotInteracting();
-    method public boolean isRequireAppNotTopVisible();
-    method public boolean isRequireDeviceIdle();
-    method public boolean isRequireNotInCall();
+    method public boolean isAppNotForegroundRequired();
+    method public boolean isAppNotInteractingRequired();
+    method public boolean isAppNotTopVisibleRequired();
+    method public boolean isDeviceIdleRequired();
+    method public boolean isNotInCallRequired();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.InstallConstraints> CREATOR;
     field @NonNull public static final android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE;
@@ -12118,16 +12136,16 @@
   public static final class PackageInstaller.InstallConstraints.Builder {
     ctor public PackageInstaller.InstallConstraints.Builder();
     method @NonNull public android.content.pm.PackageInstaller.InstallConstraints build();
-    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotForeground();
-    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotInteracting();
-    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotTopVisible();
-    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireDeviceIdle();
-    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder requireNotInCall();
+    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotForegroundRequired();
+    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotInteractingRequired();
+    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotTopVisibleRequired();
+    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder setDeviceIdleRequired();
+    method @NonNull public android.content.pm.PackageInstaller.InstallConstraints.Builder setNotInCallRequired();
   }
 
   public static final class PackageInstaller.InstallConstraintsResult implements android.os.Parcelable {
+    method public boolean areAllConstraintsSatisfied();
     method public int describeContents();
-    method public boolean isAllConstraintsSatisfied();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.InstallConstraintsResult> CREATOR;
   }
@@ -12194,12 +12212,12 @@
     method @Nullable public String getAppPackageName();
     method @NonNull public int[] getChildSessionIds();
     method public long getCreatedMillis();
+    method public boolean getDontKillApp();
     method public int getInstallLocation();
     method public int getInstallReason();
     method @Nullable public String getInstallerAttributionTag();
     method @Nullable public String getInstallerPackageName();
     method public int getInstallerUid();
-    method @NonNull public boolean getIsPreApprovalRequested();
     method public int getMode();
     method public int getOriginatingUid();
     method @Nullable public android.net.Uri getOriginatingUri();
@@ -12219,6 +12237,7 @@
     method public boolean isApplicationEnabledSettingPersistent();
     method public boolean isCommitted();
     method public boolean isMultiPackage();
+    method public boolean isPreApprovalRequested();
     method public boolean isRequestUpdateOwnership();
     method public boolean isSealed();
     method public boolean isStaged();
@@ -12249,6 +12268,7 @@
     method public void setAppPackageName(@Nullable String);
     method public void setApplicationEnabledSettingPersistent();
     method @Deprecated public void setAutoRevokePermissionsMode(boolean);
+    method public void setDontKillApp(boolean);
     method public void setInstallLocation(int);
     method public void setInstallReason(int);
     method public void setInstallScenario(int);
@@ -12613,7 +12633,8 @@
     field public static final int FLAG_PERMISSION_WHITELIST_SYSTEM = 1; // 0x1
     field public static final int FLAG_PERMISSION_WHITELIST_UPGRADE = 4; // 0x4
     field public static final int GET_ACTIVITIES = 1; // 0x1
-    field public static final int GET_ATTRIBUTIONS = -2147483648; // 0x80000000
+    field @Deprecated public static final int GET_ATTRIBUTIONS = -2147483648; // 0x80000000
+    field public static final long GET_ATTRIBUTIONS_LONG = 2147483648L; // 0x80000000L
     field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
     field @Deprecated public static final int GET_DISABLED_COMPONENTS = 512; // 0x200
     field @Deprecated public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
@@ -12654,6 +12675,7 @@
     field public static final int PERMISSION_DENIED = -1; // 0xffffffff
     field public static final int PERMISSION_GRANTED = 0; // 0x0
     field public static final String PROPERTY_MEDIA_CAPABILITIES = "android.media.PROPERTY_MEDIA_CAPABILITIES";
+    field public static final String PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES = "android.net.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES";
     field public static final String PROPERTY_SPECIAL_USE_FGS_SUBTYPE = "android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE";
     field public static final int SIGNATURE_FIRST_NOT_SIGNED = -1; // 0xffffffff
     field public static final int SIGNATURE_MATCH = 0; // 0x0
@@ -13449,7 +13471,9 @@
   }
 
   public final class CreateCredentialRequest implements android.os.Parcelable {
+    ctor public CreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle, boolean, boolean);
     ctor public CreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle, boolean);
+    method public boolean alwaysSendAppInfoToProvider();
     method public int describeContents();
     method @NonNull public android.os.Bundle getCandidateQueryData();
     method @NonNull public android.os.Bundle getCredentialData();
@@ -13491,10 +13515,23 @@
     method public void clearCredentialState(@NonNull android.credentials.ClearCredentialStateRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.credentials.ClearCredentialStateException>);
     method public void createCredential(@NonNull android.credentials.CreateCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.CreateCredentialResponse,android.credentials.CreateCredentialException>);
     method public void getCredential(@NonNull android.credentials.GetCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.GetCredentialResponse,android.credentials.GetCredentialException>);
+    method public boolean isEnabledCredentialProviderService(@NonNull android.content.ComponentName);
     method public void registerCredentialDescription(@NonNull android.credentials.RegisterCredentialDescriptionRequest);
     method public void unregisterCredentialDescription(@NonNull android.credentials.UnregisterCredentialDescriptionRequest);
   }
 
+  public final class CredentialOption implements android.os.Parcelable {
+    ctor public CredentialOption(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle, boolean);
+    method public int describeContents();
+    method @NonNull public android.os.Bundle getCandidateQueryData();
+    method @NonNull public android.os.Bundle getCredentialRetrievalData();
+    method @NonNull public String getType();
+    method public boolean isSystemProviderRequired();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CredentialOption> CREATOR;
+    field public static final String FLATTENED_REQUEST = "android.credentials.GetCredentialOption.FLATTENED_REQUEST_STRING";
+  }
+
   public class GetCredentialException extends java.lang.Exception {
     ctor public GetCredentialException(@NonNull String, @Nullable String);
     ctor public GetCredentialException(@NonNull String, @Nullable String, @Nullable Throwable);
@@ -13507,31 +13544,21 @@
     field @NonNull public static final String TYPE_USER_CANCELED = "android.credentials.GetCredentialException.TYPE_USER_CANCELED";
   }
 
-  public final class GetCredentialOption implements android.os.Parcelable {
-    ctor public GetCredentialOption(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle, boolean);
-    method public int describeContents();
-    method @NonNull public android.os.Bundle getCandidateQueryData();
-    method @NonNull public android.os.Bundle getCredentialRetrievalData();
-    method @NonNull public String getType();
-    method public boolean isSystemProviderRequired();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.credentials.GetCredentialOption> CREATOR;
-    field public static final String FLATTENED_REQUEST = "android.credentials.GetCredentialOption.FLATTENED_REQUEST_STRING";
-  }
-
   public final class GetCredentialRequest implements android.os.Parcelable {
+    method public boolean alwaysSendAppInfoToProvider();
     method public int describeContents();
+    method @NonNull public java.util.List<android.credentials.CredentialOption> getCredentialOptions();
     method @NonNull public android.os.Bundle getData();
-    method @NonNull public java.util.List<android.credentials.GetCredentialOption> getGetCredentialOptions();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.credentials.GetCredentialRequest> CREATOR;
   }
 
   public static final class GetCredentialRequest.Builder {
     ctor public GetCredentialRequest.Builder(@NonNull android.os.Bundle);
-    method @NonNull public android.credentials.GetCredentialRequest.Builder addGetCredentialOption(@NonNull android.credentials.GetCredentialOption);
+    method @NonNull public android.credentials.GetCredentialRequest.Builder addCredentialOption(@NonNull android.credentials.CredentialOption);
     method @NonNull public android.credentials.GetCredentialRequest build();
-    method @NonNull public android.credentials.GetCredentialRequest.Builder setGetCredentialOptions(@NonNull java.util.List<android.credentials.GetCredentialOption>);
+    method @NonNull public android.credentials.GetCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean);
+    method @NonNull public android.credentials.GetCredentialRequest.Builder setCredentialOptions(@NonNull java.util.List<android.credentials.CredentialOption>);
   }
 
   public final class GetCredentialResponse implements android.os.Parcelable {
@@ -14995,7 +15022,7 @@
     method public void drawLine(float, float, float, float, @NonNull android.graphics.Paint);
     method public void drawLines(@NonNull @Size(multiple=4) float[], int, int, @NonNull android.graphics.Paint);
     method public void drawLines(@NonNull @Size(multiple=4) float[], @NonNull android.graphics.Paint);
-    method public void drawMesh(@NonNull android.graphics.Mesh, android.graphics.BlendMode, @NonNull android.graphics.Paint);
+    method public void drawMesh(@NonNull android.graphics.Mesh, @Nullable android.graphics.BlendMode, @NonNull android.graphics.Paint);
     method public void drawOval(@NonNull android.graphics.RectF, @NonNull android.graphics.Paint);
     method public void drawOval(float, float, float, float, @NonNull android.graphics.Paint);
     method public void drawPaint(@NonNull android.graphics.Paint);
@@ -15597,10 +15624,10 @@
   }
 
   public class Mesh {
-    method @NonNull public static android.graphics.Mesh make(@NonNull android.graphics.MeshSpecification, int, @NonNull java.nio.Buffer, int, @NonNull android.graphics.Rect);
-    method @NonNull public static android.graphics.Mesh makeIndexed(@NonNull android.graphics.MeshSpecification, int, @NonNull java.nio.Buffer, int, @NonNull java.nio.ShortBuffer, @NonNull android.graphics.Rect);
-    method public void setColorUniform(@NonNull String, int);
-    method public void setColorUniform(@NonNull String, long);
+    ctor public Mesh(@NonNull android.graphics.MeshSpecification, int, @NonNull java.nio.Buffer, int, @NonNull android.graphics.RectF);
+    ctor public Mesh(@NonNull android.graphics.MeshSpecification, int, @NonNull java.nio.Buffer, int, @NonNull java.nio.ShortBuffer, @NonNull android.graphics.RectF);
+    method public void setColorUniform(@NonNull String, @ColorInt int);
+    method public void setColorUniform(@NonNull String, @ColorLong long);
     method public void setColorUniform(@NonNull String, @NonNull android.graphics.Color);
     method public void setFloatUniform(@NonNull String, float);
     method public void setFloatUniform(@NonNull String, float, float);
@@ -19353,7 +19380,9 @@
 
   public final class DisplayManager {
     method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int);
+    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int);
     method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler);
+    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int, @Nullable android.os.Handler, @Nullable android.hardware.display.VirtualDisplay.Callback);
     method public android.view.Display getDisplay(int);
     method public android.view.Display[] getDisplays();
     method public android.view.Display[] getDisplays(String);
@@ -24014,6 +24043,7 @@
     method @Nullable public android.net.Uri getIconUri();
     method @NonNull public String getId();
     method @NonNull public CharSequence getName();
+    method public int getType();
     method public int getVolume();
     method public int getVolumeHandling();
     method public int getVolumeMax();
@@ -24030,6 +24060,22 @@
     field public static final String FEATURE_REMOTE_VIDEO_PLAYBACK = "android.media.route.feature.REMOTE_VIDEO_PLAYBACK";
     field public static final int PLAYBACK_VOLUME_FIXED = 0; // 0x0
     field public static final int PLAYBACK_VOLUME_VARIABLE = 1; // 0x1
+    field public static final int TYPE_BLE_HEADSET = 26; // 0x1a
+    field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8
+    field public static final int TYPE_BUILTIN_SPEAKER = 2; // 0x2
+    field public static final int TYPE_DOCK = 13; // 0xd
+    field public static final int TYPE_GROUP = 2000; // 0x7d0
+    field public static final int TYPE_HDMI = 9; // 0x9
+    field public static final int TYPE_HEARING_AID = 23; // 0x17
+    field public static final int TYPE_REMOTE_AUDIO_VIDEO_RECEIVER = 1003; // 0x3eb
+    field public static final int TYPE_REMOTE_SPEAKER = 1002; // 0x3ea
+    field public static final int TYPE_REMOTE_TV = 1001; // 0x3e9
+    field public static final int TYPE_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_USB_ACCESSORY = 12; // 0xc
+    field public static final int TYPE_USB_DEVICE = 11; // 0xb
+    field public static final int TYPE_USB_HEADSET = 22; // 0x16
+    field public static final int TYPE_WIRED_HEADPHONES = 4; // 0x4
+    field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
   }
 
   public static final class MediaRoute2Info.Builder {
@@ -24045,6 +24091,7 @@
     method @NonNull public android.media.MediaRoute2Info.Builder setDescription(@Nullable CharSequence);
     method @NonNull public android.media.MediaRoute2Info.Builder setExtras(@Nullable android.os.Bundle);
     method @NonNull public android.media.MediaRoute2Info.Builder setIconUri(@Nullable android.net.Uri);
+    method @NonNull public android.media.MediaRoute2Info.Builder setType(int);
     method @NonNull public android.media.MediaRoute2Info.Builder setVisibilityPublic();
     method @NonNull public android.media.MediaRoute2Info.Builder setVisibilityRestricted(@NonNull java.util.Set<java.lang.String>);
     method @NonNull public android.media.MediaRoute2Info.Builder setVolume(int);
@@ -24590,8 +24637,8 @@
 
   public final class RouteListingPreference implements android.os.Parcelable {
     method public int describeContents();
-    method @Nullable public android.content.ComponentName getInAppOnlyItemRoutingReceiver();
     method @NonNull public java.util.List<android.media.RouteListingPreference.Item> getItems();
+    method @Nullable public android.content.ComponentName getLinkedItemComponentName();
     method public boolean getUseSystemOrdering();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final String ACTION_TRANSFER_MEDIA = "android.media.action.TRANSFER_MEDIA";
@@ -24602,37 +24649,44 @@
   public static final class RouteListingPreference.Builder {
     ctor public RouteListingPreference.Builder();
     method @NonNull public android.media.RouteListingPreference build();
-    method @NonNull public android.media.RouteListingPreference.Builder setInAppOnlyItemRoutingReceiver(@Nullable android.content.ComponentName);
     method @NonNull public android.media.RouteListingPreference.Builder setItems(@NonNull java.util.List<android.media.RouteListingPreference.Item>);
+    method @NonNull public android.media.RouteListingPreference.Builder setLinkedItemComponentName(@Nullable android.content.ComponentName);
     method @NonNull public android.media.RouteListingPreference.Builder setUseSystemOrdering(boolean);
   }
 
   public static final class RouteListingPreference.Item implements android.os.Parcelable {
     method public int describeContents();
-    method @Nullable public CharSequence getCustomDisableReasonMessage();
-    method public int getDisableReason();
+    method @Nullable public CharSequence getCustomSubtextMessage();
     method public int getFlags();
     method @NonNull public String getRouteId();
-    method public int getSessionParticipantCount();
+    method public int getSelectionBehavior();
+    method public int getSubText();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.media.RouteListingPreference.Item> CREATOR;
-    field public static final int DISABLE_REASON_AD = 3; // 0x3
-    field public static final int DISABLE_REASON_CUSTOM = 5; // 0x5
-    field public static final int DISABLE_REASON_DOWNLOADED_CONTENT = 2; // 0x2
-    field public static final int DISABLE_REASON_IN_APP_ONLY = 4; // 0x4
-    field public static final int DISABLE_REASON_NONE = 0; // 0x0
-    field public static final int DISABLE_REASON_SUBSCRIPTION_REQUIRED = 1; // 0x1
     field public static final int FLAG_ONGOING_SESSION = 1; // 0x1
-    field public static final int FLAG_SUGGESTED_ROUTE = 2; // 0x2
+    field public static final int FLAG_ONGOING_SESSION_MANAGED = 2; // 0x2
+    field public static final int FLAG_SUGGESTED = 4; // 0x4
+    field public static final int SELECTION_BEHAVIOR_GO_TO_APP = 2; // 0x2
+    field public static final int SELECTION_BEHAVIOR_NONE = 0; // 0x0
+    field public static final int SELECTION_BEHAVIOR_TRANSFER = 1; // 0x1
+    field public static final int SUBTEXT_AD_ROUTING_DISALLOWED = 4; // 0x4
+    field public static final int SUBTEXT_CUSTOM = 10000; // 0x2710
+    field public static final int SUBTEXT_DEVICE_LOW_POWER = 5; // 0x5
+    field public static final int SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED = 3; // 0x3
+    field public static final int SUBTEXT_ERROR_UNKNOWN = 1; // 0x1
+    field public static final int SUBTEXT_NONE = 0; // 0x0
+    field public static final int SUBTEXT_SUBSCRIPTION_REQUIRED = 2; // 0x2
+    field public static final int SUBTEXT_TRACK_UNSUPPORTED = 7; // 0x7
+    field public static final int SUBTEXT_UNAUTHORIZED = 6; // 0x6
   }
 
   public static final class RouteListingPreference.Item.Builder {
     ctor public RouteListingPreference.Item.Builder(@NonNull String);
     method @NonNull public android.media.RouteListingPreference.Item build();
-    method @NonNull public android.media.RouteListingPreference.Item.Builder setCustomDisableReasonMessage(@Nullable CharSequence);
-    method @NonNull public android.media.RouteListingPreference.Item.Builder setDisableReason(int);
+    method @NonNull public android.media.RouteListingPreference.Item.Builder setCustomSubtextMessage(@Nullable CharSequence);
     method @NonNull public android.media.RouteListingPreference.Item.Builder setFlags(int);
-    method @NonNull public android.media.RouteListingPreference.Item.Builder setSessionParticipantCount(@IntRange(from=0) int);
+    method @NonNull public android.media.RouteListingPreference.Item.Builder setSelectionBehavior(int);
+    method @NonNull public android.media.RouteListingPreference.Item.Builder setSubText(int);
   }
 
   public final class RoutingSessionInfo implements android.os.Parcelable {
@@ -26309,8 +26363,23 @@
 
 package android.media.tv {
 
+  public final class AdBuffer implements android.os.Parcelable {
+    ctor public AdBuffer(int, @NonNull String, @NonNull android.os.SharedMemory, int, int, long, int);
+    method public int describeContents();
+    method public int getFlags();
+    method public int getId();
+    method public int getLength();
+    method @NonNull public String getMimeType();
+    method public int getOffset();
+    method public long getPresentationTimeUs();
+    method @NonNull public android.os.SharedMemory getSharedMemory();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.AdBuffer> CREATOR;
+  }
+
   public final class AdRequest implements android.os.Parcelable {
     ctor public AdRequest(int, int, @Nullable android.os.ParcelFileDescriptor, long, long, long, @Nullable String, @NonNull android.os.Bundle);
+    ctor public AdRequest(int, int, @Nullable android.net.Uri, long, long, long, @NonNull android.os.Bundle);
     method public int describeContents();
     method public long getEchoIntervalMillis();
     method @Nullable public android.os.ParcelFileDescriptor getFileDescriptor();
@@ -26320,6 +26389,7 @@
     method public int getRequestType();
     method public long getStartTimeMillis();
     method public long getStopTimeMillis();
+    method @Nullable public android.net.Uri getUri();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.AdRequest> CREATOR;
     field public static final int REQUEST_TYPE_START = 1; // 0x1
@@ -26334,6 +26404,7 @@
     method public int getResponseType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.AdResponse> CREATOR;
+    field public static final int RESPONSE_TYPE_BUFFERING = 5; // 0x5
     field public static final int RESPONSE_TYPE_ERROR = 4; // 0x4
     field public static final int RESPONSE_TYPE_FINISHED = 2; // 0x2
     field public static final int RESPONSE_TYPE_PLAYING = 1; // 0x1
@@ -27014,6 +27085,8 @@
     field public static final int TIME_SHIFT_STATUS_UNAVAILABLE = 2; // 0x2
     field public static final int TIME_SHIFT_STATUS_UNKNOWN = 0; // 0x0
     field public static final int TIME_SHIFT_STATUS_UNSUPPORTED = 1; // 0x1
+    field public static final String TV_MESSAGE_TYPE_CLOSED_CAPTION = "CC";
+    field public static final String TV_MESSAGE_TYPE_WATERMARK = "Watermark";
     field public static final int VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY = 4; // 0x4
     field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
     field public static final int VIDEO_UNAVAILABLE_REASON_CAS_BLACKOUT = 16; // 0x10
@@ -27087,6 +27160,7 @@
   public abstract static class TvInputService.Session implements android.view.KeyEvent.Callback {
     ctor public TvInputService.Session(android.content.Context);
     method public void layoutSurface(int, int, int, int);
+    method public void notifyAdBufferConsumed(@NonNull android.media.tv.AdBuffer);
     method public void notifyAdResponse(@NonNull android.media.tv.AdResponse);
     method public void notifyAitInfoUpdated(@NonNull android.media.tv.AitInfo);
     method public void notifyAudioPresentationChanged(@NonNull java.util.List<android.media.AudioPresentation>);
@@ -27100,8 +27174,10 @@
     method public void notifyTrackSelected(int, String);
     method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>);
     method public void notifyTuned(@NonNull android.net.Uri);
+    method public void notifyTvMessage(@NonNull String, @NonNull android.os.Bundle);
     method public void notifyVideoAvailable();
     method public void notifyVideoUnavailable(int);
+    method public void onAdBuffer(@NonNull android.media.tv.AdBuffer);
     method public void onAppPrivateCommand(@NonNull String, android.os.Bundle);
     method public android.view.View onCreateOverlayView();
     method public boolean onGenericMotionEvent(android.view.MotionEvent);
@@ -27120,6 +27196,7 @@
     method public void onSetInteractiveAppNotificationEnabled(boolean);
     method public abstract void onSetStreamVolume(@FloatRange(from=0.0, to=1.0) float);
     method public abstract boolean onSetSurface(@Nullable android.view.Surface);
+    method public void onSetTvMessageEnabled(@NonNull String, boolean);
     method public void onSurfaceChanged(int, int, int);
     method public long onTimeShiftGetCurrentPosition();
     method public long onTimeShiftGetStartPosition();
@@ -27259,6 +27336,7 @@
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
     method public void setStreamVolume(@FloatRange(from=0.0, to=1.0) float);
     method public void setTimeShiftPositionCallback(@Nullable android.media.tv.TvView.TimeShiftPositionCallback);
+    method public void setTvMessageEnabled(@NonNull String, boolean);
     method public void setZOrderMediaOverlay(boolean);
     method public void setZOrderOnTop(boolean);
     method public void timeShiftPause();
@@ -27295,6 +27373,7 @@
     method public void onTrackSelected(String, int, String);
     method public void onTracksChanged(String, java.util.List<android.media.tv.TvTrackInfo>);
     method public void onTuned(@NonNull String, @NonNull android.net.Uri);
+    method public void onTvMessage(@NonNull String, @NonNull String, @NonNull android.os.Bundle);
     method public void onVideoAvailable(String);
     method public void onVideoSizeChanged(String, int, int);
     method public void onVideoUnavailable(String, int);
@@ -27388,9 +27467,11 @@
     ctor public TvInteractiveAppService.Session(@NonNull android.content.Context);
     method public boolean isMediaViewEnabled();
     method @CallSuper public void layoutSurface(int, int, int, int);
+    method @CallSuper public void notifyAdBuffer(@NonNull android.media.tv.AdBuffer);
     method @CallSuper public final void notifyBiInteractiveAppCreated(@NonNull android.net.Uri, @Nullable String);
     method @CallSuper public void notifySessionStateChanged(int, int);
     method @CallSuper public final void notifyTeletextAppStateChanged(int);
+    method public void onAdBufferConsumed(@NonNull android.media.tv.AdBuffer);
     method public void onAdResponse(@NonNull android.media.tv.AdResponse);
     method public void onBroadcastInfoResponse(@NonNull android.media.tv.BroadcastInfoResponse);
     method public void onContentAllowed();
@@ -27426,6 +27507,9 @@
     method public boolean onTrackballEvent(@NonNull android.view.MotionEvent);
     method public void onTracksChanged(@NonNull java.util.List<android.media.tv.TvTrackInfo>);
     method public void onTuned(@NonNull android.net.Uri);
+    method public void onTvMessage(@NonNull String, @NonNull android.os.Bundle);
+    method public void onTvRecordingInfo(@Nullable android.media.tv.TvRecordingInfo);
+    method public void onTvRecordingInfoList(@NonNull java.util.List<android.media.tv.TvRecordingInfo>);
     method public void onVideoAvailable();
     method public void onVideoUnavailable(int);
     method @CallSuper public void removeBroadcastInfo(int);
@@ -27473,6 +27557,7 @@
     method public void notifyError(@NonNull String, @NonNull android.os.Bundle);
     method public void notifyRecordingStarted(@NonNull String);
     method public void notifyRecordingStopped(@NonNull String);
+    method public void notifyTvMessage(@NonNull String, @NonNull android.os.Bundle);
     method public void onAttachedToWindow();
     method public void onDetachedFromWindow();
     method public void onLayout(boolean, int, int, int, int);
@@ -27488,6 +27573,8 @@
     method public void sendSigningResult(@NonNull String, @NonNull byte[]);
     method public void sendStreamVolume(float);
     method public void sendTrackInfoList(@Nullable java.util.List<android.media.tv.TvTrackInfo>);
+    method public void sendTvRecordingInfo(@Nullable android.media.tv.TvRecordingInfo);
+    method public void sendTvRecordingInfoList(@NonNull java.util.List<android.media.tv.TvRecordingInfo>);
     method public void setCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppView.TvInteractiveAppCallback);
     method public void setOnUnhandledInputEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppView.OnUnhandledInputEventListener);
     method public void setTeletextAppEnabled(boolean);
@@ -32130,6 +32217,7 @@
     method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
     field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
     field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
+    field public static final int BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE = 6; // 0x6
     field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
     field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
     field public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3; // 0x3
@@ -36679,6 +36767,7 @@
     field public static final String ACTION_MANAGE_ALL_SIM_PROFILES_SETTINGS = "android.settings.MANAGE_ALL_SIM_PROFILES_SETTINGS";
     field public static final String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
     field public static final String ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION = "android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION";
+    field public static final String ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT = "android.settings.MANAGE_APP_USE_FULL_SCREEN_INTENT";
     field public static final String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
     field public static final String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
     field public static final String ACTION_MANAGE_SUPERVISOR_RESTRICTED_SETTING = "android.settings.MANAGE_SUPERVISOR_RESTRICTED_SETTING";
@@ -39305,6 +39394,19 @@
 
 }
 
+package android.service.assist.classification {
+
+  public final class FieldClassification implements android.os.Parcelable {
+    ctor public FieldClassification(@NonNull android.view.autofill.AutofillId, @NonNull java.util.Set<java.lang.String>);
+    method public int describeContents();
+    method @NonNull public android.view.autofill.AutofillId getAutofillId();
+    method @NonNull public java.util.Set<java.lang.String> getHints();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.assist.classification.FieldClassification> CREATOR;
+  }
+
+}
+
 package android.service.autofill {
 
   public abstract class AutofillService extends android.app.Service {
@@ -40129,9 +40231,10 @@
   }
 
   public class BeginCreateCredentialRequest implements android.os.Parcelable {
-    ctor public BeginCreateCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull String, @NonNull android.os.Bundle);
+    ctor public BeginCreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle, @Nullable android.service.credentials.CallingAppInfo);
+    ctor public BeginCreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle);
     method public int describeContents();
-    method @NonNull public android.service.credentials.CallingAppInfo getCallingAppInfo();
+    method @Nullable public android.service.credentials.CallingAppInfo getCallingAppInfo();
     method @NonNull public android.os.Bundle getData();
     method @NonNull public String getType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -40155,7 +40258,7 @@
   }
 
   public class BeginGetCredentialOption implements android.os.Parcelable {
-    ctor public BeginGetCredentialOption(@NonNull String, @NonNull android.os.Bundle);
+    ctor public BeginGetCredentialOption(@NonNull String, @NonNull String, @NonNull android.os.Bundle);
     method public int describeContents();
     method @NonNull public android.os.Bundle getCandidateQueryData();
     method @NonNull public String getType();
@@ -40166,28 +40269,41 @@
   public final class BeginGetCredentialRequest implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public java.util.List<android.service.credentials.BeginGetCredentialOption> getBeginGetCredentialOptions();
-    method @NonNull public android.service.credentials.CallingAppInfo getCallingAppInfo();
+    method @Nullable public android.service.credentials.CallingAppInfo getCallingAppInfo();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginGetCredentialRequest> CREATOR;
   }
 
   public static final class BeginGetCredentialRequest.Builder {
-    ctor public BeginGetCredentialRequest.Builder(@NonNull android.service.credentials.CallingAppInfo);
+    ctor public BeginGetCredentialRequest.Builder();
     method @NonNull public android.service.credentials.BeginGetCredentialRequest.Builder addBeginGetCredentialOption(@NonNull android.service.credentials.BeginGetCredentialOption);
     method @NonNull public android.service.credentials.BeginGetCredentialRequest build();
     method @NonNull public android.service.credentials.BeginGetCredentialRequest.Builder setBeginGetCredentialOptions(@NonNull java.util.List<android.service.credentials.BeginGetCredentialOption>);
+    method @NonNull public android.service.credentials.BeginGetCredentialRequest.Builder setCallingAppInfo(@Nullable android.service.credentials.CallingAppInfo);
   }
 
   public final class BeginGetCredentialResponse implements android.os.Parcelable {
-    method @NonNull public static android.service.credentials.BeginGetCredentialResponse createWithAuthentication(@NonNull android.service.credentials.Action);
-    method @NonNull public static android.service.credentials.BeginGetCredentialResponse createWithResponseContent(@NonNull android.service.credentials.CredentialsResponseContent);
     method public int describeContents();
-    method @Nullable public android.service.credentials.Action getAuthenticationAction();
-    method @Nullable public android.service.credentials.CredentialsResponseContent getCredentialsResponseContent();
+    method @NonNull public java.util.List<android.service.credentials.Action> getActions();
+    method @NonNull public java.util.List<android.service.credentials.Action> getAuthenticationActions();
+    method @NonNull public java.util.List<android.service.credentials.CredentialEntry> getCredentialEntries();
+    method @Nullable public android.service.credentials.CredentialEntry getRemoteCredentialEntry();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginGetCredentialResponse> CREATOR;
   }
 
+  public static final class BeginGetCredentialResponse.Builder {
+    ctor public BeginGetCredentialResponse.Builder();
+    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder addAction(@NonNull android.service.credentials.Action);
+    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder addAuthenticationAction(@NonNull android.service.credentials.Action);
+    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder addCredentialEntry(@NonNull android.service.credentials.CredentialEntry);
+    method @NonNull public android.service.credentials.BeginGetCredentialResponse build();
+    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setActions(@NonNull java.util.List<android.service.credentials.Action>);
+    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setAuthenticationActions(@NonNull java.util.List<android.service.credentials.Action>);
+    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setCredentialEntries(@NonNull java.util.List<android.service.credentials.CredentialEntry>);
+    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.CredentialEntry);
+  }
+
   public final class CallingAppInfo implements android.os.Parcelable {
     ctor public CallingAppInfo(@NonNull String, @NonNull android.content.pm.SigningInfo);
     method public int describeContents();
@@ -40225,8 +40341,9 @@
   }
 
   public class CredentialEntry implements android.os.Parcelable {
-    ctor public CredentialEntry(@NonNull String, @NonNull android.app.slice.Slice);
+    ctor public CredentialEntry(@NonNull android.service.credentials.BeginGetCredentialOption, @NonNull android.app.slice.Slice);
     method public int describeContents();
+    method @NonNull public android.service.credentials.BeginGetCredentialOption getBeginGetCredentialOption();
     method @NonNull public android.app.slice.Slice getSlice();
     method @NonNull public String getType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -40241,40 +40358,21 @@
     method public abstract void onClearCredentialState(@NonNull android.service.credentials.ClearCredentialStateRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.credentials.ClearCredentialStateException>);
     field public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities";
     field public static final String EXTRA_BEGIN_GET_CREDENTIAL_REQUEST = "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_REQUEST";
+    field public static final String EXTRA_BEGIN_GET_CREDENTIAL_RESPONSE = "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_RESPONSE";
     field public static final String EXTRA_CREATE_CREDENTIAL_EXCEPTION = "android.service.credentials.extra.CREATE_CREDENTIAL_EXCEPTION";
     field public static final String EXTRA_CREATE_CREDENTIAL_REQUEST = "android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST";
     field public static final String EXTRA_CREATE_CREDENTIAL_RESPONSE = "android.service.credentials.extra.CREATE_CREDENTIAL_RESPONSE";
-    field public static final String EXTRA_CREDENTIALS_RESPONSE_CONTENT = "android.service.credentials.extra.CREDENTIALS_RESPONSE_CONTENT";
     field public static final String EXTRA_GET_CREDENTIAL_EXCEPTION = "android.service.credentials.extra.GET_CREDENTIAL_EXCEPTION";
     field public static final String EXTRA_GET_CREDENTIAL_REQUEST = "android.service.credentials.extra.GET_CREDENTIAL_REQUEST";
     field public static final String EXTRA_GET_CREDENTIAL_RESPONSE = "android.service.credentials.extra.GET_CREDENTIAL_RESPONSE";
     field public static final String SERVICE_INTERFACE = "android.service.credentials.CredentialProviderService";
   }
 
-  public final class CredentialsResponseContent implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public java.util.List<android.service.credentials.Action> getActions();
-    method @NonNull public java.util.List<android.service.credentials.CredentialEntry> getCredentialEntries();
-    method @Nullable public android.service.credentials.CredentialEntry getRemoteCredentialEntry();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.CredentialsResponseContent> CREATOR;
-  }
-
-  public static final class CredentialsResponseContent.Builder {
-    ctor public CredentialsResponseContent.Builder();
-    method @NonNull public android.service.credentials.CredentialsResponseContent.Builder addAction(@NonNull android.service.credentials.Action);
-    method @NonNull public android.service.credentials.CredentialsResponseContent.Builder addCredentialEntry(@NonNull android.service.credentials.CredentialEntry);
-    method @NonNull public android.service.credentials.CredentialsResponseContent build();
-    method @NonNull public android.service.credentials.CredentialsResponseContent.Builder setActions(@NonNull java.util.List<android.service.credentials.Action>);
-    method @NonNull public android.service.credentials.CredentialsResponseContent.Builder setCredentialEntries(@NonNull java.util.List<android.service.credentials.CredentialEntry>);
-    method @NonNull public android.service.credentials.CredentialsResponseContent.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.CredentialEntry);
-  }
-
   public final class GetCredentialRequest implements android.os.Parcelable {
-    ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull android.credentials.GetCredentialOption);
+    ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull android.credentials.CredentialOption);
     method public int describeContents();
     method @NonNull public android.service.credentials.CallingAppInfo getCallingAppInfo();
-    method @NonNull public android.credentials.GetCredentialOption getGetCredentialOption();
+    method @NonNull public android.credentials.CredentialOption getCredentialOption();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.GetCredentialRequest> CREATOR;
   }
@@ -40698,12 +40796,12 @@
     method @Nullable public CharSequence getCardLabel();
     method @NonNull public int getCardType();
     method @NonNull public CharSequence getContentDescription();
+    method @Nullable public android.graphics.drawable.Icon getNonPaymentCardSecondaryImage();
     method @NonNull public android.app.PendingIntent getPendingIntent();
-    method @Nullable public android.graphics.drawable.Icon getValuableCardSecondaryImage();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int CARD_TYPE_NON_PAYMENT = 2; // 0x2
     field public static final int CARD_TYPE_PAYMENT = 1; // 0x1
     field public static final int CARD_TYPE_UNKNOWN = 0; // 0x0
-    field public static final int CARD_TYPE_VALUABLE = 2; // 0x2
     field @NonNull public static final android.os.Parcelable.Creator<android.service.quickaccesswallet.WalletCard> CREATOR;
   }
 
@@ -40713,7 +40811,7 @@
     method @NonNull public android.service.quickaccesswallet.WalletCard build();
     method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setCardIcon(@Nullable android.graphics.drawable.Icon);
     method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setCardLabel(@Nullable CharSequence);
-    method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setValuableCardSecondaryImage(@Nullable android.graphics.drawable.Icon);
+    method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setNonPaymentCardSecondaryImage(@Nullable android.graphics.drawable.Icon);
   }
 
   public final class WalletServiceEvent implements android.os.Parcelable {
@@ -41636,7 +41734,6 @@
   public final class CallControl {
     method public void disconnect(@NonNull android.telecom.DisconnectCause, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
     method @NonNull public android.os.ParcelUuid getCallId();
-    method public void rejectCall(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
     method public void requestCallEndpointChange(@NonNull android.telecom.CallEndpoint, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
     method public void setActive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
     method public void setInactive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
@@ -41685,7 +41782,6 @@
   }
 
   public final class CallException extends java.lang.RuntimeException implements android.os.Parcelable {
-    ctor public CallException(@Nullable String);
     ctor public CallException(@Nullable String, int);
     method public int describeContents();
     method public int getCode();
@@ -42435,7 +42531,7 @@
     method @NonNull public String getDisplayName();
     method @NonNull public android.os.Bundle getExtras();
     method public int getState();
-    method public void setStreamingState(int);
+    method public void requestStreamingState(int);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telecom.StreamingCall> CREATOR;
     field public static final int STATE_DISCONNECTED = 3; // 0x3
@@ -43278,7 +43374,7 @@
     field public static final String KEY_PREFIX = "imssms.";
     field public static final String KEY_SMS_CSFB_RETRY_ON_FAILURE_BOOL = "imssms.sms_csfb_retry_on_failure_bool";
     field public static final String KEY_SMS_MAX_RETRY_COUNT_INT = "imssms.sms_max_retry_count_int";
-    field public static final String KEY_SMS_MAX_RETRY_COUNT_OVER_IMS_INT = "imssms.sms_max_retry_count_over_ims_int";
+    field public static final String KEY_SMS_MAX_RETRY_OVER_IMS_COUNT_INT = "imssms.sms_max_retry_over_ims_count_int";
     field public static final String KEY_SMS_OVER_IMS_FORMAT_INT = "imssms.sms_over_ims_format_int";
     field public static final String KEY_SMS_OVER_IMS_SEND_RETRY_DELAY_MILLIS_INT = "imssms.sms_over_ims_send_retry_delay_millis_int";
     field public static final String KEY_SMS_OVER_IMS_SUPPORTED_BOOL = "imssms.sms_over_ims_supported_bool";
@@ -45336,6 +45432,7 @@
     field public static final String EXTRA_HIDE_PUBLIC_SETTINGS = "android.telephony.extra.HIDE_PUBLIC_SETTINGS";
     field @Deprecated public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
     field public static final String EXTRA_IS_REFRESH = "android.telephony.extra.IS_REFRESH";
+    field public static final String EXTRA_LAST_KNOWN_NETWORK_COUNTRY = "android.telephony.extra.LAST_KNOWN_NETWORK_COUNTRY";
     field public static final String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
     field public static final String EXTRA_NETWORK_COUNTRY = "android.telephony.extra.NETWORK_COUNTRY";
     field public static final String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
@@ -51296,7 +51393,7 @@
     method public void onTransactionCommitted();
   }
 
-  public static class SurfaceControl.TrustedPresentationThresholds {
+  public static final class SurfaceControl.TrustedPresentationThresholds {
     ctor public SurfaceControl.TrustedPresentationThresholds(@FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @IntRange(from=1) int);
   }
 
@@ -51368,8 +51465,12 @@
     method public android.view.SurfaceControl getSurfaceControl();
     method public void setChildSurfacePackage(@NonNull android.view.SurfaceControlViewHost.SurfacePackage);
     method public void setSecure(boolean);
+    method public void setSurfaceLifecycle(int);
     method public void setZOrderMediaOverlay(boolean);
     method public void setZOrderOnTop(boolean);
+    field public static final int SURFACE_LIFECYCLE_DEFAULT = 0; // 0x0
+    field public static final int SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT = 2; // 0x2
+    field public static final int SURFACE_LIFECYCLE_FOLLOWS_VISIBILITY = 1; // 0x1
   }
 
   public class TextureView extends android.view.View {
@@ -52456,7 +52557,9 @@
     method public int getScaledHoverSlop();
     method public int getScaledMaximumDrawingCacheSize();
     method public int getScaledMaximumFlingVelocity();
+    method public int getScaledMaximumFlingVelocity(int, int, int);
     method public int getScaledMinimumFlingVelocity();
+    method public int getScaledMinimumFlingVelocity(int, int, int);
     method public int getScaledMinimumScalingSpan();
     method public int getScaledOverflingDistance();
     method public int getScaledOverscrollDistance();
@@ -60304,7 +60407,7 @@
     method @UiThread public void remove();
   }
 
-  public class SurfaceSyncGroup {
+  public final class SurfaceSyncGroup {
     ctor public SurfaceSyncGroup(@NonNull String);
     method @UiThread public boolean add(@Nullable android.view.AttachedSurfaceControl, @Nullable Runnable);
     method public boolean add(@NonNull android.view.SurfaceControlViewHost.SurfacePackage, @Nullable Runnable);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 9c7d220..20b3a26 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -55,6 +55,7 @@
     field public static final String BIND_DOMAIN_VERIFICATION_AGENT = "android.permission.BIND_DOMAIN_VERIFICATION_AGENT";
     field public static final String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE";
     field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE";
+    field public static final String BIND_FIELD_CLASSIFICATION_SERVICE = "android.permission.BIND_FIELD_CLASSIFICATION_SERVICE";
     field public static final String BIND_GBA_SERVICE = "android.permission.BIND_GBA_SERVICE";
     field public static final String BIND_HOTWORD_DETECTION_SERVICE = "android.permission.BIND_HOTWORD_DETECTION_SERVICE";
     field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
@@ -546,7 +547,7 @@
 
   public class AlarmManager {
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void set(int, long, long, long, @NonNull android.app.PendingIntent, @Nullable android.os.WorkSource);
-    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void set(int, long, long, long, @NonNull android.app.AlarmManager.OnAlarmListener, @Nullable android.os.Handler, @Nullable android.os.WorkSource);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void set(int, long, long, long, @NonNull android.app.AlarmManager.OnAlarmListener, @Nullable android.os.Handler, @Nullable android.os.WorkSource);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void setExact(int, long, @Nullable String, @NonNull java.util.concurrent.Executor, @NonNull android.os.WorkSource, @NonNull android.app.AlarmManager.OnAlarmListener);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void setExactAndAllowWhileIdle(int, long, @Nullable String, @NonNull java.util.concurrent.Executor, @Nullable android.os.WorkSource, @NonNull android.app.AlarmManager.OnAlarmListener);
     method @RequiresPermission(android.Manifest.permission.SCHEDULE_PRIORITIZED_ALARM) public void setPrioritized(int, long, long, @Nullable String, @NonNull java.util.concurrent.Executor, @NonNull android.app.AlarmManager.OnAlarmListener);
@@ -1230,6 +1231,7 @@
     field @Deprecated public static final String ACTION_STATE_USER_SETUP_COMPLETE = "android.app.action.STATE_USER_SETUP_COMPLETE";
     field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER = "android.app.action.UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER";
     field public static final int EXEMPT_FROM_APP_STANDBY = 0; // 0x0
+    field public static final int EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS = 1; // 0x1
     field public static final String EXTRA_FORCE_UPDATE_ROLE_HOLDER = "android.app.extra.FORCE_UPDATE_ROLE_HOLDER";
     field public static final String EXTRA_LOST_MODE_LOCATION = "android.app.extra.LOST_MODE_LOCATION";
     field public static final String EXTRA_PROFILE_OWNER_NAME = "android.app.extra.PROFILE_OWNER_NAME";
@@ -2119,6 +2121,13 @@
     method protected void finalize();
     method public void notifyEvent(@NonNull android.app.search.Query, @NonNull android.app.search.SearchTargetEvent);
     method @Nullable public void query(@NonNull android.app.search.Query, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.search.SearchTarget>>);
+    method public void registerEmptyQueryResultUpdateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.search.SearchSession.Callback);
+    method public void requestEmptyQueryResultUpdate();
+    method public void unregisterEmptyQueryResultUpdateCallback(@NonNull android.app.search.SearchSession.Callback);
+  }
+
+  public static interface SearchSession.Callback {
+    method public void onTargetsAvailable(@NonNull java.util.List<android.app.search.SearchTarget>);
   }
 
   public final class SearchSessionId implements android.os.Parcelable {
@@ -3005,7 +3014,8 @@
 
   public static interface VirtualDeviceManager.ActivityListener {
     method public void onDisplayEmpty(int);
-    method public void onTopActivityChanged(int, @NonNull android.content.ComponentName);
+    method @Deprecated public void onTopActivityChanged(int, @NonNull android.content.ComponentName);
+    method public default void onTopActivityChanged(int, @NonNull android.content.ComponentName, int);
   }
 
   public static interface VirtualDeviceManager.IntentInterceptorCallback {
@@ -3264,6 +3274,7 @@
     field public static final String SAFETY_CENTER_SERVICE = "safety_center";
     field public static final String SEARCH_UI_SERVICE = "search_ui";
     field public static final String SECURE_ELEMENT_SERVICE = "secure_element";
+    field public static final String SHARED_CONNECTIVITY_SERVICE = "shared_connectivity";
     field public static final String SMARTSPACE_SERVICE = "smartspace";
     field public static final String STATS_MANAGER = "stats";
     field public static final String SYSTEM_CONFIG_SERVICE = "system_config";
@@ -3586,7 +3597,7 @@
   }
 
   public class PackageInstaller {
-    method @NonNull public android.content.pm.PackageInstaller.InstallInfo getInstallInfo(@NonNull java.io.File, int) throws android.content.pm.PackageInstaller.PackageParsingException;
+    method @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull java.io.File, int) throws android.content.pm.PackageInstaller.PackageParsingException;
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean);
     field public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
     field public static final String ACTION_CONFIRM_PRE_APPROVAL = "android.content.pm.action.CONFIRM_PRE_APPROVAL";
@@ -3626,7 +3637,6 @@
     method public boolean getAllocateAggressive();
     method @Deprecated public boolean getAllowDowngrade();
     method public int getAutoRevokePermissionsMode();
-    method public boolean getDontKillApp();
     method public boolean getEnableRollback();
     method @Nullable public String[] getGrantedRuntimePermissions();
     method public boolean getInstallAsFullApp(boolean);
@@ -3642,7 +3652,6 @@
     method @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) public void setAllocateAggressive(boolean);
     method @Deprecated public void setAllowDowngrade(boolean);
     method @RequiresPermission(allOf={android.Manifest.permission.INSTALL_PACKAGES, "com.android.permission.USE_INSTALLER_V2"}) public void setDataLoaderParams(@NonNull android.content.pm.DataLoaderParams);
-    method public void setDontKillApp(boolean);
     method public void setEnableRollback(boolean);
     method public void setEnableRollback(boolean, int);
     method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
@@ -4887,8 +4896,8 @@
 
   public final class VirtualNavigationTouchpadConfig extends android.hardware.input.VirtualInputDeviceConfig implements android.os.Parcelable {
     method public int describeContents();
-    method public int getHeight();
-    method public int getWidth();
+    method @IntRange(from=1) public int getHeight();
+    method @IntRange(from=1) public int getWidth();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.input.VirtualNavigationTouchpadConfig> CREATOR;
   }
@@ -5826,6 +5835,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public long getCurrentFunctions();
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USB) public java.util.List<android.hardware.usb.UsbPort> getPorts();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void grantPermission(android.hardware.usb.UsbDevice, String);
+    method public static boolean isUvcSupportEnabled();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public boolean registerDisplayPortAltModeInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.usb.UsbManager.DisplayPortAltModeInfoListener);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbGadget();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long);
@@ -5847,6 +5857,7 @@
     field public static final long FUNCTION_NONE = 0L; // 0x0L
     field public static final long FUNCTION_PTP = 16L; // 0x10L
     field public static final long FUNCTION_RNDIS = 32L; // 0x20L
+    field public static final long FUNCTION_UVC = 128L; // 0x80L
     field public static final String USB_CONFIGURED = "configured";
     field public static final String USB_CONNECTED = "connected";
     field public static final String USB_FUNCTION_NCM = "ncm";
@@ -6748,6 +6759,7 @@
     field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
     field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
     field public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE = 3; // 0x3
+    field public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY = 5; // 0x5
     field public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE = 4; // 0x4
     field public static final int DEVICE_VOLUME_BEHAVIOR_FIXED = 2; // 0x2
     field public static final int DEVICE_VOLUME_BEHAVIOR_FULL = 1; // 0x1
@@ -7249,40 +7261,40 @@
     method public final void operationFinished(@Nullable java.util.UUID, int);
   }
 
-  public final class SoundTriggerDetector {
-    method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public boolean startRecognition(int);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public boolean stopRecognition();
-    field public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
-    field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
-    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
-    field public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
-    field public static final int RECOGNITION_FLAG_RUN_IN_BATTERY_SAVER = 16; // 0x10
+  @Deprecated public final class SoundTriggerDetector {
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public boolean startRecognition(int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public boolean stopRecognition();
+    field @Deprecated public static final int RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS = 2; // 0x2
+    field @Deprecated public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
+    field @Deprecated public static final int RECOGNITION_FLAG_ENABLE_AUDIO_ECHO_CANCELLATION = 4; // 0x4
+    field @Deprecated public static final int RECOGNITION_FLAG_ENABLE_AUDIO_NOISE_SUPPRESSION = 8; // 0x8
+    field @Deprecated public static final int RECOGNITION_FLAG_RUN_IN_BATTERY_SAVER = 16; // 0x10
   }
 
-  public abstract static class SoundTriggerDetector.Callback {
-    ctor public SoundTriggerDetector.Callback();
-    method public abstract void onAvailabilityChanged(int);
-    method public abstract void onDetected(@NonNull android.media.soundtrigger.SoundTriggerDetector.EventPayload);
-    method public abstract void onError();
-    method public abstract void onRecognitionPaused();
-    method public abstract void onRecognitionResumed();
+  @Deprecated public abstract static class SoundTriggerDetector.Callback {
+    ctor @Deprecated public SoundTriggerDetector.Callback();
+    method @Deprecated public abstract void onAvailabilityChanged(int);
+    method @Deprecated public abstract void onDetected(@NonNull android.media.soundtrigger.SoundTriggerDetector.EventPayload);
+    method @Deprecated public abstract void onError();
+    method @Deprecated public abstract void onRecognitionPaused();
+    method @Deprecated public abstract void onRecognitionResumed();
   }
 
-  public static class SoundTriggerDetector.EventPayload {
-    method @Nullable public android.media.AudioFormat getCaptureAudioFormat();
-    method @Nullable public byte[] getTriggerAudio();
+  @Deprecated public static class SoundTriggerDetector.EventPayload {
+    method @Deprecated @Nullable public android.media.AudioFormat getCaptureAudioFormat();
+    method @Deprecated @Nullable public byte[] getTriggerAudio();
   }
 
   public final class SoundTriggerManager {
-    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerDetector createSoundTriggerDetector(java.util.UUID, @NonNull android.media.soundtrigger.SoundTriggerDetector.Callback, @Nullable android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void deleteModel(java.util.UUID);
+    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerDetector createSoundTriggerDetector(java.util.UUID, @NonNull android.media.soundtrigger.SoundTriggerDetector.Callback, @Nullable android.os.Handler);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void deleteModel(java.util.UUID);
     method public int getDetectionServiceOperationsTimeout();
-    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
+    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.hardware.soundtrigger.SoundTrigger.ModuleProperties getModuleProperties();
     method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int getParameter(@NonNull java.util.UUID, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.hardware.soundtrigger.SoundTrigger.ModelParamRange queryParameter(@Nullable java.util.UUID, int);
     method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int setParameter(@Nullable java.util.UUID, int, int);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model);
   }
 
   public static class SoundTriggerManager.Model {
@@ -7955,6 +7967,7 @@
 
   public class MediaEvent extends android.media.tv.tuner.filter.FilterEvent {
     method public long getAudioHandle();
+    method @NonNull public java.util.List<android.media.AudioPresentation> getAudioPresentations();
     method public long getAvDataId();
     method public long getDataLength();
     method public long getDts();
@@ -8904,8 +8917,11 @@
     field public static final int FRONTEND_STATUS_READINESS_UNSUPPORTED = 4; // 0x4
   }
 
+  public class IptvFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+    method public int getProtocolCapability();
+  }
+
   public class IptvFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
-    ctor public IptvFrontendSettings(@NonNull byte[], @NonNull byte[], int, int, @NonNull android.media.tv.tuner.frontend.IptvFrontendSettingsFec, int, int, long, @NonNull String);
     method @NonNull public static android.media.tv.tuner.frontend.IptvFrontendSettings.Builder builder();
     method @IntRange(from=0) public long getBitrate();
     method @NonNull public String getContentUrl();
@@ -8940,7 +8956,6 @@
   }
 
   public class IptvFrontendSettingsFec {
-    ctor public IptvFrontendSettingsFec(int, int, int);
     method @NonNull public static android.media.tv.tuner.frontend.IptvFrontendSettingsFec.Builder builder();
     method @IntRange(from=0) public int getFecColNum();
     method @IntRange(from=0) public int getFecRowNum();
@@ -9778,6 +9793,132 @@
 
 }
 
+package android.net.wifi.sharedconnectivity.app {
+
+  public final class DeviceInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=0, to=100) @NonNull public int getBatteryPercentage();
+    method @IntRange(from=0, to=3) @NonNull public int getConnectionStrength();
+    method @NonNull public String getDeviceName();
+    method public int getDeviceType();
+    method @NonNull public String getModelName();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.DeviceInfo> CREATOR;
+    field public static final int DEVICE_TYPE_LAPTOP = 3; // 0x3
+    field public static final int DEVICE_TYPE_PHONE = 1; // 0x1
+    field public static final int DEVICE_TYPE_TABLET = 2; // 0x2
+    field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
+  }
+
+  public static final class DeviceInfo.Builder {
+    ctor public DeviceInfo.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setBatteryPercentage(@IntRange(from=0, to=100) int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setConnectionStrength(@IntRange(from=0, to=3) int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setDeviceName(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setDeviceType(int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setModelName(@NonNull String);
+  }
+
+  public final class KnownNetwork implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo getDeviceInfo();
+    method @NonNull public int getNetworkSource();
+    method @NonNull public int[] getSecurityTypes();
+    method @NonNull public String getSsid();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.KnownNetwork> CREATOR;
+    field public static final int NETWORK_SOURCE_CLOUD_SELF = 1; // 0x1
+    field public static final int NETWORK_SOURCE_NEARBY_SELF = 0; // 0x0
+  }
+
+  public static final class KnownNetwork.Builder {
+    ctor public KnownNetwork.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setDeviceInfo(@NonNull android.net.wifi.sharedconnectivity.app.DeviceInfo);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setNetworkSource(int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setSecurityTypes(@NonNull int[]);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setSsid(@NonNull String);
+  }
+
+  public interface SharedConnectivityClientCallback {
+    method public void onKnownNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
+    method public void onSharedConnectivitySettingsChanged(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
+    method public void onTetherNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork>);
+  }
+
+  public class SharedConnectivityManager {
+    method public boolean connectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method public boolean connectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
+    method public boolean disconnectTetherNetwork();
+    method public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method public boolean registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+    method public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+  }
+
+  public final class SharedConnectivitySettingsState implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.os.Bundle getExtras();
+    method @NonNull public boolean isInstantTetherEnabled();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState> CREATOR;
+  }
+
+  public static final class SharedConnectivitySettingsState.Builder {
+    ctor public SharedConnectivitySettingsState.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState.Builder setExtras(@NonNull android.os.Bundle);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState.Builder setInstantTetherEnabled(boolean);
+  }
+
+  public final class TetherNetwork implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public long getDeviceId();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo getDeviceInfo();
+    method @Nullable public String getHotspotBssid();
+    method @Nullable public int[] getHotspotSecurityTypes();
+    method @Nullable public String getHotspotSsid();
+    method @NonNull public String getNetworkName();
+    method @NonNull public int getNetworkType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.TetherNetwork> CREATOR;
+    field public static final int NETWORK_TYPE_CELLULAR = 1; // 0x1
+    field public static final int NETWORK_TYPE_ETHERNET = 3; // 0x3
+    field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
+    field public static final int NETWORK_TYPE_WIFI = 2; // 0x2
+  }
+
+  public static final class TetherNetwork.Builder {
+    ctor public TetherNetwork.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setDeviceId(long);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setDeviceInfo(@NonNull android.net.wifi.sharedconnectivity.app.DeviceInfo);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotBssid(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotSecurityTypes(@NonNull int[]);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotSsid(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setNetworkName(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setNetworkType(int);
+  }
+
+}
+
+package android.net.wifi.sharedconnectivity.service {
+
+  public abstract class SharedConnectivityService extends android.app.Service {
+    ctor public SharedConnectivityService();
+    ctor public SharedConnectivityService(@NonNull android.os.Handler);
+    method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
+    method public abstract void onConnectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method public abstract void onConnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
+    method public abstract void onDisconnectTetherNetwork();
+    method public abstract void onForgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method public final void setKnownNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
+    method public final void setSettingsState(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
+    method public final void setTetherNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork>);
+  }
+
+}
+
 package android.nfc {
 
   public final class NfcAdapter {
@@ -9935,14 +10076,20 @@
   public final class BugreportManager {
     method @RequiresPermission(android.Manifest.permission.DUMP) @WorkerThread public void preDumpUiData();
     method @RequiresPermission(android.Manifest.permission.DUMP) public void requestBugreport(@NonNull android.os.BugreportParams, @Nullable CharSequence, @Nullable CharSequence);
+    method @RequiresPermission(android.Manifest.permission.DUMP) @WorkerThread public void retrieveBugreport(@NonNull String, @NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
     method @RequiresPermission(android.Manifest.permission.DUMP) @WorkerThread public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
   }
 
+  public abstract static class BugreportManager.BugreportCallback {
+    method public void onFinished(@NonNull String);
+  }
+
   public final class BugreportParams {
     ctor public BugreportParams(int);
     ctor public BugreportParams(int, int);
     method public int getFlags();
     method public int getMode();
+    field public static final int BUGREPORT_FLAG_DEFER_CONSENT = 2; // 0x2
     field public static final int BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA = 1; // 0x1
     field public static final int BUGREPORT_MODE_FULL = 0; // 0x0
     field public static final int BUGREPORT_MODE_INTERACTIVE = 1; // 0x1
@@ -11542,6 +11689,39 @@
 
 }
 
+package android.service.assist.classification {
+
+  public final class FieldClassification implements android.os.Parcelable {
+    ctor public FieldClassification(@NonNull android.view.autofill.AutofillId, @NonNull java.util.Set<java.lang.String>, @NonNull java.util.Set<java.lang.String>);
+    method @NonNull public java.util.Set<java.lang.String> getGroupHints();
+  }
+
+  public final class FieldClassificationRequest implements android.os.Parcelable {
+    ctor public FieldClassificationRequest(@NonNull android.app.assist.AssistStructure);
+    method public int describeContents();
+    method @NonNull public android.app.assist.AssistStructure getAssistStructure();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.assist.classification.FieldClassificationRequest> CREATOR;
+  }
+
+  public final class FieldClassificationResponse implements android.os.Parcelable {
+    ctor public FieldClassificationResponse(@NonNull java.util.Set<android.service.assist.classification.FieldClassification>);
+    method public int describeContents();
+    method @NonNull public java.util.Set<android.service.assist.classification.FieldClassification> getClassifications();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.assist.classification.FieldClassificationResponse> CREATOR;
+  }
+
+  public abstract class FieldClassificationService extends android.app.Service {
+    ctor public FieldClassificationService();
+    method public abstract void onClassificationRequest(@NonNull android.service.assist.classification.FieldClassificationRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.service.assist.classification.FieldClassificationResponse,java.lang.Exception>);
+    method public void onConnected();
+    method public void onDisconnected();
+    field public static final String SERVICE_INTERFACE = "android.service.assist.classification.FieldClassificationService";
+  }
+
+}
+
 package android.service.attention {
 
   public abstract class AttentionService extends android.app.Service {
@@ -11904,9 +12084,10 @@
     method public int onSwitchToSubscriptionWithPort(int, int, @Nullable String, boolean);
     method public abstract int onUpdateSubscriptionNickname(int, String, String);
     field public static final String ACTION_BIND_CARRIER_PROVISIONING_SERVICE = "android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE";
+    field @RequiresPermission(android.Manifest.permission.BIND_EUICC_SERVICE) public static final String ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION = "android.service.euicc.action.CONVERT_TO_EMBEDDED_SUBSCRIPTION";
     field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.service.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
-    field public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
-    field public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
+    field @RequiresPermission(android.Manifest.permission.BIND_EUICC_SERVICE) public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
+    field @RequiresPermission(android.Manifest.permission.BIND_EUICC_SERVICE) public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
     field public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED = "android.service.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED";
     field @Deprecated public static final String ACTION_RESOLVE_CONFIRMATION_CODE = "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE";
     field public static final String ACTION_RESOLVE_DEACTIVATE_SIM = "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM";
@@ -11915,6 +12096,7 @@
     field public static final String ACTION_START_CARRIER_ACTIVATION = "android.service.euicc.action.START_CARRIER_ACTIVATION";
     field public static final String ACTION_START_EUICC_ACTIVATION = "android.service.euicc.action.START_EUICC_ACTIVATION";
     field public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED = "android.service.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED";
+    field @RequiresPermission(android.Manifest.permission.BIND_EUICC_SERVICE) public static final String ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS = "android.service.euicc.action.TRANSFER_EMBEDDED_SUBSCRIPTIONS";
     field public static final String CATEGORY_EUICC_UI = "android.service.euicc.category.EUICC_UI";
     field public static final String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService";
     field public static final String EXTRA_RESOLUTION_ALLOW_POLICY_RULES = "android.service.euicc.extra.RESOLUTION_ALLOW_POLICY_RULES";
@@ -12267,7 +12449,11 @@
     method @MainThread public abstract void onDestroy(@NonNull android.app.search.SearchSessionId);
     method @MainThread public abstract void onNotifyEvent(@NonNull android.app.search.SearchSessionId, @NonNull android.app.search.Query, @NonNull android.app.search.SearchTargetEvent);
     method @MainThread public abstract void onQuery(@NonNull android.app.search.SearchSessionId, @NonNull android.app.search.Query, @NonNull java.util.function.Consumer<java.util.List<android.app.search.SearchTarget>>);
+    method @MainThread public void onRequestEmptyQueryResultUpdate(@NonNull android.app.search.SearchSessionId);
     method public void onSearchSessionCreated(@NonNull android.app.search.SearchContext, @NonNull android.app.search.SearchSessionId);
+    method @MainThread public void onStartUpdateEmptyQueryResult();
+    method @MainThread public void onStopUpdateEmptyQueryResult();
+    method public final void updateEmptyQueryResult(@NonNull android.app.search.SearchSessionId, @NonNull java.util.List<android.app.search.SearchTarget>);
   }
 
 }
@@ -14339,7 +14525,6 @@
     field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
     field public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3; // 0x3
     field public static final int ALLOWED_NETWORK_TYPES_REASON_POWER = 1; // 0x1
-    field public static final int ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS = 4; // 0x4
     field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2
     field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1
     field public static final int CALL_WAITING_STATUS_FDN_CHECK_FAILURE = 5; // 0x5
@@ -14869,11 +15054,13 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public boolean isSupportedCountry(@NonNull String);
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setSupportedCountries(@NonNull java.util.List<java.lang.String>);
     method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setUnsupportedCountries(@NonNull java.util.List<java.lang.String>);
+    field @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public static final String ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.CONVERT_TO_EMBEDDED_SUBSCRIPTION";
     field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
     field @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public static final String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
     field public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
     field public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED";
     field public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED";
+    field @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public static final String ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS = "android.telephony.euicc.action.TRANSFER_EMBEDDED_SUBSCRIPTIONS";
     field public static final int EUICC_ACTIVATION_TYPE_ACCOUNT_REQUIRED = 4; // 0x4
     field public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2; // 0x2
     field public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1; // 0x1
@@ -15663,11 +15850,12 @@
   }
 
   public final class MediaQualityStatus implements android.os.Parcelable {
+    ctor public MediaQualityStatus(@NonNull String, int, int, @IntRange(from=0, to=100) int, @IntRange(from=0) int, @IntRange(from=0) long);
     method public int describeContents();
     method @NonNull public String getCallSessionId();
     method public int getMediaSessionType();
-    method public long getRtpInactivityMillis();
-    method public int getRtpJitterMillis();
+    method @IntRange(from=0) public long getRtpInactivityMillis();
+    method @IntRange(from=0) public int getRtpJitterMillis();
     method @IntRange(from=0, to=100) public int getRtpPacketLossRate();
     method public int getTransportType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -15676,14 +15864,6 @@
     field public static final int MEDIA_SESSION_TYPE_VIDEO = 2; // 0x2
   }
 
-  public static final class MediaQualityStatus.Builder {
-    ctor public MediaQualityStatus.Builder(@NonNull String, int, int);
-    method @NonNull public android.telephony.ims.MediaQualityStatus build();
-    method @NonNull public android.telephony.ims.MediaQualityStatus.Builder setRtpInactivityMillis(long);
-    method @NonNull public android.telephony.ims.MediaQualityStatus.Builder setRtpJitterMillis(int);
-    method @NonNull public android.telephony.ims.MediaQualityStatus.Builder setRtpPacketLossRate(@IntRange(from=0, to=100) int);
-  }
-
   public final class MediaThreshold implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public long[] getThresholdsRtpInactivityTimeMillis();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 219f5f4..85861c3 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -144,8 +144,6 @@
     method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.DUMP) public void waitForBroadcastIdle();
     field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL
-    field public static final int PROCESS_CAPABILITY_ALL = 15; // 0xf
-    field public static final int PROCESS_CAPABILITY_ALL_EXPLICIT = 1; // 0x1
     field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
     field public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
     field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4
@@ -446,7 +444,6 @@
 
   public final class UiAutomation {
     method public void destroy();
-    method @NonNull public android.os.ParcelFileDescriptor[] executeShellCommandRwe(@NonNull String);
     method @NonNull public java.util.Set<java.lang.String> getAdoptedShellPermissions();
     method @Deprecated public boolean grantRuntimePermission(String, String, android.os.UserHandle);
     method public boolean injectInputEvent(@NonNull android.view.InputEvent, boolean, boolean);
@@ -470,8 +467,11 @@
 
   public class WallpaperManager {
     method @Nullable public android.graphics.Bitmap getBitmap();
+    method @Nullable public android.graphics.Bitmap getBitmapAsUser(int, boolean, int);
+    method public boolean isLockscreenLiveWallpaperEnabled();
     method @Nullable public android.graphics.Rect peekBitmapDimensions();
     method @Nullable public android.graphics.Rect peekBitmapDimensions(int);
+    method public void setWallpaperZoomOut(@NonNull android.os.IBinder, float);
     method public boolean shouldEnableWideColorGamut();
     method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public boolean wallpaperSupportsWcg(int);
   }
@@ -1030,9 +1030,9 @@
   }
 
   public final class GetCredentialProviderData extends android.credentials.ui.ProviderData implements android.os.Parcelable {
-    ctor public GetCredentialProviderData(@NonNull String, @NonNull java.util.List<android.credentials.ui.Entry>, @NonNull java.util.List<android.credentials.ui.Entry>, @Nullable android.credentials.ui.Entry, @Nullable android.credentials.ui.Entry);
+    ctor public GetCredentialProviderData(@NonNull String, @NonNull java.util.List<android.credentials.ui.Entry>, @NonNull java.util.List<android.credentials.ui.Entry>, @NonNull java.util.List<android.credentials.ui.Entry>, @Nullable android.credentials.ui.Entry);
     method @NonNull public java.util.List<android.credentials.ui.Entry> getActionChips();
-    method @Nullable public android.credentials.ui.Entry getAuthenticationEntry();
+    method @NonNull public java.util.List<android.credentials.ui.Entry> getAuthenticationEntries();
     method @NonNull public java.util.List<android.credentials.ui.Entry> getCredentialEntries();
     method @Nullable public android.credentials.ui.Entry getRemoteEntry();
     field @NonNull public static final android.os.Parcelable.Creator<android.credentials.ui.GetCredentialProviderData> CREATOR;
@@ -1042,7 +1042,7 @@
     ctor public GetCredentialProviderData.Builder(@NonNull String);
     method @NonNull public android.credentials.ui.GetCredentialProviderData build();
     method @NonNull public android.credentials.ui.GetCredentialProviderData.Builder setActionChips(@NonNull java.util.List<android.credentials.ui.Entry>);
-    method @NonNull public android.credentials.ui.GetCredentialProviderData.Builder setAuthenticationEntry(@Nullable android.credentials.ui.Entry);
+    method @NonNull public android.credentials.ui.GetCredentialProviderData.Builder setAuthenticationEntries(@NonNull java.util.List<android.credentials.ui.Entry>);
     method @NonNull public android.credentials.ui.GetCredentialProviderData.Builder setCredentialEntries(@NonNull java.util.List<android.credentials.ui.Entry>);
     method @NonNull public android.credentials.ui.GetCredentialProviderData.Builder setRemoteEntry(@Nullable android.credentials.ui.Entry);
   }
@@ -1735,6 +1735,7 @@
 
   public final class MediaCas implements java.lang.AutoCloseable {
     method public void forceResourceLost();
+    method public boolean isAidlHal();
   }
 
   public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
@@ -1745,6 +1746,10 @@
     method public int getMaxMacroBlocks();
   }
 
+  public final class MediaDescrambler implements java.lang.AutoCloseable {
+    method public boolean isAidlHal();
+  }
+
   public final class MediaRoute2Info implements android.os.Parcelable {
     method @NonNull public String getOriginalId();
   }
@@ -1862,6 +1867,14 @@
 
 }
 
+package android.net.wifi.sharedconnectivity.app {
+
+  public class SharedConnectivityManager {
+    method public void setService(@Nullable android.os.IInterface);
+  }
+
+}
+
 package android.os {
 
   public final class BatteryStatsManager {
@@ -1875,7 +1888,10 @@
   public class Build {
     method public static boolean is64BitAbi(String);
     method public static boolean isDebuggable();
+    field @Nullable public static final String BRAND_FOR_ATTESTATION;
     field public static final boolean IS_EMULATOR;
+    field @Nullable public static final String MODEL_FOR_ATTESTATION;
+    field @Nullable public static final String PRODUCT_FOR_ATTESTATION;
   }
 
   public static class Build.VERSION {
@@ -2073,6 +2089,7 @@
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers(boolean, boolean, boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isUserTypeEnabled(@NonNull String);
+    method public boolean isVisibleBackgroundUsersOnDefaultDisplaySupported();
     method public boolean isVisibleBackgroundUsersSupported();
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo preCreateUser(@NonNull String) throws android.os.UserManager.UserOperationException;
   }
@@ -2401,6 +2418,8 @@
     field public static final String DISABLE_WINDOW_BLURS = "disable_window_blurs";
     field public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
     field public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
+    field public static final String HDR_CONVERSION_MODE = "hdr_conversion_mode";
+    field public static final String HDR_FORCE_CONVERSION_TYPE = "hdr_force_conversion_type";
     field public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
     field public static final String HIDDEN_API_POLICY = "hidden_api_policy";
     field public static final String HIDE_ERROR_DIALOGS = "hide_error_dialogs";
@@ -3138,6 +3157,9 @@
 
   public final class SurfaceControl implements android.os.Parcelable {
     ctor public SurfaceControl(@NonNull android.view.SurfaceControl, @NonNull String);
+    method @NonNull public android.view.Choreographer getChoreographer();
+    method @NonNull public android.view.Choreographer getChoreographer(@NonNull android.os.Looper);
+    method public boolean hasChoreographer();
     method public boolean isSameSurface(@NonNull android.view.SurfaceControl);
   }
 
@@ -3255,6 +3277,7 @@
     field public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED = "autofill_credential_manager_enabled";
     field public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS = "autofill_credential_manager_ignore_views";
     field public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled";
+    field public static final String DEVICE_CONFIG_AUTOFILL_PCC_CLASSIFICATION_ENABLED = "pcc_classification_enabled";
     field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes";
     field public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS = "non_autofillable_ime_action_ids";
     field public static final String DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW = "package_deny_list_for_unimportant_view";
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index e849cdbc..4a97280 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -855,6 +855,10 @@
     New setting keys are not allowed (Field: DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#DYNAMIC_POWER_SAVINGS_ENABLED:
     New setting keys are not allowed (Field: DYNAMIC_POWER_SAVINGS_ENABLED); use getters/setters in relevant manager class
+NoSettingsProvider: android.provider.Settings.Global#HDR_CONVERSION_MODE:
+    New setting keys are not allowed (Field: HDR_CONVERSION_MODE); use getters/setters in relevant manager class
+NoSettingsProvider: android.provider.Settings.Global#HDR_FORCE_CONVERSION_TYPE:
+    New setting keys are not allowed (Field: HDR_FORCE_CONVERSION_TYPE); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#HIDDEN_API_BLACKLIST_EXEMPTIONS:
     New setting keys are not allowed (Field: HIDDEN_API_BLACKLIST_EXEMPTIONS); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#HIDDEN_API_POLICY:
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index ae57959..65b0cfb 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -48,6 +48,7 @@
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.util.Xml;
+import android.view.InputDevice;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -612,9 +613,29 @@
     private boolean mIsAccessibilityTool = false;
 
     /**
+     * {@link InputDevice} sources which may send {@link android.view.MotionEvent}s.
+     * @see #setMotionEventSources(int)
+     * @hide
+     */
+    @IntDef(flag = true, prefix = { "SOURCE_" }, value = {
+            InputDevice.SOURCE_MOUSE,
+            InputDevice.SOURCE_STYLUS,
+            InputDevice.SOURCE_BLUETOOTH_STYLUS,
+            InputDevice.SOURCE_TRACKBALL,
+            InputDevice.SOURCE_MOUSE_RELATIVE,
+            InputDevice.SOURCE_TOUCHPAD,
+            InputDevice.SOURCE_TOUCH_NAVIGATION,
+            InputDevice.SOURCE_ROTARY_ENCODER,
+            InputDevice.SOURCE_JOYSTICK,
+            InputDevice.SOURCE_SENSOR
+    })
+    public @interface MotionEventSources {}
+
+    /**
      * The bit mask of {@link android.view.InputDevice} sources that the accessibility
      * service wants to listen to for generic {@link android.view.MotionEvent}s.
      */
+    @MotionEventSources
     private int mMotionEventSources = 0;
 
     /**
@@ -966,6 +987,7 @@
      * Returns the bit mask of {@link android.view.InputDevice} sources that the accessibility
      * service wants to listen to for generic {@link android.view.MotionEvent}s.
      */
+    @MotionEventSources
     public int getMotionEventSources() {
         return mMotionEventSources;
     }
@@ -975,28 +997,29 @@
      * service wants to listen to for generic {@link android.view.MotionEvent}s.
      *
      * <p>
-     * Note: including an {@link android.view.InputDevice} source that does not send
+     * Including an {@link android.view.InputDevice} source that does not send
      * {@link android.view.MotionEvent}s is effectively a no-op for that source, since you will
      * not receive any events from that source.
      * </p>
+     *
      * <p>
-     * Allowed sources include:
-     * <li>{@link android.view.InputDevice#SOURCE_MOUSE}</li>
-     * <li>{@link android.view.InputDevice#SOURCE_STYLUS}</li>
-     * <li>{@link android.view.InputDevice#SOURCE_BLUETOOTH_STYLUS}</li>
-     * <li>{@link android.view.InputDevice#SOURCE_TRACKBALL}</li>
-     * <li>{@link android.view.InputDevice#SOURCE_MOUSE_RELATIVE}</li>
-     * <li>{@link android.view.InputDevice#SOURCE_TOUCHPAD}</li>
-     * <li>{@link android.view.InputDevice#SOURCE_TOUCH_NAVIGATION}</li>
-     * <li>{@link android.view.InputDevice#SOURCE_ROTARY_ENCODER}</li>
-     * <li>{@link android.view.InputDevice#SOURCE_JOYSTICK}</li>
-     * <li>{@link android.view.InputDevice#SOURCE_SENSOR}</li>
+     * See {@link android.view.InputDevice} for complete source definitions.
+     * Many input devices send {@link android.view.InputEvent}s from more than one type of source so
+     * you may need to include multiple {@link android.view.MotionEvent} sources here, in addition
+     * to using {@link AccessibilityService#onKeyEvent} to listen to {@link android.view.KeyEvent}s.
+     * </p>
+     *
+     * <p>
+     * <strong>Note:</strong> {@link android.view.InputDevice} sources contain source class bits
+     * that complicate bitwise flag removal operations. To remove a specific source you should
+     * rebuild the entire value using bitwise OR operations on the individual source constants.
      * </p>
      *
      * @param motionEventSources A bit mask of {@link android.view.InputDevice} sources.
      * @see AccessibilityService#onMotionEvent
+     * @see MotionEventSources
      */
-    public void setMotionEventSources(int motionEventSources) {
+    public void setMotionEventSources(@MotionEventSources int motionEventSources) {
         mMotionEventSources = motionEventSources;
     }
 
diff --git a/core/java/android/accessibilityservice/MagnificationConfig.java b/core/java/android/accessibilityservice/MagnificationConfig.java
index ddafb22..486dc50 100644
--- a/core/java/android/accessibilityservice/MagnificationConfig.java
+++ b/core/java/android/accessibilityservice/MagnificationConfig.java
@@ -76,6 +76,7 @@
     }
 
     private int mMode = MAGNIFICATION_MODE_DEFAULT;
+    private boolean mActivated = false;
     private float mScale = Float.NaN;
     private float mCenterX = Float.NaN;
     private float mCenterY = Float.NaN;
@@ -86,6 +87,7 @@
 
     private MagnificationConfig(@NonNull Parcel parcel) {
         mMode = parcel.readInt();
+        mActivated = parcel.readBoolean();
         mScale = parcel.readFloat();
         mCenterX = parcel.readFloat();
         mCenterY = parcel.readFloat();
@@ -102,9 +104,20 @@
     }
 
     /**
+     * Returns the activated state of the controlling magnifier. The controlling magnifier can be
+     * activated even if the scale returned by {@link MagnificationConfig#getScale()} equals to 1.0.
+     *
+     * @return {@code true} if the magnifier is showing on screen,
+     *         {@code false} otherwise.
+     */
+    public boolean isActivated() {
+        return mActivated;
+    }
+
+    /**
      * Returns the magnification scale of the controlling magnifier
      *
-     * @return the scale If the controlling magnifier is not activated, it returns 1 by default
+     * @return The magnification scale
      */
     public float getScale() {
         return mScale;
@@ -113,9 +126,7 @@
     /**
      * Returns the screen-relative X coordinate of the center of the magnification viewport.
      *
-     * @return the X coordinate. If the controlling magnifier is {@link #MAGNIFICATION_MODE_WINDOW}
-     * but not enabled, it returns {@link Float#NaN}. If the controlling magnifier is {@link
-     * #MAGNIFICATION_MODE_FULLSCREEN} but not enabled, it returns 0
+     * @return The X coordinate
      */
     public float getCenterX() {
         return mCenterX;
@@ -124,9 +135,7 @@
     /**
      * Returns the screen-relative Y coordinate of the center of the magnification viewport.
      *
-     * @return the Y coordinate If the controlling magnifier is {@link #MAGNIFICATION_MODE_WINDOW}
-     * but not enabled, it returns {@link Float#NaN}. If the controlling magnifier is {@link
-     * #MAGNIFICATION_MODE_FULLSCREEN} but not enabled, it returns 0
+     * @return The Y coordinate
      */
     public float getCenterY() {
         return mCenterY;
@@ -138,6 +147,8 @@
         StringBuilder stringBuilder = new StringBuilder("MagnificationConfig[");
         stringBuilder.append("mode: ").append(getMode());
         stringBuilder.append(", ");
+        stringBuilder.append("activated: ").append(isActivated());
+        stringBuilder.append(", ");
         stringBuilder.append("scale: ").append(getScale());
         stringBuilder.append(", ");
         stringBuilder.append("centerX: ").append(getCenterX());
@@ -155,6 +166,7 @@
     @Override
     public void writeToParcel(@NonNull Parcel parcel, int flags) {
         parcel.writeInt(mMode);
+        parcel.writeBoolean(mActivated);
         parcel.writeFloat(mScale);
         parcel.writeFloat(mCenterX);
         parcel.writeFloat(mCenterY);
@@ -166,6 +178,7 @@
     public static final class Builder {
 
         private int mMode = MAGNIFICATION_MODE_DEFAULT;
+        private boolean mActivated = true;
         private float mScale = Float.NaN;
         private float mCenterX = Float.NaN;
         private float mCenterY = Float.NaN;
@@ -189,6 +202,18 @@
         }
 
         /**
+         * Sets magnification activated state.
+         *
+         * @param activated The magnification activated state
+         * @return This builder
+         */
+        @NonNull
+        public MagnificationConfig.Builder setActivated(boolean activated) {
+            mActivated = activated;
+            return this;
+        }
+
+        /**
          * Sets the magnification scale.
          *
          * @param scale The magnification scale, in the range [1, 8]
@@ -237,6 +262,7 @@
         public MagnificationConfig build() {
             MagnificationConfig magnificationConfig = new MagnificationConfig();
             magnificationConfig.mMode = mMode;
+            magnificationConfig.mActivated = mActivated;
             magnificationConfig.mScale = mScale;
             magnificationConfig.mCenterX = mCenterX;
             magnificationConfig.mCenterY = mCenterY;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index c4d6ad7..f408916 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -630,6 +630,8 @@
             PROCESS_CAPABILITY_FOREGROUND_LOCATION,
             PROCESS_CAPABILITY_FOREGROUND_CAMERA,
             PROCESS_CAPABILITY_FOREGROUND_MICROPHONE,
+            PROCESS_CAPABILITY_NETWORK,
+            PROCESS_CAPABILITY_BFSL,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProcessCapability {}
@@ -654,20 +656,36 @@
     @TestApi
     public static final int PROCESS_CAPABILITY_NETWORK = 1 << 3;
 
-    /** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/
-    @TestApi
+    /**
+     * Flag used to indicate whether an app is allowed to start a foreground service from the
+     * background, decided by the procstates. ("BFSL" == "background foreground service launch")
+     *
+     * - BFSL has a number of exemptions -- e.g. when an app is power-allowlisted, including
+     *   temp-allowlist -- but this capability is *not* used to represent such exemptions.
+     *   This is set only based on the procstate and the foreground service type.
+     * - Basically, procstates <= BFGS (i.e. BFGS, FGS, BTOP, TOP, ...) are BFSL-allowed,
+     *   and that's how things worked on Android S/T.
+     *   However, Android U added a "SHORT_SERVICE" FGS type, which gets the FGS procstate
+     *   *but* can't start another FGS. So now we use this flag to decide whether FGS/BFGS
+     *   procstates are BFSL-allowed. (higher procstates, such as BTOP, will still always be
+     *   BFSL-allowed.)
+     *   We propagate this flag across via service bindings and provider references.
+     *
+     * @hide
+     */
+    public static final int PROCESS_CAPABILITY_BFSL = 1 << 4;
+
+    /**
+     * @hide all capabilities, the ORing of all flags in {@link ProcessCapability}.
+     *
+     * Don't expose it as TestApi -- we may add new capabilities any time, which could
+     * break CTS tests if they relied on it.
+     */
     public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
             | PROCESS_CAPABILITY_FOREGROUND_CAMERA
             | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
-            | PROCESS_CAPABILITY_NETWORK;
-    /**
-     * All explicit capabilities. These are capabilities that need to be specified from manifest
-     * file.
-     * @hide
-     */
-    @TestApi
-    public static final int PROCESS_CAPABILITY_ALL_EXPLICIT =
-            PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+            | PROCESS_CAPABILITY_NETWORK
+            | PROCESS_CAPABILITY_BFSL;
 
     /**
      * All implicit capabilities. There are capabilities that process automatically have.
@@ -686,6 +704,7 @@
         pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
         pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
         pw.print((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
+        pw.print((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
     }
 
     /** @hide */
@@ -694,6 +713,7 @@
         sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
         sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
         sb.append((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
+        sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
     }
 
     /**
@@ -702,13 +722,10 @@
      */
     public static void printCapabilitiesFull(PrintWriter pw, @ProcessCapability int caps) {
         printCapabilitiesSummary(pw, caps);
-        final int remain = caps & ~(PROCESS_CAPABILITY_FOREGROUND_LOCATION
-                | PROCESS_CAPABILITY_FOREGROUND_CAMERA
-                | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
-                | PROCESS_CAPABILITY_NETWORK);
+        final int remain = caps & ~PROCESS_CAPABILITY_ALL;
         if (remain != 0) {
-            pw.print('+');
-            pw.print(remain);
+            pw.print("+0x");
+            pw.print(Integer.toHexString(remain));
         }
     }
 
@@ -4417,7 +4434,8 @@
                     "device does not support users on secondary displays");
         }
         try {
-            return getService().startUserInBackgroundVisibleOnDisplay(userId, displayId);
+            return getService().startUserInBackgroundVisibleOnDisplay(userId, displayId,
+                    /* unlockProgressListener= */ null);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index b57fb20..3b88257 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -343,6 +343,13 @@
             "android:activity.applyActivityFlagsForBubbles";
 
     /**
+     * Indicates to apply {@link Intent#FLAG_ACTIVITY_MULTIPLE_TASK} to the launching shortcut.
+     * @hide
+     */
+    private static final String KEY_APPLY_MULTIPLE_TASK_FLAG_FOR_SHORTCUT =
+            "android:activity.applyMultipleTaskFlagForShortcut";
+
+    /**
      * For Activity transitions, the calling Activity's TransitionListener used to
      * notify the called Activity when the shared element and the exit transitions
      * complete.
@@ -397,8 +404,8 @@
     /** See {@link #setDismissKeyguard()}. */
     private static final String KEY_DISMISS_KEYGUARD = "android.activity.dismissKeyguard";
 
-    private static final String KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE =
-            "android.activity.ignorePendingIntentCreatorForegroundState";
+    private static final String KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE =
+            "android.activity.pendingIntentCreatorBackgroundActivityStartMode";
 
     /**
      * @see #setLaunchCookie
@@ -476,6 +483,7 @@
     private boolean mShareIdentity = false;
     private boolean mDisallowEnterPictureInPictureWhileLaunching;
     private boolean mApplyActivityFlagsForBubbles;
+    private boolean mApplyMultipleTaskFlagForShortcut;
     private boolean mTaskAlwaysOnTop;
     private boolean mTaskOverlay;
     private boolean mTaskOverlayCanResume;
@@ -499,7 +507,9 @@
     private boolean mTransientLaunch;
     private PictureInPictureParams mLaunchIntoPipParams;
     private boolean mDismissKeyguard;
-    private boolean mIgnorePendingIntentCreatorForegroundState;
+    @BackgroundActivityStartMode
+    private int mPendingIntentCreatorBackgroundActivityStartMode =
+            MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
     private boolean mDisableStartingWindow;
 
     /**
@@ -1276,6 +1286,8 @@
                 KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING, false);
         mApplyActivityFlagsForBubbles = opts.getBoolean(
                 KEY_APPLY_ACTIVITY_FLAGS_FOR_BUBBLES, false);
+        mApplyMultipleTaskFlagForShortcut = opts.getBoolean(
+                KEY_APPLY_MULTIPLE_TASK_FLAG_FOR_SHORTCUT, false);
         if (opts.containsKey(KEY_ANIM_SPECS)) {
             Parcelable[] specs = opts.getParcelableArray(KEY_ANIM_SPECS);
             mAnimSpecs = new AppTransitionAnimationSpec[specs.length];
@@ -1307,8 +1319,9 @@
         mIsEligibleForLegacyPermissionPrompt =
                 opts.getBoolean(KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE);
         mDismissKeyguard = opts.getBoolean(KEY_DISMISS_KEYGUARD);
-        mIgnorePendingIntentCreatorForegroundState = opts.getBoolean(
-                KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE);
+        mPendingIntentCreatorBackgroundActivityStartMode = opts.getInt(
+                KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE,
+                MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED);
         mDisableStartingWindow = opts.getBoolean(KEY_DISABLE_STARTING_WINDOW);
     }
 
@@ -1903,6 +1916,16 @@
         return mApplyActivityFlagsForBubbles;
     }
 
+    /** @hide */
+    public void setApplyMultipleTaskFlagForShortcut(boolean apply) {
+        mApplyMultipleTaskFlagForShortcut = apply;
+    }
+
+    /** @hide */
+    public boolean isApplyMultipleTaskFlagForShortcut() {
+        return mApplyMultipleTaskFlagForShortcut;
+    }
+
     /**
      * Sets a launch cookie that can be used to track the activity and task that are launch as a
      * result of this option. If the launched activity is a trampoline that starts another activity
@@ -2009,19 +2032,38 @@
      * Sets background activity launch logic won't use pending intent creator foreground state.
      *
      * @hide
+     * @deprecated use {@link #setPendingIntentCreatorBackgroundActivityStartMode(int)} instead
      */
-    public ActivityOptions setIgnorePendingIntentCreatorForegroundState(boolean state) {
-        mIgnorePendingIntentCreatorForegroundState = state;
+    @Deprecated
+    public ActivityOptions setIgnorePendingIntentCreatorForegroundState(boolean ignore) {
+        mPendingIntentCreatorBackgroundActivityStartMode = ignore
+                ? MODE_BACKGROUND_ACTIVITY_START_DENIED : MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
         return this;
     }
 
     /**
-     * @return whether background activity launch logic should use pending intent creator
-     * foreground state.
-     * @hide
+     * Allow a {@link PendingIntent} to use the privilege of its creator to start background
+     * activities.
+     *
+     * @param mode the {@link android.app.ComponentOptions.BackgroundActivityStartMode} being set
+     * @throws IllegalArgumentException is the value is not a valid
+     * {@link android.app.ComponentOptions.BackgroundActivityStartMode}
      */
-    public boolean getIgnorePendingIntentCreatorForegroundState() {
-        return mIgnorePendingIntentCreatorForegroundState;
+    @NonNull
+    public ActivityOptions setPendingIntentCreatorBackgroundActivityStartMode(
+            @BackgroundActivityStartMode int mode) {
+        mPendingIntentCreatorBackgroundActivityStartMode = mode;
+        return this;
+    }
+
+    /**
+     * Returns the mode to start background activities granted by the creator of the
+     * {@link PendingIntent}.
+     *
+     * @return the {@link android.app.ComponentOptions.BackgroundActivityStartMode} currently set
+     */
+    public @BackgroundActivityStartMode int getPendingIntentCreatorBackgroundActivityStartMode() {
+        return mPendingIntentCreatorBackgroundActivityStartMode;
     }
 
     /**
@@ -2240,6 +2282,10 @@
         if (mApplyActivityFlagsForBubbles) {
             b.putBoolean(KEY_APPLY_ACTIVITY_FLAGS_FOR_BUBBLES, mApplyActivityFlagsForBubbles);
         }
+        if (mApplyMultipleTaskFlagForShortcut) {
+            b.putBoolean(KEY_APPLY_MULTIPLE_TASK_FLAG_FOR_SHORTCUT,
+                    mApplyMultipleTaskFlagForShortcut);
+        }
         if (mAnimSpecs != null) {
             b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs);
         }
@@ -2295,9 +2341,10 @@
         if (mDismissKeyguard) {
             b.putBoolean(KEY_DISMISS_KEYGUARD, mDismissKeyguard);
         }
-        if (mIgnorePendingIntentCreatorForegroundState) {
-            b.putBoolean(KEY_IGNORE_PENDING_INTENT_CREATOR_FOREGROUND_STATE,
-                    mIgnorePendingIntentCreatorForegroundState);
+        if (mPendingIntentCreatorBackgroundActivityStartMode
+                != MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED) {
+            b.putInt(KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE,
+                    mPendingIntentCreatorBackgroundActivityStartMode);
         }
         if (mDisableStartingWindow) {
             b.putBoolean(KEY_DISABLE_STARTING_WINDOW, mDisableStartingWindow);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d974a24..8395ec6 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -505,6 +505,7 @@
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     static volatile Handler sMainThreadHandler;  // set once in main()
+    private long mStartSeq; // Only accesssed from the main thread
 
     Bundle mCoreSettings = null;
 
@@ -6987,6 +6988,12 @@
                 throw e.rethrowFromSystemServer();
             }
         }
+
+        try {
+            mgr.finishAttachApplication(mStartSeq);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
     }
 
     @UnsupportedAppUsage
@@ -7791,6 +7798,8 @@
         sCurrentActivityThread = this;
         mConfigurationController = new ConfigurationController(this);
         mSystemThread = system;
+        mStartSeq = startSeq;
+
         if (!system) {
             android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                     UserHandle.myUserId());
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 25b395b..7d40a22 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -42,7 +42,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.database.DatabaseUtils;
-import android.healthconnect.HealthConnectManager;
+import android.health.connect.HealthConnectManager;
 import android.media.AudioAttributes.AttributeUsage;
 import android.os.Binder;
 import android.os.Build;
@@ -1432,14 +1432,14 @@
                     .APP_OP_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION;
 
     /**
-     * Hide foreground service stop button in quick settings.
+     * Allows an application to start an activity while running in the background.
      *
      * Only to be used by the system.
      *
      * @hide
      */
-    public static final int OP_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON =
-            AppProtoEnums.APP_OP_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON;
+    public static final int OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION =
+            AppProtoEnums.APP_OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION;
 
     /**
      * Allows an application to capture bugreport directly without consent dialog when using the
@@ -1454,9 +1454,16 @@
     public static final int OP_BODY_SENSORS_WRIST_TEMPERATURE =
             AppProtoEnums.APP_OP_BODY_SENSORS_WRIST_TEMPERATURE;
 
+    /**
+     * Send an intent to launch instead of posting the notification to the status bar.
+     *
+     * @hide
+     */
+    public static final int OP_USE_FULL_SCREEN_INTENT = AppProtoEnums.APP_OP_USE_FULL_SCREEN_INTENT;
+
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int _NUM_OP = 133;
+    public static final int _NUM_OP = 134;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -2020,14 +2027,14 @@
             "android:system_exempt_from_fgs_bg_start_while_in_use_permission_restriction";
 
     /**
-     * Hide foreground service stop button in quick settings.
+     * Allows an application to start an activity while running in the background.
      *
      * Only to be used by the system.
      *
      * @hide
      */
-    public static final String OPSTR_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON =
-            "android:system_exempt_from_fgs_stop_button";
+    public static final String OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION =
+            "android:system_exempt_from_activity_bg_start_restriction";
 
     /**
      * Allows an application to capture bugreport directly without consent dialog when using the
@@ -2043,6 +2050,13 @@
     public static final String OPSTR_BODY_SENSORS_WRIST_TEMPERATURE =
             "android:body_sensors_wrist_temperature";
 
+    /**
+     * Send an intent to launch instead of posting the notification to the status bar.
+     *
+     * @hide
+     */
+    public static final String OPSTR_USE_FULL_SCREEN_INTENT = "android:use_full_screen_intent";
+
     /** {@link #sAppOpsToNote} not initialized yet for this op */
     private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
     /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -2142,6 +2156,7 @@
             OP_FOREGROUND_SERVICE_SPECIAL_USE,
             OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
             OP_BODY_SENSORS_WRIST_TEMPERATURE,
+            OP_USE_FULL_SCREEN_INTENT
     };
 
     static final AppOpInfo[] sAppOpInfos = new AppOpInfo[]{
@@ -2547,9 +2562,9 @@
                 OPSTR_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION,
                 "SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION")
                 .build(),
-        new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON,
-                OPSTR_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON,
-                "SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON").build(),
+        new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
+                OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
+                "SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION").build(),
         new AppOpInfo.Builder(
                 OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
                 OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
@@ -2560,7 +2575,10 @@
                 OPSTR_BODY_SENSORS_WRIST_TEMPERATURE,
                 "BODY_SENSORS_WRIST_TEMPERATURE")
                 .setPermission(Manifest.permission.BODY_SENSORS_WRIST_TEMPERATURE)
-                .setDefaultMode(AppOpsManager.MODE_ALLOWED).build()
+                .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
+        new AppOpInfo.Builder(OP_USE_FULL_SCREEN_INTENT, OPSTR_USE_FULL_SCREEN_INTENT,
+                "USE_FULL_SCREEN_INTENT").setPermission(Manifest.permission.USE_FULL_SCREEN_INTENT)
+                .build()
     };
 
     // The number of longs needed to form a full bitmask of app ops
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index 51ea04f..c628ec4 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -133,6 +133,10 @@
      * Application process was killed because of the user request, for example,
      * user clicked the "Force stop" button of the application in the Settings,
      * or removed the application away from Recents.
+     * <p>
+     * Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, one of the uses of this
+     * reason was to indicate that an app was killed due to it being updated or any of its component
+     * states have changed without {@link android.content.pm.PackageManager#DONT_KILL_APP}
      */
     public static final int REASON_USER_REQUESTED = 10;
 
@@ -162,6 +166,23 @@
     public static final int REASON_FREEZER = 14;
 
     /**
+     * Application process was killed because the app was disabled, or any of its
+     * component states have changed without {@link android.content.pm.PackageManager#DONT_KILL_APP}
+     * <p>
+     * Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+     * {@link #REASON_USER_REQUESTED} was used to indicate that an app was updated.
+     */
+    public static final int REASON_PACKAGE_STATE_CHANGE = 15;
+
+    /**
+     * Application process was killed because it was updated.
+     * <p>
+     * Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+     * {@link #REASON_USER_REQUESTED} was used to indicate that an app was updated.
+     */
+    public static final int REASON_PACKAGE_UPDATED = 16;
+
+    /**
      * Application process kills subreason is unknown.
      *
      * For internal use only.
@@ -403,6 +424,11 @@
      * {@link #REASON_USER_REQUESTED}.
      *
      * For internal use only.
+     *
+     * @deprecated starting {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+     * an app being killed due to a package update will have the reason
+     * {@link #REASON_PACKAGE_UPDATED}
+     *
      * @hide
      */
     public static final int SUBREASON_PACKAGE_UPDATE = 25;
@@ -566,6 +592,8 @@
         REASON_DEPENDENCY_DIED,
         REASON_OTHER,
         REASON_FREEZER,
+        REASON_PACKAGE_STATE_CHANGE,
+        REASON_PACKAGE_UPDATED,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Reason {}
@@ -706,7 +734,22 @@
      * guarantees that the format is stable across devices or Android releases.</p>
      */
     public @Nullable String getDescription() {
-        return mDescription;
+        final StringBuilder sb = new StringBuilder();
+
+        if (mSubReason != SUBREASON_UNKNOWN) {
+            sb.append("[");
+            sb.append(subreasonToString(mSubReason));
+            sb.append("]");
+        }
+
+        if (!TextUtils.isEmpty(mDescription)) {
+            if (sb.length() > 0) {
+                sb.append(" ");
+            }
+            sb.append(mDescription);
+        }
+
+        return sb.toString();
     }
 
     /**
@@ -1246,6 +1289,10 @@
                 return "OTHER KILLS BY SYSTEM";
             case REASON_FREEZER:
                 return "FREEZER";
+            case REASON_PACKAGE_STATE_CHANGE:
+                return "STATE CHANGE";
+            case REASON_PACKAGE_UPDATED:
+                return "PACKAGE UPDATED";
             default:
                 return "UNKNOWN";
         }
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index f6992c9..d3b03c0 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -774,7 +774,15 @@
         return this;
     }
 
-    /** @hide */
+    /**
+     * Returns if this broadcast should not run until the process is in an active process state.
+     *
+     * @return {@code true} if this broadcast should not run until the process is in an active
+     *                      process state. Otherwise, {@code false}.
+     * @see #setDeferUntilActive(boolean)
+     *
+     * @hide
+     */
     @SystemApi
     public boolean isDeferUntilActive() {
         return mIsDeferUntilActive;
diff --git a/core/java/android/app/ForegroundServiceTypePolicy.java b/core/java/android/app/ForegroundServiceTypePolicy.java
index 20d19c1..5ef29e4 100644
--- a/core/java/android/app/ForegroundServiceTypePolicy.java
+++ b/core/java/android/app/ForegroundServiceTypePolicy.java
@@ -388,7 +388,6 @@
                 new RegularPermission(Manifest.permission.SCHEDULE_EXACT_ALARM),
                 new RegularPermission(Manifest.permission.USE_EXACT_ALARM),
                 new AppOpPermission(AppOpsManager.OP_ACTIVATE_VPN),
-                new AppOpPermission(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN),
             }, false)
     );
 
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 058c389..c5c3d30 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -147,6 +147,7 @@
     oneway void finishReceiver(in IBinder who, int resultCode, in String resultData, in Bundle map,
             boolean abortBroadcast, int flags);
     void attachApplication(in IApplicationThread app, long startSeq);
+    void finishAttachApplication(long startSeq);
     List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);
     @UnsupportedAppUsage
     void moveTaskToFront(in IApplicationThread caller, in String callingPackage, int task,
@@ -310,7 +311,8 @@
     int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
             boolean requireFull, in String name, in String callerPackage);
     void addPackageDependency(in String packageName);
-    void killApplication(in String pkg, int appId, int userId, in String reason);
+    void killApplication(in String pkg, int appId, int userId, in String reason,
+            int exitInfoReason);
     @UnsupportedAppUsage
     void closeSystemDialogs(in String reason);
     @UnsupportedAppUsage
@@ -719,8 +721,8 @@
 
     /**
      * Control the app freezer state. Returns true in case of success, false if the operation
-     * didn't succeed (for example, when the app freezer isn't supported). 
-     * Handling the freezer state via this method is reentrant, that is it can be 
+     * didn't succeed (for example, when the app freezer isn't supported).
+     * Handling the freezer state via this method is reentrant, that is it can be
      * disabled and re-enabled multiple times in parallel. As long as there's a 1:1 disable to
      * enable match, the freezer is re-enabled at last enable only.
      * @param enable set it to true to enable the app freezer, false to disable it.
@@ -803,7 +805,7 @@
      */
     @JavaPassthrough(annotation=
             "@android.annotation.RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional = true)")
-    boolean startUserInBackgroundVisibleOnDisplay(int userid, int displayId);
+    boolean startUserInBackgroundVisibleOnDisplay(int userid, int displayId, IProgressListener unlockProgressListener);
 
     /**
      * Similar to {@link #startProfile(int userId)}, but with a listener to report user unlock
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 70d8a5e..bb91ecd 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -2324,10 +2324,13 @@
                 mUiAutomation.connect(flags);
                 return mUiAutomation;
             }
+            final long startUptime = SystemClock.uptimeMillis();
             try {
                 mUiAutomation.connectWithTimeout(flags, CONNECT_TIMEOUT_MILLIS);
                 return mUiAutomation;
             } catch (TimeoutException e) {
+                final long waited = SystemClock.uptimeMillis() - startUptime;
+                Log.e(TAG, "Unable to connect to UiAutomation. Waited for " + waited + " ms", e);
                 mUiAutomation.destroy();
                 mUiAutomation = null;
             }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 9b348fc..b86b09d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -703,6 +703,16 @@
      */
     public static final int FLAG_BUBBLE = 0x00001000;
 
+    /**
+     * Bit to be bitswised-ored into the {@link #flags} field that should be
+     * set by the system if this notification is not dismissible.
+     *
+     * This flag is for internal use only; applications cannot set this flag directly.
+     * @hide
+     */
+    public static final int FLAG_NO_DISMISS = 0x00002000;
+
+
     private static final List<Class<? extends Style>> PLATFORM_STYLE_CLASSES = Arrays.asList(
             BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class,
             DecoratedCustomViewStyle.class, DecoratedMediaCustomViewStyle.class,
@@ -3885,8 +3895,11 @@
                 }
 
                 if (mN.extras.containsKey(EXTRA_PEOPLE_LIST)) {
-                    ArrayList<Person> people = mN.extras.getParcelableArrayList(EXTRA_PEOPLE_LIST, android.app.Person.class);
-                    mPersonList.addAll(people);
+                    ArrayList<Person> people = mN.extras.getParcelableArrayList(EXTRA_PEOPLE_LIST,
+                            android.app.Person.class);
+                    if (people != null && !people.isEmpty()) {
+                        mPersonList.addAll(people);
+                    }
                 }
 
                 if (mN.getSmallIcon() == null && mN.icon != 0) {
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index f6d27ad..4e94a1d 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -31,6 +31,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.PermissionChecker;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ShortcutInfo;
 import android.graphics.drawable.Icon;
@@ -855,6 +856,32 @@
     }
 
     /**
+     * Returns whether the calling app can send fullscreen intents.
+     * <p>From Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, apps may not have
+     * permission to use {@link android.Manifest.permission#USE_FULL_SCREEN_INTENT}. If permission
+     * is denied, notification will show up as an expanded heads up notification on lockscreen.
+     * <p> To request access, add the {@link android.Manifest.permission#USE_FULL_SCREEN_INTENT}
+     * permission to your manifest, and use
+     * {@link android.provider.Settings#ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT}.
+     */
+    public boolean canSendFullScreenIntent() {
+        final int result = PermissionChecker.checkPermissionForPreflight(mContext,
+                android.Manifest.permission.USE_FULL_SCREEN_INTENT,
+                mContext.getAttributionSource());
+
+        switch (result) {
+            case PermissionChecker.PERMISSION_GRANTED:
+                return true;
+            case PermissionChecker.PERMISSION_SOFT_DENIED:
+            case PermissionChecker.PERMISSION_HARD_DENIED:
+                return false;
+            default:
+                if (localLOGV) Log.v(TAG, "Unknown PermissionChecker result: " + result);
+                return false;
+        }
+    }
+
+    /**
      * Creates a group container for {@link NotificationChannel} objects.
      *
      * This can be used to rename an existing group.
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/core/java/android/app/RemoteLockscreenValidationResult.aidl
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to core/java/android/app/RemoteLockscreenValidationResult.aidl
index 497c272..504f78f 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/core/java/android/app/RemoteLockscreenValidationResult.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package android.app;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+/** {@hide} */
+parcelable RemoteLockscreenValidationResult;
diff --git a/core/java/android/app/RemoteLockscreenValidationResult.java b/core/java/android/app/RemoteLockscreenValidationResult.java
new file mode 100644
index 0000000..4f15be2
--- /dev/null
+++ b/core/java/android/app/RemoteLockscreenValidationResult.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.DurationMillisLong;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+/**
+ * Result of lock screen credentials verification.
+ *
+ * @hide
+ */
+public final class RemoteLockscreenValidationResult implements Parcelable {
+
+    /**
+     * The guess was correct
+     */
+    public static final int RESULT_GUESS_VALID = 1;
+
+    /**
+     * Remote device provided incorrect credentials.
+     */
+    public static final int RESULT_GUESS_INVALID = 2;
+
+    /**
+     * The operation was canceled because the API is locked out due to too many attempts. It
+     * usually happens after 5 failed attempts and API may be called again after a short
+     * delay specified by {@code getTimeoutMillis}.
+     */
+    public static final int RESULT_LOCKOUT = 3;
+
+    /**
+     * There were too many invalid guesses.
+     */
+    public static final int RESULT_NO_REMAINING_ATTEMPTS = 4;
+
+    @IntDef({RESULT_GUESS_VALID,
+            RESULT_GUESS_INVALID,
+            RESULT_LOCKOUT,
+            RESULT_NO_REMAINING_ATTEMPTS})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface ResultCode {}
+
+    private int mResultCode;
+    private long mTimeoutMillis;
+
+    public static final @NonNull Parcelable.Creator<RemoteLockscreenValidationResult> CREATOR =
+            new Parcelable.Creator<RemoteLockscreenValidationResult>() {
+        @Override
+        public RemoteLockscreenValidationResult createFromParcel(Parcel source) {
+            return new RemoteLockscreenValidationResult(source);
+        }
+
+        @Override
+        public RemoteLockscreenValidationResult[] newArray(int size) {
+            return new RemoteLockscreenValidationResult[size];
+        }
+    };
+
+    /**
+     * Builder for {@code RemoteLockscreenValidationResult}
+     */
+    public static final class Builder {
+        private RemoteLockscreenValidationResult mInstance = new RemoteLockscreenValidationResult();
+
+        /**
+         * Sets the result code.
+         */
+        public @NonNull Builder setResultCode(@ResultCode int resultCode) {
+            mInstance.mResultCode = resultCode;
+            return this;
+        }
+
+        /**
+         * Sets timeout for {@code RESULT_LOCKOUT}.
+         * Default value is {@code 0}.
+         */
+        public @NonNull Builder setTimeoutMillis(@DurationMillisLong long timeoutMillis) {
+            mInstance.mTimeoutMillis = timeoutMillis;
+            return this;
+        }
+
+        /**
+         * Creates {@code RemoteLockscreenValidationResult}.
+         *
+         * @throws IllegalStateException if result code was not set.
+         */
+        public @NonNull RemoteLockscreenValidationResult build() {
+            if (mInstance.mResultCode == 0) {
+                throw new IllegalStateException("Result code must be set");
+            }
+            return mInstance;
+        }
+    }
+
+    /**
+     * Gets the result code.
+     */
+    public @ResultCode int getResultCode() {
+        return mResultCode;
+    }
+
+    /**
+     * Delay before next attempt to verify credentials.
+     *
+     * Default value is {@code 0}.
+     */
+    public @DurationMillisLong long getTimeoutMillis() {
+        return mTimeoutMillis;
+    }
+
+
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeInt(mResultCode);
+        out.writeLong(mTimeoutMillis);
+    }
+
+    private RemoteLockscreenValidationResult() {
+    }
+
+    private RemoteLockscreenValidationResult(Parcel in) {
+        mResultCode = in.readInt();
+        mTimeoutMillis = in.readLong();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index e485397..a155457 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -1140,6 +1140,22 @@
      * Callback called on timeout for {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}.
      * See {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE} for more details.
      *
+     * <p>If the foreground service of type
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
+     * doesn't finish even after it's timed out,
+     * the app will be declared an ANR after a short grace period of several seconds.
+     *
+     * <p>Note, even though
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
+     * was added
+     * on Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+     * it can be also used on
+     * on prior android versions (just like other new foreground service types can be used).
+     * However, because {@link android.app.Service#onTimeout(int)} did not exist on prior versions,
+     * it will never called on such versions.
+     * Because of this, developers must make sure to stop the foreground service even if
+     * {@link android.app.Service#onTimeout(int)} is not called on such versions.
+     *
      * @param startId the startId passed to {@link #onStartCommand(Intent, int, int)} when
      * the service started.
      */
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/core/java/android/app/StartLockscreenValidationRequest.aidl
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to core/java/android/app/StartLockscreenValidationRequest.aidl
index 497c272..367dfee 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/core/java/android/app/StartLockscreenValidationRequest.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package android.app;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+/** {@hide} */
+parcelable StartLockscreenValidationRequest;
diff --git a/core/java/android/app/StartLockscreenValidationRequest.java b/core/java/android/app/StartLockscreenValidationRequest.java
new file mode 100644
index 0000000..69c268bcb
--- /dev/null
+++ b/core/java/android/app/StartLockscreenValidationRequest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.annotation.NonNull;
+import android.app.KeyguardManager.LockTypes;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Provides information necessary to perform remote lock screen credentials check.
+ *
+ * @hide
+ */
+public final class StartLockscreenValidationRequest implements Parcelable {
+
+    @LockTypes
+    private int mLockscreenUiType;
+
+    private byte[] mSourcePublicKey;
+
+    private int mRemainingAttempts;
+
+    public static final @NonNull Parcelable.Creator<StartLockscreenValidationRequest> CREATOR = new
+            Parcelable.Creator<StartLockscreenValidationRequest>() {
+        @Override
+        public StartLockscreenValidationRequest createFromParcel(Parcel source) {
+            return new StartLockscreenValidationRequest(source);
+        }
+
+        @Override
+        public StartLockscreenValidationRequest[] newArray(int size) {
+            return new StartLockscreenValidationRequest[size];
+        }
+    };
+
+
+    /**
+     * Builder for {@code StartLockscreenValidationRequest}
+     */
+    public static final class Builder {
+        private StartLockscreenValidationRequest mInstance = new StartLockscreenValidationRequest();
+
+        /**
+         * Sets UI type.
+         * Default value is {@code LockTypes.PASSWORD}
+         *
+         * @param lockscreenUiType The UI format
+         * @return This builder.
+         */
+        public @NonNull Builder setLockscreenUiType(@LockTypes int lockscreenUiType) {
+            mInstance.mLockscreenUiType = lockscreenUiType;
+            return this;
+        }
+
+        /**
+         * Sets public key using secure box encoding
+         * @return This builder.
+         */
+        public @NonNull Builder setSourcePublicKey(@NonNull byte[] publicKey) {
+            mInstance.mSourcePublicKey = publicKey;
+            return this;
+        }
+
+        /**
+         * Sets the number of remaining credentials check
+         * Default value is {@code 0}
+         *
+         * @return This builder.
+         */
+        public @NonNull Builder setRemainingAttempts(int remainingAttempts) {
+            mInstance.mRemainingAttempts = remainingAttempts;
+            return this;
+        }
+
+        /**
+         * Creates {@code StartLockscreenValidationRequest}
+         *
+         * @throws NullPointerException if required fields are not set.
+         */
+        public @NonNull StartLockscreenValidationRequest build() {
+            Objects.requireNonNull(mInstance.mSourcePublicKey);
+            return mInstance;
+        }
+    }
+
+    /**
+     * Specifies lock screen credential type.
+     */
+    public @LockTypes int getLockscreenUiType() {
+        return mLockscreenUiType;
+    }
+
+    /**
+     * Public key used to send encrypted credentials.
+     */
+    public @NonNull byte[] getSourcePublicKey() {
+        return mSourcePublicKey;
+    }
+
+    /**
+     * Number of remaining attempts to verify credentials.
+     *
+     * <p>After correct guess counter is reset to {@code 5}.
+     */
+    public int getRemainingAttempts() {
+        return mRemainingAttempts;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeInt(mLockscreenUiType);
+        out.writeByteArray(mSourcePublicKey);
+        out.writeInt(mRemainingAttempts);
+    }
+
+    private StartLockscreenValidationRequest() {
+    }
+
+    private StartLockscreenValidationRequest(Parcel in) {
+        mLockscreenUiType = in.readInt();
+        mSourcePublicKey = in.createByteArray();
+        mRemainingAttempts = in.readInt();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 1c1a558..9e31011 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -30,6 +30,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.drawable.Icon;
 import android.media.INearbyMediaDevicesProvider;
 import android.media.INearbyMediaDevicesUpdateCallback;
@@ -47,6 +48,7 @@
 import android.util.Slog;
 import android.view.View;
 
+import com.android.internal.statusbar.AppClipsServiceConnector;
 import com.android.internal.statusbar.IAddTileResultCallback;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.IUndoMediaTransferCallback;
@@ -1190,6 +1192,37 @@
         return CompatChanges.isChangeEnabled(MEDIA_CONTROL_SESSION_ACTIONS, packageName, user);
     }
 
+    /**
+     * Checks whether the supplied activity can {@link Activity#startActivityForResult(Intent, int)}
+     * a system activity that captures content on the screen to take a screenshot.
+     *
+     * <p>Note: The result should not be cached.
+     *
+     * <p>The system activity displays an editing tool that allows user to edit the screenshot, save
+     * it on device, and return the edited screenshot as {@link android.net.Uri} to the calling
+     * activity. User interaction is required to return the edited screenshot to the calling
+     * activity.
+     *
+     * <p>When {@code true}, callers can use {@link Activity#startActivityForResult(Intent, int)}
+     * to start start the content capture activity using
+     * {@link Intent#ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE}.
+     *
+     * @param activity Calling activity
+     * @return true if the activity supports launching the capture content activity for note.
+     *
+     * @see Intent#ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE
+     * @see Manifest.permission#LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE
+     * @see android.app.role.RoleManager#ROLE_NOTES
+     */
+    @RequiresPermission(Manifest.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE)
+    public boolean canLaunchCaptureContentActivityForNote(@NonNull Activity activity) {
+        Objects.requireNonNull(activity);
+        IBinder activityToken = activity.getActivityToken();
+        int taskId = ActivityClient.getInstance().getTaskForActivity(activityToken, false);
+        return new AppClipsServiceConnector(mContext)
+                .canLaunchCaptureContentActivityForNote(taskId);
+    }
+
     /** @hide */
     public static String windowStateToString(int state) {
         if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING";
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 52d1d68..0365f8c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -116,7 +116,7 @@
 import android.hardware.radio.RadioManager;
 import android.hardware.usb.IUsbManager;
 import android.hardware.usb.UsbManager;
-import android.healthconnect.HealthServicesInitializer;
+import android.health.connect.HealthServicesInitializer;
 import android.location.CountryDetector;
 import android.location.ICountryDetector;
 import android.location.ILocationManager;
@@ -156,6 +156,7 @@
 import android.net.vcn.VcnManager;
 import android.net.wifi.WifiFrameworkInitializer;
 import android.net.wifi.nl80211.WifiNl80211Manager;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
 import android.nfc.NfcManager;
 import android.ondevicepersonalization.OnDevicePersonalizationFrameworkInitializer;
 import android.os.BatteryManager;
@@ -1572,6 +1573,13 @@
                                                 Context.GRAMMATICAL_INFLECTION_SERVICE)));
                     }});
 
+        registerService(Context.SHARED_CONNECTIVITY_SERVICE, SharedConnectivityManager.class,
+                new CachedServiceFetcher<SharedConnectivityManager>() {
+                    @Override
+                    public SharedConnectivityManager createService(ContextImpl ctx) {
+                        return new SharedConnectivityManager(ctx);
+                    }
+                });
 
         sInitializing = true;
         try {
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index e75b503..249937a 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -1447,10 +1447,7 @@
      *
      * @param command The command to execute.
      * @return File descriptors (out, in, err) to the standard output/input/error streams.
-     *
-     * @hide
      */
-    @TestApi
     @SuppressLint("ArrayReturn") // For consistency with other APIs
     public @NonNull ParcelFileDescriptor[] executeShellCommandRwe(@NonNull String command) {
         return executeShellCommandInternal(command, true /* includeStderr */);
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
index 067a4c3..a34a50c 100644
--- a/core/java/android/app/WallpaperColors.java
+++ b/core/java/android/app/WallpaperColors.java
@@ -27,6 +27,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemProperties;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.Size;
@@ -101,11 +102,13 @@
     // Decides when dark theme is optimal for this wallpaper
     private static final float DARK_THEME_MEAN_LUMINANCE = 0.3f;
     // Minimum mean luminosity that an image needs to have to support dark text
-    private static final float BRIGHT_IMAGE_MEAN_LUMINANCE = 0.7f;
+    private static final float BRIGHT_IMAGE_MEAN_LUMINANCE = SystemProperties.getInt(
+            "persist.wallpapercolors.threshold", 70) / 100f;
     // We also check if the image has dark pixels in it,
     // to avoid bright images with some dark spots.
     private static final float DARK_PIXEL_CONTRAST = 5.5f;
-    private static final float MAX_DARK_AREA = 0.05f;
+    private static final float MAX_DARK_AREA = SystemProperties.getInt(
+            "persist.wallpapercolors.max_dark_area", 5) / 100f;
 
     private final List<Color> mMainColors;
     private final Map<Integer, Integer> mAllColors;
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index f3a83d8..ff17824 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -784,6 +784,7 @@
      * @return true if the lockscreen wallpaper always uses a wallpaperService, not a static image
      * @hide
      */
+    @TestApi
     public boolean isLockscreenLiveWallpaperEnabled() {
         return mLockscreenLiveWallpaper;
     }
@@ -1258,6 +1259,8 @@
      * @param which Specifies home or lock screen
      * @hide
      */
+    @TestApi
+    @Nullable
     public Bitmap getBitmapAsUser(int userId, boolean hardware, @SetWallpaperFlags int which) {
         final ColorManagementProxy cmProxy = getColorManagementProxy();
         return sGlobals.peekWallpaperBitmap(mContext, true, which, userId, hardware, cmProxy);
@@ -1496,6 +1499,13 @@
     /**
      * Returns the information about the home screen wallpaper if its current wallpaper is a live
      * wallpaper component. Otherwise, if the wallpaper is a static image, this returns null.
+     *
+     * <p>
+     * In order to use this, apps should declare a {@code <queries>} tag with the action
+     * {@code "android.service.wallpaper.WallpaperService"}. Otherwise,
+     * this method will return {@code null} if the caller doesn't otherwise have
+     * <a href="{@docRoot}training/package-visibility">visibility</a> of the wallpaper package.
+     * </p>
      */
     public WallpaperInfo getWallpaperInfo() {
         return getWallpaperInfoForUser(mContext.getUserId());
@@ -1517,6 +1527,13 @@
      * wallpaper component. Otherwise, if the wallpaper is a static image or is not set, this
      * returns null.
      *
+     * <p>
+     * In order to use this, apps should declare a {@code <queries>} tag with the action
+     * {@code "android.service.wallpaper.WallpaperService"}. Otherwise,
+     * this method will return {@code null} if the caller doesn't otherwise have
+     * <a href="{@docRoot}training/package-visibility">visibility</a> of the wallpaper package.
+     * </p>
+     *
      * @param which Specifies wallpaper to request (home or lock).
      * @throws IllegalArgumentException if {@code which} is not exactly one of
      * {{@link #FLAG_SYSTEM},{@link #FLAG_LOCK}}.
@@ -2421,6 +2438,7 @@
      *
      * @hide
      */
+    @TestApi
     public void setWallpaperZoomOut(@NonNull IBinder windowToken, float zoom) {
         if (zoom < 0 || zoom > 1f) {
             throw new IllegalArgumentException("zoom must be between 0 and 1: " + zoom);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6e6d4e3..3fe63d8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -39,6 +39,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.StringDef;
+import android.annotation.SupportsCoexistence;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -3876,13 +3877,24 @@
     public static final int EXEMPT_FROM_APP_STANDBY =  0;
 
     /**
+     * Prevent an app from dismissible notifications. Starting from Android U, notifications with
+     * the ongoing parameter can be dismissed by a user on an unlocked device. An app with
+     * this exemption can create non-dismissable notifications.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS =  1;
+
+    /**
      * Exemptions to platform restrictions, given to an application through
      * {@link #setApplicationExemptions(String, Set)}.
      *
      * @hide
      */
     @IntDef(prefix = { "EXEMPT_FROM_"}, value = {
-            EXEMPT_FROM_APP_STANDBY
+            EXEMPT_FROM_APP_STANDBY,
+            EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApplicationExemptionConstants {}
@@ -3961,6 +3973,7 @@
      *
      * @throws SecurityException if caller is not device owner or profile owner of org-owned device
      *     or if called on a parent instance
+     * @throws UnsupportedOperationException if the device does not support MTE
      * @param policy the MTE policy to be set
      */
     public void setMtePolicy(@MtePolicy int policy) {
@@ -8595,6 +8608,7 @@
      * primary user, or a profile owner of an organization-owned managed profile or a holder of the
      * permission {@link android.Manifest.permission#SET_TIME_ZONE}.
      */
+    @SupportsCoexistence
     @RequiresPermission(value = SET_TIME_ZONE, conditional = true)
     public void setAutoTimeZoneEnabled(@NonNull ComponentName admin, boolean enabled) {
         throwIfParentInstance("setAutoTimeZone");
@@ -9664,6 +9678,7 @@
      * @param activity The Activity that is added as default intent handler.
      * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
+    @SupportsCoexistence
     public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter,
             @NonNull ComponentName activity) {
         throwIfParentInstance("addPersistentPreferredActivity");
@@ -10623,6 +10638,7 @@
      *                           profile owner of an organization-owned managed profile and the
      *                           list of permitted input method package names is not null or empty.
      */
+    @SupportsCoexistence
     public boolean setPermittedInputMethods(
             @NonNull ComponentName admin, List<String> packageNames) {
         if (mService != null) {
@@ -11695,6 +11711,7 @@
      * @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent)
      * @see UserManager#DISALLOW_CREATE_WINDOWS
      */
+    @SupportsCoexistence
     public void setLockTaskPackages(@NonNull ComponentName admin, @NonNull String[] packages)
             throws SecurityException {
         throwIfParentInstance("setLockTaskPackages");
@@ -11763,6 +11780,7 @@
      * affiliated user or profile, or the profile owner when no device owner is set.
      * @see #isAffiliatedUser
      **/
+    @SupportsCoexistence
     public void setLockTaskFeatures(@NonNull ComponentName admin, @LockTaskFeature int flags) {
         throwIfParentInstance("setLockTaskFeatures");
         if (mService != null) {
@@ -12266,6 +12284,7 @@
      * @see #setDelegatedScopes
      * @see #DELEGATION_BLOCK_UNINSTALL
      */
+    @SupportsCoexistence
     public void setUninstallBlocked(@Nullable ComponentName admin, String packageName,
             boolean uninstallBlocked) {
         throwIfParentInstance("setUninstallBlocked");
@@ -12754,6 +12773,7 @@
      * @see #setDelegatedScopes
      * @see #DELEGATION_PERMISSION_GRANT
      */
+    @SupportsCoexistence
     public boolean setPermissionGrantState(@NonNull ComponentName admin,
             @NonNull String packageName, @NonNull String permission,
             @PermissionGrantState int grantState) {
@@ -15300,6 +15320,7 @@
      * @param packages The package names for the apps.
      * @throws SecurityException if {@code admin} is not a device owner or a profile owner.
      */
+    @SupportsCoexistence
     public void setUserControlDisabledPackages(@NonNull ComponentName admin,
             @NonNull List<String> packages) {
         throwIfParentInstance("setUserControlDisabledPackages");
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 3a61ca1..1b5c196 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -304,4 +304,9 @@
      * True if either the entire device or the user is organization managed.
      */
     public abstract boolean isUserOrganizationManaged(@UserIdInt int userId);
+
+    /**
+     * Returns whether the application exemptions feature flag is enabled.
+     */
+    public abstract boolean isApplicationExemptionsFlagEnabled();
 }
diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
index 0513099..4c97efb 100644
--- a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
+++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
@@ -544,9 +544,9 @@
         pw.print("blockNonMatchingNetworks=");
         pw.println(mShouldBlockNonMatchingNetworks);
         pw.print("includedUids=");
-        pw.println(mIncludedUids);
+        pw.println(Arrays.toString(mIncludedUids));
         pw.print("excludedUids=");
-        pw.println(mExcludedUids);
+        pw.println(Arrays.toString(mExcludedUids));
     }
 
     @Override
diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index b100eb2..c760298 100644
--- a/core/java/android/app/admin/SystemUpdatePolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -50,8 +50,8 @@
 
 /**
  * Determines when over-the-air system updates are installed on a device. Only a device policy
- * controller (DPC) running in device owner mode can set an update policy for the device—by calling
- * the {@code DevicePolicyManager} method
+ * controller (DPC) running in device owner mode or in profile owner mode for an organization-owned
+ * device can set an update policy for the device—by calling the {@code DevicePolicyManager} method
  * {@link DevicePolicyManager#setSystemUpdatePolicy setSystemUpdatePolicy()}. An update
  * policy affects the pending system update (if there is one) and any future updates for the device.
  *
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 6e49e95..b7ec7b5 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -545,6 +545,7 @@
         int resolveViewAutofillFlags(Context context, int fillRequestFlags) {
             return (fillRequestFlags & FillRequest.FLAG_MANUAL_REQUEST) != 0
                         || context.isAutofillCompatibilityEnabled()
+                        || (fillRequestFlags & FillRequest.FLAG_PCC_DETECTION) != 0
                     ? View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0;
         }
 
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index e323e89..909073e 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -265,15 +265,9 @@
     public void onCreate() {
     }
 
-    /**
-     * Provided as a convenience for agent implementations that need an opportunity
-     * to do one-time initialization before the actual backup or restore operation
-     * is begun with information about the calling user.
-     * <p>
-     *
-     * @hide
-     */
+    /** @hide */
     public void onCreate(UserHandle user) {
+        mUser = user;
         onCreate();
     }
 
@@ -284,7 +278,6 @@
      */
     @Deprecated
     public void onCreate(UserHandle user, @BackupDestination int backupDestination) {
-        mUser = user;
         mBackupDestination = backupDestination;
 
         onCreate(user);
@@ -295,7 +288,6 @@
     */
     public void onCreate(UserHandle user, @BackupDestination int backupDestination,
             @OperationType int operationType) {
-        mUser = user;
         mBackupDestination = backupDestination;
         mLogger = new BackupRestoreEventLogger(operationType);
 
diff --git a/core/java/android/app/search/ISearchUiManager.aidl b/core/java/android/app/search/ISearchUiManager.aidl
index a298a2c..fefbd5a 100644
--- a/core/java/android/app/search/ISearchUiManager.aidl
+++ b/core/java/android/app/search/ISearchUiManager.aidl
@@ -36,5 +36,11 @@
 
     void notifyEvent(in SearchSessionId sessionId, in Query input, in SearchTargetEvent event);
 
+    void registerEmptyQueryResultUpdateCallback(in SearchSessionId sessionId, in ISearchCallback callback);
+
+    void requestEmptyQueryResultUpdate(in SearchSessionId sessionId);
+
+    void unregisterEmptyQueryResultUpdateCallback(in SearchSessionId sessionId, in ISearchCallback callback);
+
     void destroySearchSession(in SearchSessionId sessionId);
 }
diff --git a/core/java/android/app/search/SearchSession.java b/core/java/android/app/search/SearchSession.java
index 10db337..9e0a1d0 100644
--- a/core/java/android/app/search/SearchSession.java
+++ b/core/java/android/app/search/SearchSession.java
@@ -28,8 +28,11 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.util.ArrayMap;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
+
 import dalvik.system.CloseGuard;
 
 import java.util.List;
@@ -83,6 +86,8 @@
 
     private final SearchSessionId mSessionId;
     private final IBinder mToken = new Binder();
+    @GuardedBy("itself")
+    private final ArrayMap<Callback, CallbackWrapper> mRegisteredCallbacks = new ArrayMap<>();
 
     /**
      * Creates a new search ui client.
@@ -156,6 +161,94 @@
             e.rethrowFromSystemServer();
         }
     }
+    /**
+     * Request the search ui service provide continuous updates of {@link SearchTarget} list
+     * via the provided callback to render for zero state, until the given callback is
+     * unregistered. Zero state means when user entered search ui but not issued any query yet.
+     *
+     * @see SearchSession.Callback#onTargetsAvailable(List).
+     *
+     * @param callbackExecutor The callback executor to use when calling the callback.
+     * @param callback The Callback to be called when updates of search targets for zero state
+     *                 are available.
+     */
+    public void registerEmptyQueryResultUpdateCallback(
+            @NonNull @CallbackExecutor Executor callbackExecutor,
+            @NonNull Callback callback) {
+        synchronized (mRegisteredCallbacks) {
+            if (mIsClosed.get()) {
+                throw new IllegalStateException("This client has already been destroyed.");
+            }
+            if (mRegisteredCallbacks.containsKey(callback)) {
+                // Skip if this callback is already registered
+                return;
+            }
+            try {
+                final CallbackWrapper callbackWrapper = new CallbackWrapper(callbackExecutor,
+                        callback::onTargetsAvailable);
+                mInterface.registerEmptyQueryResultUpdateCallback(mSessionId, callbackWrapper);
+                mRegisteredCallbacks.put(callback, callbackWrapper);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to register for empty query result updates", e);
+                e.rethrowAsRuntimeException();
+            }
+        }
+    }
+
+    /**
+     * Requests the search ui service to stop providing continuous updates of {@link SearchTarget}
+     * to the provided callback for zero state until the callback is re-registered. Zero state
+     * means when user entered search ui but not issued any query yet.
+     *
+     * @see {@link SearchSession#registerEmptyQueryResultUpdateCallback(Executor, Callback)}
+     * @param callback The callback to be unregistered.
+     */
+    public void unregisterEmptyQueryResultUpdateCallback(
+            @NonNull Callback callback) {
+        synchronized (mRegisteredCallbacks) {
+            if (mIsClosed.get()) {
+                throw new IllegalStateException("This client has already been destroyed.");
+            }
+
+            if (!mRegisteredCallbacks.containsKey(callback)) {
+                // Skip if this callback was never registered
+                return;
+            }
+            try {
+                final CallbackWrapper callbackWrapper = mRegisteredCallbacks.remove(callback);
+                mInterface.unregisterEmptyQueryResultUpdateCallback(mSessionId, callbackWrapper);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to unregister for empty query result updates", e);
+                e.rethrowAsRuntimeException();
+            }
+        }
+    }
+
+    /**
+     * Requests the search ui service to dispatch a new set of search targets to the pre-registered
+     * callback for zero state. Zero state means when user entered search ui but not issued any
+     * query yet. This method can be used for client to sync up with server data if they think data
+     * might be out of sync, for example, after restart.
+     * Pre-register a callback with
+     * {@link SearchSession#registerEmptyQueryResultUpdateCallback(Executor, Callback)}
+     * is required before calling this method. Otherwise this is no-op.
+     *
+     * @see {@link SearchSession#registerEmptyQueryResultUpdateCallback(Executor, Callback)}
+     * @see {@link SearchSession.Callback#onTargetsAvailable(List)}.
+     */
+    public void requestEmptyQueryResultUpdate() {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
+        try {
+            mInterface.requestEmptyQueryResultUpdate(mSessionId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to request empty query result update", e);
+            e.rethrowAsRuntimeException();
+        }
+    }
+
 
     /**
      * Destroys the client and unregisters the callback. Any method on this class after this call
@@ -213,6 +306,19 @@
         }
     }
 
+    /**
+     *  Callback for receiving {@link SearchTarget} updates for zero state. Zero state
+     *  means when user entered search ui but not issued any query yet.
+     */
+    public interface Callback {
+
+        /**
+         * Called when a new set of {@link SearchTarget} are available for zero state.
+         * @param targets Sorted list of search targets.
+         */
+        void onTargetsAvailable(@NonNull List<SearchTarget> targets);
+    }
+
     static class CallbackWrapper extends Stub {
 
         private final Consumer<List<SearchTarget>> mCallback;
diff --git a/core/java/android/app/time/TimeZoneCapabilities.java b/core/java/android/app/time/TimeZoneCapabilities.java
index b647fc3..4dee159 100644
--- a/core/java/android/app/time/TimeZoneCapabilities.java
+++ b/core/java/android/app/time/TimeZoneCapabilities.java
@@ -57,6 +57,16 @@
      */
     @NonNull private final UserHandle mUserHandle;
     private final @CapabilityState int mConfigureAutoDetectionEnabledCapability;
+
+    /**
+     * The values of the user's "Use location" value, AKA the Master Location Switch.
+     *
+     * <p>This is only exposed for SettingsUI and so is not part of the SDK API.
+     *
+     * <p>This is not treated as a CapabilityState as it's a boolean value that all user's have.
+     */
+    private final boolean mUseLocationEnabled;
+
     private final @CapabilityState int mConfigureGeoDetectionEnabledCapability;
     private final @CapabilityState int mSetManualTimeZoneCapability;
 
@@ -64,6 +74,7 @@
         this.mUserHandle = Objects.requireNonNull(builder.mUserHandle);
         this.mConfigureAutoDetectionEnabledCapability =
                 builder.mConfigureAutoDetectionEnabledCapability;
+        this.mUseLocationEnabled = builder.mUseLocationEnabled;
         this.mConfigureGeoDetectionEnabledCapability =
                 builder.mConfigureGeoDetectionEnabledCapability;
         this.mSetManualTimeZoneCapability = builder.mSetManualTimeZoneCapability;
@@ -74,6 +85,7 @@
         UserHandle userHandle = UserHandle.readFromParcel(in);
         return new TimeZoneCapabilities.Builder(userHandle)
                 .setConfigureAutoDetectionEnabledCapability(in.readInt())
+                .setUseLocationEnabled(in.readBoolean())
                 .setConfigureGeoDetectionEnabledCapability(in.readInt())
                 .setSetManualTimeZoneCapability(in.readInt())
                 .build();
@@ -83,6 +95,7 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         UserHandle.writeToParcel(mUserHandle, dest);
         dest.writeInt(mConfigureAutoDetectionEnabledCapability);
+        dest.writeBoolean(mUseLocationEnabled);
         dest.writeInt(mConfigureGeoDetectionEnabledCapability);
         dest.writeInt(mSetManualTimeZoneCapability);
     }
@@ -98,6 +111,20 @@
     }
 
     /**
+     * Returns {@code true} if the device's location can be used by the Android system, and
+     * therefore the platform components running on behalf of the user. At the time of writing, the
+     * user can change this via the "Use location" setting on the Location settings screen.
+     *
+     * Not part of the SDK API because it is intended for use by SettingsUI, which can display
+     * text about needing it to be on for location-based time zone detection.
+     * @hide
+     *
+     */
+    public boolean isUseLocationEnabled() {
+        return mUseLocationEnabled;
+    }
+
+    /**
      * Returns the capability state associated with the user's ability to modify the geolocation
      * detection setting. The setting can be updated via {@link
      * TimeManager#updateTimeZoneConfiguration(TimeZoneConfiguration)}.
@@ -167,6 +194,7 @@
         return mUserHandle.equals(that.mUserHandle)
                 && mConfigureAutoDetectionEnabledCapability
                 == that.mConfigureAutoDetectionEnabledCapability
+                && mUseLocationEnabled == that.mUseLocationEnabled
                 && mConfigureGeoDetectionEnabledCapability
                 == that.mConfigureGeoDetectionEnabledCapability
                 && mSetManualTimeZoneCapability == that.mSetManualTimeZoneCapability;
@@ -184,6 +212,7 @@
                 + "mUserHandle=" + mUserHandle
                 + ", mConfigureAutoDetectionEnabledCapability="
                 + mConfigureAutoDetectionEnabledCapability
+                + ", mUseLocationEnabled=" + mUseLocationEnabled
                 + ", mConfigureGeoDetectionEnabledCapability="
                 + mConfigureGeoDetectionEnabledCapability
                 + ", mSetManualTimeZoneCapability=" + mSetManualTimeZoneCapability
@@ -199,6 +228,7 @@
 
         @NonNull private UserHandle mUserHandle;
         private @CapabilityState int mConfigureAutoDetectionEnabledCapability;
+        private Boolean mUseLocationEnabled;
         private @CapabilityState int mConfigureGeoDetectionEnabledCapability;
         private @CapabilityState int mSetManualTimeZoneCapability;
 
@@ -211,6 +241,7 @@
             mUserHandle = capabilitiesToCopy.mUserHandle;
             mConfigureAutoDetectionEnabledCapability =
                 capabilitiesToCopy.mConfigureAutoDetectionEnabledCapability;
+            mUseLocationEnabled = capabilitiesToCopy.mUseLocationEnabled;
             mConfigureGeoDetectionEnabledCapability =
                 capabilitiesToCopy.mConfigureGeoDetectionEnabledCapability;
             mSetManualTimeZoneCapability =
@@ -223,6 +254,12 @@
             return this;
         }
 
+        /** Sets the values for "use location". See {@link #isUseLocationEnabled()}. */
+        public Builder setUseLocationEnabled(boolean useLocation) {
+            mUseLocationEnabled = useLocation;
+            return this;
+        }
+
         /**
          * Sets the value for the "configure geolocation time zone detection enabled" capability.
          */
@@ -242,6 +279,7 @@
         public TimeZoneCapabilities build() {
             verifyCapabilitySet(mConfigureAutoDetectionEnabledCapability,
                     "configureAutoDetectionEnabledCapability");
+            Objects.requireNonNull(mUseLocationEnabled, "useLocationEnabled");
             verifyCapabilitySet(mConfigureGeoDetectionEnabledCapability,
                     "configureGeoDetectionEnabledCapability");
             verifyCapabilitySet(mSetManualTimeZoneCapability,
diff --git a/core/java/android/companion/CompanionDeviceService.java b/core/java/android/companion/CompanionDeviceService.java
index 01c5fa1..f660377 100644
--- a/core/java/android/companion/CompanionDeviceService.java
+++ b/core/java/android/companion/CompanionDeviceService.java
@@ -210,6 +210,10 @@
      * As an example, it's valid to provide streams obtained from a
      * {@link BluetoothSocket} to this method, since {@link BluetoothSocket}
      * meets the API contract described above.
+     * <p>
+     * This method passes through to
+     * {@link CompanionDeviceManager#attachSystemDataTransport(int, InputStream, OutputStream)}
+     * for your convenience if you get callbacks in this class.
      *
      * @param associationId id of the associated device
      * @param in already connected stream of data incoming from remote
@@ -229,6 +233,10 @@
     /**
      * Detach any bidirectional communication streams previously configured
      * through {@link #attachSystemDataTransport}.
+     * <p>
+     * This method passes through to
+     * {@link CompanionDeviceManager#detachSystemDataTransport(int)}
+     * for your convenience if you get callbacks in this class.
      *
      * @param associationId id of the associated device
      */
diff --git a/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl
index a46dc53..fc7f85c 100644
--- a/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl
+++ b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl
@@ -30,8 +30,9 @@
      *
      * @param displayId The display ID on which the activity change happened.
      * @param topActivity The component name of the top activity.
+     * @param userId The user ID associated with the top activity.
      */
-    void onTopActivityChanged(int displayId, in ComponentName topActivity);
+    void onTopActivityChanged(int displayId, in ComponentName topActivity, in int userId);
 
     /**
      * Called when the display becomes empty (e.g. if the user hits back on the last
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index d585e8f..3e6b380 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -27,6 +27,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UserIdInt;
 import android.app.PendingIntent;
 import android.companion.AssociationInfo;
 import android.companion.virtual.audio.VirtualAudioDevice;
@@ -378,13 +379,16 @@
                 new IVirtualDeviceActivityListener.Stub() {
 
                     @Override
-                    public void onTopActivityChanged(int displayId, ComponentName topActivity) {
+                    public void onTopActivityChanged(int displayId, ComponentName topActivity,
+                            @UserIdInt int userId) {
                         final long token = Binder.clearCallingIdentity();
                         try {
                             synchronized (mActivityListenersLock) {
                                 for (int i = 0; i < mActivityListeners.size(); i++) {
                                     mActivityListeners.valueAt(i)
                                             .onTopActivityChanged(displayId, topActivity);
+                                    mActivityListeners.valueAt(i)
+                                          .onTopActivityChanged(displayId, topActivity, userId);
                                 }
                             }
                         } finally {
@@ -1087,10 +1091,25 @@
          *
          * @param displayId The display ID on which the activity change happened.
          * @param topActivity The component name of the top activity.
+         * @deprecated Use {@link #onTopActivityChanged(int, ComponentName, int)} instead
          */
         void onTopActivityChanged(int displayId, @NonNull ComponentName topActivity);
 
         /**
+         * Called when the top activity is changed.
+         *
+         * <p>Note: When there are no activities running on the virtual display, the
+         * {@link #onDisplayEmpty(int)} will be called. If the value topActivity is cached, it
+         * should be cleared when {@link #onDisplayEmpty(int)} is called.
+         *
+         * @param displayId   The display ID on which the activity change happened.
+         * @param topActivity The component name of the top activity.
+         * @param userId      The user ID associated with the top activity.
+         */
+        default void onTopActivityChanged(int displayId, @NonNull ComponentName topActivity,
+                @UserIdInt int userId) {}
+
+        /**
          * Called when the display becomes empty (e.g. if the user hits back on the last
          * activity of the root task).
          *
@@ -1115,6 +1134,12 @@
             mExecutor.execute(() -> mActivityListener.onTopActivityChanged(displayId, topActivity));
         }
 
+        public void onTopActivityChanged(int displayId, ComponentName topActivity,
+                @UserIdInt int userId) {
+            mExecutor.execute(() ->
+                    mActivityListener.onTopActivityChanged(displayId, topActivity, userId));
+        }
+
         public void onDisplayEmpty(int displayId) {
             mExecutor.execute(() -> mActivityListener.onDisplayEmpty(displayId));
         }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ac2eae41..0d330ce 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -6175,10 +6175,10 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
-     * {@link android.healthconnect.HealthConnectManager}.
+     * {@link android.health.connect.HealthConnectManager}.
      *
      * @see #getSystemService(String)
-     * @see android.healthconnect.HealthConnectManager
+     * @see android.health.connect.HealthConnectManager
      */
     public static final String HEALTHCONNECT_SERVICE = "healthconnect";
 
@@ -6222,12 +6222,34 @@
     public static final String GRAMMATICAL_INFLECTION_SERVICE = "grammatical_inflection";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.telephony.satellite.SatelliteManager} for accessing satellite functionality.
+     *
+     * @see #getSystemService(String)
+     * @see android.telephony.satellite.SatelliteManager
+     * @hide
+     */
+    public static final String SATELLITE_SERVICE = "satellite";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.net.wifi.sharedconnectivity.app.SharedConnectivityManager} for accessing
+     * shared connectivity services.
+     *
+     * @see #getSystemService(String)
+     * @see android.net.wifi.sharedconnectivity.app.SharedConnectivityManager
+     * @hide
+     */
+    @SystemApi
+    public static final String SHARED_CONNECTIVITY_SERVICE = "shared_connectivity";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
      * @param permission The name of the permission being checked.
      * @param pid The process ID being checked against.  Must be > 0.
-     * @param uid The user ID being checked against.  A uid of 0 is the root
+     * @param uid The UID being checked against.  A uid of 0 is the root
      * user, which will pass every permission check.
      *
      * @return {@link PackageManager#PERMISSION_GRANTED} if the given
@@ -6317,7 +6339,7 @@
      *
      * @param permission The name of the permission being checked.
      * @param pid The process ID being checked against.  Must be &gt; 0.
-     * @param uid The user ID being checked against.  A uid of 0 is the root
+     * @param uid The UID being checked against.  A uid of 0 is the root
      * user, which will pass every permission check.
      * @param message A message to include in the exception if it is thrown.
      *
@@ -6461,7 +6483,7 @@
      *
      * @param uri The uri that is being checked.
      * @param pid The process ID being checked against.  Must be &gt; 0.
-     * @param uid The user ID being checked against.  A uid of 0 is the root
+     * @param uid The UID being checked against.  A uid of 0 is the root
      * user, which will pass every permission check.
      * @param modeFlags The access modes to check.
      *
@@ -6489,7 +6511,7 @@
      *
      * @param uris The list of URIs that is being checked.
      * @param pid The process ID being checked against.  Must be &gt; 0.
-     * @param uid The user ID being checked against.  A uid of 0 is the root
+     * @param uid The UID being checked against.  A uid of 0 is the root
      * user, which will pass every permission check.
      * @param modeFlags The access modes to check for the list of uris
      *
@@ -6615,7 +6637,7 @@
      * @param writePermission The permission that provides overall write
      * access, or null to not do this check.
      * @param pid The process ID being checked against.  Must be &gt; 0.
-     * @param uid The user ID being checked against.  A uid of 0 is the root
+     * @param uid The UID being checked against.  A uid of 0 is the root
      * user, which will pass every permission check.
      * @param modeFlags The access modes to check.
      *
@@ -6639,7 +6661,7 @@
      *
      * @param uri The uri that is being checked.
      * @param pid The process ID being checked against.  Must be &gt; 0.
-     * @param uid The user ID being checked against.  A uid of 0 is the root
+     * @param uid The UID being checked against.  A uid of 0 is the root
      * user, which will pass every permission check.
      * @param modeFlags The access modes to enforce.
      * @param message A message to include in the exception if it is thrown.
@@ -6698,7 +6720,7 @@
      * @param writePermission The permission that provides overall write
      * access, or null to not do this check.
      * @param pid The process ID being checked against.  Must be &gt; 0.
-     * @param uid The user ID being checked against.  A uid of 0 is the root
+     * @param uid The UID being checked against.  A uid of 0 is the root
      * user, which will pass every permission check.
      * @param modeFlags The access modes to enforce.
      * @param message A message to include in the exception if it is thrown.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5714032..5818ed7 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -31,8 +31,10 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.app.Activity;
 import android.app.ActivityThread;
 import android.app.AppGlobals;
+import android.app.StatusBarManager;
 import android.bluetooth.BluetoothDevice;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
@@ -576,6 +578,13 @@
  *     <li> {@link #ACTION_SHUTDOWN}
  * </ul>
  *
+ * <p class="note"><strong>Note: </strong>If your app targets Android 11
+ * (API level 30) or higher, registering broadcast such as
+ * {@link #ACTION_PACKAGES_SUSPENDED} that includes package details in the
+ * extras receives a filtered list of apps or nothing. Learn more about how to
+ * <a href="/training/basics/intents/package-visibility">manage package visibility</a>.
+ * </p>
+ *
  * <h3>Standard Categories</h3>
  *
  * <p>These are the current standard categories that can be used to further
@@ -4549,8 +4558,8 @@
      * @see #EXTRA_SIM_LOCKED_REASON
      * @see #EXTRA_REBROADCAST_ON_UNLOCK
      *
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or
-     * {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED} or
+     * {@link android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED}
      *
      * @hide
      */
@@ -4573,42 +4582,42 @@
      * @see #SIM_STATE_IMSI
      * @see #SIM_STATE_LOADED
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     public static final String EXTRA_SIM_STATE = "ss";
 
     /**
      * The intent value UNKNOWN represents the SIM state unknown
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     public static final String SIM_STATE_UNKNOWN = "UNKNOWN";
 
     /**
      * The intent value NOT_READY means that the SIM is not ready eg. radio is off or powering on
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     public static final String SIM_STATE_NOT_READY = "NOT_READY";
 
     /**
      * The intent value ABSENT means the SIM card is missing
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     public static final String SIM_STATE_ABSENT = "ABSENT";
 
     /**
      * The intent value PRESENT means the device has a SIM card inserted
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     public static final String SIM_STATE_PRESENT = "PRESENT";
 
     /**
      * The intent value CARD_IO_ERROR means for three consecutive times there was SIM IO error
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     static public final String SIM_STATE_CARD_IO_ERROR = "CARD_IO_ERROR";
 
@@ -4616,35 +4625,35 @@
      * The intent value CARD_RESTRICTED means card is present but not usable due to carrier
      * restrictions
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     static public final String SIM_STATE_CARD_RESTRICTED = "CARD_RESTRICTED";
 
     /**
      * The intent value LOCKED means the SIM is locked by PIN or by network
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     public static final String SIM_STATE_LOCKED = "LOCKED";
 
     /**
      * The intent value READY means the SIM is ready to be accessed
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     public static final String SIM_STATE_READY = "READY";
 
     /**
      * The intent value IMSI means the SIM IMSI is ready in property
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     public static final String SIM_STATE_IMSI = "IMSI";
 
     /**
      * The intent value LOADED means all SIM records, including IMSI, are loaded
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED}
      */
     public static final String SIM_STATE_LOADED = "LOADED";
 
@@ -4658,21 +4667,24 @@
      * @see #SIM_ABSENT_ON_PERM_DISABLED
      *
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     * @deprecated Use
+     * {@link android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED}
      */
     public static final String EXTRA_SIM_LOCKED_REASON = "reason";
 
     /**
      * The intent value PIN means the SIM is locked on PIN1
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     * @deprecated Use
+     * {@link android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED}
      */
     public static final String SIM_LOCKED_ON_PIN = "PIN";
 
     /**
      * The intent value PUK means the SIM is locked on PUK1
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     * @deprecated Use
+     * {@link android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED}
      */
     /* PUK means ICC is locked on PUK1 */
     public static final String SIM_LOCKED_ON_PUK = "PUK";
@@ -4680,14 +4692,16 @@
     /**
      * The intent value NETWORK means the SIM is locked on NETWORK PERSONALIZATION
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     * @deprecated Use
+     * {@link android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED}
      */
     public static final String SIM_LOCKED_NETWORK = "NETWORK";
 
     /**
      * The intent value PERM_DISABLED means SIM is permanently disabled due to puk fails
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     * @deprecated Use
+     * {@link android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED}
      */
     public static final String SIM_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED";
 
@@ -4696,8 +4710,8 @@
      * is a rebroadcast on unlock. Defaults to {@code false} if not specified.
      *
      * @hide
-     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or
-     * {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     * @deprecated Use {@link android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED} or
+     * {@link android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED}
      */
     public static final String EXTRA_REBROADCAST_ON_UNLOCK = "rebroadcastOnUnlock";
 
@@ -5137,6 +5151,86 @@
     public static final String EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE";
 
     /**
+     * Activity Action: Use with startActivityForResult to start a system activity that captures
+     * content on the screen to take a screenshot and present it to the user for editing. The
+     * edited screenshot is saved on device and returned to the calling activity as a {@link Uri}
+     * through {@link #getData()}. User interaction is required to return the edited screenshot to
+     * the calling activity.
+     *
+     * <p>This intent action requires the permission
+     * {@link android.Manifest.permission#LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE}.
+     *
+     * <p>Callers should query
+     * {@link StatusBarManager#canLaunchCaptureContentActivityForNote(Activity)} before showing a UI
+     * element that allows users to trigger this flow.
+     */
+    @RequiresPermission(Manifest.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE)
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE =
+            "android.intent.action.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE";
+
+    /**
+     * An int extra used by activity started with
+     * {@link #ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE} to indicate status of the response.
+     * This extra is used along with result code set to {@link android.app.Activity#RESULT_OK}.
+     *
+     * <p>The value for this extra can be one of the following:
+     * <ul>
+     *     <li>{@link #CAPTURE_CONTENT_FOR_NOTE_SUCCESS}</li>
+     *     <li>{@link #CAPTURE_CONTENT_FOR_NOTE_FAILED}</li>
+     *     <li>{@link #CAPTURE_CONTENT_FOR_NOTE_USER_CANCELED}</li>
+     *     <li>{@link #CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED}</li>
+     *     <li>{@link #CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN}</li>
+     * </ul>
+     */
+    public static final String EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE =
+            "android.intent.extra.CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE";
+
+    /**
+     * A response code used with {@link #EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE} to indicate
+     * that the request was a success.
+     *
+     * <p>This code will only be returned after the user has interacted with the system screenshot
+     * activity to consent to sharing the data with the note.
+     *
+     * <p>The captured screenshot is returned as a {@link Uri} through {@link #getData()}.
+     */
+    public static final int CAPTURE_CONTENT_FOR_NOTE_SUCCESS = 0;
+
+    /**
+     * A response code used with {@link #EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE} to indicate
+     * that something went wrong.
+     */
+    public static final int CAPTURE_CONTENT_FOR_NOTE_FAILED = 1;
+
+    /**
+     * A response code used with {@link #EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE} to indicate
+     * that user canceled the content capture flow.
+     */
+    public static final int CAPTURE_CONTENT_FOR_NOTE_USER_CANCELED = 2;
+
+    /**
+     * A response code used with {@link #EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE} to indicate
+     * that the intent action {@link #ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE} was started
+     * by an activity that is running in a non-supported window mode.
+     */
+    public static final int CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED = 3;
+
+    /**
+     * A response code used with {@link #EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE} to indicate
+     * that screenshot is blocked by IT admin.
+     */
+    public static final int CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN = 4;
+
+    /** @hide */
+    @IntDef(value = {
+            CAPTURE_CONTENT_FOR_NOTE_SUCCESS, CAPTURE_CONTENT_FOR_NOTE_FAILED,
+            CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED,
+            CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CaptureContentForNoteStatusCodes {}
+
+    /**
      * Broadcast Action: Sent to the integrity component when a package
      * needs to be verified. The data contains the package URI along with other relevant
      * information.
@@ -5825,14 +5919,12 @@
 
     /**
      * Optional argument to be used with {@link #ACTION_CHOOSER}.
-     * A {@link android.app.PendingIntent} to be sent when the user wants to do payload reselection
-     * in the sharesheet.
-     * A reselection action allows the user to return to the source app to change the content being
-     * shared.
-     * @hide
+     * A {@link android.app.PendingIntent} to be sent when the user wants to modify the content that
+     * they're sharing. This can be used to allow the user to return to the source app to, for
+     * example, select different media.
      */
-    public static final String EXTRA_CHOOSER_PAYLOAD_RESELECTION_ACTION =
-            "android.intent.extra.CHOOSER_PAYLOAD_RESELECTION_ACTION";
+    public static final String EXTRA_CHOOSER_MODIFY_SHARE_ACTION =
+            "android.intent.extra.CHOOSER_MODIFY_SHARE_ACTION";
 
     /**
      * An {@code ArrayList} of {@code String} annotations describing content for
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 8853b70..ccb53cf 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -18,9 +18,10 @@
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
+import android.app.ActivityOptions;
 import android.app.ActivityThread;
 import android.app.IApplicationThread;
-import android.app.ActivityManager.PendingIntentInfo;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Handler;
@@ -160,7 +161,7 @@
      */
     public void sendIntent(Context context, int code, Intent intent,
             OnFinished onFinished, Handler handler) throws SendIntentException {
-        sendIntent(context, code, intent, onFinished, handler, null);
+        sendIntent(context, code, intent, onFinished, handler, null, null /* options */);
     }
 
     /**
@@ -192,6 +193,42 @@
     public void sendIntent(Context context, int code, Intent intent,
             OnFinished onFinished, Handler handler, String requiredPermission)
             throws SendIntentException {
+        sendIntent(context, code, intent, onFinished, handler, requiredPermission,
+                null /* options */);
+    }
+
+    /**
+     * Perform the operation associated with this IntentSender, allowing the
+     * caller to specify information about the Intent to use and be notified
+     * when the send has completed.
+     *
+     * @param context The Context of the caller.  This may be null if
+     * <var>intent</var> is also null.
+     * @param code Result code to supply back to the IntentSender's target.
+     * @param intent Additional Intent data.  See {@link Intent#fillIn
+     * Intent.fillIn()} for information on how this is applied to the
+     * original Intent.  Use null to not modify the original Intent.
+     * @param onFinished The object to call back on when the send has
+     * completed, or null for no callback.
+     * @param handler Handler identifying the thread on which the callback
+     * should happen.  If null, the callback will happen from the thread
+     * pool of the process.
+     * @param requiredPermission Name of permission that a recipient of the PendingIntent
+     * is required to hold.  This is only valid for broadcast intents, and
+     * corresponds to the permission argument in
+     * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+     * If null, no permission is required.
+     * @param options Additional options the caller would like to provide to modify the sending
+     * behavior.  May be built from an {@link ActivityOptions} to apply to an activity start.
+     *
+     * @throws SendIntentException Throws CanceledIntentException if the IntentSender
+     * is no longer allowing more intents to be sent through it.
+     * @hide
+     */
+    public void sendIntent(Context context, int code, Intent intent,
+            OnFinished onFinished, Handler handler, String requiredPermission,
+            @Nullable Bundle options)
+            throws SendIntentException {
         try {
             String resolvedType = intent != null ?
                     intent.resolveTypeIfNeeded(context.getContentResolver())
@@ -203,7 +240,7 @@
                     onFinished != null
                             ? new FinishedDispatcher(this, onFinished, handler)
                             : null,
-                    requiredPermission, null);
+                    requiredPermission, options);
             if (res < 0) {
                 throw new SendIntentException();
             }
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 68b0631..db72e29 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1103,6 +1103,17 @@
     public static final long ALWAYS_SANDBOX_DISPLAY_APIS = 185004937L; // buganizer id
 
     /**
+     * This change id excludes the packages it is applied to from ignoreOrientationRequest behaviour
+     * that can be enabled by the device manufacturers for the com.android.server.wm.DisplayArea
+     * or for the whole display.
+     * @hide
+     */
+    @ChangeId
+    @Overridable
+    @Disabled
+    public static final long OVERRIDE_RESPECT_REQUESTED_ORIENTATION = 236283604L; // buganizer id
+
+    /**
      * This change id excludes the packages it is applied to from the camera compat force rotation
      * treatment. See com.android.server.wm.DisplayRotationCompatPolicy for context.
      * @hide
@@ -1285,6 +1296,18 @@
     public static final long OVERRIDE_ANY_ORIENTATION = 265464455L;
 
     /**
+     * When enabled, activates OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE,
+     * OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR and OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT
+     * only when an app is connected to the camera. See
+     * com.android.server.wm.DisplayRotationCompatPolicy for more context.
+     * @hide
+     */
+    @ChangeId
+    @Disabled
+    @Overridable
+    public static final long OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA = 265456536L;
+
+    /**
      * This override fixes display orientation to landscape natural orientation when a task is
      * fullscreen. While display rotation is fixed to landscape, the orientation requested by the
      * activity will be still respected by bounds resolution logic. For instance, if an activity
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 94c5e25..ffe73d6 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -2576,7 +2576,7 @@
     /**
      * Returns whether attributions provided by the application are meant to be user-visible.
      * Defaults to false if application info is retrieved without
-     * {@link PackageManager#GET_ATTRIBUTIONS}.
+     * {@link PackageManager#GET_ATTRIBUTIONS_LONG}.
      */
     public boolean areAttributionsUserVisible() {
         return (privateFlagsExt & PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE) != 0;
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index 115d4b0..e3016a4 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -65,6 +65,8 @@
 
     void bypassNextAllowedApexUpdateCheck(boolean value);
 
+    void disableVerificationForUid(int uid);
+
     void setAllowUnlimitedSilentUpdates(String installerPackageName);
     void setSilentUpdatesThrottleTime(long throttleTimeInSeconds);
     void checkInstallConstraints(String installerPackageName, in List<String> packageNames,
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 9c1318e..081f263 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -69,4 +69,5 @@
 
     ParcelFileDescriptor getAppMetadataFd();
     ParcelFileDescriptor openWriteAppMetadata();
+    void removeAppMetadata();
 }
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 4259600..a89d17b 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -221,7 +221,7 @@
     /**
      * Array of all {@link android.R.styleable#AndroidManifestAttribution
      * &lt;attribution&gt;} tags included under &lt;manifest&gt;, or null if there were none. This
-     * is only filled if the flag {@link PackageManager#GET_ATTRIBUTIONS} was set.
+     * is only filled if the flag {@link PackageManager#GET_ATTRIBUTIONS_LONG} was set.
      */
     @SuppressWarnings({"ArrayReturn", "NullableCollection"})
     public @Nullable Attribution[] attributions;
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 0b74dd1..c2b047a 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1060,7 +1060,7 @@
                             PackageInstaller.EXTRA_INSTALL_CONSTRAINTS_RESULT,
                             InstallConstraintsResult.class);
                     try {
-                        if (result.isAllConstraintsSatisfied()) {
+                        if (result.areAllConstraintsSatisfied()) {
                             session.commit(statusReceiver, false);
                         } else {
                             // timeout
@@ -1955,17 +1955,23 @@
 
         /**
          * Optionally set the app metadata. The size of this data cannot exceed the maximum allowed.
-         * If no data is provided, then any existing app metadata from the previous install will be
-         * removed for the package.
+         * Any existing data from the previous install will not be retained even if no data is set
+         * for the current install session. Setting data to null or an empty PersistableBundle will
+         * remove any metadata that has previously been set in the same session.
          *
-         * @param data a PersistableBundle containing the app metadata. If this is set to null then
-         *     any existing app metadata will be removed.
+         * @param data a PersistableBundle containing the app metadata.
          * @throws IOException if writing the data fails.
          */
         public void setAppMetadata(@Nullable PersistableBundle data) throws IOException {
-            if (data == null) {
+            if (data == null || data.isEmpty()) {
+                try {
+                    mSession.removeAppMetadata();
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
                 return;
             }
+            Objects.requireNonNull(data);
             try (OutputStream outputStream = openWriteAppMetadata()) {
                 data.writeToStream(outputStream);
             }
@@ -2042,7 +2048,7 @@
      */
     @SystemApi
     @NonNull
-    public InstallInfo getInstallInfo(@NonNull File file, int flags)
+    public InstallInfo readInstallInfo(@NonNull File file, int flags)
             throws PackageParsingException {
         final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
         final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
@@ -2616,8 +2622,17 @@
             installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
         }
 
-        /** {@hide} */
-        @SystemApi
+        /**
+         * Requests that the system not kill any of the package's running
+         * processes as part of a {@link SessionParams#MODE_INHERIT_EXISTING}
+         * session in which splits being added. By default, all installs will
+         * result in the package's running processes being killed before the
+         * install completes.
+         *
+         * @param dontKillApp set to {@code true} to request that the processes
+         *                    belonging to the package not be killed as part of
+         *                    this install.
+         */
         public void setDontKillApp(boolean dontKillApp) {
             if (dontKillApp) {
                 installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
@@ -3456,10 +3471,7 @@
 
         /**
          * Get the value set in {@link SessionParams#setDontKillApp(boolean)}.
-         *
-         * @hide
          */
-        @SystemApi
         public boolean getDontKillApp() {
             return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0;
         }
@@ -3740,7 +3752,7 @@
         /**
          * Returns whether this session has requested user pre-approval.
          */
-        public @NonNull boolean getIsPreApprovalRequested() {
+        public boolean isPreApprovalRequested() {
             return isPreapprovalRequested;
         }
 
@@ -4110,12 +4122,20 @@
      * The callback result of {@link #checkInstallConstraints(List, InstallConstraints, Executor, Consumer)}.
      */
     @DataClass(genParcelable = true, genHiddenConstructor = true)
+    @DataClass.Suppress("isAllConstraintsSatisfied")
     public static final class InstallConstraintsResult implements Parcelable {
         /**
          * True if all constraints are satisfied.
          */
         private boolean mAllConstraintsSatisfied;
 
+        /**
+         * True if all constraints are satisfied.
+         */
+        public boolean areAllConstraintsSatisfied() {
+            return mAllConstraintsSatisfied;
+        }
+
 
 
         // Code below generated by codegen v1.0.23.
@@ -4146,14 +4166,6 @@
             // onConstructed(); // You can define this method to get a callback
         }
 
-        /**
-         * True if all constraints are satisfied.
-         */
-        @DataClass.Generated.Member
-        public boolean isAllConstraintsSatisfied() {
-            return mAllConstraintsSatisfied;
-        }
-
         @Override
         @DataClass.Generated.Member
         public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -4199,10 +4211,10 @@
         };
 
         @DataClass.Generated(
-                time = 1668650523745L,
+                time = 1675135664641L,
                 codegenVersion = "1.0.23",
                 sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
-                inputSignatures = "private  boolean mAllConstraintsSatisfied\nclass InstallConstraintsResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true)")
+                inputSignatures = "private  boolean mAllConstraintsSatisfied\npublic  boolean areAllConstraintsSatisfied()\nclass InstallConstraintsResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true)")
         @Deprecated
         private void __metadata() {}
 
@@ -4241,41 +4253,41 @@
          */
         @NonNull
         public static final InstallConstraints GENTLE_UPDATE =
-                new Builder().requireAppNotInteracting().build();
+                new Builder().setAppNotInteractingRequired().build();
 
-        private final boolean mRequireDeviceIdle;
-        private final boolean mRequireAppNotForeground;
-        private final boolean mRequireAppNotInteracting;
-        private final boolean mRequireAppNotTopVisible;
-        private final boolean mRequireNotInCall;
+        private final boolean mDeviceIdleRequired;
+        private final boolean mAppNotForegroundRequired;
+        private final boolean mAppNotInteractingRequired;
+        private final boolean mAppNotTopVisibleRequired;
+        private final boolean mNotInCallRequired;
 
         /**
          * Builder class for constructing {@link InstallConstraints}.
          */
         public static final class Builder {
-            private boolean mRequireDeviceIdle;
-            private boolean mRequireAppNotForeground;
-            private boolean mRequireAppNotInteracting;
-            private boolean mRequireAppNotTopVisible;
-            private boolean mRequireNotInCall;
+            private boolean mDeviceIdleRequired;
+            private boolean mAppNotForegroundRequired;
+            private boolean mAppNotInteractingRequired;
+            private boolean mAppNotTopVisibleRequired;
+            private boolean mNotInCallRequired;
 
             /**
              * This constraint requires the device is idle.
              */
-            @SuppressLint("BuilderSetStyle")
+            @SuppressLint("MissingGetterMatchingBuilder")
             @NonNull
-            public Builder requireDeviceIdle() {
-                mRequireDeviceIdle = true;
+            public Builder setDeviceIdleRequired() {
+                mDeviceIdleRequired = true;
                 return this;
             }
 
             /**
              * This constraint requires the app in question is not in the foreground.
              */
-            @SuppressLint("BuilderSetStyle")
+            @SuppressLint("MissingGetterMatchingBuilder")
             @NonNull
-            public Builder requireAppNotForeground() {
-                mRequireAppNotForeground = true;
+            public Builder setAppNotForegroundRequired() {
+                mAppNotForegroundRequired = true;
                 return this;
             }
 
@@ -4288,10 +4300,10 @@
              *     <li>being visible to the user</li>
              * </ul>
              */
-            @SuppressLint("BuilderSetStyle")
+            @SuppressLint("MissingGetterMatchingBuilder")
             @NonNull
-            public Builder requireAppNotInteracting() {
-                mRequireAppNotInteracting = true;
+            public Builder setAppNotInteractingRequired() {
+                mAppNotInteractingRequired = true;
                 return this;
             }
 
@@ -4300,25 +4312,27 @@
              * A top-visible app is showing UI at the top of the screen that the user is
              * interacting with.
              *
-             * Note this constraint is a subset of {@link #requireAppNotForeground()}
+             * Note this constraint is a subset of {@link #setAppNotForegroundRequired()}
              * because a top-visible app is also a foreground app. This is also a subset
-             * of {@link #requireAppNotInteracting()} because a top-visible app is interacting
+             * of {@link #setAppNotInteractingRequired()} because a top-visible app is interacting
              * with the user.
+             *
+             * @see ActivityManager.RunningAppProcessInfo#IMPORTANCE_FOREGROUND
              */
-            @SuppressLint("BuilderSetStyle")
+            @SuppressLint("MissingGetterMatchingBuilder")
             @NonNull
-            public Builder requireAppNotTopVisible() {
-                mRequireAppNotTopVisible = true;
+            public Builder setAppNotTopVisibleRequired() {
+                mAppNotTopVisibleRequired = true;
                 return this;
             }
 
             /**
              * This constraint requires there is no ongoing call in the device.
              */
-            @SuppressLint("BuilderSetStyle")
+            @SuppressLint("MissingGetterMatchingBuilder")
             @NonNull
-            public Builder requireNotInCall() {
-                mRequireNotInCall = true;
+            public Builder setNotInCallRequired() {
+                mNotInCallRequired = true;
                 return this;
             }
 
@@ -4327,8 +4341,8 @@
              */
             @NonNull
             public InstallConstraints build() {
-                return new InstallConstraints(mRequireDeviceIdle, mRequireAppNotForeground,
-                        mRequireAppNotInteracting, mRequireAppNotTopVisible, mRequireNotInCall);
+                return new InstallConstraints(mDeviceIdleRequired, mAppNotForegroundRequired,
+                        mAppNotInteractingRequired, mAppNotTopVisibleRequired, mNotInCallRequired);
             }
         }
 
@@ -4354,43 +4368,43 @@
          */
         @DataClass.Generated.Member
         public InstallConstraints(
-                boolean requireDeviceIdle,
-                boolean requireAppNotForeground,
-                boolean requireAppNotInteracting,
-                boolean requireAppNotTopVisible,
-                boolean requireNotInCall) {
-            this.mRequireDeviceIdle = requireDeviceIdle;
-            this.mRequireAppNotForeground = requireAppNotForeground;
-            this.mRequireAppNotInteracting = requireAppNotInteracting;
-            this.mRequireAppNotTopVisible = requireAppNotTopVisible;
-            this.mRequireNotInCall = requireNotInCall;
+                boolean deviceIdleRequired,
+                boolean appNotForegroundRequired,
+                boolean appNotInteractingRequired,
+                boolean appNotTopVisibleRequired,
+                boolean notInCallRequired) {
+            this.mDeviceIdleRequired = deviceIdleRequired;
+            this.mAppNotForegroundRequired = appNotForegroundRequired;
+            this.mAppNotInteractingRequired = appNotInteractingRequired;
+            this.mAppNotTopVisibleRequired = appNotTopVisibleRequired;
+            this.mNotInCallRequired = notInCallRequired;
 
             // onConstructed(); // You can define this method to get a callback
         }
 
         @DataClass.Generated.Member
-        public boolean isRequireDeviceIdle() {
-            return mRequireDeviceIdle;
+        public boolean isDeviceIdleRequired() {
+            return mDeviceIdleRequired;
         }
 
         @DataClass.Generated.Member
-        public boolean isRequireAppNotForeground() {
-            return mRequireAppNotForeground;
+        public boolean isAppNotForegroundRequired() {
+            return mAppNotForegroundRequired;
         }
 
         @DataClass.Generated.Member
-        public boolean isRequireAppNotInteracting() {
-            return mRequireAppNotInteracting;
+        public boolean isAppNotInteractingRequired() {
+            return mAppNotInteractingRequired;
         }
 
         @DataClass.Generated.Member
-        public boolean isRequireAppNotTopVisible() {
-            return mRequireAppNotTopVisible;
+        public boolean isAppNotTopVisibleRequired() {
+            return mAppNotTopVisibleRequired;
         }
 
         @DataClass.Generated.Member
-        public boolean isRequireNotInCall() {
-            return mRequireNotInCall;
+        public boolean isNotInCallRequired() {
+            return mNotInCallRequired;
         }
 
         @Override
@@ -4406,11 +4420,11 @@
             InstallConstraints that = (InstallConstraints) o;
             //noinspection PointlessBooleanExpression
             return true
-                    && mRequireDeviceIdle == that.mRequireDeviceIdle
-                    && mRequireAppNotForeground == that.mRequireAppNotForeground
-                    && mRequireAppNotInteracting == that.mRequireAppNotInteracting
-                    && mRequireAppNotTopVisible == that.mRequireAppNotTopVisible
-                    && mRequireNotInCall == that.mRequireNotInCall;
+                    && mDeviceIdleRequired == that.mDeviceIdleRequired
+                    && mAppNotForegroundRequired == that.mAppNotForegroundRequired
+                    && mAppNotInteractingRequired == that.mAppNotInteractingRequired
+                    && mAppNotTopVisibleRequired == that.mAppNotTopVisibleRequired
+                    && mNotInCallRequired == that.mNotInCallRequired;
         }
 
         @Override
@@ -4420,11 +4434,11 @@
             // int fieldNameHashCode() { ... }
 
             int _hash = 1;
-            _hash = 31 * _hash + Boolean.hashCode(mRequireDeviceIdle);
-            _hash = 31 * _hash + Boolean.hashCode(mRequireAppNotForeground);
-            _hash = 31 * _hash + Boolean.hashCode(mRequireAppNotInteracting);
-            _hash = 31 * _hash + Boolean.hashCode(mRequireAppNotTopVisible);
-            _hash = 31 * _hash + Boolean.hashCode(mRequireNotInCall);
+            _hash = 31 * _hash + Boolean.hashCode(mDeviceIdleRequired);
+            _hash = 31 * _hash + Boolean.hashCode(mAppNotForegroundRequired);
+            _hash = 31 * _hash + Boolean.hashCode(mAppNotInteractingRequired);
+            _hash = 31 * _hash + Boolean.hashCode(mAppNotTopVisibleRequired);
+            _hash = 31 * _hash + Boolean.hashCode(mNotInCallRequired);
             return _hash;
         }
 
@@ -4435,11 +4449,11 @@
             // void parcelFieldName(Parcel dest, int flags) { ... }
 
             byte flg = 0;
-            if (mRequireDeviceIdle) flg |= 0x1;
-            if (mRequireAppNotForeground) flg |= 0x2;
-            if (mRequireAppNotInteracting) flg |= 0x4;
-            if (mRequireAppNotTopVisible) flg |= 0x8;
-            if (mRequireNotInCall) flg |= 0x10;
+            if (mDeviceIdleRequired) flg |= 0x1;
+            if (mAppNotForegroundRequired) flg |= 0x2;
+            if (mAppNotInteractingRequired) flg |= 0x4;
+            if (mAppNotTopVisibleRequired) flg |= 0x8;
+            if (mNotInCallRequired) flg |= 0x10;
             dest.writeByte(flg);
         }
 
@@ -4455,17 +4469,17 @@
             // static FieldType unparcelFieldName(Parcel in) { ... }
 
             byte flg = in.readByte();
-            boolean requireDeviceIdle = (flg & 0x1) != 0;
-            boolean requireAppNotForeground = (flg & 0x2) != 0;
-            boolean requireAppNotInteracting = (flg & 0x4) != 0;
-            boolean requireAppNotTopVisible = (flg & 0x8) != 0;
-            boolean requireNotInCall = (flg & 0x10) != 0;
+            boolean deviceIdleRequired = (flg & 0x1) != 0;
+            boolean appNotForegroundRequired = (flg & 0x2) != 0;
+            boolean appNotInteractingRequired = (flg & 0x4) != 0;
+            boolean appNotTopVisibleRequired = (flg & 0x8) != 0;
+            boolean notInCallRequired = (flg & 0x10) != 0;
 
-            this.mRequireDeviceIdle = requireDeviceIdle;
-            this.mRequireAppNotForeground = requireAppNotForeground;
-            this.mRequireAppNotInteracting = requireAppNotInteracting;
-            this.mRequireAppNotTopVisible = requireAppNotTopVisible;
-            this.mRequireNotInCall = requireNotInCall;
+            this.mDeviceIdleRequired = deviceIdleRequired;
+            this.mAppNotForegroundRequired = appNotForegroundRequired;
+            this.mAppNotInteractingRequired = appNotInteractingRequired;
+            this.mAppNotTopVisibleRequired = appNotTopVisibleRequired;
+            this.mNotInCallRequired = notInCallRequired;
 
             // onConstructed(); // You can define this method to get a callback
         }
@@ -4485,10 +4499,10 @@
         };
 
         @DataClass.Generated(
-                time = 1670207178734L,
+                time = 1675135664653L,
                 codegenVersion = "1.0.23",
                 sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
-                inputSignatures = "public static final @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE\nprivate final  boolean mRequireDeviceIdle\nprivate final  boolean mRequireAppNotForeground\nprivate final  boolean mRequireAppNotInteracting\nprivate final  boolean mRequireAppNotTopVisible\nprivate final  boolean mRequireNotInCall\nclass InstallConstraints extends java.lang.Object implements [android.os.Parcelable]\nprivate  boolean mRequireDeviceIdle\nprivate  boolean mRequireAppNotForeground\nprivate  boolean mRequireAppNotInteracting\nprivate  boolean mRequireAppNotTopVisible\nprivate  boolean mRequireNotInCall\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireDeviceIdle()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotForeground()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotInteracting()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireAppNotTopVisible()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder requireNotInCall()\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genEqualsHashCode=true)")
+                inputSignatures = "public static final @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE\nprivate final  boolean mDeviceIdleRequired\nprivate final  boolean mAppNotForegroundRequired\nprivate final  boolean mAppNotInteractingRequired\nprivate final  boolean mAppNotTopVisibleRequired\nprivate final  boolean mNotInCallRequired\nclass InstallConstraints extends java.lang.Object implements [android.os.Parcelable]\nprivate  boolean mDeviceIdleRequired\nprivate  boolean mAppNotForegroundRequired\nprivate  boolean mAppNotInteractingRequired\nprivate  boolean mAppNotTopVisibleRequired\nprivate  boolean mNotInCallRequired\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setDeviceIdleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotForegroundRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotInteractingRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotTopVisibleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setNotInCallRequired()\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genEqualsHashCode=true)")
         @Deprecated
         private void __metadata() {}
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index dc8c0ab..3060b7f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -151,6 +151,29 @@
             "android.media.PROPERTY_MEDIA_CAPABILITIES";
 
     /**
+     * &lt;application&gt; level {@link android.content.pm.PackageManager.Property} tag
+     * specifying the XML resource ID containing the declaration of the self-certified network
+     * capabilities used by the application.
+     *
+     * <p> Starting from Android 14, usage of some network capabilities in
+     * {@link android.net.ConnectivityManager#requestNetwork} require the application to
+     * declare its usage of that particular capability in this resource. Only some capabilities
+     * require a declaration. Please look up the specific capability you want to use in
+     * {@link android.net.NetworkCapabilities} to see if it needs declaration in this property.
+     *
+     * For example:
+     * &lt;application&gt;
+     *   &lt;property android:name="android.net.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES"
+     *     android:resource="@xml/self_certified_network_capabilities"&gt;
+     * &lt;application&gt;
+     *
+     * <p> The detail format of self_certified_network_capabilities.xml is described in
+     * {@link android.net.NetworkRequest}
+     */
+    public static final String PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES =
+            "android.net.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES";
+
+    /**
      * Application level property that an app can specify to opt-out from having private data
      * directories both on the internal and external storages.
      *
@@ -717,7 +740,7 @@
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
             MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS,
-            GET_ATTRIBUTIONS,
+            GET_ATTRIBUTIONS_LONG,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface PackageInfoFlagsBits {}
@@ -1127,8 +1150,9 @@
     public static final int MATCH_CLONE_PROFILE = 0x20000000;
 
     /**
-     * {@link PackageInfo} flag: return all attributions declared in the package manifest
+     * @deprecated Use {@link #GET_ATTRIBUTIONS_LONG} to avoid unintended sign extension.
      */
+    @Deprecated
     public static final int GET_ATTRIBUTIONS = 0x80000000;
 
     /** @hide */
@@ -1153,6 +1177,11 @@
     public static final int MATCH_APEX = 0x40000000;
 
     /**
+     * {@link PackageInfo} flag: return all attributions declared in the package manifest
+     */
+    public static final long GET_ATTRIBUTIONS_LONG = 0x80000000L;
+
+    /**
      * Flag for {@link #addCrossProfileIntentFilter}: if this flag is set: when
      * resolving an intent that matches the {@code CrossProfileIntentFilter},
      * the current profile will be skipped. Only activities in the target user
@@ -5827,7 +5856,7 @@
     /**
      * Returns the app metadata for a package.
      *
-     * @param packageName
+     * @param packageName The package name for which to get the app metadata.
      * @return A PersistableBundle containing the app metadata that was provided by the installer.
      *         In the case where a package does not have any metadata, an empty PersistableBundle is
      *         returned.
@@ -10923,10 +10952,13 @@
 
     /**
      * Attempt to relinquish the update ownership of the given package. Only the current
-     * update owner of the given package can use this API or a SecurityException will be
-     * thrown.
+     * update owner of the given package can use this API.
      *
      * @param targetPackage The installed package whose update owner will be changed.
+     * @throws IllegalArgumentException if the given package is invalid.
+     * @throws SecurityException if you are not the current update owner of the given package.
+     *
+     * @see PackageInstaller.SessionParams#setRequestUpdateOwnership
      */
     public void relinquishUpdateOwnership(@NonNull String targetPackage) {
         throw new UnsupportedOperationException(
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index f3209f9..49d21da 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -401,8 +401,9 @@
      *
      *         <p>If the service isn't stopped within the timeout,
      *         {@link android.app.Service#onTimeout(int)} will be called.
-     *         If the service is still not stopped after the callback,
-     *         the app will be declared an ANR.
+     *
+     *         <p>If the service is still not stopped after the callback,
+     *         the app will be declared an ANR after a short grace period of several seconds.
      *
      *     <li>
      *         A foreground service of this type cannot be made "sticky"
@@ -419,6 +420,17 @@
      *         </a>
      * </ul>
      *
+     * <p>Note, even though
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
+     * was added
+     * on Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+     * it can be also used on
+     * on prior android versions (just like other new foreground service types can be used).
+     * However, because {@link android.app.Service#onTimeout(int)} did not exist on prior versions,
+     * it will never called on such versions.
+     * Because of this, developers must make sure to stop the foreground service even if
+     * {@link android.app.Service#onTimeout(int)} is not called on such versions.
+     *
      * @see android.app.Service#onTimeout(int)
      */
     public static final int FOREGROUND_SERVICE_TYPE_SHORT_SERVICE = 1 << 11;
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 335975b..1c8276c 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1107,7 +1107,7 @@
         } else {
             sb.append("?mcc");
         }
-        if (mnc != 0) {
+        if (mnc != MNC_ZERO) {
             sb.append(mnc);
             sb.append("mnc");
         } else {
@@ -1998,7 +1998,7 @@
             changed |= ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT;
         }
 
-        if (!publicOnly && mGrammaticalGender != delta.mGrammaticalGender) {
+        if (mGrammaticalGender != delta.mGrammaticalGender) {
             changed |= ActivityInfo.CONFIG_GRAMMATICAL_GENDER;
         }
         return changed;
diff --git a/core/java/android/credentials/CreateCredentialRequest.java b/core/java/android/credentials/CreateCredentialRequest.java
index 26f8831..aec88b9 100644
--- a/core/java/android/credentials/CreateCredentialRequest.java
+++ b/core/java/android/credentials/CreateCredentialRequest.java
@@ -33,6 +33,18 @@
 public final class CreateCredentialRequest implements Parcelable {
 
     /**
+     * True/false value to determine if the calling app info should be
+     * sent to the provider at every stage.
+     *
+     * Developers must set this to false if they wish to remove the
+     * {@link android.service.credentials.CallingAppInfo} from the query phase request
+     * that providers receive. Note, that providers will still receive the app info in
+     * the final phase after the user has selected the entry.
+     */
+    private final boolean mAlwaysSendAppInfoToProvider;
+
+
+    /**
      * The requested credential type.
      */
     @NonNull
@@ -103,12 +115,21 @@
         return mIsSystemProviderRequired;
     }
 
+    /**
+     * Return true/false value to determine if the calling app info should always be sent
+     * to providers (if true), or removed from the query phase (if false).
+     */
+    public boolean alwaysSendAppInfoToProvider() {
+        return mAlwaysSendAppInfoToProvider;
+    }
+
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString8(mType);
         dest.writeBundle(mCredentialData);
         dest.writeBundle(mCandidateQueryData);
         dest.writeBoolean(mIsSystemProviderRequired);
+        dest.writeBoolean(mAlwaysSendAppInfoToProvider);
     }
 
     @Override
@@ -123,6 +144,8 @@
                 + ", credentialData=" + mCredentialData
                 + ", candidateQueryData=" + mCandidateQueryData
                 + ", isSystemProviderRequired=" + mIsSystemProviderRequired
+                + ", alwaysSendAppInfoToProvider="
+                + mAlwaysSendAppInfoToProvider
                 + "}";
     }
 
@@ -135,6 +158,39 @@
      *                           during the initial creation candidate query stage
      * @param isSystemProviderRequired whether the request must only be fulfilled by a system
      *                                provider
+     * @param alwaysSendAppInfoToProvider whether the
+     * {@link android.service.credentials.CallingAppInfo} should be propagated to the provider
+     *                                    at every stage of the request. If set to false,
+     *                                    the calling app info will be removed from
+     *                                    the query phase, and will only be sent along
+     *                                    with the final request, after the user has selected
+     *                                    an entry on the UI.
+     *
+     * @throws IllegalArgumentException If type is empty.
+     */
+    public CreateCredentialRequest(
+            @NonNull String type,
+            @NonNull Bundle credentialData,
+            @NonNull Bundle candidateQueryData,
+            boolean isSystemProviderRequired,
+            boolean alwaysSendAppInfoToProvider) {
+        mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
+        mCredentialData = requireNonNull(credentialData, "credentialData must not be null");
+        mCandidateQueryData = requireNonNull(candidateQueryData,
+                "candidateQueryData must not be null");
+        mIsSystemProviderRequired = isSystemProviderRequired;
+        mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
+    }
+
+    /**
+     * Constructs a {@link CreateCredentialRequest}.
+     *
+     * @param type the requested credential type
+     * @param credentialData the full credential creation request data
+     * @param candidateQueryData the partial request data that will be sent to the provider
+     *                           during the initial creation candidate query stage
+     * @param isSystemProviderRequired whether the request must only be fulfilled by a system
+     *                                provider
      *
      * @throws IllegalArgumentException If type is empty.
      */
@@ -143,11 +199,8 @@
             @NonNull Bundle credentialData,
             @NonNull Bundle candidateQueryData,
             boolean isSystemProviderRequired) {
-        mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
-        mCredentialData = requireNonNull(credentialData, "credentialData must not be null");
-        mCandidateQueryData = requireNonNull(candidateQueryData,
-                "candidateQueryData must not be null");
-        mIsSystemProviderRequired = isSystemProviderRequired;
+        this(type, credentialData, candidateQueryData, isSystemProviderRequired,
+                /*mAlwaysSendAppInfoToProvider=*/true);
     }
 
     private CreateCredentialRequest(@NonNull Parcel in) {
@@ -155,6 +208,7 @@
         Bundle credentialData = in.readBundle();
         Bundle candidateQueryData = in.readBundle();
         boolean isSystemProviderRequired = in.readBoolean();
+        boolean alwaysSendAppInfoToProvider = in.readBoolean();
 
         mType = type;
         AnnotationValidations.validate(NonNull.class, null, mType);
@@ -163,6 +217,7 @@
         mCandidateQueryData = candidateQueryData;
         AnnotationValidations.validate(NonNull.class, null, mCandidateQueryData);
         mIsSystemProviderRequired = isSystemProviderRequired;
+        mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
     }
 
     public static final @NonNull Parcelable.Creator<CreateCredentialRequest> CREATOR =
diff --git a/core/java/android/credentials/CredentialDescription.java b/core/java/android/credentials/CredentialDescription.java
index c67d37e..f9db5e8 100644
--- a/core/java/android/credentials/CredentialDescription.java
+++ b/core/java/android/credentials/CredentialDescription.java
@@ -48,7 +48,7 @@
     private final String mFlattenedRequestString;
 
     /**
-     * The entry to be used in the UI.
+     * The credential entries to be used in the UI.
      */
     @NonNull
     private final List<CredentialEntry> mCredentialEntries;
@@ -128,16 +128,25 @@
         dest.writeTypedList(mCredentialEntries, flags);
     }
 
+    /**
+     * Returns the type of the Credential described.
+     */
     @NonNull
     public String getType() {
         return mType;
     }
 
+    /**
+     * Returns the flattened JSON string that will be matched with requests.
+     */
     @NonNull
     public String getFlattenedRequestString() {
         return mFlattenedRequestString;
     }
 
+    /**
+     * Returns the credential entries to be used in the UI.
+     */
     @NonNull
     public List<CredentialEntry> getCredentialEntries() {
         return mCredentialEntries;
@@ -151,6 +160,7 @@
     @Override
     public boolean equals(Object obj) {
         return Objects.equals(mType, ((CredentialDescription) obj).getType())
-                && Objects.equals(mFlattenedRequestString, ((CredentialDescription) obj).getType());
+                && Objects.equals(mFlattenedRequestString, ((CredentialDescription) obj)
+                .getFlattenedRequestString());
     }
 }
diff --git a/core/java/android/credentials/CredentialManager.java b/core/java/android/credentials/CredentialManager.java
index 1db14a3..8b43a21 100644
--- a/core/java/android/credentials/CredentialManager.java
+++ b/core/java/android/credentials/CredentialManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SystemService;
 import android.app.Activity;
 import android.app.PendingIntent;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.IntentSender;
 import android.os.CancellationSignal;
@@ -222,7 +223,7 @@
      * @param callback the callback invoked when the request succeeds or fails
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public void listEnabledProviders(
             @Nullable CancellationSignal cancellationSignal,
             @CallbackExecutor @NonNull Executor executor,
@@ -280,13 +281,32 @@
     }
 
     /**
+     * Returns {@code true} if the calling application provides a CredentialProviderService that is
+     * enabled for the current user, or {@code false} otherwise. CredentialProviderServices are
+     * enabled on a per-service basis so the individual component name of the service should be
+     * passed in here.
+     *
+     * @param componentName the component name to check is enabled
+     */
+    public boolean isEnabledCredentialProviderService(@NonNull ComponentName componentName) {
+        requireNonNull(componentName, "componentName must not be null");
+
+        try {
+            return mService.isEnabledCredentialProviderService(
+                    componentName, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns whether the service is enabled.
      *
      * @hide
      */
     public static boolean isServiceEnabled(Context context) {
         if (context == null) {
-	    return false;
+            return false;
         }
         CredentialManager credentialManager =
                 (CredentialManager) context.getSystemService(Context.CREDENTIAL_SERVICE);
@@ -298,8 +318,7 @@
 
     private boolean isServiceEnabled() {
         return DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_MANAGER,
-                true);
+                DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_MANAGER, true);
     }
 
     /**
@@ -313,22 +332,19 @@
     }
 
     /**
-     * Registers a {@link CredentialDescription} for an actively provisioned {@link Credential}
-     * a CredentialProvider has. This registry will then be used to determine where to
-     * fetch the requested {@link Credential} from. Not all credential types will be supported.
-     * The distinction will be made by the JetPack layer. For the types that are supported,
-     * JetPack will add a new key-value pair into {@link GetCredentialRequest}. These will not
-     * be persistent on the device. The Credential Providers will need to call this API again
-     * upon device reboot.
+     * Registers a {@link CredentialDescription} for an actively provisioned {@link Credential} a
+     * CredentialProvider has. This registry will then be used to determine where to fetch the
+     * requested {@link Credential} from. Not all credential types will be supported. The
+     * distinction will be made by the JetPack layer. For the types that are supported, JetPack will
+     * add a new key-value pair into {@link GetCredentialRequest}. These will not be persistent on
+     * the device. The Credential Providers will need to call this API again upon device reboot.
      *
      * @param request the request data
-     *
-     * @throws {@link  UnsupportedOperationException} if the feature has not been enabled.
-     * @throws {@link  com.android.server.credentials.NonCredentialProviderCallerException}
-     * if the calling package name is not also listed as a Credential Provider.
-     * @throws {@link  IllegalArgumentException} if the calling Credential Provider can not handle
-     * one or more of the Credential Types that are sent for registration.
-     *
+     * @throws {@link UnsupportedOperationException} if the feature has not been enabled.
+     * @throws {@link com.android.server.credentials.NonCredentialProviderCallerException} if the
+     *     calling package name is not also listed as a Credential Provider.
+     * @throws {@link IllegalArgumentException} if the calling Credential Provider can not handle
+     *     one or more of the Credential Types that are sent for registration.
      */
     public void registerCredentialDescription(
             @NonNull RegisterCredentialDescriptionRequest request) {
@@ -346,16 +362,12 @@
         }
     }
 
-
     /**
-     *  Unregisters a {@link CredentialDescription} for an actively provisioned {@link Credential}
+     * Unregisters a {@link CredentialDescription} for an actively provisioned {@link Credential}
      * that has been registered previously.
      *
-     *
      * @param request the request data
-     *
-     * @throws {@link  UnsupportedOperationException} if the feature has not been enabled.
-     *
+     * @throws {@link UnsupportedOperationException} if the feature has not been enabled.
      */
     public void unregisterCredentialDescription(
             @NonNull UnregisterCredentialDescriptionRequest request) {
@@ -371,7 +383,6 @@
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
-
     }
 
     private static class GetCredentialTransport extends IGetCredentialCallback.Stub {
diff --git a/core/java/android/credentials/GetCredentialOption.java b/core/java/android/credentials/CredentialOption.java
similarity index 79%
rename from core/java/android/credentials/GetCredentialOption.java
rename to core/java/android/credentials/CredentialOption.java
index f2895c7..9a3b46d 100644
--- a/core/java/android/credentials/GetCredentialOption.java
+++ b/core/java/android/credentials/CredentialOption.java
@@ -27,9 +27,11 @@
 import com.android.internal.util.Preconditions;
 
 /**
- * A specific type of credential request.
+ * Information about a specific type of credential to be requested during a {@link
+ * CredentialManager#getCredential(GetCredentialRequest, Activity, CancellationSignal, Executor,
+ * OutcomeReceiver)} operation.
  */
-public final class GetCredentialOption implements Parcelable {
+public final class CredentialOption implements Parcelable {
 
     /**
      * Bundle key to the flattened version of the JSON request string. Framework will use this key
@@ -118,7 +120,7 @@
 
     @Override
     public String toString() {
-        return "GetCredentialOption {"
+        return "CredentialOption {"
                 + "type=" + mType
                 + ", requestData=" + mCredentialRetrievalData
                 + ", candidateQueryData=" + mCandidateQueryData
@@ -127,17 +129,17 @@
     }
 
     /**
-     * Constructs a {@link GetCredentialOption}.
+     * Constructs a {@link CredentialOption}.
      *
-     * @param type                    the requested credential type
-     * @param credentialRetrievalData the request data
-     * @param candidateQueryData      the partial request data that will be sent to the provider
-     *                                during the initial credential candidate query stage
-     * @param isSystemProviderRequired   whether the request must only be fulfilled by a system
-     *                                provider
+     * @param type                     the requested credential type
+     * @param credentialRetrievalData  the request data
+     * @param candidateQueryData       the partial request data that will be sent to the provider
+     *                                 during the initial credential candidate query stage
+     * @param isSystemProviderRequired whether the request must only be fulfilled by a system
+     *                                 provider
      * @throws IllegalArgumentException If type is empty.
      */
-    public GetCredentialOption(
+    public CredentialOption(
             @NonNull String type,
             @NonNull Bundle credentialRetrievalData,
             @NonNull Bundle candidateQueryData,
@@ -150,7 +152,7 @@
         mIsSystemProviderRequired = isSystemProviderRequired;
     }
 
-    private GetCredentialOption(@NonNull Parcel in) {
+    private CredentialOption(@NonNull Parcel in) {
         String type = in.readString8();
         Bundle data = in.readBundle();
         Bundle candidateQueryData = in.readBundle();
@@ -165,16 +167,16 @@
         mIsSystemProviderRequired = isSystemProviderRequired;
     }
 
-    public static final @NonNull Parcelable.Creator<GetCredentialOption> CREATOR =
-            new Parcelable.Creator<GetCredentialOption>() {
-                @Override
-                public GetCredentialOption[] newArray(int size) {
-                    return new GetCredentialOption[size];
-                }
+    @NonNull
+    public static final Parcelable.Creator<CredentialOption> CREATOR = new Parcelable.Creator<>() {
+        @Override
+        public CredentialOption[] newArray(int size) {
+            return new CredentialOption[size];
+        }
 
-                @Override
-                public GetCredentialOption createFromParcel(@NonNull Parcel in) {
-                    return new GetCredentialOption(in);
-                }
-            };
+        @Override
+        public CredentialOption createFromParcel(@NonNull Parcel in) {
+            return new CredentialOption(in);
+        }
+    };
 }
diff --git a/core/java/android/credentials/GetCredentialRequest.java b/core/java/android/credentials/GetCredentialRequest.java
index 85b4468..bc92c7c 100644
--- a/core/java/android/credentials/GetCredentialRequest.java
+++ b/core/java/android/credentials/GetCredentialRequest.java
@@ -19,6 +19,7 @@
 import static java.util.Objects.requireNonNull;
 
 import android.annotation.NonNull;
+import android.annotation.SuppressLint;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -39,7 +40,7 @@
      * The list of credential requests.
      */
     @NonNull
-    private final List<GetCredentialOption> mGetCredentialOptions;
+    private final List<CredentialOption> mCredentialOptions;
 
     /**
      * The top request level data.
@@ -48,11 +49,22 @@
     private final Bundle mData;
 
     /**
+     * True/False value to determine if the calling app info should be
+     * removed from the request that is sent to the providers.
+     * Developers must set this to false if they wish to remove the
+     * {@link android.service.credentials.CallingAppInfo} from the query phases requests that
+     * providers receive.
+     * If not set, the default value will be true and the calling app info will be
+     * propagated to the providers.
+     */
+    private final boolean mAlwaysSendAppInfoToProvider;
+
+    /**
      * Returns the list of credential options to be requested.
      */
     @NonNull
-    public List<GetCredentialOption> getGetCredentialOptions() {
-        return mGetCredentialOptions;
+    public List<CredentialOption> getCredentialOptions() {
+        return mCredentialOptions;
     }
 
     /**
@@ -63,10 +75,21 @@
         return mData;
     }
 
+    /**
+     * Returns a value to determine if the calling app info should be always
+     * sent to the provider in every phase (if true), or should be removed
+     * from the query phase, and only sent as part of the request in the final phase,
+     * after the user has made a selection on the UI (if false).
+     */
+    public boolean alwaysSendAppInfoToProvider() {
+        return mAlwaysSendAppInfoToProvider;
+    }
+
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeTypedList(mGetCredentialOptions, flags);
+        dest.writeTypedList(mCredentialOptions, flags);
         dest.writeBundle(mData);
+        dest.writeBoolean(mAlwaysSendAppInfoToProvider);
     }
 
     @Override
@@ -76,38 +99,43 @@
 
     @Override
     public String toString() {
-        return "GetCredentialRequest {getCredentialOption=" + mGetCredentialOptions
+        return "GetCredentialRequest {credentialOption=" + mCredentialOptions
                 + ", data=" + mData
+                + ", alwaysSendAppInfoToProvider="
+                + mAlwaysSendAppInfoToProvider
                 + "}";
     }
 
-    private GetCredentialRequest(@NonNull List<GetCredentialOption> getCredentialOptions,
-            @NonNull Bundle data) {
+    private GetCredentialRequest(@NonNull List<CredentialOption> credentialOptions,
+            @NonNull Bundle data, @NonNull boolean alwaysSendAppInfoToProvider) {
         Preconditions.checkCollectionNotEmpty(
-                getCredentialOptions,
-                /*valueName=*/ "getCredentialOptions");
+                credentialOptions,
+                /*valueName=*/ "credentialOptions");
         Preconditions.checkCollectionElementsNotNull(
-                getCredentialOptions,
-                /*valueName=*/ "getCredentialOptions");
-        mGetCredentialOptions = getCredentialOptions;
+                credentialOptions,
+                /*valueName=*/ "credentialOptions");
+        mCredentialOptions = credentialOptions;
         mData = requireNonNull(data,
                 "data must not be null");
+        mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
     }
 
     private GetCredentialRequest(@NonNull Parcel in) {
-        List<GetCredentialOption> getCredentialOptions = new ArrayList<GetCredentialOption>();
-        in.readTypedList(getCredentialOptions, GetCredentialOption.CREATOR);
-        mGetCredentialOptions = getCredentialOptions;
-        AnnotationValidations.validate(NonNull.class, null, mGetCredentialOptions);
+        List<CredentialOption> credentialOptions = new ArrayList<CredentialOption>();
+        in.readTypedList(credentialOptions, CredentialOption.CREATOR);
+        mCredentialOptions = credentialOptions;
+        AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);
 
 
         Bundle data = in.readBundle();
         mData = data;
         AnnotationValidations.validate(NonNull.class, null, mData);
+
+        mAlwaysSendAppInfoToProvider = in.readBoolean();
     }
 
-    public static final @NonNull Parcelable.Creator<GetCredentialRequest> CREATOR =
-            new Parcelable.Creator<GetCredentialRequest>() {
+    @NonNull public static final Parcelable.Creator<GetCredentialRequest> CREATOR =
+            new Parcelable.Creator<>() {
                 @Override
                 public GetCredentialRequest[] newArray(int size) {
                     return new GetCredentialRequest[size];
@@ -123,11 +151,14 @@
     public static final class Builder {
 
         @NonNull
-        private List<GetCredentialOption> mGetCredentialOptions = new ArrayList<>();
+        private List<CredentialOption> mCredentialOptions = new ArrayList<>();
 
         @NonNull
         private final Bundle mData;
 
+        @NonNull
+        private boolean mAlwaysSendAppInfoToProvider = true;
+
         /**
          * @param data the top request level data
          */
@@ -136,43 +167,62 @@
         }
 
         /**
-         * Adds a specific type of {@link GetCredentialOption}.
+         * Adds a specific type of {@link CredentialOption}.
          */
         @NonNull
-        public Builder addGetCredentialOption(
-                @NonNull GetCredentialOption getCredentialOption) {
-            mGetCredentialOptions.add(requireNonNull(
-                    getCredentialOption, "getCredentialOption must not be null"));
+        public Builder addCredentialOption(@NonNull CredentialOption credentialOption) {
+            mCredentialOptions.add(requireNonNull(
+                    credentialOption, "credentialOption must not be null"));
             return this;
         }
 
         /**
-         * Sets the list of {@link GetCredentialOption}.
+         * Sets a true/false value to determine if the calling app info should be
+         * removed from the request that is sent to the providers.
+         *
+         * Developers must set this to false if they wish to remove the
+         * {@link android.service.credentials.CallingAppInfo} from the query phases requests that
+         * providers receive. Note that the calling app info will still be sent in the
+         * final phase after the user has made a selection on the UI.
+         *
+         * If not set, the default value will be true and the calling app info will be
+         * propagated to the providers in every phase.
+         */
+        @SuppressLint("MissingGetterMatchingBuilder")
+        @NonNull
+        public Builder setAlwaysSendAppInfoToProvider(boolean value) {
+            mAlwaysSendAppInfoToProvider = value;
+            return this;
+        }
+
+        /**
+         * Sets the list of {@link CredentialOption}.
          */
         @NonNull
-        public Builder setGetCredentialOptions(
-                @NonNull List<GetCredentialOption> getCredentialOptions) {
+        public Builder setCredentialOptions(
+                @NonNull List<CredentialOption> credentialOptions) {
             Preconditions.checkCollectionElementsNotNull(
-                    getCredentialOptions,
-                    /*valueName=*/ "getCredentialOptions");
-            mGetCredentialOptions = new ArrayList<>(getCredentialOptions);
+                    credentialOptions,
+                    /*valueName=*/ "credentialOptions");
+            mCredentialOptions = new ArrayList<>(credentialOptions);
             return this;
         }
 
         /**
          * Builds a {@link GetCredentialRequest}.
          *
-         * @throws IllegalArgumentException If getCredentialOptions is empty.
+         * @throws IllegalArgumentException If credentialOptions is empty.
          */
         @NonNull
         public GetCredentialRequest build() {
             Preconditions.checkCollectionNotEmpty(
-                    mGetCredentialOptions,
-                    /*valueName=*/ "getCredentialOptions");
+                    mCredentialOptions,
+                    /*valueName=*/ "credentialOptions");
             Preconditions.checkCollectionElementsNotNull(
-                    mGetCredentialOptions,
-                    /*valueName=*/ "getCredentialOptions");
-            return new GetCredentialRequest(mGetCredentialOptions, mData);
+                    mCredentialOptions,
+                    /*valueName=*/ "credentialOptions");
+            return new GetCredentialRequest(mCredentialOptions, mData,
+                    mAlwaysSendAppInfoToProvider);
         }
     }
 }
diff --git a/core/java/android/credentials/ICredentialManager.aidl b/core/java/android/credentials/ICredentialManager.aidl
index 4ca3124..885acd4 100644
--- a/core/java/android/credentials/ICredentialManager.aidl
+++ b/core/java/android/credentials/ICredentialManager.aidl
@@ -28,6 +28,7 @@
 import android.credentials.IGetCredentialCallback;
 import android.credentials.IListEnabledProvidersCallback;
 import android.credentials.ISetEnabledProvidersCallback;
+import android.content.ComponentName;
 import android.os.ICancellationSignal;
 
 /**
@@ -50,5 +51,7 @@
     void registerCredentialDescription(in RegisterCredentialDescriptionRequest request, String callingPackage);
 
     void unregisterCredentialDescription(in UnregisterCredentialDescriptionRequest request, String callingPackage);
+
+    boolean isEnabledCredentialProviderService(in ComponentName componentName, String callingPackage);
 }
 
diff --git a/core/java/android/credentials/ui/GetCredentialProviderData.java b/core/java/android/credentials/ui/GetCredentialProviderData.java
index 5fe1441..c44d1dd 100644
--- a/core/java/android/credentials/ui/GetCredentialProviderData.java
+++ b/core/java/android/credentials/ui/GetCredentialProviderData.java
@@ -38,19 +38,19 @@
     private final List<Entry> mCredentialEntries;
     @NonNull
     private final List<Entry> mActionChips;
-    @Nullable
-    private final Entry mAuthenticationEntry;
+    @NonNull
+    private final List<Entry> mAuthenticationEntries;
     @Nullable
     private final Entry mRemoteEntry;
 
     public GetCredentialProviderData(
             @NonNull String providerFlattenedComponentName, @NonNull List<Entry> credentialEntries,
-            @NonNull List<Entry> actionChips, @Nullable Entry authenticationEntry,
+            @NonNull List<Entry> actionChips, @NonNull List<Entry> authenticationEntries,
             @Nullable Entry remoteEntry) {
         super(providerFlattenedComponentName);
         mCredentialEntries = credentialEntries;
         mActionChips = actionChips;
-        mAuthenticationEntry = authenticationEntry;
+        mAuthenticationEntries = authenticationEntries;
         mRemoteEntry = remoteEntry;
     }
 
@@ -64,9 +64,9 @@
         return mActionChips;
     }
 
-    @Nullable
-    public Entry getAuthenticationEntry() {
-        return mAuthenticationEntry;
+    @NonNull
+    public List<Entry> getAuthenticationEntries() {
+        return mAuthenticationEntries;
     }
 
     @Nullable
@@ -87,8 +87,10 @@
         mActionChips = actionChips;
         AnnotationValidations.validate(NonNull.class, null, mActionChips);
 
-        Entry authenticationEntry = in.readTypedObject(Entry.CREATOR);
-        mAuthenticationEntry = authenticationEntry;
+        List<Entry> authenticationEntries  = new ArrayList<>();
+        in.readTypedList(authenticationEntries, Entry.CREATOR);
+        mAuthenticationEntries = authenticationEntries;
+        AnnotationValidations.validate(NonNull.class, null, mAuthenticationEntries);
 
         Entry remoteEntry = in.readTypedObject(Entry.CREATOR);
         mRemoteEntry = remoteEntry;
@@ -99,7 +101,7 @@
         super.writeToParcel(dest, flags);
         dest.writeTypedList(mCredentialEntries);
         dest.writeTypedList(mActionChips);
-        dest.writeTypedObject(mAuthenticationEntry, flags);
+        dest.writeTypedList(mAuthenticationEntries);
         dest.writeTypedObject(mRemoteEntry, flags);
     }
 
@@ -131,7 +133,7 @@
         @NonNull private String mProviderFlattenedComponentName;
         @NonNull private List<Entry> mCredentialEntries = new ArrayList<>();
         @NonNull private List<Entry> mActionChips = new ArrayList<>();
-        @Nullable private Entry mAuthenticationEntry = null;
+        @NonNull private List<Entry> mAuthenticationEntries = new ArrayList<>();
         @Nullable private Entry mRemoteEntry = null;
 
         /** Constructor with required properties. */
@@ -155,8 +157,8 @@
 
         /** Sets the authentication entry to be displayed to the user. */
         @NonNull
-        public Builder setAuthenticationEntry(@Nullable Entry authenticationEntry) {
-            mAuthenticationEntry = authenticationEntry;
+        public Builder setAuthenticationEntries(@NonNull List<Entry> authenticationEntry) {
+            mAuthenticationEntries = authenticationEntry;
             return this;
         }
 
@@ -171,7 +173,7 @@
         @NonNull
         public GetCredentialProviderData build() {
             return new GetCredentialProviderData(mProviderFlattenedComponentName,
-                    mCredentialEntries, mActionChips, mAuthenticationEntry, mRemoteEntry);
+                    mCredentialEntries, mActionChips, mAuthenticationEntries, mRemoteEntry);
         }
     }
 }
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 6c3233c..fa678fc 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -188,6 +188,19 @@
         }
 
         /**
+         * Shows a default subtitle for the prompt if the subtitle would otherwise be
+         * null or empty. Currently for internal use only.
+         * @return This builder.
+         * @hide
+         */
+        @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+        @NonNull
+        public Builder setUseDefaultSubtitle() {
+            mPromptInfo.setUseDefaultSubtitle(true);
+            return this;
+        }
+
+        /**
          * Optional: Sets a description that will be shown on the prompt.
          * @param description The description to display.
          * @return This builder.
@@ -629,6 +642,16 @@
     }
 
     /**
+     * Whether to use a default subtitle. For internal use only.
+     * @return See {@link Builder#setUseDefaultSubtitle()}.
+     * @hide
+     */
+    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+    public boolean shouldUseDefaultSubtitle() {
+        return mPromptInfo.isUseDefaultSubtitle();
+    }
+
+    /**
      * Gets the description for the prompt, as set by {@link Builder#setDescription(CharSequence)}.
      * @return The description for the prompt, or null if the prompt has no description.
      */
diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java
index a6b8096..02aad1d 100644
--- a/core/java/android/hardware/biometrics/PromptInfo.java
+++ b/core/java/android/hardware/biometrics/PromptInfo.java
@@ -33,6 +33,7 @@
     @NonNull private CharSequence mTitle;
     private boolean mUseDefaultTitle;
     @Nullable private CharSequence mSubtitle;
+    private boolean mUseDefaultSubtitle;
     @Nullable private CharSequence mDescription;
     @Nullable private CharSequence mDeviceCredentialTitle;
     @Nullable private CharSequence mDeviceCredentialSubtitle;
@@ -56,6 +57,7 @@
         mTitle = in.readCharSequence();
         mUseDefaultTitle = in.readBoolean();
         mSubtitle = in.readCharSequence();
+        mUseDefaultSubtitle = in.readBoolean();
         mDescription = in.readCharSequence();
         mDeviceCredentialTitle = in.readCharSequence();
         mDeviceCredentialSubtitle = in.readCharSequence();
@@ -94,6 +96,7 @@
         dest.writeCharSequence(mTitle);
         dest.writeBoolean(mUseDefaultTitle);
         dest.writeCharSequence(mSubtitle);
+        dest.writeBoolean(mUseDefaultSubtitle);
         dest.writeCharSequence(mDescription);
         dest.writeCharSequence(mDeviceCredentialTitle);
         dest.writeCharSequence(mDeviceCredentialSubtitle);
@@ -128,6 +131,8 @@
             return true;
         } else if (mUseDefaultTitle) {
             return true;
+        } else if (mUseDefaultSubtitle) {
+            return true;
         } else if (mDeviceCredentialTitle != null) {
             return true;
         } else if (mDeviceCredentialSubtitle != null) {
@@ -154,6 +159,10 @@
         mSubtitle = subtitle;
     }
 
+    public void setUseDefaultSubtitle(boolean useDefaultSubtitle) {
+        mUseDefaultSubtitle = useDefaultSubtitle;
+    }
+
     public void setDescription(CharSequence description) {
         mDescription = description;
     }
@@ -227,6 +236,10 @@
         return mSubtitle;
     }
 
+    public boolean isUseDefaultSubtitle() {
+        return mUseDefaultSubtitle;
+    }
+
     public CharSequence getDescription() {
         return mDescription;
     }
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index c9fc722..e9df553 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -124,7 +124,7 @@
      *
      * <p>Note that if 2 surfaces share the same stream via {@link
      * OutputConfiguration#enableSurfaceSharing} and {@link OutputConfiguration#addSurface},
-     * prepare() only needs to be called on one surface, and {link
+     * prepare() only needs to be called on one surface, and {@link
      * StateCallback#onSurfacePrepared} will be triggered for both surfaces.</p>
      *
      * <p>{@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index da847a8..19719a8 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -2387,9 +2387,8 @@
             }
 
             //TODO: Do we need to treat this as error?
-            if (!mDeviceStatus.containsKey(id) || !isAvailable(mDeviceStatus.get(id))
-                    || !mUnavailablePhysicalDevices.containsKey(id)) {
-                Log.e(TAG, String.format("Camera %s is not available. Ignore physical camera "
+            if (!mDeviceStatus.containsKey(id) || !mUnavailablePhysicalDevices.containsKey(id)) {
+                Log.e(TAG, String.format("Camera %s is not present. Ignore physical camera "
                         + "status change", id));
                 return;
             }
@@ -2414,6 +2413,12 @@
                 return;
             }
 
+            if (!isAvailable(mDeviceStatus.get(id))) {
+                Log.i(TAG, String.format("Camera %s is not available. Ignore physical camera "
+                        + "status change callback(s)", id));
+                return;
+            }
+
             final int callbackCount = mCallbackMap.size();
             for (int i = 0; i < callbackCount; i++) {
                 Executor executor = mCallbackMap.valueAt(i);
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 08238ca..d49cc44 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -66,6 +66,7 @@
 public final class DisplayManager {
     private static final String TAG = "DisplayManager";
     private static final boolean DEBUG = false;
+    private static final boolean ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE = false;
 
     private final Context mContext;
     private final DisplayManagerGlobal mGlobal;
@@ -114,6 +115,23 @@
             "android.hardware.display.category.PRESENTATION";
 
     /**
+     * Display category: Rear displays.
+     * <p>
+     * This category can be used to identify complementary internal displays that are facing away
+     * from the user.
+     * Certain applications may present to this display.
+     * Similar to presentation displays.
+     * </p>
+     *
+     * @see android.app.Presentation
+     * @see Display#FLAG_PRESENTATION
+     * @see #getDisplays(String)
+     * @hide
+     */
+    public static final String DISPLAY_CATEGORY_REAR =
+            "android.hardware.display.category.REAR";
+
+    /**
      * Display category: All displays, including disabled displays.
      * <p>
      * This returns all displays, including currently disabled and inaccessible displays.
@@ -618,11 +636,19 @@
         synchronized (mLock) {
             try {
                 if (DISPLAY_CATEGORY_PRESENTATION.equals(category)) {
-                    addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
-                    addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_EXTERNAL);
-                    addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
-                    addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL);
-                    addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_INTERNAL);
+                    addDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI,
+                            Display.FLAG_PRESENTATION);
+                    addDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_EXTERNAL,
+                            Display.FLAG_PRESENTATION);
+                    addDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY,
+                            Display.FLAG_PRESENTATION);
+                    addDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL,
+                            Display.FLAG_PRESENTATION);
+                    addDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_INTERNAL,
+                            Display.FLAG_PRESENTATION);
+                } else if (DISPLAY_CATEGORY_REAR.equals(category)) {
+                    addDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_INTERNAL,
+                            Display.FLAG_REAR);
                 } else if (category == null
                         || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) {
                     addAllDisplaysLocked(mTempDisplays, displayIds);
@@ -643,15 +669,16 @@
         }
     }
 
-    private void addPresentationDisplaysLocked(
-            ArrayList<Display> displays, int[] displayIds, int matchType) {
-        for (int i = 0; i < displayIds.length; i++) {
-            if (displayIds[i] == DEFAULT_DISPLAY) {
+    private void addDisplaysLocked(
+            ArrayList<Display> displays, int[] displayIds, int matchType, int flagMask) {
+        for (int displayId : displayIds) {
+            if (displayId == DEFAULT_DISPLAY) {
                 continue;
             }
-            Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/);
+
+            Display display = getOrCreateDisplayLocked(displayId, /* assumeValid= */ true);
             if (display != null
-                    && (display.getFlags() & Display.FLAG_PRESENTATION) != 0
+                    && (display.getFlags() & flagMask) == flagMask
                     && display.getType() == matchType) {
                 displays.add(display);
             }
@@ -938,6 +965,24 @@
 
     /**
      * Creates a virtual display.
+     *
+     * @see #createVirtualDisplay(String, int, int, int, float, Surface, int,
+     * Handler, VirtualDisplay.Callback)
+     */
+    @Nullable
+    public VirtualDisplay createVirtualDisplay(@NonNull String name,
+            @IntRange(from = 1) int width,
+            @IntRange(from = 1) int height,
+            @IntRange(from = 1) int densityDpi,
+            float requestedRefreshRate,
+            @Nullable Surface surface,
+            @VirtualDisplayFlag int flags) {
+        return createVirtualDisplay(name, width, height, densityDpi, requestedRefreshRate,
+                surface, flags, null, null);
+    }
+
+    /**
+     * Creates a virtual display.
      * <p>
      * The content of a virtual display is rendered to a {@link Surface} provided
      * by the application.
@@ -987,12 +1032,82 @@
             @VirtualDisplayFlag int flags,
             @Nullable VirtualDisplay.Callback callback,
             @Nullable Handler handler) {
+        return createVirtualDisplay(name, width, height, densityDpi, 0.0f, surface,
+                flags, handler, callback);
+    }
+
+    /**
+     * Creates a virtual display.
+     * <p>
+     * The content of a virtual display is rendered to a {@link Surface} provided
+     * by the application.
+     * </p><p>
+     * The virtual display should be {@link VirtualDisplay#release released}
+     * when no longer needed.  Because a virtual display renders to a surface
+     * provided by the application, it will be released automatically when the
+     * process terminates and all remaining windows on it will be forcibly removed.
+     * </p><p>
+     * The behavior of the virtual display depends on the flags that are provided
+     * to this method.  By default, virtual displays are created to be private,
+     * non-presentation and unsecure.  Permissions may be required to use certain flags.
+     * </p><p>
+     * As of {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}, the surface may
+     * be attached or detached dynamically using {@link VirtualDisplay#setSurface}.
+     * Previously, the surface had to be non-null when {@link #createVirtualDisplay}
+     * was called and could not be changed for the lifetime of the display.
+     * </p><p>
+     * Detaching the surface that backs a virtual display has a similar effect to
+     * turning off the screen.
+     * </p>
+     *
+     * @param name The name of the virtual display, must be non-empty.
+     * @param width The width of the virtual display in pixels, must be greater than 0.
+     * @param height The height of the virtual display in pixels, must be greater than 0.
+     * @param densityDpi The density of the virtual display in dpi, must be greater than 0.
+     * @param requestedRefreshRate The requested refresh rate in frames per second.
+     * For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on
+     * 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded
+     * up or down to a divisor of the physical display. If 0 is specified, the virtual
+     * display is refreshed at the physical display refresh rate.
+     * @param surface The surface to which the content of the virtual display should
+     * be rendered, or null if there is none initially.
+     * @param flags A combination of virtual display flags:
+     * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION},
+     * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
+     * or {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+     * @param handler The handler on which the listener should be invoked, or null
+     * if the listener should be invoked on the calling thread's looper.
+     * @param callback Callback to call when the state of the {@link VirtualDisplay} changes
+     * @return The newly created virtual display, or null if the application could
+     * not create the virtual display.
+     *
+     * @throws SecurityException if the caller does not have permission to create
+     * a virtual display with the specified flags.
+     */
+    @Nullable
+    public VirtualDisplay createVirtualDisplay(@NonNull String name,
+            @IntRange(from = 1) int width,
+            @IntRange(from = 1) int height,
+            @IntRange(from = 1) int densityDpi,
+            float requestedRefreshRate,
+            @Nullable Surface surface,
+            @VirtualDisplayFlag int flags,
+            @Nullable Handler handler,
+            @Nullable VirtualDisplay.Callback callback) {
+        if (!ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE && requestedRefreshRate != 0.0f) {
+            Slog.e(TAG, "Please turn on ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE to use the new api");
+            return null;
+        }
+
         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
                 height, densityDpi);
         builder.setFlags(flags);
         if (surface != null) {
             builder.setSurface(surface);
         }
+        if (requestedRefreshRate != 0.0f) {
+            builder.setRequestedRefreshRate(requestedRefreshRate);
+        }
         return createVirtualDisplay(null /* projection */, builder.build(), callback, handler,
                 null /* windowContext */);
     }
diff --git a/core/java/android/hardware/display/HdrConversionMode.java b/core/java/android/hardware/display/HdrConversionMode.java
index 1accd17..da2b016 100644
--- a/core/java/android/hardware/display/HdrConversionMode.java
+++ b/core/java/android/hardware/display/HdrConversionMode.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -119,4 +120,40 @@
         dest.writeInt(mConversionMode);
         dest.writeInt(mPreferredHdrOutputType);
     }
-}
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        return o instanceof HdrConversionMode && equals((HdrConversionMode) o);
+    }
+
+    @Override
+    public int hashCode() {
+        return 0; // don't care
+    }
+
+    @Override
+    public String toString() {
+        return "HdrConversionMode{ConversionMode=" + hdrConversionModeString(getConversionMode())
+                + ", PreferredHdrOutputType="
+                + Display.HdrCapabilities.hdrTypeToString(getPreferredHdrOutputType()) + "}";
+    }
+
+    private boolean equals(HdrConversionMode other) {
+        return other != null
+                && mConversionMode == other.getConversionMode()
+                && mPreferredHdrOutputType == other.getPreferredHdrOutputType();
+    }
+
+    private static String hdrConversionModeString(int hdrConversionMode) {
+        switch (hdrConversionMode) {
+            case HDR_CONVERSION_PASSTHROUGH:
+                return "HDR_CONVERSION_PASSTHROUGH";
+            case HDR_CONVERSION_SYSTEM:
+                return "HDR_CONVERSION_SYSTEM";
+            case HDR_CONVERSION_FORCE:
+                return "HDR_CONVERSION_FORCE";
+            default:
+                return "HDR_CONVERSION_UNKNOWN";
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.java b/core/java/android/hardware/display/VirtualDisplayConfig.java
index abd647f..f6a2e33 100644
--- a/core/java/android/hardware/display/VirtualDisplayConfig.java
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.java
@@ -109,6 +109,13 @@
     @DataClass.PluralOf("displayCategory")
     @NonNull private List<String> mDisplayCategories = new ArrayList<>();
 
+    /**
+     * The refresh rate of a virtual display in frames per second.
+     * If this value is non-zero, this is the requested refresh rate to set.
+     * If this value is zero, the system chooses a default refresh rate.
+     */
+    private float mRequestedRefreshRate = 0.0f;
+
 
 
     // Code below generated by codegen v1.0.23.
@@ -135,7 +142,8 @@
             @Nullable String uniqueId,
             int displayIdToMirror,
             boolean windowManagerMirroring,
-            @NonNull List<String> displayCategories) {
+            @NonNull List<String> displayCategories,
+            float requestedRefreshRate) {
         this.mName = name;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mName);
@@ -161,6 +169,7 @@
         this.mDisplayCategories = displayCategories;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mDisplayCategories);
+        this.mRequestedRefreshRate = requestedRefreshRate;
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -256,6 +265,16 @@
         return mDisplayCategories;
     }
 
+    /**
+     * The refresh rate of a virtual display in frames per second.
+     * If this value is none zero, this is the requested refresh rate to set.
+     * If this value is zero, the system chooses a default refresh rate.
+     */
+    @DataClass.Generated.Member
+    public float getRequestedRefreshRate() {
+        return mRequestedRefreshRate;
+    }
+
     @Override
     @DataClass.Generated.Member
     public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -276,6 +295,7 @@
         if (mUniqueId != null) dest.writeString(mUniqueId);
         dest.writeInt(mDisplayIdToMirror);
         dest.writeStringList(mDisplayCategories);
+        dest.writeFloat(mRequestedRefreshRate);
     }
 
     @Override
@@ -301,6 +321,7 @@
         int displayIdToMirror = in.readInt();
         List<String> displayCategories = new ArrayList<>();
         in.readStringList(displayCategories);
+        float requestedRefreshRate = in.readFloat();
 
         this.mName = name;
         com.android.internal.util.AnnotationValidations.validate(
@@ -327,6 +348,7 @@
         this.mDisplayCategories = displayCategories;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mDisplayCategories);
+        this.mRequestedRefreshRate = requestedRefreshRate;
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -362,6 +384,7 @@
         private int mDisplayIdToMirror;
         private boolean mWindowManagerMirroring;
         private @NonNull List<String> mDisplayCategories;
+        private float mRequestedRefreshRate;
 
         private long mBuilderFieldsSet = 0L;
 
@@ -528,10 +551,23 @@
             return this;
         }
 
+        /**
+         * The refresh rate of a virtual display in frames per second.
+         * If this value is none zero, this is the requested refresh rate to set.
+         * If this value is zero, the system chooses a default refresh rate.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setRequestedRefreshRate(float value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x400;
+            mRequestedRefreshRate = value;
+            return this;
+        }
+
         /** Builds the instance. This builder should not be touched after calling this! */
         public @NonNull VirtualDisplayConfig build() {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x400; // Mark builder used
+            mBuilderFieldsSet |= 0x800; // Mark builder used
 
             if ((mBuilderFieldsSet & 0x10) == 0) {
                 mFlags = 0;
@@ -551,6 +587,9 @@
             if ((mBuilderFieldsSet & 0x200) == 0) {
                 mDisplayCategories = new ArrayList<>();
             }
+            if ((mBuilderFieldsSet & 0x400) == 0) {
+                mRequestedRefreshRate = 0.0f;
+            }
             VirtualDisplayConfig o = new VirtualDisplayConfig(
                     mName,
                     mWidth,
@@ -561,12 +600,13 @@
                     mUniqueId,
                     mDisplayIdToMirror,
                     mWindowManagerMirroring,
-                    mDisplayCategories);
+                    mDisplayCategories,
+                    mRequestedRefreshRate);
             return o;
         }
 
         private void checkNotUsed() {
-            if ((mBuilderFieldsSet & 0x400) != 0) {
+            if ((mBuilderFieldsSet & 0x800) != 0) {
                 throw new IllegalStateException(
                         "This Builder should not be reused. Use a new Builder instance instead");
             }
@@ -574,10 +614,10 @@
     }
 
     @DataClass.Generated(
-            time = 1668534501320L,
+            time = 1671047069703L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java",
-            inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate  int mDisplayIdToMirror\nprivate  boolean mWindowManagerMirroring\nprivate @com.android.internal.util.DataClass.PluralOf(\"displayCategory\") @android.annotation.NonNull java.util.List<java.lang.String> mDisplayCategories\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
+            inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate  int mDisplayIdToMirror\nprivate  boolean mWindowManagerMirroring\nprivate @com.android.internal.util.DataClass.PluralOf(\"displayCategory\") @android.annotation.NonNull java.util.List<java.lang.String> mDisplayCategories\nprivate  float mRequestedRefreshRate\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/hardware/fingerprint/IUdfpsRefreshRateRequestCallback.aidl b/core/java/android/hardware/fingerprint/IUdfpsRefreshRateRequestCallback.aidl
index 8587348..7844b40 100644
--- a/core/java/android/hardware/fingerprint/IUdfpsRefreshRateRequestCallback.aidl
+++ b/core/java/android/hardware/fingerprint/IUdfpsRefreshRateRequestCallback.aidl
@@ -39,5 +39,15 @@
      *        {@link android.view.Display#getDisplayId()}.
      */
     void onRequestDisabled(int displayId);
+
+    /**
+     * To avoid delay in switching refresh rate when activating LHBM, allow screens to request
+     * higher refersh rate if auth is possible on particular screen
+     *
+     * @param displayId The displayId for which the refresh rate should be unset. See
+     *        {@link android.view.Display#getDisplayId()}.
+     * @param isPossible If authentication is possible on particualr screen
+     */
+    void onAuthenticationPossible(int displayId, boolean isPossible);
 }
 
diff --git a/core/java/android/hardware/hdmi/DeviceFeatures.java b/core/java/android/hardware/hdmi/DeviceFeatures.java
index dc530ff..3805b55 100644
--- a/core/java/android/hardware/hdmi/DeviceFeatures.java
+++ b/core/java/android/hardware/hdmi/DeviceFeatures.java
@@ -130,12 +130,12 @@
         byte result = 0;
 
         if (mRecordTvScreenSupport == FEATURE_SUPPORTED) result |= (byte) (1 << 6);
-        if (mSetOsdStringSupport == FEATURE_SUPPORTED) result = (byte) (1 << 5);
-        if (mDeckControlSupport == FEATURE_SUPPORTED) result = (byte) (1 << 4);
-        if (mSetAudioRateSupport == FEATURE_SUPPORTED) result = (byte) (1 << 3);
-        if (mArcTxSupport == FEATURE_SUPPORTED) result = (byte) (1 << 2);
-        if (mArcRxSupport == FEATURE_SUPPORTED) result = (byte) (1 << 1);
-        if (mSetAudioVolumeLevelSupport == FEATURE_SUPPORTED) result = (byte) 1;
+        if (mSetOsdStringSupport == FEATURE_SUPPORTED) result |= (byte) (1 << 5);
+        if (mDeckControlSupport == FEATURE_SUPPORTED) result |= (byte) (1 << 4);
+        if (mSetAudioRateSupport == FEATURE_SUPPORTED) result |= (byte) (1 << 3);
+        if (mArcTxSupport == FEATURE_SUPPORTED) result |= (byte) (1 << 2);
+        if (mArcRxSupport == FEATURE_SUPPORTED) result |= (byte) (1 << 1);
+        if (mSetAudioVolumeLevelSupport == FEATURE_SUPPORTED) result |= (byte) 1;
 
         return new byte[]{ result };
     }
diff --git a/core/java/android/hardware/input/VirtualNavigationTouchpadConfig.java b/core/java/android/hardware/input/VirtualNavigationTouchpadConfig.java
index 5ad5fd9..8935efa 100644
--- a/core/java/android/hardware/input/VirtualNavigationTouchpadConfig.java
+++ b/core/java/android/hardware/input/VirtualNavigationTouchpadConfig.java
@@ -49,12 +49,12 @@
     }
 
     /** Returns the touchpad height. */
-    public int getHeight() {
+    @IntRange(from = 1) public int getHeight() {
         return mHeight;
     }
 
     /** Returns the touchpad width. */
-    public int getWidth() {
+    @IntRange(from = 1) public int getWidth() {
         return mWidth;
     }
 
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 0483b71..71ec1c6 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -45,6 +45,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
@@ -99,6 +100,8 @@
      * audio source function is enabled
      * <li> {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the
      * MIDI function is enabled
+     * <li> {@link #USB_FUNCTION_UVC} boolean extra indicating whether the
+     * UVC function is enabled
      * </ul>
      * If the sticky intent has not been found, that indicates USB is disconnected,
      * USB is not configured, MTP function is enabled, and all the other functions are disabled.
@@ -314,6 +317,14 @@
     public static final String USB_FUNCTION_NCM = "ncm";
 
     /**
+     * Name of the UVC USB function.
+     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+     *
+     * @hide
+     */
+    public static final String USB_FUNCTION_UVC = "uvc";
+
+    /**
      * Name of Gadget Hal Not Present;
      *
      * @hide
@@ -683,8 +694,17 @@
     @SystemApi
     public static final long FUNCTION_NCM = 1 << 10;
 
+    /**
+     * Code for the uvc usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+     * Only supported if {@link #isUvcSupportEnabled()} returns true.
+     * Must be equal to {@link GadgetFunction#UVC}
+     * @hide
+     */
+    @SystemApi
+    public static final long FUNCTION_UVC = 1 << 7;
+
     private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS
-            | FUNCTION_MIDI | FUNCTION_NCM;
+            | FUNCTION_MIDI | FUNCTION_NCM | FUNCTION_UVC;
 
     private static final Map<String, Long> FUNCTION_NAME_TO_CODE = new HashMap<>();
 
@@ -702,6 +722,7 @@
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE);
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB);
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_NCM, FUNCTION_NCM);
+        FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_UVC, FUNCTION_UVC);
     }
 
     /** @hide */
@@ -715,6 +736,7 @@
             FUNCTION_AUDIO_SOURCE,
             FUNCTION_ADB,
             FUNCTION_NCM,
+            FUNCTION_UVC,
     })
     public @interface UsbFunctionMode {}
 
@@ -1337,6 +1359,21 @@
     }
 
     /**
+     * Returns whether UVC is advertised to be supported or not. SELinux
+     * enforces that this function returns {@code false} when called from a
+     * process that doesn't belong either to a system app, or the
+     * DeviceAsWebcam Service.
+     *
+     * @return true if UVC is supported, false if UVC is not supported or if
+     *         called from a non-system app that isn't DeviceAsWebcam Service.
+     * @hide
+     */
+    @SystemApi
+    public static boolean isUvcSupportEnabled() {
+        return SystemProperties.getBoolean("ro.usb.uvc.enabled", false);
+    }
+
+    /**
      * Enable/Disable the USB data signaling.
      * <p>
      * Enables/Disables USB data path of all USB ports.
@@ -1716,7 +1753,7 @@
 
     /**
      * Returns whether the given functions are valid inputs to UsbManager.
-     * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI, NCM are accepted.
+     * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI, NCM, UVC are accepted.
      *
      * Only one function may be set at a time, except for RNDIS and NCM, which can be set together
      * because from a user perspective they are the same function (tethering).
@@ -1762,6 +1799,9 @@
         if ((functions & FUNCTION_NCM) != 0) {
             joiner.add(UsbManager.USB_FUNCTION_NCM);
         }
+        if ((functions & FUNCTION_UVC) != 0) {
+            joiner.add(UsbManager.USB_FUNCTION_UVC);
+        }
         if ((functions & FUNCTION_ADB) != 0) {
             joiner.add(UsbManager.USB_FUNCTION_ADB);
         }
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index d55367f..ed6a88f 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -223,11 +223,13 @@
                 final SomeArgs args = (SomeArgs) msg.obj;
                 final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3;
                 if (isValid(inputMethod, target, "DO_SHOW_SOFT_INPUT")) {
-                    ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+                    ImeTracker.forLogging().onProgress(
+                            statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
                     inputMethod.showSoftInputWithToken(
                             msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1, statsToken);
                 } else {
-                    ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+                    ImeTracker.forLogging().onFailed(
+                            statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
                 }
                 args.recycle();
                 return;
@@ -236,11 +238,13 @@
                 final SomeArgs args = (SomeArgs) msg.obj;
                 final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3;
                 if (isValid(inputMethod, target, "DO_HIDE_SOFT_INPUT")) {
-                    ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+                    ImeTracker.forLogging().onProgress(
+                            statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
                     inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2,
                             (IBinder) args.arg1, statsToken);
                 } else {
-                    ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+                    ImeTracker.forLogging().onFailed(
+                            statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
                 }
                 args.recycle();
                 return;
@@ -428,7 +432,7 @@
     @Override
     public void showSoftInput(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
             int flags, ResultReceiver resultReceiver) {
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
+        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
         mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_SHOW_SOFT_INPUT,
                 flags, showInputToken, resultReceiver, statsToken));
     }
@@ -437,7 +441,7 @@
     @Override
     public void hideSoftInput(IBinder hideInputToken, @Nullable ImeTracker.Token statsToken,
             int flags, ResultReceiver resultReceiver) {
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
+        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
         mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_HIDE_SOFT_INPUT,
                 flags, hideInputToken, resultReceiver, statsToken));
     }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 872414a..ee9d8a4 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -896,7 +896,8 @@
         @MainThread
         @Override
         public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
-            ImeTracker.get().onProgress(mCurStatsToken, ImeTracker.PHASE_IME_HIDE_SOFT_INPUT);
+            ImeTracker.forLogging().onProgress(
+                    mCurStatsToken, ImeTracker.PHASE_IME_HIDE_SOFT_INPUT);
             if (DEBUG) Log.v(TAG, "hideSoftInput()");
             if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R
                     && !mSystemCallingHideSoftInput) {
@@ -950,7 +951,8 @@
         @MainThread
         @Override
         public void showSoftInput(int flags, ResultReceiver resultReceiver) {
-            ImeTracker.get().onProgress(mCurStatsToken, ImeTracker.PHASE_IME_SHOW_SOFT_INPUT);
+            ImeTracker.forLogging().onProgress(
+                    mCurStatsToken, ImeTracker.PHASE_IME_SHOW_SOFT_INPUT);
             if (DEBUG) Log.v(TAG, "showSoftInput()");
             // TODO(b/148086656): Disallow IME developers from calling InputMethodImpl methods.
             if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R
@@ -966,11 +968,11 @@
                     null /* icProto */);
             final boolean wasVisible = isInputViewShown();
             if (dispatchOnShowInputRequested(flags, false)) {
-                ImeTracker.get().onProgress(mCurStatsToken,
+                ImeTracker.forLogging().onProgress(mCurStatsToken,
                         ImeTracker.PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE);
                 showWindow(true);
             } else {
-                ImeTracker.get().onFailed(mCurStatsToken,
+                ImeTracker.forLogging().onFailed(mCurStatsToken,
                         ImeTracker.PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE);
             }
             setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
@@ -2979,7 +2981,7 @@
         ImeTracing.getInstance().triggerServiceDump(
                 "InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", mDumper,
                 null /* icProto */);
-        ImeTracker.get().onProgress(mCurStatsToken,
+        ImeTracker.forLogging().onProgress(mCurStatsToken,
                 ImeTracker.PHASE_IME_APPLY_VISIBILITY_INSETS_CONSUMER);
         mPrivOps.applyImeVisibilityAsync(setVisible
                 ? mCurShowInputToken : mCurHideInputToken, setVisible, mCurStatsToken);
diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index dcf0026..6f9c9dd 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -22,6 +22,7 @@
 import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER;
 import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -37,6 +38,10 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.vcn.util.PersistableBundleUtils;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -54,6 +59,17 @@
 public final class VcnConfig implements Parcelable {
     @NonNull private static final String TAG = VcnConfig.class.getSimpleName();
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            prefix = {"TRANSPORT_"},
+            value = {
+                NetworkCapabilities.TRANSPORT_CELLULAR,
+                NetworkCapabilities.TRANSPORT_WIFI,
+            })
+    @Target({ElementType.TYPE_USE})
+    public @interface VcnUnderlyingNetworkTransport {}
+
     private static final Set<Integer> ALLOWED_TRANSPORTS = new ArraySet<>();
 
     static {
@@ -164,7 +180,7 @@
      * @see Builder#setRestrictedUnderlyingNetworkTransports(Set)
      */
     @NonNull
-    public Set<Integer> getRestrictedUnderlyingNetworkTransports() {
+    public Set<@VcnUnderlyingNetworkTransport Integer> getRestrictedUnderlyingNetworkTransports() {
         return Collections.unmodifiableSet(mRestrictedTransports);
     }
 
@@ -308,16 +324,20 @@
         /**
          * Sets transports that will be restricted by the VCN.
          *
-         * @param transports transports that will be restricted by VCN. Networks that include any
-         *     of the transports will be marked as restricted. Only {@link
-         *     NetworkCapabilities#TRANSPORT_WIFI} and {@link
-         *     NetworkCapabilities#TRANSPORT_CELLULAR} are allowed. {@link
+         * <p>In general, apps will not be able to bind to, or use a restricted network. In other
+         * words, unless the network type is marked restricted, any app can opt to use underlying
+         * networks, instead of through the VCN.
+         *
+         * @param transports transports that will be restricted by VCN. Networks that include any of
+         *     the transports will be marked as restricted. {@link
          *     NetworkCapabilities#TRANSPORT_WIFI} is marked restricted by default.
          * @return this {@link Builder} instance, for chaining
          * @throws IllegalArgumentException if the input contains unsupported transport types.
+         * @see NetworkCapabilities#NET_CAPABILITY_NOT_RESTRICTED
          */
         @NonNull
-        public Builder setRestrictedUnderlyingNetworkTransports(@NonNull Set<Integer> transports) {
+        public Builder setRestrictedUnderlyingNetworkTransports(
+                @NonNull Set<@VcnUnderlyingNetworkTransport Integer> transports) {
             validateRestrictedTransportsOrThrow(transports);
 
             mRestrictedTransports.clear();
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index a980158..6dc80cf 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -32,7 +32,6 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.IntentFilter;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.nfc.tech.MifareClassic;
@@ -572,66 +571,6 @@
     }
 
     /**
-     * Helper to check if this device has FEATURE_NFC_BEAM, but without using
-     * a context.
-     * Equivalent to
-     * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_BEAM)
-     */
-    private static boolean hasBeamFeature() {
-        IPackageManager pm = ActivityThread.getPackageManager();
-        if (pm == null) {
-            Log.e(TAG, "Cannot get package manager, assuming no Android Beam feature");
-            return false;
-        }
-        try {
-            return pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM, 0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Package manager query failed, assuming no Android Beam feature", e);
-            return false;
-        }
-    }
-
-    /**
-     * Helper to check if this device has FEATURE_NFC, but without using
-     * a context.
-     * Equivalent to
-     * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)
-     */
-    private static boolean hasNfcFeature() {
-        IPackageManager pm = ActivityThread.getPackageManager();
-        if (pm == null) {
-            Log.e(TAG, "Cannot get package manager, assuming no NFC feature");
-            return false;
-        }
-        try {
-            return pm.hasSystemFeature(PackageManager.FEATURE_NFC, 0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Package manager query failed, assuming no NFC feature", e);
-            return false;
-        }
-    }
-
-    /**
-     * Helper to check if this device is NFC HCE capable, by checking for
-     * FEATURE_NFC_HOST_CARD_EMULATION and/or FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
-     * but without using a context.
-     */
-    private static boolean hasNfcHceFeature() {
-        IPackageManager pm = ActivityThread.getPackageManager();
-        if (pm == null) {
-            Log.e(TAG, "Cannot get package manager, assuming no NFC feature");
-            return false;
-        }
-        try {
-            return pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0)
-                || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Package manager query failed, assuming no NFC feature", e);
-            return false;
-        }
-    }
-
-    /**
      * Return list of Secure Elements which support off host card emulation.
      *
      * @return List<String> containing secure elements on the device which supports
@@ -640,23 +579,21 @@
      * @hide
      */
     public @NonNull List<String> getSupportedOffHostSecureElements() {
+        if (mContext == null) {
+            throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
+                    + " getSupportedOffHostSecureElements APIs");
+        }
         List<String> offHostSE = new ArrayList<String>();
-        IPackageManager pm = ActivityThread.getPackageManager();
+        PackageManager pm = mContext.getPackageManager();
         if (pm == null) {
             Log.e(TAG, "Cannot get package manager, assuming no off-host CE feature");
             return offHostSE;
         }
-        try {
-            if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC, 0)) {
-                offHostSE.add("SIM");
-            }
-            if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE, 0)) {
-                offHostSE.add("eSE");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Package manager query failed, assuming no off-host CE feature", e);
-            offHostSE.clear();
-            return offHostSE;
+        if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC)) {
+            offHostSE.add("SIM");
+        }
+        if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE)) {
+            offHostSE.add("eSE");
         }
         return offHostSE;
     }
@@ -668,10 +605,20 @@
      */
     @UnsupportedAppUsage
     public static synchronized NfcAdapter getNfcAdapter(Context context) {
+        if (context == null) {
+            if (sNullContextNfcAdapter == null) {
+                sNullContextNfcAdapter = new NfcAdapter(null);
+            }
+            return sNullContextNfcAdapter;
+        }
         if (!sIsInitialized) {
-            sHasNfcFeature = hasNfcFeature();
-            sHasBeamFeature = hasBeamFeature();
-            boolean hasHceFeature = hasNfcHceFeature();
+            PackageManager pm;
+            pm = context.getPackageManager();
+            sHasNfcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC);
+            sHasBeamFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM);
+            boolean hasHceFeature =
+                    pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
+                    || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
             /* is this device meant to have NFC */
             if (!sHasNfcFeature && !hasHceFeature) {
                 Log.v(TAG, "this device does not have NFC support");
@@ -707,12 +654,6 @@
 
             sIsInitialized = true;
         }
-        if (context == null) {
-            if (sNullContextNfcAdapter == null) {
-                sNullContextNfcAdapter = new NfcAdapter(null);
-            }
-            return sNullContextNfcAdapter;
-        }
         NfcAdapter adapter = sNfcAdapters.get(context);
         if (adapter == null) {
             adapter = new NfcAdapter(context);
@@ -2510,8 +2451,18 @@
      *
      * <p>This returns a mapping of package names for this user id to whether we dispatch Tag
      * intents to the package. {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or
-    *  {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is
-    *  disallowed.
+     * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is
+     * mapped to {@code false}.
+     * <p>There are three different possible cases:
+     * <p>A package not being in the preference list.
+     * It does not contain any Tag intent filters or the user never triggers a Tag detection that
+     * matches the intent filter of the package.
+     * <p>A package being mapped to {@code true}.
+     * When a package has been launched by a tag detection for the first time, the package name is
+     * put to the map and by default mapped to {@code true}. The package will receive Tag intents as
+     * usual.
+     * <p>A package being mapped to {@code false}.
+     * The user chooses to disable this package and it will not receive any Tag intents anymore.
      *
      * @param userId the user to whom this preference list will belong to
      * @return a map of the UserId which indicates the mapping from package name to
diff --git a/core/java/android/nfc/OWNERS b/core/java/android/nfc/OWNERS
index 9a2e446..35e9713 100644
--- a/core/java/android/nfc/OWNERS
+++ b/core/java/android/nfc/OWNERS
@@ -1,5 +1,2 @@
 # Bug component: 48448
-
-sattiraju@google.com
-henrichataing@google.com
-alisher@google.com
+include platform/packages/apps/Nfc:/OWNERS
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 0b56d19..6a42091 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -22,11 +22,9 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Activity;
-import android.app.ActivityThread;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.nfc.INfcCardEmulation;
 import android.nfc.NfcAdapter;
@@ -158,18 +156,13 @@
             throw new UnsupportedOperationException();
         }
         if (!sIsInitialized) {
-            IPackageManager pm = ActivityThread.getPackageManager();
+            PackageManager pm = context.getPackageManager();
             if (pm == null) {
                 Log.e(TAG, "Cannot get PackageManager");
                 throw new UnsupportedOperationException();
             }
-            try {
-                if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0)) {
-                    Log.e(TAG, "This device does not support card emulation");
-                    throw new UnsupportedOperationException();
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "PackageManager query failed.");
+            if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
+                Log.e(TAG, "This device does not support card emulation");
                 throw new UnsupportedOperationException();
             }
             sIsInitialized = true;
diff --git a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java
index 3c92455..48bbf5b6 100644
--- a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java
+++ b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java
@@ -17,10 +17,8 @@
 package android.nfc.cardemulation;
 
 import android.app.Activity;
-import android.app.ActivityThread;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.nfc.INfcFCardEmulation;
 import android.nfc.NfcAdapter;
@@ -70,18 +68,13 @@
             throw new UnsupportedOperationException();
         }
         if (!sIsInitialized) {
-            IPackageManager pm = ActivityThread.getPackageManager();
+            PackageManager pm = context.getPackageManager();
             if (pm == null) {
                 Log.e(TAG, "Cannot get PackageManager");
                 throw new UnsupportedOperationException();
             }
-            try {
-                if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 0)) {
-                    Log.e(TAG, "This device does not support NFC-F card emulation");
-                    throw new UnsupportedOperationException();
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "PackageManager query failed.");
+            if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF)) {
+                Log.e(TAG, "This device does not support NFC-F card emulation");
                 throw new UnsupportedOperationException();
             }
             sIsInitialized = true;
diff --git a/core/java/android/nfc/cardemulation/OWNERS b/core/java/android/nfc/cardemulation/OWNERS
index 9a2e446..35e9713 100644
--- a/core/java/android/nfc/cardemulation/OWNERS
+++ b/core/java/android/nfc/cardemulation/OWNERS
@@ -1,5 +1,2 @@
 # Bug component: 48448
-
-sattiraju@google.com
-henrichataing@google.com
-alisher@google.com
+include platform/packages/apps/Nfc:/OWNERS
diff --git a/core/java/android/nfc/dta/OWNERS b/core/java/android/nfc/dta/OWNERS
index 9a2e446..35e9713 100644
--- a/core/java/android/nfc/dta/OWNERS
+++ b/core/java/android/nfc/dta/OWNERS
@@ -1,5 +1,2 @@
 # Bug component: 48448
-
-sattiraju@google.com
-henrichataing@google.com
-alisher@google.com
+include platform/packages/apps/Nfc:/OWNERS
diff --git a/core/java/android/nfc/tech/OWNERS b/core/java/android/nfc/tech/OWNERS
index 9a2e446..35e9713 100644
--- a/core/java/android/nfc/tech/OWNERS
+++ b/core/java/android/nfc/tech/OWNERS
@@ -1,5 +1,2 @@
 # Bug component: 48448
-
-sattiraju@google.com
-henrichataing@google.com
-alisher@google.com
+include platform/packages/apps/Nfc:/OWNERS
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 0307c10..2bad670 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -4356,13 +4356,6 @@
         }
     }
 
-    /**
-     * Temporary for settings.
-     */
-    public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) {
-        dumpCheckinLocked(context, pw, which, reqUid, checkWifiOnly(context));
-    }
-
     private static final String[] CHECKIN_POWER_COMPONENT_LABELS =
             new String[BatteryConsumer.POWER_COMPONENT_COUNT];
     static {
@@ -7477,22 +7470,8 @@
     public static final int DUMP_DEVICE_WIFI_ONLY = 1<<6;
 
     private void dumpHistory(PrintWriter pw, int flags, long histStart, boolean checkin) {
-        if (!checkin) {
-            synchronized (this) {
-                final long historyTotalSize = getHistoryTotalSize();
-                final long historyUsedSize = getHistoryUsedSize();
-                pw.print("Battery History (");
-                pw.print((100 * historyUsedSize) / historyTotalSize);
-                pw.print("% used, ");
-                printSizeValue(pw, historyUsedSize);
-                pw.print(" used of ");
-                printSizeValue(pw, historyTotalSize);
-                pw.print(", ");
-                pw.print(getHistoryStringPoolSize());
-                pw.print(" strings using ");
-                printSizeValue(pw, getHistoryStringPoolBytes());
-                pw.println("):");
-            }
+        synchronized (this) {
+            dumpHistoryTagPoolLocked(pw, checkin);
         }
 
         final HistoryPrinter hprinter = new HistoryPrinter();
@@ -7586,6 +7565,43 @@
         }
     }
 
+    private void dumpHistoryTagPoolLocked(PrintWriter pw, boolean checkin) {
+        if (checkin) {
+            for (int i = 0; i < getHistoryStringPoolSize(); i++) {
+                pw.print(BATTERY_STATS_CHECKIN_VERSION);
+                pw.print(',');
+                pw.print(HISTORY_STRING_POOL);
+                pw.print(',');
+                pw.print(i);
+                pw.print(",");
+                pw.print(getHistoryTagPoolUid(i));
+                pw.print(",\"");
+                String str = getHistoryTagPoolString(i);
+                if (str != null) {
+                    str = str.replace("\\", "\\\\");
+                    str = str.replace("\"", "\\\"");
+                    pw.print(str);
+                }
+                pw.print("\"");
+                pw.println();
+            }
+        } else {
+            final long historyTotalSize = getHistoryTotalSize();
+            final long historyUsedSize = getHistoryUsedSize();
+            pw.print("Battery History (");
+            pw.print((100 * historyUsedSize) / historyTotalSize);
+            pw.print("% used, ");
+            printSizeValue(pw, historyUsedSize);
+            pw.print(" used of ");
+            printSizeValue(pw, historyTotalSize);
+            pw.print(", ");
+            pw.print(getHistoryStringPoolSize());
+            pw.print(" strings using ");
+            printSizeValue(pw, getHistoryStringPoolBytes());
+            pw.println("):");
+        }
+    }
+
     private void dumpDailyLevelStepSummary(PrintWriter pw, String prefix, String label,
             LevelStepTracker steps, StringBuilder tmpSb, int[] tmpOutInt) {
         if (steps == null) {
@@ -7640,7 +7656,9 @@
      */
     @SuppressWarnings("unused")
     public void dump(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
-        prepareForDumpLocked();
+        synchronized (this) {
+            prepareForDumpLocked();
+        }
 
         final boolean filtering = (flags
                 & (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
@@ -7802,33 +7820,17 @@
 
     // This is called from BatteryStatsService.
     @SuppressWarnings("unused")
-    public void dumpCheckinLocked(Context context, PrintWriter pw,
+    public void dumpCheckin(Context context, PrintWriter pw,
             List<ApplicationInfo> apps, int flags, long histStart) {
-        prepareForDumpLocked();
+        synchronized (this) {
+            prepareForDumpLocked();
 
-        dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
-                CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(),
-                getEndPlatformVersion());
+            dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
+                    CHECKIN_VERSION, getParcelVersion(), getStartPlatformVersion(),
+                    getEndPlatformVersion());
+        }
 
         if ((flags & (DUMP_INCLUDE_HISTORY | DUMP_HISTORY_ONLY)) != 0) {
-            for (int i = 0; i < getHistoryStringPoolSize(); i++) {
-                pw.print(BATTERY_STATS_CHECKIN_VERSION);
-                pw.print(',');
-                pw.print(HISTORY_STRING_POOL);
-                pw.print(',');
-                pw.print(i);
-                pw.print(",");
-                pw.print(getHistoryTagPoolUid(i));
-                pw.print(",\"");
-                String str = getHistoryTagPoolString(i);
-                if (str != null) {
-                    str = str.replace("\\", "\\\\");
-                    str = str.replace("\"", "\\\"");
-                    pw.print(str);
-                }
-                pw.print("\"");
-                pw.println();
-            }
             dumpHistory(pw, flags, histStart, true);
         }
 
@@ -7836,6 +7838,13 @@
             return;
         }
 
+        synchronized (this) {
+            dumpCheckinLocked(context, pw, apps, flags);
+        }
+    }
+
+    private void dumpCheckinLocked(Context context, PrintWriter pw, List<ApplicationInfo> apps,
+            int flags) {
         if (apps != null) {
             SparseArray<Pair<ArrayList<String>, MutableBoolean>> uids = new SparseArray<>();
             for (int i=0; i<apps.size(); i++) {
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 222e88f..086b0e5 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.Manifest;
 import android.annotation.CallbackExecutor;
 import android.annotation.FloatRange;
 import android.annotation.IntDef;
@@ -88,7 +89,8 @@
                     BUGREPORT_ERROR_RUNTIME,
                     BUGREPORT_ERROR_USER_DENIED_CONSENT,
                     BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT,
-                    BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS
+                    BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS,
+                    BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE
                 })
         public @interface BugreportErrorCode {}
 
@@ -115,6 +117,10 @@
         public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS =
                 IDumpstateListener.BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS;
 
+        /** There is no bugreport to retrieve for the caller. */
+        public static final int BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE =
+                IDumpstateListener.BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE;
+
         /**
          * Called when there is a progress update.
          *
@@ -137,9 +143,26 @@
          */
         public void onError(@BugreportErrorCode int errorCode) {}
 
-        /** Called when taking bugreport finishes successfully. */
+        /** Called when taking bugreport finishes successfully.
+         *
+         * <p>This callback will be invoked if the
+         * {@link BugreportParams#BUGREPORT_FLAG_DEFER_CONSENT} flag is not set.
+         */
         public void onFinished() {}
 
+        /** Called when taking bugreport finishes successfully.
+         *
+         * <p>This callback will only be invoked if the
+         * {@link BugreportParams#BUGREPORT_FLAG_DEFER_CONSENT} flag is set. Otherwise, the
+         * {@link #onFinished()} callback will be invoked.
+         *
+         * @param bugreportFile the absolute path of the generated bugreport file.
+         * @hide
+
+         */
+        @SystemApi
+        public void onFinished(@NonNull String bugreportFile) {}
+
         /**
          * Called when it is ready for calling app to show UI, showing any extra UI before this
          * callback can interfere with bugreport generation.
@@ -178,7 +201,9 @@
      * updates.
      *
      * <p>The bugreport artifacts will be copied over to the given file descriptors only if the user
-     * consents to sharing with the calling app.
+     * consents to sharing with the calling app. If
+     * {@link BugreportParams#BUGREPORT_FLAG_DEFER_CONSENT} is set, user consent will be deferred
+     * and no files will be copied to the given file descriptors.
      *
      * <p>{@link BugreportManager} takes ownership of {@code bugreportFd} and {@code screenshotFd}.
      *
@@ -205,7 +230,9 @@
             Preconditions.checkNotNull(executor);
             Preconditions.checkNotNull(callback);
 
-            boolean isScreenshotRequested = screenshotFd != null;
+            boolean deferConsent =
+                    (params.getFlags() & BugreportParams.BUGREPORT_FLAG_DEFER_CONSENT) != 0;
+            boolean isScreenshotRequested = screenshotFd != null || deferConsent;
             if (screenshotFd == null) {
                 // Binder needs a valid File Descriptor to be passed
                 screenshotFd =
@@ -213,7 +240,7 @@
                                 new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
             }
             DumpstateListener dsListener =
-                    new DumpstateListener(executor, callback, isScreenshotRequested);
+                    new DumpstateListener(executor, callback, isScreenshotRequested, deferConsent);
             // Note: mBinder can get callingUid from the binder transaction.
             mBinder.startBugreport(
                     -1 /* callingUid */,
@@ -238,6 +265,58 @@
     }
 
     /**
+     * Retrieves a previously generated bugreport.
+     *
+     * <p>The previously generated bugreport must have been generated by calling {@link
+     * #startBugreport(ParcelFileDescriptor, ParcelFileDescriptor, BugreportParams,
+     * Executor, BugreportCallback)} with the {@link BugreportParams#BUGREPORT_FLAG_DEFER_CONSENT}
+     * flag set. The bugreport file returned by the {@link BugreportCallback#onFinished(String)}
+     * callback for a previously generated bugreport must be passed to this method. A caller may
+     * only retrieve bugreports that they have previously requested.
+     *
+     * <p>The bugreport artifacts will be copied over to the given file descriptor only if the user
+     * consents to sharing with the calling app.
+     *
+     * <p>{@link BugreportManager} takes ownership of {@code bugreportFd}.
+     *
+     * <p>The caller may only request to retrieve a given bugreport once. Subsequent calls will fail
+     * with error code {@link BugreportCallback#BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE}.
+     *
+     * @param bugreportFile the identifier for a bugreport that was previously generated for this
+     *      caller using {@code startBugreport}.
+     * @param bugreportFd file to copy over the previous bugreport. This should be opened in
+     *      write-only, append mode.
+     * @param executor the executor to execute callback methods.
+     * @param callback callback for progress and status updates.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.DUMP)
+    @WorkerThread
+    public void retrieveBugreport(
+            @NonNull String bugreportFile,
+            @NonNull ParcelFileDescriptor bugreportFd,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull BugreportCallback callback
+    ) {
+        try {
+            Preconditions.checkNotNull(bugreportFile);
+            Preconditions.checkNotNull(bugreportFd);
+            Preconditions.checkNotNull(executor);
+            Preconditions.checkNotNull(callback);
+            DumpstateListener dsListener = new DumpstateListener(executor, callback, false, false);
+            mBinder.retrieveBugreport(Binder.getCallingUid(), mContext.getOpPackageName(),
+                    bugreportFd.getFileDescriptor(),
+                    bugreportFile,
+                    dsListener);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } finally {
+            IoUtils.closeQuietly(bugreportFd);
+        }
+    }
+
+    /**
      * Starts a connectivity bugreport.
      *
      * <p>The connectivity bugreport is a specialized version of bugreport that only includes
@@ -316,7 +395,7 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.DUMP)
+    @RequiresPermission(Manifest.permission.DUMP)
     public void requestBugreport(
             @NonNull BugreportParams params,
             @Nullable CharSequence shareTitle,
@@ -335,12 +414,15 @@
         private final Executor mExecutor;
         private final BugreportCallback mCallback;
         private final boolean mIsScreenshotRequested;
+        private final boolean mIsConsentDeferred;
 
         DumpstateListener(
-                Executor executor, BugreportCallback callback, boolean isScreenshotRequested) {
+                Executor executor, BugreportCallback callback, boolean isScreenshotRequested,
+                boolean isConsentDeferred) {
             mExecutor = executor;
             mCallback = callback;
             mIsScreenshotRequested = isScreenshotRequested;
+            mIsConsentDeferred = isConsentDeferred;
         }
 
         @Override
@@ -364,10 +446,14 @@
         }
 
         @Override
-        public void onFinished() throws RemoteException {
+        public void onFinished(String bugreportFile) throws RemoteException {
             final long identity = Binder.clearCallingIdentity();
             try {
-                mExecutor.execute(() -> mCallback.onFinished());
+                if (mIsConsentDeferred) {
+                    mExecutor.execute(() -> mCallback.onFinished(bugreportFile));
+                } else {
+                    mExecutor.execute(() -> mCallback.onFinished());
+                }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
diff --git a/core/java/android/os/BugreportParams.java b/core/java/android/os/BugreportParams.java
index 990883f..d9d14b0 100644
--- a/core/java/android/os/BugreportParams.java
+++ b/core/java/android/os/BugreportParams.java
@@ -21,6 +21,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
 
 /**
  * Parameters that specify what kind of bugreport should be taken.
@@ -125,7 +126,8 @@
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, prefix = { "BUGREPORT_FLAG_" }, value = {
-            BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA
+            BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA,
+            BUGREPORT_FLAG_DEFER_CONSENT
     })
     public @interface BugreportFlag {}
 
@@ -135,4 +137,14 @@
      */
     public static final int BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA =
             IDumpstate.BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA;
+
+    /**
+     * Flag for deferring user consent.
+     *
+     * <p>This flag should be used in cases where it may not be possible for the user to respond
+     * to a consent dialog immediately, such as when the user is driving. The generated bugreport
+     * may be retrieved at a later time using {@link BugreportManager#retrieveBugreport(
+     * String, ParcelFileDescriptor, Executor, BugreportManager.BugreportCallback)}.
+     */
+    public static final int BUGREPORT_FLAG_DEFER_CONSENT = IDumpstate.BUGREPORT_FLAG_DEFER_CONSENT;
 }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 249f486..832f23c 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -61,6 +61,17 @@
     /** The name of the overall product. */
     public static final String PRODUCT = getString("ro.product.name");
 
+    /**
+     * The product name for attestation. In non-default builds (like the AOSP build) the value of
+     * the 'PRODUCT' system property may be different to the one provisioned to KeyMint,
+     * and Keymint attestation would still attest to the product name, it's running on.
+     * @hide
+     */
+    @Nullable
+    @TestApi
+    public static final String PRODUCT_FOR_ATTESTATION =
+            getString("ro.product.name_for_attestation");
+
     /** The name of the industrial design. */
     public static final String DEVICE = getString("ro.product.device");
 
@@ -89,9 +100,31 @@
     /** The consumer-visible brand with which the product/hardware will be associated, if any. */
     public static final String BRAND = getString("ro.product.brand");
 
+    /**
+     * The product brand for attestation. In non-default builds (like the AOSP build) the value of
+     * the 'BRAND' system property may be different to the one provisioned to KeyMint,
+     * and Keymint attestation would still attest to the product brand, it's running on.
+     * @hide
+     */
+    @Nullable
+    @TestApi
+    public static final String BRAND_FOR_ATTESTATION =
+                getString("ro.product.brand_for_attestation");
+
     /** The end-user-visible name for the end product. */
     public static final String MODEL = getString("ro.product.model");
 
+    /**
+     * The product model for attestation. In non-default builds (like the AOSP build) the value of
+     * the 'MODEL' system property may be different to the one provisioned to KeyMint,
+     * and Keymint attestation would still attest to the product model, it's running on.
+     * @hide
+     */
+    @Nullable
+    @TestApi
+    public static final String MODEL_FOR_ATTESTATION =
+                getString("ro.product.model_for_attestation");
+
     /** The manufacturer of the device's primary system-on-chip. */
     @NonNull
     public static final String SOC_MANUFACTURER = SocProperties.soc_manufacturer().orElse(UNKNOWN);
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 810bd63..7ad1735 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -34,6 +34,7 @@
 import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.annotation.TestApi;
+import android.app.ActivityThread;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ContentProvider;
@@ -45,6 +46,7 @@
 import android.system.OsConstants;
 import android.system.StructStat;
 import android.util.Log;
+import android.util.Slog;
 
 import dalvik.system.CloseGuard;
 import dalvik.system.VMRuntime;
@@ -329,6 +331,17 @@
     }
 
     private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException {
+        if ((mode & MODE_WRITE_ONLY) != 0 && (mode & MODE_APPEND) == 0
+                && (mode & MODE_TRUNCATE) == 0 && ((mode & MODE_READ_ONLY) == 0)
+                && file.exists()) {
+            String packageName = ActivityThread.currentApplication().getApplicationContext()
+                    .getPackageName();
+            Slog.wtfQuiet(TAG, "ParcelFileDescriptor.open is called with w without t or a or r, "
+                    + "which will have a different behavior beginning in Android Q."
+                    + "\nPackage Name: " + packageName + "\nMode: " + mode
+                    + "\nFilename: " + file.getPath());
+        }
+
         final int flags = FileUtils.translateModePfdToPosix(mode) | ifAtLeastQ(O_CLOEXEC);
 
         int realMode = S_IRWXU | S_IRWXG;
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index adc73c8..0d0d1da 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -110,7 +110,8 @@
     public static final long TRACE_TAG_THERMAL = 1L << 27;
 
     private static final long TRACE_TAG_NOT_READY = 1L << 63;
-    private static final int MAX_SECTION_NAME_LEN = 127;
+    /** @hide **/
+    public static final int MAX_SECTION_NAME_LEN = 127;
 
     // Must be volatile to avoid word tearing.
     // This is only kept in case any apps get this by reflection but do not
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d63d87d..1df45d1 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1069,11 +1069,6 @@
      * Specifies that windows besides app windows should not be
      * created. This will block the creation of the following types of windows.
      * <li>{@link LayoutParams#TYPE_TOAST}</li>
-     * <li>{@link LayoutParams#TYPE_PHONE}</li>
-     * <li>{@link LayoutParams#TYPE_PRIORITY_PHONE}</li>
-     * <li>{@link LayoutParams#TYPE_SYSTEM_ALERT}</li>
-     * <li>{@link LayoutParams#TYPE_SYSTEM_ERROR}</li>
-     * <li>{@link LayoutParams#TYPE_SYSTEM_OVERLAY}</li>
      * <li>{@link LayoutParams#TYPE_APPLICATION_OVERLAY}</li>
      *
      * <p>This can only be set by device owners and profile owners on the primary user.
@@ -2976,6 +2971,29 @@
     }
 
     /**
+     * @hide
+     */
+    public static boolean isVisibleBackgroundUsersOnDefaultDisplayEnabled() {
+        return SystemProperties.getBoolean("fw.visible_bg_users_on_default_display",
+                Resources.getSystem()
+                        .getBoolean(R.bool.config_multiuserVisibleBackgroundUsersOnDefaultDisplay));
+    }
+
+    /**
+     * Returns whether the device allows (full) users to be started in background visible in the
+     * {@link android.view.Display#DEFAULT_DISPLAY default display}.
+     *
+     * @return {@code false} for most devices, except passenger-only automotive build (i.e., when
+     * Android runs in a separate system in the back seat to manage the passenger displays).
+     *
+     * @hide
+     */
+    @TestApi
+    public boolean isVisibleBackgroundUsersOnDefaultDisplaySupported() {
+        return isVisibleBackgroundUsersOnDefaultDisplayEnabled();
+    }
+
+    /**
      * Checks if the user is visible at the moment.
      *
      * <p>Roughly speaking, a "visible user" is a user that can present UI on at least one display.
diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS
index c80c57c..e5b76f6 100644
--- a/core/java/android/os/storage/OWNERS
+++ b/core/java/android/os/storage/OWNERS
@@ -1,7 +1,9 @@
 # Bug component: 95221
 
+# Please assign new bugs to android-storage-triage@, not to individual people
+
 # Android Storage Team
-abkaur@google.com
+alukin@google.com
 corinac@google.com
 dipankarb@google.com
 krishang@google.com
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index f5f1c37..2a4c01e1 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -398,7 +398,8 @@
             Context userContext = getUserContext(user);
             PackageInfo packageInfo = userContext.getPackageManager().getPackageInfo(
                     packageName,
-                    PackageManager.GET_PERMISSIONS | PackageManager.GET_ATTRIBUTIONS);
+                    PackageManager.PackageInfoFlags.of(
+                            PackageManager.GET_PERMISSIONS | PackageManager.GET_ATTRIBUTIONS_LONG));
             Context pkgContext = userContext.createPackageContext(packageInfo.packageName, 0);
             for (Attribution attribution : packageInfo.attributions) {
                 try {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b2d89962..cf68572 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7392,6 +7392,9 @@
          *
          * Format like "ime0;subtype0;subtype1;subtype2:ime1:ime2;subtype0"
          * where imeId is ComponentName and subtype is int32.
+         *
+         * <p>Note: This setting is not readable to the app targeting API level 34 or higher. use
+         * {@link android.view.inputmethod.InputMethodManager#getEnabledInputMethodList()} instead.
          */
         @Readable(maxTargetSdk = Build.VERSION_CODES.TIRAMISU)
         public static final String ENABLED_INPUT_METHODS = "enabled_input_methods";
@@ -7422,7 +7425,7 @@
          * @hide
          */
         @SuppressLint("NoSettingsProvider")
-        public static final String STYLUS_BUTTONS_DISABLED = "stylus_buttons_disabled";
+        public static final String STYLUS_BUTTONS_ENABLED = "stylus_buttons_enabled";
 
         /**
          * Host name and port for global http proxy. Uses ':' seperator for
@@ -10268,6 +10271,17 @@
                 "active_unlock_on_unlock_intent_when_biometric_enrolled";
 
         /**
+         * If active unlock triggers on unlock intents, then also request active unlock on
+         * these wake-up reasons. See PowerManager.WakeReason for value mappings.
+         * WakeReasons should be separated by a pipe. For example: "0|3" or "0". If this
+         * setting should be disabled, then this should be set to an empty string. A null value
+         * will use the system default value (WAKE_REASON_UNFOLD_DEVICE).
+         * @hide
+         */
+        public static final String ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS =
+                "active_unlock_wakeups_considered_unlock_intents";
+
+        /**
          * Whether the assist gesture should be enabled.
          *
          * @hide
@@ -11147,6 +11161,15 @@
         public static final int ACCESSIBILITY_MAGNIFICATION_MODE_ALL = 0x3;
 
         /**
+         * Whether the magnification always on feature is enabled. If true, the magnifier will not
+         * deactivate on Activity transitions; it will only zoom out to 100%.
+         *
+         * @hide
+         */
+        public static final String ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED =
+                "accessibility_magnification_always_on_enabled";
+
+        /**
          * Whether the following typing focus feature for magnification is enabled.
          * @hide
          */
@@ -11454,6 +11477,13 @@
                 "extra_automatic_power_save_mode";
 
         /**
+         * Whether lockscreen weather is enabled.
+         *
+         * @hide
+         */
+        public static final String LOCK_SCREEN_WEATHER_ENABLED = "lockscreen_weather_enabled";
+
+        /**
          * These entries are considered common between the personal and the managed profile,
          * since the managed profile doesn't get to change them.
          */
@@ -15498,6 +15528,25 @@
         public static final String AUDIO_SAFE_VOLUME_STATE = "audio_safe_volume_state";
 
         /**
+         * Persisted safe hearding current CSD value. Values are stored as float percentages where
+         * 1.f represents 100% sound dose has been reached.
+         * @hide
+         */
+        public static final String AUDIO_SAFE_CSD_CURRENT_VALUE = "audio_safe_csd_current_value";
+
+        /**
+         * Persisted safe hearding next CSD warning value. Values are stored as float percentages.
+         * @hide
+         */
+        public static final String AUDIO_SAFE_CSD_NEXT_WARNING = "audio_safe_csd_next_warning";
+
+        /**
+         * Persisted safe hearding dose records (see {@link android.media.SoundDoseRecord})
+         * @hide
+         */
+        public static final String AUDIO_SAFE_CSD_DOSE_RECORDS = "audio_safe_csd_dose_records";
+
+        /**
          * URL for tzinfo (time zone) updates
          * @hide
          */
@@ -15879,6 +15928,36 @@
                 "user_preferred_resolution_width";
 
         /**
+         * The HDR output mode chosen by the user. This is one of:
+         * {@link android.hardware.display.HdrConversionMode#HDR_CONVERSION_PASSTHROUGH},
+         * {@link android.hardware.display.HdrConversionMode#HDR_CONVERSION_SYSTEM},
+         * {@link android.hardware.display.HdrConversionMode#HDR_CONVERSION_FORCE}.
+         *
+         * @hide
+         */
+        @TestApi
+        @Readable
+        public static final String HDR_CONVERSION_MODE = "hdr_conversion_mode";
+
+        /**
+         * The output HDR type chosen by the user in case when {@link #HDR_CONVERSION_MODE} is
+         * {@link #HDR_CONVERSION_FORCE}. This is one of:
+         * {@link android.view.Display.HdrCapabilities#HDR_TYPE_INVALID},
+         * {@link android.view.Display.HdrCapabilities#HDR_TYPE_DOLBY_VISION},
+         * {@link android.view.Display.HdrCapabilities#HDR_TYPE_HDR10},
+         * {@link android.view.Display.HdrCapabilities#HDR_TYPE_HLG},
+         * {@link android.view.Display.HdrCapabilities#HDR_TYPE_HDR10_PLUS}
+         * <p>
+         * The value is {@link android.view.Display.HdrCapabilities#HDR_TYPE_INVALID} when user
+         * chooses SDR output type. </p>
+         *
+         * @hide
+         */
+        @TestApi
+        @Readable
+        public static final String HDR_FORCE_CONVERSION_TYPE = "hdr_force_conversion_type";
+
+        /**
          * The name of the device
          */
         @Readable
@@ -19289,6 +19368,18 @@
             "android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION";
 
     /**
+     * Activity Action: Show screen for controlling whether an app can send full screen intents.
+     * <p>
+     *     Input: the intent's data URI must specify the application package name for which you want
+     *     to manage full screen intents.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT =
+            "android.settings.MANAGE_APP_USE_FULL_SCREEN_INTENT";
+
+    /**
      * Activity Action: For system or preinstalled apps to show their {@link Activity} embedded
      * in Settings app on large screen devices.
      *
diff --git a/core/java/android/security/ConfirmationNotAvailableException.java b/core/java/android/security/ConfirmationNotAvailableException.java
index 8d0e672..0b37ae4 100644
--- a/core/java/android/security/ConfirmationNotAvailableException.java
+++ b/core/java/android/security/ConfirmationNotAvailableException.java
@@ -17,7 +17,7 @@
 package android.security;
 
 /**
- * This exception is thrown when presenting a prompt fails because the the environment lacks
+ * This exception is thrown when presenting a prompt fails because the environment lacks
  * facilities for showing confirmations.
  */
 public class ConfirmationNotAvailableException extends Exception {
diff --git a/core/java/android/security/rkp/IGetKeyCallback.aidl b/core/java/android/security/rkp/IGetKeyCallback.aidl
index 85ceae62..a36d054 100644
--- a/core/java/android/security/rkp/IGetKeyCallback.aidl
+++ b/core/java/android/security/rkp/IGetKeyCallback.aidl
@@ -25,6 +25,36 @@
  * @hide
  */
 oneway interface IGetKeyCallback {
+    enum ErrorCode {
+        /**
+         * An unexpected error occurred and there's no standard way to describe it. See the
+         * corresponding error string for more information.
+         */
+        ERROR_UNKNOWN = 1,
+
+        /**
+         * Device will not receive remotely provisioned keys because it's running vulnerable
+         * code. The device needs to be updated to a fixed build to recover.
+         */
+        ERROR_REQUIRES_SECURITY_PATCH = 2,
+
+        /**
+         * Indicates that the attestation key pool has been exhausted, and the remote key
+         * provisioning server cannot currently be reached. Clients should wait for the
+         * device to have connectivity, then retry.
+         */
+        ERROR_PENDING_INTERNET_CONNECTIVITY = 3,
+
+        /**
+         * Indicates that this device will never be able to provision attestation keys using
+         * the remote provsisioning server. This may be due to multiple causes, such as the
+         * device is not registered with the remote provisioning backend or the device has
+         * been permanently revoked. Clients who receive this error should not attempt to
+         * retry key creation.
+         */
+        ERROR_PERMANENT = 5,
+    }
+
     /**
      * Called in response to {@link IRegistration.getKey}, indicating
      * a remotely-provisioned key is available.
@@ -42,8 +72,9 @@
     /**
      * Called when an error has occurred while trying to get a remotely provisioned key.
      *
-     * @param error A description of what failed, suitable for logging.
+     * @param error allows code to handle certain errors, if desired
+     * @param description human-readable explanation of what failed, suitable for logging.
      */
-    void onError(String error);
+    void onError(ErrorCode error, String description);
 }
 
diff --git a/core/java/android/service/assist/OWNERS b/core/java/android/service/assist/OWNERS
new file mode 100644
index 0000000..533b1f1
--- /dev/null
+++ b/core/java/android/service/assist/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 351486
+
+include /core/java/android/view/autofill/OWNERS
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/core/java/android/service/assist/classification/FieldClassification.aidl
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to core/java/android/service/assist/classification/FieldClassification.aidl
index 497c272..7d0c078 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/core/java/android/service/assist/classification/FieldClassification.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package android.service.assist.classification;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+parcelable FieldClassification;
diff --git a/core/java/android/service/assist/classification/FieldClassification.java b/core/java/android/service/assist/classification/FieldClassification.java
new file mode 100644
index 0000000..0ea8112
--- /dev/null
+++ b/core/java/android/service/assist/classification/FieldClassification.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.assist.classification;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+import android.view.autofill.AutofillId;
+
+
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Represents a classified field from the detection service.
+ */
+// TODO(b/266930067): Once @SystemApi is supported, use genSetters and genConstructor.
+@DataClass(
+        genToString = true,
+        genConstructor = false
+)
+public final class FieldClassification implements Parcelable {
+
+    /**
+     * Autofill id of the detected field
+     */
+    private final @NonNull AutofillId mAutofillId;
+
+    /**
+     * Detected fields types represented as autofill hints
+     *
+     * A particular field can be detected as multiple types. For eg: A sign-in field may take in a
+     * username, an email address or a phone number. In such cases, it should be detected as
+     * "username", "emailAddress" and "phoneNumber"
+     *
+     * The value of these hints are contained in androidx.autofill.HintConstants
+     */
+    private final @NonNull Set<String> mHints;
+
+
+    /**
+     * Group hints are the hints that may represent the group of related hints (including
+     * themselves). The value of these group hints are contained in androidx.autofill.HintConstants
+     *
+     * <p>
+     *
+     * "creditCardNumber" is the group hint for hints containing credit card related fields:
+     * "creditCardNumber", "creditCardExpirationDate", "creditCardExpirationDay",
+     * "creditCardExpirationMonth", "creditCardExpirationYear", "creditCardSecurityCode",
+     *
+     * <p>
+     *
+     * "postalAddress" is the group hint for hints all postal address related fields:
+     * "postalAddress", "streetAddress", "aptNumber", "dependentLocality", "extendedAddress",
+     * "postalCode", "extendedPostalCode", "addressLocality", "addressRegion", "addressCountry".
+     *
+     * <p>
+     *
+     * "phoneNumber" is the group hint for hints all phone number related fields: "phoneNumber",
+     * "phoneNumberDevice", "phoneNational", "phoneCountryCode".
+     *
+     * <p>
+     *
+     * "personName" is the group hint for hints all name related fields: "personName",
+     * "personFamilyName", "personGivenName", "personMiddleName", "personMiddleInitial",
+     * "personNamePrefix", "personNameSuffix" .
+     *
+     * <p>
+     *
+     * "birthDateFull" is the group hint for hints containing birthday related fields:
+     * "birthDateFull", "birthDateMonth", "birthDateYear",
+     *
+     * @hide
+     */
+    private final @NonNull Set<String> mGroupHints;
+
+    /**
+     * Autofill id of the detected field.
+     */
+    public @NonNull AutofillId getAutofillId() {
+        return mAutofillId;
+    }
+
+    /**
+     * Detected fields types represented as autofill hints.
+     *
+     * A particular field can be detected as multiple types. For eg: A sign-in field may take in a
+     * username, an email address or a phone number. In such cases, it should be detected as
+     * "username", "emailAddress" and "phoneNumber"
+     *
+     * The value of these hints are contained in androidx.autofill.HintConstants
+     */
+    public @NonNull Set<String> getHints() {
+        return mHints;
+    }
+
+    /**
+    * Group hints are the hints that may represent the group of related hints (including
+    * themselves). The value of these group hints are contained in androidx.autofill.HintConstants
+    *
+    * <p>
+    *
+    * "creditCardNumber" is the group hint for hints containing credit card related fields:
+    * "creditCardNumber", "creditCardExpirationDate", "creditCardExpirationDay",
+    * "creditCardExpirationMonth", "creditCardExpirationYear", "creditCardSecurityCode",
+    *
+    * <p>
+    *
+    * "postalAddress" is the group hint for hints all postal address related fields:
+    * "postalAddress", "streetAddress", "aptNumber", "dependentLocality", "extendedAddress",
+    * "postalCode", "extendedPostalCode", "addressLocality", "addressRegion", "addressCountry".
+    *
+    * <p>
+    *
+    * "phoneNumber" is the group hint for hints all phone number related fields: "phoneNumber",
+    * "phoneNumberDevice", "phoneNational", "phoneCountryCode".
+    *
+    * <p>
+    *
+    * "personName" is the group hint for hints all name related fields: "personName",
+    * "personFamilyName", "personGivenName", "personMiddleName", "personMiddleInitial",
+    * "personNamePrefix", "personNameSuffix" .
+    *
+    * <p>
+    *
+    * "birthDateFull" is the group hint for hints containing birthday related fields:
+    * "birthDateFull", "birthDateMonth", "birthDateYear",
+    *
+    * @hide
+    */
+    @SystemApi
+    public @NonNull Set<String> getGroupHints() {
+        return mGroupHints;
+    }
+
+    static Set<String> unparcelHints(Parcel in) {
+        List<String> hints = new java.util.ArrayList<>();
+        in.readStringList(hints);
+        return new ArraySet<>(hints);
+    }
+
+    void parcelHints(Parcel dest, int flags) {
+        dest.writeStringList(new ArrayList<>(mHints));
+    }
+
+    static Set<String> unparcelGroupHints(Parcel in) {
+        List<String> groupHints = new java.util.ArrayList<>();
+        in.readStringList(groupHints);
+        return new ArraySet<>(groupHints);
+    }
+
+    void parcelGroupHints(Parcel dest, int flags) {
+        dest.writeStringList(new ArrayList<>(mGroupHints));
+    }
+
+    /**
+     * Creates a new FieldClassification.
+     *
+     * @param autofillId
+     *   Autofill id of the detected field
+     * @param hints
+     *   Detected fields types represented as autofill hints.
+     *   A particular field can be detected as multiple types. For eg: A sign-in field may take in
+     *   a username, an email address or a phone number. In such cases, it should be detected as
+     *   "username", "emailAddress" and "phoneNumber"
+     */
+    public FieldClassification(
+            @NonNull AutofillId autofillId,
+            @NonNull Set<String> hints) {
+        this(autofillId, hints, new ArraySet<>());
+    }
+
+    /**
+    * Creates a new FieldClassification.
+    *
+    * @param autofillId Autofill id of the detected field
+    * @param hints Detected fields types represented as autofill hints A particular field can be
+    *     detected as multiple types. For eg: A sign-in field may take in a username, an email
+    *     address or a phone number. In such cases, it should be detected as "username",
+    *     "emailAddress" and "phoneNumber"
+    * @param groupHints Hints that may represent the group of related hints (including themselves).
+    *     The value of these group hints are contained in androidx.autofill.HintConstants.
+     *    See {@link #getGroupHints()} for more details
+    * @hide
+    */
+    @SystemApi
+    @DataClass.Generated.Member
+    public FieldClassification(
+            @NonNull AutofillId autofillId,
+            @NonNull Set<String> hints,
+            @NonNull Set<String> groupHints) {
+        this.mAutofillId = autofillId;
+//        com.android.internal.util.AnnotationValidations.validate(
+//                NonNull.class, null, mAutofillId);
+        this.mHints = hints;
+//        com.android.internal.util.AnnotationValidations.validate(
+//                NonNull.class, null, mHints);
+        this.mGroupHints = groupHints;
+//        com.android.internal.util.AnnotationValidations.validate(
+//                NonNull.class, null, mGroupHints);
+    }
+
+
+
+    // Code below generated by codegen v1.0.23.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/assist/classification/FieldClassification.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "FieldClassification { " +
+                "autofillId = " + mAutofillId + ", " +
+                "hints = " + mHints + ", " +
+                "groupHints = " + mGroupHints +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeTypedObject(mAutofillId, flags);
+        parcelHints(dest, flags);
+        parcelGroupHints(dest, flags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ FieldClassification(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        AutofillId autofillId = (AutofillId) in.readTypedObject(AutofillId.CREATOR);
+        Set<String> hints = unparcelHints(in);
+        Set<String> groupHints = unparcelGroupHints(in);
+
+        this.mAutofillId = autofillId;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAutofillId);
+        this.mHints = hints;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mHints);
+        this.mGroupHints = groupHints;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mGroupHints);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<FieldClassification> CREATOR
+            = new Parcelable.Creator<FieldClassification>() {
+        @Override
+        public FieldClassification[] newArray(int size) {
+            return new FieldClassification[size];
+        }
+
+        @Override
+        public FieldClassification createFromParcel(@NonNull Parcel in) {
+            return new FieldClassification(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1675320464097L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/service/assist/classification/FieldClassification.java",
+            inputSignatures = "private final @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate final @android.annotation.NonNull java.util.Set<java.lang.String> mHints\nprivate final @android.annotation.NonNull java.util.Set<java.lang.String> mGroupHints\npublic @android.annotation.NonNull android.view.autofill.AutofillId getAutofillId()\npublic @android.annotation.NonNull java.util.Set<java.lang.String> getHints()\npublic @android.annotation.SystemApi @android.annotation.NonNull java.util.Set<java.lang.String> getGroupHints()\nstatic  java.util.Set<java.lang.String> unparcelHints(android.os.Parcel)\n  void parcelHints(android.os.Parcel,int)\nstatic  java.util.Set<java.lang.String> unparcelGroupHints(android.os.Parcel)\n  void parcelGroupHints(android.os.Parcel,int)\nclass FieldClassification extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genConstructor=false)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/service/assist/classification/FieldClassificationRequest.aidl b/core/java/android/service/assist/classification/FieldClassificationRequest.aidl
new file mode 100644
index 0000000..740c5cb9
--- /dev/null
+++ b/core/java/android/service/assist/classification/FieldClassificationRequest.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.assist.classification;
+
+parcelable FieldClassificationRequest;
\ No newline at end of file
diff --git a/core/java/android/service/assist/classification/FieldClassificationRequest.java b/core/java/android/service/assist/classification/FieldClassificationRequest.java
new file mode 100644
index 0000000..0afcca9
--- /dev/null
+++ b/core/java/android/service/assist/classification/FieldClassificationRequest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.assist.classification;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.app.assist.AssistStructure;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Represents a request to detect fields on an activity.
+ * @hide
+ */
+@SystemApi
+@DataClass(
+        genToString = true
+)
+public final class FieldClassificationRequest implements Parcelable {
+    private final @NonNull AssistStructure mAssistStructure;
+
+
+
+    // Code below generated by codegen v1.0.23.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/assist/classification/FieldClassificationRequest.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    public FieldClassificationRequest(
+            @NonNull AssistStructure assistStructure) {
+        this.mAssistStructure = assistStructure;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAssistStructure);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull AssistStructure getAssistStructure() {
+        return mAssistStructure;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "FieldClassificationRequest { " +
+                "assistStructure = " + mAssistStructure +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeTypedObject(mAssistStructure, flags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ FieldClassificationRequest(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        AssistStructure assistStructure = (AssistStructure) in.readTypedObject(AssistStructure.CREATOR);
+
+        this.mAssistStructure = assistStructure;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAssistStructure);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<FieldClassificationRequest> CREATOR
+            = new Parcelable.Creator<FieldClassificationRequest>() {
+        @Override
+        public FieldClassificationRequest[] newArray(int size) {
+            return new FieldClassificationRequest[size];
+        }
+
+        @Override
+        public FieldClassificationRequest createFromParcel(@NonNull Parcel in) {
+            return new FieldClassificationRequest(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1675320491692L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/service/assist/classification/FieldClassificationRequest.java",
+            inputSignatures = "private final @android.annotation.NonNull android.app.assist.AssistStructure mAssistStructure\nclass FieldClassificationRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/core/java/android/service/assist/classification/FieldClassificationResponse.aidl
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to core/java/android/service/assist/classification/FieldClassificationResponse.aidl
index 497c272..1b0de85 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/core/java/android/service/assist/classification/FieldClassificationResponse.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package android.service.assist.classification;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+parcelable FieldClassificationResponse;
diff --git a/core/java/android/service/assist/classification/FieldClassificationResponse.java b/core/java/android/service/assist/classification/FieldClassificationResponse.java
new file mode 100644
index 0000000..faa9488
--- /dev/null
+++ b/core/java/android/service/assist/classification/FieldClassificationResponse.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.assist.classification;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * Represents a response from detection service.
+ * @hide
+ */
+@SystemApi
+@DataClass(
+        genToString = true
+)
+public final class FieldClassificationResponse implements Parcelable {
+
+    /**
+     * List of classified fields
+     */
+    private final @NonNull Set<FieldClassification> mClassifications;
+
+    static Set<FieldClassification> unparcelClassifications(Parcel in) {
+        List<FieldClassification> detections = new java.util.ArrayList<>();
+        in.readParcelableList(
+                detections, FieldClassification.class.getClassLoader(), FieldClassification.class);
+        return new ArraySet<>(detections);
+    }
+
+    void parcelClassifications(Parcel dest, int flags) {
+        dest.writeParcelableList(new ArrayList<>(mClassifications), flags);
+    }
+
+
+
+    // Code below generated by codegen v1.0.23.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/assist/classification/FieldClassificationResponse.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Creates a new FieldClassificationResponse.
+     *
+     * @param classifications
+     *   List of classified fields
+     */
+    @DataClass.Generated.Member
+    public FieldClassificationResponse(
+            @NonNull Set<FieldClassification> classifications) {
+        this.mClassifications = classifications;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mClassifications);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * List of classified fields
+     */
+    @DataClass.Generated.Member
+    public @NonNull Set<FieldClassification> getClassifications() {
+        return mClassifications;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "FieldClassificationResponse { " +
+                "classifications = " + mClassifications +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        parcelClassifications(dest, flags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ FieldClassificationResponse(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        Set<FieldClassification> classifications = unparcelClassifications(in);
+
+        this.mClassifications = classifications;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mClassifications);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<FieldClassificationResponse> CREATOR
+            = new Parcelable.Creator<FieldClassificationResponse>() {
+        @Override
+        public FieldClassificationResponse[] newArray(int size) {
+            return new FieldClassificationResponse[size];
+        }
+
+        @Override
+        public FieldClassificationResponse createFromParcel(@NonNull Parcel in) {
+            return new FieldClassificationResponse(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1675320458276L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/service/assist/classification/FieldClassificationResponse.java",
+            inputSignatures = "private final @android.annotation.NonNull java.util.Set<android.service.assist.classification.FieldClassification> mClassifications\nstatic  java.util.Set<android.service.assist.classification.FieldClassification> unparcelClassifications(android.os.Parcel)\n  void parcelClassifications(android.os.Parcel,int)\nclass FieldClassificationResponse extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/service/assist/classification/FieldClassificationService.java b/core/java/android/service/assist/classification/FieldClassificationService.java
new file mode 100644
index 0000000..abffdbf
--- /dev/null
+++ b/core/java/android/service/assist/classification/FieldClassificationService.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.assist.classification;
+
+import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.BaseBundle;
+import android.os.Build;
+import android.os.CancellationSignal;
+import android.os.IBinder;
+import android.os.ICancellationSignal;
+import android.os.OutcomeReceiver;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A service using {@link android.app.assist.AssistStructure} to detect fields on the screen.
+ * Service may use classifiers to look at the un-stripped AssistStructure to make informed decision
+ * and classify the fields.
+ *
+ * Currently, it's used to detect the field types for the Autofill Framework to provide relevant
+ * autofill suggestions to the user.
+ *
+ *
+ * The methods are invoked on the binder threads.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class FieldClassificationService extends Service {
+
+    private static final String TAG = FieldClassificationService.class.getSimpleName();
+
+    static boolean sDebug = Build.IS_USER ? false : true;
+    static boolean sVerbose = false;
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     * To be supported, the service must also require the
+     * {@link android.Manifest.permission#BIND_FIELD_CLASSIFICATION_SERVICE} permission so
+     * that other applications can not abuse it.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE =
+            "android.service.assist.classification.FieldClassificationService";
+
+    // Used for metrics / debug only
+    private ComponentName mServiceComponentName;
+
+    private final class FieldClassificationServiceImpl
+            extends IFieldClassificationService.Stub {
+
+        @Override
+        public void onConnected(boolean debug, boolean verbose) {
+            handleOnConnected(debug, verbose);
+        }
+
+        @Override
+        public void onDisconnected() {
+            handleOnDisconnected();
+        }
+
+        @Override
+        public void onFieldClassificationRequest(
+                FieldClassificationRequest request, IFieldClassificationCallback callback) {
+            handleOnClassificationRequest(request, callback);
+        }
+    };
+
+    @CallSuper
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        BaseBundle.setShouldDefuse(true);
+    }
+
+    /** @hide */
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            mServiceComponentName = intent.getComponent();
+            return new FieldClassificationServiceImpl().asBinder();
+        }
+        Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+        return null;
+    }
+
+    /**
+     * Called when the Android system connects to service.
+     *
+     * <p>You should generally do initialization here rather than in {@link #onCreate}.
+     */
+    public void onConnected() {
+    }
+
+    /**
+     * Requests the service to handle field classification request.
+     * @param cancellationSignal signal for observing cancellation requests. The system will use
+     *     this to notify you that the detection result is no longer needed and the service should
+     *     stop handling this detection request in order to save resources.
+     * @param outcomeReceiver object used to notify the result of the request. Service <b>must</b>
+     *     call {@link OutcomeReceiver<>#onResult(FieldClassificationResponse)}.
+     */
+    public abstract void onClassificationRequest(
+            @NonNull FieldClassificationRequest request,
+            @NonNull CancellationSignal cancellationSignal,
+            @NonNull OutcomeReceiver<FieldClassificationResponse, Exception> outcomeReceiver);
+
+    /**
+     * Called when the Android system disconnects from the service.
+     *
+     * <p> At this point this service may no longer be an active
+     * {@link FieldClassificationService}.
+     */
+    public void onDisconnected() {
+    }
+
+    private void handleOnConnected(boolean debug, boolean verbose) {
+        if (sDebug || debug) {
+            Log.d(TAG, "handleOnConnected(): debug=" + debug + ", verbose=" + verbose);
+        }
+        sDebug = debug;
+        sVerbose = verbose;
+        onConnected();
+    }
+
+    private void handleOnDisconnected() {
+        onDisconnected();
+    }
+
+    private void handleOnClassificationRequest(
+            FieldClassificationRequest request, @NonNull IFieldClassificationCallback callback) {
+
+        final ICancellationSignal transport = CancellationSignal.createTransport();
+        final CancellationSignal cancellationSignal = CancellationSignal.fromTransport(transport);
+        onClassificationRequest(
+                request,
+                cancellationSignal,
+                new OutcomeReceiver<FieldClassificationResponse, Exception>() {
+                    @Override
+                    public void onResult(FieldClassificationResponse result) {
+                        try {
+                            callback.onSuccess(result);
+                        } catch (RemoteException e) {
+                            e.rethrowFromSystemServer();
+                        }
+                    }
+                    @Override
+                    public void onError(Exception e) {
+                        try {
+                            callback.onFailure();
+                        } catch (RemoteException ex) {
+                            ex.rethrowFromSystemServer();
+                        }
+                    }
+                });
+    }
+}
+
diff --git a/core/java/android/service/assist/classification/IFieldClassificationCallback.aidl b/core/java/android/service/assist/classification/IFieldClassificationCallback.aidl
new file mode 100644
index 0000000..ca9e939
--- /dev/null
+++ b/core/java/android/service/assist/classification/IFieldClassificationCallback.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.assist.classification;
+
+import android.os.Bundle;
+import android.os.ICancellationSignal;
+
+import android.service.assist.classification.FieldClassificationResponse;
+
+import java.util.List;
+
+/**
+ * Interface to receive the result of an autofill request.
+ *
+ * @hide
+ */
+interface IFieldClassificationCallback {
+
+    void onCancellable(in ICancellationSignal cancellation);
+
+    void onSuccess(in FieldClassificationResponse response);
+
+    void onFailure();
+
+    boolean isCompleted();
+
+    void cancel();
+}
diff --git a/core/java/android/service/assist/classification/IFieldClassificationService.aidl b/core/java/android/service/assist/classification/IFieldClassificationService.aidl
new file mode 100644
index 0000000..a93688d
--- /dev/null
+++ b/core/java/android/service/assist/classification/IFieldClassificationService.aidl
@@ -0,0 +1,38 @@
+
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.assist.classification;
+
+import android.content.ComponentName;
+import android.os.IBinder;
+import android.service.assist.classification.IFieldClassificationCallback;
+import android.service.assist.classification.FieldClassificationRequest;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.view.inputmethod.InlineSuggestionsRequest;
+import java.util.List;
+/**
+ * Interface from the system to an Autofill classification service.
+ *
+ * @hide
+ */
+oneway interface IFieldClassificationService {
+    void onConnected(boolean debug, boolean verbose);
+    void onDisconnected();
+    void onFieldClassificationRequest(
+            in FieldClassificationRequest request, in IFieldClassificationCallback callback);
+}
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 0f7c9b6..eb5e893 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -117,6 +117,12 @@
      */
     public static final @RequestFlags int FLAG_RESET_FILL_DIALOG_STATE = 0x100;
 
+    /**
+     * Indicate the fill request is made for PCC detection
+     * @hide
+     */
+    public static final @RequestFlags int FLAG_PCC_DETECTION = 0x200;
+
     /** @hide */
     public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
 
@@ -200,7 +206,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/./frameworks/base/core/java/android/service/autofill/FillRequest.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/autofill/FillRequest.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -215,7 +221,8 @@
         FLAG_VIEW_NOT_FOCUSED,
         FLAG_SUPPORTS_FILL_DIALOG,
         FLAG_IME_SHOWING,
-        FLAG_RESET_FILL_DIALOG_STATE
+        FLAG_RESET_FILL_DIALOG_STATE,
+        FLAG_PCC_DETECTION
     })
     @Retention(RetentionPolicy.SOURCE)
     @DataClass.Generated.Member
@@ -245,6 +252,8 @@
                     return "FLAG_IME_SHOWING";
             case FLAG_RESET_FILL_DIALOG_STATE:
                     return "FLAG_RESET_FILL_DIALOG_STATE";
+            case FLAG_PCC_DETECTION:
+                    return "FLAG_PCC_DETECTION";
             default: return Integer.toHexString(value);
         }
     }
@@ -322,7 +331,8 @@
                         | FLAG_VIEW_NOT_FOCUSED
                         | FLAG_SUPPORTS_FILL_DIALOG
                         | FLAG_IME_SHOWING
-                        | FLAG_RESET_FILL_DIALOG_STATE);
+                        | FLAG_RESET_FILL_DIALOG_STATE
+                        | FLAG_PCC_DETECTION);
         this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
         this.mDelayedFillIntentSender = delayedFillIntentSender;
 
@@ -463,7 +473,7 @@
         byte flg = in.readByte();
         int id = in.readInt();
         List<FillContext> fillContexts = new ArrayList<>();
-        in.readParcelableList(fillContexts, FillContext.class.getClassLoader(), android.service.autofill.FillContext.class);
+        in.readParcelableList(fillContexts, FillContext.class.getClassLoader());
         Bundle clientState = (flg & 0x4) == 0 ? null : in.readBundle();
         int flags = in.readInt();
         InlineSuggestionsRequest inlineSuggestionsRequest = (flg & 0x10) == 0 ? null : (InlineSuggestionsRequest) in.readTypedObject(InlineSuggestionsRequest.CREATOR);
@@ -484,7 +494,8 @@
                         | FLAG_VIEW_NOT_FOCUSED
                         | FLAG_SUPPORTS_FILL_DIALOG
                         | FLAG_IME_SHOWING
-                        | FLAG_RESET_FILL_DIALOG_STATE);
+                        | FLAG_RESET_FILL_DIALOG_STATE
+                        | FLAG_PCC_DETECTION);
         this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
         this.mDelayedFillIntentSender = delayedFillIntentSender;
 
@@ -506,10 +517,10 @@
     };
 
     @DataClass.Generated(
-            time = 1663290803064L,
+            time = 1675460688829L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
-            inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SUPPORTS_FILL_DIALOG\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_IME_SHOWING\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_RESET_FILL_DIALOG_STATE\npublic static final  int INVALID_REQUEST_ID\nprivate final  int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate  void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
+            inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SUPPORTS_FILL_DIALOG\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_IME_SHOWING\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_RESET_FILL_DIALOG_STATE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PCC_DETECTION\npublic static final  int INVALID_REQUEST_ID\nprivate final  int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate  void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/service/credentials/BeginCreateCredentialRequest.java b/core/java/android/service/credentials/BeginCreateCredentialRequest.java
index 348bb2b..e9f7c8a6 100644
--- a/core/java/android/service/credentials/BeginCreateCredentialRequest.java
+++ b/core/java/android/service/credentials/BeginCreateCredentialRequest.java
@@ -17,6 +17,7 @@
 package android.service.credentials;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -38,7 +39,7 @@
  */
 @SuppressLint("ParcelNotFinal")
 public class BeginCreateCredentialRequest implements Parcelable {
-    private final @NonNull CallingAppInfo mCallingAppInfo;
+    private final @Nullable CallingAppInfo mCallingAppInfo;
     private final @NonNull String mType;
     private final @NonNull Bundle mData;
 
@@ -49,13 +50,23 @@
      * null or empty.
      * @throws NullPointerException If {@code data} is null.
      */
-    public BeginCreateCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
-            @NonNull String type, @NonNull Bundle data) {
-        mCallingAppInfo = Objects.requireNonNull(callingAppInfo,
-                "callingAppInfo must not be null");
+    public BeginCreateCredentialRequest(@NonNull String type, @NonNull Bundle data,
+            @Nullable CallingAppInfo callingAppInfo) {
         mType = Preconditions.checkStringNotEmpty(type,
                 "type must not be null or empty");
         mData = Objects.requireNonNull(data, "data must not be null");
+        mCallingAppInfo = callingAppInfo;
+    }
+
+    /**
+     * Constructs a new instance without {@link CallingAppInfo}.
+     *
+     * @throws IllegalArgumentException If {{@code type} string is
+     * null or empty.
+     * @throws NullPointerException If {@code data} is null.
+     */
+    public BeginCreateCredentialRequest(@NonNull String type, @NonNull Bundle data) {
+        this(type, data, /*callingAppInfo=*/null);
     }
 
     private BeginCreateCredentialRequest(@NonNull Parcel in) {
@@ -90,7 +101,7 @@
     }
 
     /** Returns the info pertaining to the calling app. */
-    @NonNull
+    @Nullable
     public CallingAppInfo getCallingAppInfo() {
         return mCallingAppInfo;
     }
diff --git a/core/java/android/service/credentials/BeginGetCredentialOption.java b/core/java/android/service/credentials/BeginGetCredentialOption.java
index 65d63c3..1df908a 100644
--- a/core/java/android/service/credentials/BeginGetCredentialOption.java
+++ b/core/java/android/service/credentials/BeginGetCredentialOption.java
@@ -39,6 +39,11 @@
  */
 @SuppressLint("ParcelNotFinal")
 public class BeginGetCredentialOption implements Parcelable {
+    /**
+     * A unique id associated with this request option.
+     */
+    @NonNull
+    private final String mId;
 
     /**
      * The requested credential type.
@@ -53,6 +58,18 @@
     private final Bundle mCandidateQueryData;
 
     /**
+     * Returns the unique id associated with this request. Providers must pass this id
+     * to the constructor of {@link CredentialEntry} while creating a candidate credential
+     * entry for this request option.
+     *
+     * @hide
+     */
+    @NonNull
+    public String getId() {
+        return mId;
+    }
+
+    /**
      * Returns the requested credential type.
      */
     @NonNull
@@ -80,6 +97,7 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString8(mType);
         dest.writeBundle(mCandidateQueryData);
+        dest.writeString8(mId);
     }
 
     @Override
@@ -92,20 +110,22 @@
         return "GetCredentialOption {"
                 + "type=" + mType
                 + ", candidateQueryData=" + mCandidateQueryData
+                + ", id=" + mId
                 + "}";
     }
 
     /**
      * Constructs a {@link BeginGetCredentialOption}.
      *
-     * @param type the requested credential type
+     * @param id the unique id associated with this option
+     * @param type               the requested credential type
      * @param candidateQueryData the request candidateQueryData
-     *
      * @throws IllegalArgumentException If type is empty.
      */
     public BeginGetCredentialOption(
-            @NonNull String type,
+            @NonNull String id, @NonNull String type,
             @NonNull Bundle candidateQueryData) {
+        mId = id;
         mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
         mCandidateQueryData = requireNonNull(
                 candidateQueryData, "candidateQueryData must not be null");
@@ -114,11 +134,13 @@
     private BeginGetCredentialOption(@NonNull Parcel in) {
         String type = in.readString8();
         Bundle candidateQueryData = in.readBundle();
+        String id = in.readString8();
 
         mType = type;
         AnnotationValidations.validate(NonNull.class, null, mType);
         mCandidateQueryData = candidateQueryData;
         AnnotationValidations.validate(NonNull.class, null, mCandidateQueryData);
+        mId = id;
     }
 
     public static final @NonNull Creator<BeginGetCredentialOption> CREATOR =
diff --git a/core/java/android/service/credentials/BeginGetCredentialRequest.java b/core/java/android/service/credentials/BeginGetCredentialRequest.java
index e375cdd..48b2b05 100644
--- a/core/java/android/service/credentials/BeginGetCredentialRequest.java
+++ b/core/java/android/service/credentials/BeginGetCredentialRequest.java
@@ -17,9 +17,9 @@
 package android.service.credentials;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.content.Intent;
-import android.credentials.GetCredentialOption;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -33,7 +33,7 @@
 /**
  * Query stage request for getting user's credentials from a given credential provider.
  *
- * <p>This request contains a list of {@link GetCredentialOption} that have parameters
+ * <p>This request contains a list of {@link BeginGetCredentialOption} that have parameters
  * to be used to query credentials, and return a list of {@link CredentialEntry} to be set
  * on the {@link BeginGetCredentialResponse}. This list is then shown to the user on a selector.
  *
@@ -44,7 +44,7 @@
  */
 public final class BeginGetCredentialRequest implements Parcelable {
     /** Info pertaining to the app requesting for credentials. */
-    @NonNull private final CallingAppInfo mCallingAppInfo;
+    @Nullable private final CallingAppInfo mCallingAppInfo;
 
     /**
      * List of credential options. Each {@link BeginGetCredentialOption} object holds parameters to
@@ -52,12 +52,12 @@
      *
      * This request does not reveal sensitive parameters. Complete list of parameters
      * is retrieved through the {@link PendingIntent} set on each {@link CredentialEntry}
-     * on {@link CredentialsResponseContent} set on {@link BeginGetCredentialResponse},
+     * on {@link BeginGetCredentialResponse} set on {@link BeginGetCredentialResponse},
      * when the user selects one of these entries.
      */
     @NonNull private final List<BeginGetCredentialOption> mBeginGetCredentialOptions;
 
-    private BeginGetCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
+    private BeginGetCredentialRequest(@Nullable CallingAppInfo callingAppInfo,
             @NonNull List<BeginGetCredentialOption> getBeginCredentialOptions) {
         this.mCallingAppInfo = callingAppInfo;
         this.mBeginGetCredentialOptions = getBeginCredentialOptions;
@@ -99,7 +99,7 @@
     /**
      * Returns info pertaining to the app requesting credentials.
      */
-    public @NonNull CallingAppInfo getCallingAppInfo() {
+    public @Nullable CallingAppInfo getCallingAppInfo() {
         return mCallingAppInfo;
     }
 
@@ -115,17 +115,16 @@
      * Builder for {@link BeginGetCredentialRequest}.
      */
     public static final class Builder {
-        private CallingAppInfo mCallingAppInfo;
+        private CallingAppInfo mCallingAppInfo = null;
         private List<BeginGetCredentialOption> mBeginGetCredentialOptions = new ArrayList<>();
 
         /**
-         * Creates a new builder.
-         * @param callingAppInfo info pertaining to the app requesting credentials
-         *
-         * @throws IllegalArgumentException If {@code callingAppInfo} is null or empty.
+         * Sets information pertaining to the calling app.
+         * @param callingAppInfo the info object containing the package name, and app signatures
          */
-        public Builder(@NonNull CallingAppInfo callingAppInfo) {
-            mCallingAppInfo = Objects.requireNonNull(callingAppInfo);
+        public @NonNull Builder setCallingAppInfo(@Nullable CallingAppInfo callingAppInfo) {
+            mCallingAppInfo = callingAppInfo;
+            return this;
         }
 
         /**
@@ -166,7 +165,6 @@
          * {@code callingAppInfo} is null or empty.
          */
         public @NonNull BeginGetCredentialRequest build() {
-            Objects.requireNonNull(mCallingAppInfo, "callingAppInfo");
             Preconditions.checkCollectionNotEmpty(mBeginGetCredentialOptions,
                     "beginGetCredentialOptions");
             return new BeginGetCredentialRequest(mCallingAppInfo, mBeginGetCredentialOptions);
diff --git a/core/java/android/service/credentials/BeginGetCredentialResponse.java b/core/java/android/service/credentials/BeginGetCredentialResponse.java
index 85e8d85..0f64c63 100644
--- a/core/java/android/service/credentials/BeginGetCredentialResponse.java
+++ b/core/java/android/service/credentials/BeginGetCredentialResponse.java
@@ -21,6 +21,10 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -28,70 +32,44 @@
  * data to be shown on the account selector UI.
  */
 public final class BeginGetCredentialResponse implements Parcelable {
-    /** Content to be used for the UI. */
-    private final @Nullable CredentialsResponseContent mCredentialsResponseContent;
+    /** List of credential entries to be displayed on the UI. */
+    private final @NonNull List<CredentialEntry> mCredentialEntries;
 
-    /**
-     * Authentication action that must be launched and completed before showing any content
-     * from the provider.
-     */
-    private final @Nullable Action mAuthenticationAction;
+    /** List of authentication entries to be displayed on the UI. */
+    private final @NonNull List<Action> mAuthenticationEntries;
 
-    /**
-     * Creates a {@link BeginGetCredentialResponse} instance with an authentication
-     * {@link Action} set. Providers must use this method when no content can be shown
-     * before authentication.
-     *
-     * <p> When the user selects this {@code authenticationAction}, the system invokes the
-     * corresponding {@code pendingIntent}. Once the authentication flow is complete,
-     * the {@link android.app.Activity} result should be set
-     * to {@link android.app.Activity#RESULT_OK} and the
-     * {@link CredentialProviderService#EXTRA_CREDENTIALS_RESPONSE_CONTENT} extra should be set
-     * with a fully populated {@link CredentialsResponseContent} object.
-     * the authentication action activity is launched, and the user is authenticated, providers
-     * should create another response with {@link CredentialsResponseContent} using
-     * {@code createWithDisplayContent}, and add that response to the result of the authentication
-     * activity.
-     *
-     * @throws NullPointerException If {@code authenticationAction} is null.
-     */
-    public static @NonNull BeginGetCredentialResponse createWithAuthentication(
-            @NonNull Action authenticationAction) {
-        Objects.requireNonNull(authenticationAction,
-                "authenticationAction must not be null");
-        return new BeginGetCredentialResponse(null, authenticationAction);
-    }
+    /** List of provider actions to be displayed on the UI. */
+    private final @NonNull List<Action> mActions;
 
-    /**
-     * Creates a {@link BeginGetCredentialRequest} instance with content to be shown on the UI.
-     * Providers must use this method when there is content to be shown without top level
-     * authentication required, including credential entries, action entries or a remote entry,
-     *
-     * @throws NullPointerException If {@code credentialsResponseContent} is null.
-     */
-    public static @NonNull BeginGetCredentialResponse createWithResponseContent(
-            @NonNull CredentialsResponseContent credentialsResponseContent) {
-        Objects.requireNonNull(credentialsResponseContent,
-                "credentialsResponseContent must not be null");
-        return new BeginGetCredentialResponse(credentialsResponseContent, null);
-    }
+    /** Remote credential entry to get the response from a different device. */
+    private final @Nullable CredentialEntry mRemoteCredentialEntry;
 
-    private BeginGetCredentialResponse(@Nullable CredentialsResponseContent
-            credentialsResponseContent,
-            @Nullable Action authenticationAction) {
-        mCredentialsResponseContent = credentialsResponseContent;
-        mAuthenticationAction = authenticationAction;
+    private BeginGetCredentialResponse(@NonNull List<CredentialEntry> credentialEntries,
+            @NonNull List<Action> authenticationEntries, @NonNull List<Action> actions,
+            @Nullable CredentialEntry remoteCredentialEntry) {
+        mCredentialEntries = new ArrayList<>(credentialEntries);
+        mAuthenticationEntries = new ArrayList<>(authenticationEntries);
+        mActions = new ArrayList<>(actions);
+        mRemoteCredentialEntry = remoteCredentialEntry;
     }
 
     private BeginGetCredentialResponse(@NonNull Parcel in) {
-        mCredentialsResponseContent = in.readTypedObject(CredentialsResponseContent.CREATOR);
-        mAuthenticationAction = in.readTypedObject(Action.CREATOR);
+        List<CredentialEntry> credentialEntries = new ArrayList<>();
+        in.readTypedList(credentialEntries, CredentialEntry.CREATOR);
+        mCredentialEntries = credentialEntries;
+        List<Action> authenticationEntries = new ArrayList<>();
+        in.readTypedList(authenticationEntries, Action.CREATOR);
+        mAuthenticationEntries = authenticationEntries;
+        List<Action> actions = new ArrayList<>();
+        in.readTypedList(actions, Action.CREATOR);
+        mActions = actions;
+        mRemoteCredentialEntry = in.readTypedObject(CredentialEntry.CREATOR);
     }
 
     public static final @NonNull Creator<BeginGetCredentialResponse> CREATOR =
             new Creator<BeginGetCredentialResponse>() {
                 @Override
-                public BeginGetCredentialResponse createFromParcel(Parcel in) {
+                public BeginGetCredentialResponse createFromParcel(@NonNull Parcel in) {
                     return new BeginGetCredentialResponse(in);
                 }
 
@@ -108,23 +86,175 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeTypedObject(mCredentialsResponseContent, flags);
-        dest.writeTypedObject(mAuthenticationAction, flags);
+        dest.writeTypedList(mCredentialEntries, flags);
+        dest.writeTypedList(mAuthenticationEntries, flags);
+        dest.writeTypedList(mActions, flags);
+        dest.writeTypedObject(mRemoteCredentialEntry, flags);
     }
 
     /**
-     * If this response represents a top level authentication action, returns the authentication
-     * action to be invoked before any other content can be shown to the user.
+     * Returns the list of credential entries to be displayed on the UI.
      */
-    public @Nullable Action getAuthenticationAction() {
-        return mAuthenticationAction;
+    public @NonNull List<CredentialEntry> getCredentialEntries() {
+        return mCredentialEntries;
     }
 
     /**
-     * Returns the actual content to be displayed on the selector, if this response does not
-     * require any top level authentication.
+     * Returns the list of authentication entries to be displayed on the UI.
      */
-    public @Nullable CredentialsResponseContent getCredentialsResponseContent() {
-        return mCredentialsResponseContent;
+    public @NonNull List<Action> getAuthenticationActions() {
+        return mAuthenticationEntries;
+    }
+
+    /**
+     * Returns the list of actions to be displayed on the UI.
+     */
+    public @NonNull List<Action> getActions() {
+        return mActions;
+    }
+
+    /**
+     * Returns the remote credential entry to be displayed on the UI.
+     */
+    public @Nullable CredentialEntry getRemoteCredentialEntry() {
+        return mRemoteCredentialEntry;
+    }
+
+    /**
+     * Builds an instance of {@link BeginGetCredentialResponse}.
+     */
+    public static final class Builder {
+        private List<CredentialEntry> mCredentialEntries = new ArrayList<>();
+
+        private List<Action> mAuthenticationEntries = new ArrayList<>();
+        private List<Action> mActions = new ArrayList<>();
+        private CredentialEntry mRemoteCredentialEntry;
+
+        /**
+         * Sets a remote credential entry to be shown on the UI. Provider must set this if they
+         * wish to get the credential from a different device.
+         *
+         * <p> When constructing the {@link CredentialEntry} object, the {@code pendingIntent}
+         * must be set such that it leads to an activity that can provide UI to fulfill the request
+         * on a remote device. When user selects this {@code remoteCredentialEntry}, the system will
+         * invoke the {@code pendingIntent} set on the {@link CredentialEntry}.
+         *
+         * <p> Once the remote credential flow is complete, the {@link android.app.Activity}
+         * result should be set to {@link android.app.Activity#RESULT_OK} and an extra with the
+         * {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE} key should be populated
+         * with a {@link android.credentials.Credential} object.
+         */
+        public @NonNull Builder setRemoteCredentialEntry(@Nullable CredentialEntry
+                remoteCredentialEntry) {
+            mRemoteCredentialEntry = remoteCredentialEntry;
+            return this;
+        }
+
+        /**
+         * Adds a {@link CredentialEntry} to the list of entries to be displayed on
+         * the UI.
+         *
+         * @throws NullPointerException If the {@code credentialEntry} is null.
+         */
+        public @NonNull Builder addCredentialEntry(@NonNull CredentialEntry credentialEntry) {
+            mCredentialEntries.add(Objects.requireNonNull(credentialEntry));
+            return this;
+        }
+
+        /**
+         * Add an authentication entry to be shown on the UI. Providers must set this entry if
+         * the corresponding account is locked and no underlying credentials can be returned.
+         *
+         * <p> When the user selects this {@code authenticationAction}, the system invokes the
+         * corresponding {@code pendingIntent}.
+         * Once the authentication action activity is launched, and the user is authenticated,
+         * providers should create another response with {@link BeginGetCredentialResponse} using
+         * this time adding the unlocked credentials in the form of {@link CredentialEntry}'s.
+         *
+         * <p>The new response object must be set on the authentication activity's
+         * result. The result code should be set to {@link android.app.Activity#RESULT_OK} and
+         * the {@link CredentialProviderService#EXTRA_BEGIN_GET_CREDENTIAL_RESPONSE} extra
+         * should be set with the new fully populated {@link BeginGetCredentialResponse} object.
+         *
+         * @throws NullPointerException If {@code authenticationAction} is null.
+         */
+        public @NonNull Builder addAuthenticationAction(@NonNull Action authenticationAction) {
+            mAuthenticationEntries.add(Objects.requireNonNull(authenticationAction));
+            return this;
+        }
+
+        /**
+         * Adds an {@link Action} to the list of actions to be displayed on
+         * the UI.
+         *
+         * <p> An {@code action} must be used for independent user actions,
+         * such as opening the app, intenting directly into a certain app activity etc. The
+         * {@code pendingIntent} set with the {@code action} must invoke the corresponding
+         * activity.
+         *
+         * @throws NullPointerException If {@code action} is null.
+         */
+        public @NonNull Builder addAction(@NonNull Action action) {
+            mActions.add(Objects.requireNonNull(action, "action must not be null"));
+            return this;
+        }
+
+        /**
+         * Sets the list of actions to be displayed on the UI.
+         *
+         * @throws NullPointerException If {@code actions} is null, or any of its elements
+         *                              is null.
+         */
+        public @NonNull Builder setActions(@NonNull List<Action> actions) {
+            mActions = Preconditions.checkCollectionElementsNotNull(actions,
+                    "actions");
+            return this;
+        }
+
+        /**
+         * Sets the list of credential entries to be displayed on the
+         * account selector UI.
+         *
+         * @throws NullPointerException If {@code credentialEntries} is null, or any of its
+         *                              elements is null.
+         */
+        public @NonNull Builder setCredentialEntries(
+                @NonNull List<CredentialEntry> credentialEntries) {
+            mCredentialEntries = Preconditions.checkCollectionElementsNotNull(
+                    credentialEntries,
+                    "credentialEntries");
+            return this;
+        }
+
+        /**
+         * Sets the list of authentication entries to be displayed on the
+         * account selector UI.
+         *
+         * @throws NullPointerException If {@code authenticationEntries} is null, or any of its
+         *                              elements is null.
+         */
+        public @NonNull Builder setAuthenticationActions(
+                @NonNull List<Action> authenticationActions) {
+            mAuthenticationEntries = Preconditions.checkCollectionElementsNotNull(
+                    authenticationActions,
+                    "authenticationActions");
+            return this;
+        }
+
+        /**
+         * Builds a {@link BeginGetCredentialResponse} instance.
+         *
+         * @throws IllegalStateException if {@code credentialEntries}, {@code actions}
+         *                               and {@code remoteCredentialEntry} are all null or empty.
+         */
+        public @NonNull BeginGetCredentialResponse build() {
+            if (mCredentialEntries.isEmpty() && mActions.isEmpty()
+                    && mRemoteCredentialEntry == null && mAuthenticationEntries.isEmpty()) {
+                throw new IllegalStateException("must set either an authentication, "
+                        + "credential, action or remote entry");
+            }
+            return new BeginGetCredentialResponse(mCredentialEntries, mAuthenticationEntries,
+                    mActions, mRemoteCredentialEntry);
+        }
     }
 }
diff --git a/core/java/android/service/credentials/CredentialEntry.java b/core/java/android/service/credentials/CredentialEntry.java
index b037268..b6c13c4 100644
--- a/core/java/android/service/credentials/CredentialEntry.java
+++ b/core/java/android/service/credentials/CredentialEntry.java
@@ -16,7 +16,10 @@
 
 package android.service.credentials;
 
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.app.PendingIntent;
 import android.app.slice.Slice;
@@ -29,9 +32,11 @@
  * user.
  *
  * <p>If user selects this entry, the corresponding {@link PendingIntent},
- * set on the {@code slice} as a {@link androidx.slice.core.SliceAction} will be
- * invoked to launch activities that require some user engagement before getting
- * the credential corresponding to this entry, e.g. authentication, confirmation etc.
+ * set on the {@code slice} will be invoked to launch activities that require some user engagement
+ * before getting the credential corresponding to this entry, e.g. authentication,
+ * confirmation etc. The extras associated with the resulting {@link android.app.Activity} will
+ * also contain the complete credential request containing all required parameters. This request
+ * can be retrieved against {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_REQUEST}.
  *
  * Once the activity fulfills the required user engagement, the {@link android.app.Activity}
  * result should be set to {@link android.app.Activity#RESULT_OK}, and the
@@ -42,24 +47,69 @@
  * object passed into the constructor. Any other field will not be parceled through. If the
  * derived class has custom parceling implementation, this class will not be able to unpack
  * the parcel without having access to that implementation.
+ *
+ * <p>While creating this entry, providers must set a {@code requestId} to be retrieved
+ * from {@link BeginGetCredentialOption#getId()}, to determine for which request this entry is
+ * being presented to the user. This will ensure that when user selects the entry, the correct
+ * complete request is added to the {@link PendingIntent} mentioned above.
  */
 @SuppressLint("ParcelNotFinal")
 public class CredentialEntry implements Parcelable {
+    /** The request option that corresponds to this entry. **/
+    private final @Nullable BeginGetCredentialOption mBeginGetCredentialOption;
+
     /** The type of the credential entry to be shown on the UI. */
     private final @NonNull String mType;
 
+
     /** The object containing display content to be shown along with this credential entry
      * on the UI. */
     private final @NonNull Slice mSlice;
 
+    /**
+     * Creates an entry that is associated with a {@link BeginGetCredentialOption} request.
+     * Providers must use this constructor when they extend from {@link CredentialProviderService}
+     * to respond to query phase {@link CredentialProviderService#onBeginGetCredential}
+     * credential retrieval requests.
+     *
+     * @param beginGetCredentialOption the request option for which this credential entry is
+     *                                 being constructed This helps maintain an association,
+     *                                 such that when the user selects this entry, providers
+     *                                 can receive the conmplete corresponding request.
+     * @param slice the slice containing the metadata to be shown on the UI. Must be
+     *              constructed through the androidx.credentials jetpack library.
+     */
+    public CredentialEntry(@NonNull BeginGetCredentialOption beginGetCredentialOption,
+            @NonNull Slice slice) {
+        mBeginGetCredentialOption = requireNonNull(beginGetCredentialOption,
+                "beginGetCredentialOption must not be null");
+        mType = requireNonNull(mBeginGetCredentialOption.getType(),
+                "type must not be null");
+        mSlice = requireNonNull(slice, "slice must not be null");
+    }
+
+    /**
+     * Creates an entry that is independent of an incoming {@link BeginGetCredentialOption}
+     * request. Providers must use this constructor for constructing entries to be registered
+     * with the framework outside of the span of an API call.
+     *
+     * @param type the type of the credential
+     * @param slice the slice containing the metadata to be shown on the UI. Must be
+     *              constructed through the androidx.credentials jetpack library.
+     *
+     * @hide
+     */
+    // TODO: Unhide this constructor when the registry APIs are stable
     public CredentialEntry(@NonNull String type, @NonNull Slice slice) {
-        mType = type;
-        mSlice = slice;
+        mBeginGetCredentialOption = null;
+        mType = requireNonNull(type, "type must not be null");
+        mSlice = requireNonNull(slice, "slice must not be null");
     }
 
     private CredentialEntry(@NonNull Parcel in) {
         mType = in.readString8();
         mSlice = in.readTypedObject(Slice.CREATOR);
+        mBeginGetCredentialOption = in.readTypedObject(BeginGetCredentialOption.CREATOR);
     }
 
     @NonNull
@@ -85,6 +135,15 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString8(mType);
         dest.writeTypedObject(mSlice, flags);
+        dest.writeTypedObject(mBeginGetCredentialOption, flags);
+    }
+
+    /**
+     * Returns the request option for which this credential entry has been constructed.
+     */
+    @NonNull
+    public BeginGetCredentialOption getBeginGetCredentialOption() {
+        return mBeginGetCredentialOption;
     }
 
     /**
diff --git a/core/java/android/service/credentials/CredentialProviderService.java b/core/java/android/service/credentials/CredentialProviderService.java
index ee386c3..dabf08e 100644
--- a/core/java/android/service/credentials/CredentialProviderService.java
+++ b/core/java/android/service/credentials/CredentialProviderService.java
@@ -90,14 +90,15 @@
     /**
      * Intent extra: The result of an authentication flow, to be set on finish of the
      * {@link android.app.Activity} invoked through the {@link android.app.PendingIntent} set on
-     * a {@link BeginGetCredentialResponse}. This result should contain the actual content,
+     * an authentication {@link Action}, as part of the original
+     * {@link BeginGetCredentialResponse}. This result should contain the actual content,
      * including credential entries and action entries, to be shown on the selector.
      *
      * <p>
-     * Type: {@link CredentialsResponseContent}
+     * Type: {@link BeginGetCredentialResponse}
      */
-    public static final String EXTRA_CREDENTIALS_RESPONSE_CONTENT =
-            "android.service.credentials.extra.CREDENTIALS_RESPONSE_CONTENT";
+    public static final String EXTRA_BEGIN_GET_CREDENTIAL_RESPONSE =
+            "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_RESPONSE";
 
     /**
      * Intent extra: The failure exception set at the final stage of a get flow.
@@ -133,7 +134,7 @@
      * <p>When a provider app receives a {@link BeginGetCredentialRequest} through the
      * {@link CredentialProviderService#onBeginGetCredential} call, it can construct the
      * {@link BeginGetCredentialResponse} with either an authentication {@link Action} (if the app
-     * is locked), or a {@link CredentialsResponseContent} (if the app is unlocked). In the former
+     * is locked), or a {@link BeginGetCredentialResponse} (if the app is unlocked). In the former
      * case, i.e. the app is locked, user will be shown the authentication action. When selected,
      * the underlying {@link PendingIntent} will be invoked which will lead the user to provider's
      * unlock activity. This pending intent will also contain the original
@@ -141,7 +142,7 @@
      * flow is complete.
      *
      * <p>After the app is unlocked, the {@link BeginGetCredentialResponse} must be constructed
-     * using a {@link CredentialsResponseContent}, which must be set on an {@link Intent} as an
+     * using a {@link BeginGetCredentialResponse}, which must be set on an {@link Intent} as an
      * intent extra against CredentialProviderService#EXTRA_CREDENTIALS_RESPONSE_CONTENT}.
      * This intent should then be set as a result through {@link android.app.Activity#setResult}
      * before finishing the activity.
@@ -308,7 +309,7 @@
      *
      * <p>This API denotes a query stage request for getting user's credentials from a given
      * credential provider. The request contains a list of
-     * {@link android.credentials.GetCredentialOption} that have parameters to be used for
+     * {@link BeginGetCredentialOption} that have parameters to be used for
      * populating candidate credentials, as a list of {@link CredentialEntry} to be set
      * on the {@link BeginGetCredentialResponse}. This list is then shown to the user on a
      * selector.
diff --git a/core/java/android/service/credentials/CredentialsResponseContent.java b/core/java/android/service/credentials/CredentialsResponseContent.java
deleted file mode 100644
index ce6972d..0000000
--- a/core/java/android/service/credentials/CredentialsResponseContent.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.credentials;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * The content to be displayed on the account selector UI, including credential entries,
- * actions etc. Returned as part of {@link BeginGetCredentialResponse}
- */
-public final class CredentialsResponseContent implements Parcelable {
-    /** List of credential entries to be displayed on the UI. */
-    private final @NonNull List<CredentialEntry> mCredentialEntries;
-
-    /** List of provider actions to be displayed on the UI. */
-    private final @NonNull List<Action> mActions;
-
-    /** Remote credential entry to get the response from a different device. */
-    private final @Nullable CredentialEntry mRemoteCredentialEntry;
-
-    private CredentialsResponseContent(@NonNull List<CredentialEntry> credentialEntries,
-            @NonNull List<Action> actions,
-            @Nullable CredentialEntry remoteCredentialEntry) {
-        mCredentialEntries = credentialEntries;
-        mActions = actions;
-        mRemoteCredentialEntry = remoteCredentialEntry;
-    }
-
-    private CredentialsResponseContent(@NonNull Parcel in) {
-        List<CredentialEntry> credentialEntries = new ArrayList<>();
-        in.readTypedList(credentialEntries, CredentialEntry.CREATOR);
-        mCredentialEntries = credentialEntries;
-        List<Action> actions = new ArrayList<>();
-        in.readTypedList(actions, Action.CREATOR);
-        mActions = actions;
-        mRemoteCredentialEntry = in.readTypedObject(CredentialEntry.CREATOR);
-    }
-
-    public static final @NonNull Creator<CredentialsResponseContent> CREATOR =
-            new Creator<CredentialsResponseContent>() {
-                @Override
-                public CredentialsResponseContent createFromParcel(@NonNull Parcel in) {
-                    return new CredentialsResponseContent(in);
-                }
-
-                @Override
-                public CredentialsResponseContent[] newArray(int size) {
-                    return new CredentialsResponseContent[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeTypedList(mCredentialEntries, flags);
-        dest.writeTypedList(mActions, flags);
-        dest.writeTypedObject(mRemoteCredentialEntry, flags);
-    }
-
-    /**
-     * Returns the list of credential entries to be displayed on the UI.
-     */
-    public @NonNull List<CredentialEntry> getCredentialEntries() {
-        return mCredentialEntries;
-    }
-
-    /**
-     * Returns the list of actions to be displayed on the UI.
-     */
-    public @NonNull List<Action> getActions() {
-        return mActions;
-    }
-
-    /**
-     * Returns the remote credential entry to be displayed on the UI.
-     */
-    public @Nullable CredentialEntry getRemoteCredentialEntry() {
-        return mRemoteCredentialEntry;
-    }
-
-    /**
-     * Builds an instance of {@link CredentialsResponseContent}.
-     */
-    public static final class Builder {
-        private List<CredentialEntry> mCredentialEntries = new ArrayList<>();
-        private List<Action> mActions = new ArrayList<>();
-        private CredentialEntry mRemoteCredentialEntry;
-
-        /**
-         * Sets a remote credential entry to be shown on the UI. Provider must set this if they
-         * wish to get the credential from a different device.
-         *
-         * <p> When constructing the {@link CredentialEntry} object, the {@code pendingIntent}
-         * must be set such that it leads to an activity that can provide UI to fulfill the request
-         * on a remote device. When user selects this {@code remoteCredentialEntry}, the system will
-         * invoke the {@code pendingIntent} set on the {@link CredentialEntry}.
-         *
-         * <p> Once the remote credential flow is complete, the {@link android.app.Activity}
-         * result should be set to {@link android.app.Activity#RESULT_OK} and an extra with the
-         * {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE} key should be populated
-         * with a {@link android.credentials.Credential} object.
-         */
-        public @NonNull Builder setRemoteCredentialEntry(@Nullable CredentialEntry
-                remoteCredentialEntry) {
-            mRemoteCredentialEntry = remoteCredentialEntry;
-            return this;
-        }
-
-        /**
-         * Adds a {@link CredentialEntry} to the list of entries to be displayed on
-         * the UI.
-         *
-         * @throws NullPointerException If the {@code credentialEntry} is null.
-         */
-        public @NonNull Builder addCredentialEntry(@NonNull CredentialEntry credentialEntry) {
-            mCredentialEntries.add(Objects.requireNonNull(credentialEntry));
-            return this;
-        }
-
-        /**
-         * Adds an {@link Action} to the list of actions to be displayed on
-         * the UI.
-         *
-         * <p> An {@code action} must be used for independent user actions,
-         * such as opening the app, intenting directly into a certain app activity etc. The
-         * {@code pendingIntent} set with the {@code action} must invoke the corresponding
-         * activity.
-         *
-         * @throws NullPointerException If {@code action} is null.
-         */
-        public @NonNull Builder addAction(@NonNull Action action) {
-            mActions.add(Objects.requireNonNull(action, "action must not be null"));
-            return this;
-        }
-
-        /**
-         * Sets the list of actions to be displayed on the UI.
-         *
-         * @throws NullPointerException If {@code actions} is null, or any of its elements
-         * is null.
-         */
-        public @NonNull Builder setActions(@NonNull List<Action> actions) {
-            mActions = Preconditions.checkCollectionElementsNotNull(actions,
-                    "actions");
-            return this;
-        }
-
-        /**
-         * Sets the list of credential entries to be displayed on the
-         * account selector UI.
-         *
-         * @throws NullPointerException If {@code credentialEntries} is null, or any of its
-         * elements is null.
-         */
-        public @NonNull Builder setCredentialEntries(
-                @NonNull List<CredentialEntry> credentialEntries) {
-            mCredentialEntries = Preconditions.checkCollectionElementsNotNull(
-                    credentialEntries,
-                    "credentialEntries");
-            return this;
-        }
-
-        /**
-         * Builds a {@link CredentialsResponseContent} instance.
-         *
-         * @throws IllegalStateException if {@code credentialEntries}, {@code actions}
-         * and {@code remoteCredentialEntry} are all null or empty.
-         */
-        public @NonNull CredentialsResponseContent build() {
-            if (mCredentialEntries != null && mCredentialEntries.isEmpty()
-                    && mActions != null && mActions.isEmpty() && mRemoteCredentialEntry == null) {
-                throw new IllegalStateException("credentialEntries and actions must not both "
-                        + "be empty");
-            }
-            return new CredentialsResponseContent(mCredentialEntries, mActions,
-                    mRemoteCredentialEntry);
-        }
-    }
-}
diff --git a/core/java/android/service/credentials/GetCredentialRequest.java b/core/java/android/service/credentials/GetCredentialRequest.java
index 4b946f0..7cdccc6 100644
--- a/core/java/android/service/credentials/GetCredentialRequest.java
+++ b/core/java/android/service/credentials/GetCredentialRequest.java
@@ -17,7 +17,7 @@
 package android.service.credentials;
 
 import android.annotation.NonNull;
-import android.credentials.GetCredentialOption;
+import android.credentials.CredentialOption;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,28 +32,30 @@
  */
 public final class GetCredentialRequest implements Parcelable {
     /** Calling package of the app requesting for credentials. */
-    private final @NonNull CallingAppInfo mCallingAppInfo;
+    @NonNull
+    private final CallingAppInfo mCallingAppInfo;
 
     /**
      * Holds parameters to be used for retrieving a specific type of credential.
      */
-    private final @NonNull GetCredentialOption mGetCredentialOption;
+    @NonNull
+    private final CredentialOption mCredentialOption;
 
     public GetCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
-            @NonNull GetCredentialOption getCredentialOption) {
+            @NonNull CredentialOption credentialOption) {
         this.mCallingAppInfo = callingAppInfo;
-        this.mGetCredentialOption = getCredentialOption;
+        this.mCredentialOption = credentialOption;
     }
 
     private GetCredentialRequest(@NonNull Parcel in) {
         mCallingAppInfo = in.readTypedObject(CallingAppInfo.CREATOR);
         AnnotationValidations.validate(NonNull.class, null, mCallingAppInfo);
-        mGetCredentialOption = in.readTypedObject(GetCredentialOption.CREATOR);
-        AnnotationValidations.validate(NonNull.class, null, mGetCredentialOption);
+        mCredentialOption = in.readTypedObject(CredentialOption.CREATOR);
+        AnnotationValidations.validate(NonNull.class, null, mCredentialOption);
     }
 
-    public static final @NonNull Creator<GetCredentialRequest> CREATOR =
-            new Creator<GetCredentialRequest>() {
+    @NonNull public static final  Creator<GetCredentialRequest> CREATOR =
+            new Creator<>() {
                 @Override
                 public GetCredentialRequest createFromParcel(Parcel in) {
                     return new GetCredentialRequest(in);
@@ -73,20 +75,22 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeTypedObject(mCallingAppInfo, flags);
-        dest.writeTypedObject(mGetCredentialOption, flags);
+        dest.writeTypedObject(mCredentialOption, flags);
     }
 
     /**
      * Returns info pertaining to the app requesting credentials.
      */
-    public @NonNull CallingAppInfo getCallingAppInfo() {
+    @NonNull
+    public CallingAppInfo getCallingAppInfo() {
         return mCallingAppInfo;
     }
 
     /**
      * Returns the parameters needed to return a given type of credential.
      */
-    public @NonNull GetCredentialOption getGetCredentialOption() {
-        return mGetCredentialOption;
+    @NonNull
+    public CredentialOption getCredentialOption() {
+        return mCredentialOption;
     }
 }
diff --git a/core/java/android/service/quickaccesswallet/WalletCard.java b/core/java/android/service/quickaccesswallet/WalletCard.java
index 950f9b5..e52adcc 100644
--- a/core/java/android/service/quickaccesswallet/WalletCard.java
+++ b/core/java/android/service/quickaccesswallet/WalletCard.java
@@ -36,7 +36,7 @@
  * card, library card, transit pass, etc. Cards are identified by a String identifier and contain a
  * card type, card image, card image content description, and a {@link PendingIntent} to be used if
  * the user clicks on the card. Cards may be displayed with an icon and label, though these are
- * optional. Valuable cards will also have a second image that will be displayed when the card is
+ * optional. Non-payment cards will also have a second image that will be displayed when the card is
  * tapped.
  */
 
@@ -54,10 +54,10 @@
     public static final int CARD_TYPE_PAYMENT = 1;
 
     /**
-     * Valuable cards refer to any cards that are not used for cash-equivalent payment.
-     * This includes event tickets, flights, offers, loyalty cards, gift cards and transit tickets.
+     * Non-payment cards refer to any cards that are not used for cash-equivalent payment, including
+     * event tickets, flights, offers, loyalty cards, gift cards and transit tickets.
      */
-    public static final int CARD_TYPE_VALUABLE = 2;
+    public static final int CARD_TYPE_NON_PAYMENT = 2;
 
     private final String mCardId;
     private final int mCardType;
@@ -66,7 +66,7 @@
     private final PendingIntent mPendingIntent;
     private final Icon mCardIcon;
     private final CharSequence mCardLabel;
-    private final Icon mValuableCardSecondaryImage;
+    private final Icon mNonPaymentCardSecondaryImage;
 
     private WalletCard(Builder builder) {
         this.mCardId = builder.mCardId;
@@ -76,7 +76,7 @@
         this.mPendingIntent = builder.mPendingIntent;
         this.mCardIcon = builder.mCardIcon;
         this.mCardLabel = builder.mCardLabel;
-        this.mValuableCardSecondaryImage = builder.mValuableCardSecondaryImage;
+        this.mNonPaymentCardSecondaryImage = builder.mNonPaymentCardSecondaryImage;
     }
 
     /**
@@ -86,7 +86,7 @@
     @IntDef(prefix = {"CARD_TYPE_"}, value = {
             CARD_TYPE_UNKNOWN,
             CARD_TYPE_PAYMENT,
-            CARD_TYPE_VALUABLE
+            CARD_TYPE_NON_PAYMENT
     })
     public @interface CardType {
     }
@@ -105,7 +105,7 @@
         PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, dest);
         writeIconIfNonNull(mCardIcon, dest, flags);
         TextUtils.writeToParcel(mCardLabel, dest, flags);
-        writeIconIfNonNull(mValuableCardSecondaryImage, dest, flags);
+        writeIconIfNonNull(mNonPaymentCardSecondaryImage, dest, flags);
 
     }
 
@@ -128,14 +128,14 @@
         PendingIntent pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(source);
         Icon cardIcon = source.readByte() == 0 ? null : Icon.CREATOR.createFromParcel(source);
         CharSequence cardLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-        Icon valuableCardSecondaryImage = source.readByte() == 0 ? null :
+        Icon nonPaymentCardSecondaryImage = source.readByte() == 0 ? null :
                 Icon.CREATOR.createFromParcel(source);
         Builder builder = new Builder(cardId, cardType, cardImage, contentDesc, pendingIntent)
                 .setCardIcon(cardIcon)
                 .setCardLabel(cardLabel);
 
-        return cardType == CARD_TYPE_VALUABLE
-                ? builder.setValuableCardSecondaryImage(valuableCardSecondaryImage).build() :
+        return cardType == CARD_TYPE_NON_PAYMENT
+                ? builder.setNonPaymentCardSecondaryImage(nonPaymentCardSecondaryImage).build() :
                  builder.build();
     }
 
@@ -225,12 +225,12 @@
     }
 
     /**
-    * Visual representation of the card when it is tapped. Includes a barcode to scan the card in
-     * addition to the information in the primary image.
-    */
+     * Visual representation of the card when it is tapped. May include additional information
+     *  unique to the card, such as a barcode or number. Only valid for CARD_TYPE_NON_PAYMENT.
+     */
     @Nullable
-    public Icon getValuableCardSecondaryImage() {
-        return mValuableCardSecondaryImage;
+    public Icon getNonPaymentCardSecondaryImage() {
+        return mNonPaymentCardSecondaryImage;
     }
 
     /**
@@ -246,7 +246,7 @@
         private PendingIntent mPendingIntent;
         private Icon mCardIcon;
         private CharSequence mCardLabel;
-        private Icon mValuableCardSecondaryImage;
+        private Icon mNonPaymentCardSecondaryImage;
 
         /**
          * @param cardId             The card id must be non-null and unique within the list of
@@ -254,7 +254,7 @@
          *                           </b> this card ID should <b>not</b> contain PII (Personally
          *                           Identifiable Information, such as username or email address).
          * @param cardType           Integer representing the card type. The card type must be
-         *                           non-null. If not provided, it defaults to unknown.
+         *                           non-null.
          * @param cardImage          The visual representation of the card. If the card image Icon
          *                           is a bitmap, it should have a width of {@link
          *                           GetWalletCardsRequest#getCardWidthPx()} and a height of {@link
@@ -289,8 +289,8 @@
         }
 
         /**
-         * Called when a card type is not provided. Calls {@link
-         * Builder#Builder(String, int, Icon, CharSequence, PendingIntent)} with default card type
+         * Called when a card type is not provided, in which case it defaults to CARD_TYPE_UNKNOWN.
+         * Calls {@link Builder#Builder(String, int, Icon, CharSequence, PendingIntent)}
          */
         public Builder(@NonNull String cardId,
                 @NonNull Icon cardImage,
@@ -332,14 +332,15 @@
         }
 
         /**
-         * Visual representation of the card when it is tapped. Includes a barcode to scan the card
-         * in addition to the information in the primary image.
+         * Visual representation of the card when it is tapped. May include additional information
+         *  unique to the card, such as a barcode or number. Only valid for CARD_TYPE_NON_PAYMENT.
          */
         @NonNull
-        public Builder setValuableCardSecondaryImage(@Nullable Icon valuableCardSecondaryImage) {
-            Preconditions.checkState(mCardType == CARD_TYPE_VALUABLE,
-                    "This field can only be set on valuable cards");
-            mValuableCardSecondaryImage = valuableCardSecondaryImage;
+        public Builder
+                setNonPaymentCardSecondaryImage(@Nullable Icon nonPaymentCardSecondaryImage) {
+            Preconditions.checkState(mCardType == CARD_TYPE_NON_PAYMENT,
+                    "This field can only be set on non-payment cards");
+            mNonPaymentCardSecondaryImage = nonPaymentCardSecondaryImage;
             return this;
         }
 
diff --git a/core/java/android/service/search/ISearchUiService.aidl b/core/java/android/service/search/ISearchUiService.aidl
index aae66ca..bc6d421 100644
--- a/core/java/android/service/search/ISearchUiService.aidl
+++ b/core/java/android/service/search/ISearchUiService.aidl
@@ -37,5 +37,11 @@
 
     void onNotifyEvent(in SearchSessionId sessionId, in Query input, in SearchTargetEvent event);
 
+    void onRegisterEmptyQueryResultUpdateCallback (in SearchSessionId sessionId, in ISearchCallback callback);
+
+    void onRequestEmptyQueryResultUpdate(in SearchSessionId sessionId);
+
+    void onUnregisterEmptyQueryResultUpdateCallback(in SearchSessionId sessionId, in ISearchCallback callback);
+
     void onDestroy(in SearchSessionId sessionId);
 }
diff --git a/core/java/android/service/search/SearchUiService.java b/core/java/android/service/search/SearchUiService.java
index 02d41ef..55a96fa 100644
--- a/core/java/android/service/search/SearchUiService.java
+++ b/core/java/android/service/search/SearchUiService.java
@@ -20,6 +20,7 @@
 import android.annotation.CallSuper;
 import android.annotation.MainThread;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.app.search.ISearchCallback;
@@ -35,8 +36,10 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.service.search.ISearchUiService.Stub;
+import android.util.ArrayMap;
 import android.util.Slog;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Consumer;
 
@@ -66,6 +69,9 @@
     public static final String SERVICE_INTERFACE =
             "android.service.search.SearchUiService";
 
+    private final ArrayMap<SearchSessionId, ArrayList<CallbackWrapper>>
+            mSessionEmptyQueryResultCallbacks = new ArrayMap<>();
+
     private Handler mHandler;
 
     private final android.service.search.ISearchUiService mInterface = new Stub() {
@@ -87,7 +93,7 @@
             mHandler.sendMessage(
                     obtainMessage(SearchUiService::onQuery,
                             SearchUiService.this, sessionId, input,
-                            new CallbackWrapper(callback)));
+                            new CallbackWrapper(callback, null)));
         }
 
         @Override
@@ -98,6 +104,28 @@
         }
 
         @Override
+        public void onRegisterEmptyQueryResultUpdateCallback(SearchSessionId sessionId,
+                ISearchCallback callback) {
+            mHandler.sendMessage(
+                    obtainMessage(SearchUiService::doRegisterEmptyQueryResultUpdateCallback,
+                            SearchUiService.this, sessionId, callback));
+        }
+
+        @Override
+        public void onRequestEmptyQueryResultUpdate(SearchSessionId sessionId) {
+            mHandler.sendMessage(obtainMessage(SearchUiService::doRequestEmptyQueryResultUpdate,
+                    SearchUiService.this, sessionId));
+        }
+
+        @Override
+        public void onUnregisterEmptyQueryResultUpdateCallback(SearchSessionId sessionId,
+                ISearchCallback callback) {
+            mHandler.sendMessage(
+                    obtainMessage(SearchUiService::doUnregisterEmptyQueryResultUpdateCallback,
+                            SearchUiService.this, sessionId, callback));
+        }
+
+        @Override
         public void onDestroy(SearchSessionId sessionId) {
             mHandler.sendMessage(
                     obtainMessage(SearchUiService::doDestroy,
@@ -126,21 +154,23 @@
     /**
      * Creates a new search session.
      *
+     * @removed
      * @deprecated this is method will be removed as soon as
      * {@link #onSearchSessionCreated(SearchContext, SearchSessionId)}
      * is adopted by the service.
-     *
-     * @removed
      */
     @Deprecated
     public void onCreateSearchSession(@NonNull SearchContext context,
-            @NonNull SearchSessionId sessionId) {}
+            @NonNull SearchSessionId sessionId) {
+    }
 
     /**
      * A new search session is created.
      */
     public void onSearchSessionCreated(@NonNull SearchContext context,
-            @NonNull SearchSessionId sessionId) {}
+            @NonNull SearchSessionId sessionId) {
+        mSessionEmptyQueryResultCallbacks.put(sessionId, new ArrayList<>());
+    }
 
     /**
      * Called by the client to request search results using a query string.
@@ -161,6 +191,98 @@
             @NonNull Query query,
             @NonNull SearchTargetEvent event);
 
+    private void doRegisterEmptyQueryResultUpdateCallback(@NonNull SearchSessionId sessionId,
+            @NonNull ISearchCallback callback) {
+        final ArrayList<CallbackWrapper> callbacks = mSessionEmptyQueryResultCallbacks.get(
+                sessionId);
+        if (callbacks == null) {
+            Slog.e(TAG, "Failed to register for updates for unknown session: " + sessionId);
+            return;
+        }
+
+        final CallbackWrapper wrapper = findCallbackWrapper(callbacks, callback);
+        if (wrapper == null) {
+            callbacks.add(new CallbackWrapper(callback,
+                    callbackWrapper ->
+                            mHandler.post(() ->
+                                    removeCallbackWrapper(callbacks, callbackWrapper))));
+            if (callbacks.size() == 1) {
+                onStartUpdateEmptyQueryResult();
+            }
+        }
+    }
+
+    /**
+     * Called when the first empty query result callback is registered. Service provider may make
+     * their own decision whether to generate data if no callback is registered to optimize for
+     * system health.
+     */
+    @MainThread
+    public void onStartUpdateEmptyQueryResult() {}
+
+    private void doRequestEmptyQueryResultUpdate(@NonNull SearchSessionId sessionId) {
+        // Just an optimization, if there are no callbacks, then don't bother notifying the service
+        final ArrayList<CallbackWrapper> callbacks = mSessionEmptyQueryResultCallbacks.get(
+                sessionId);
+        if (callbacks != null && !callbacks.isEmpty()) {
+            onRequestEmptyQueryResultUpdate(sessionId);
+        }
+    }
+
+    /**
+     * Called by a client to request empty query search target result for zero state. This method
+     * is only called if there are one or more empty query result update callbacks registered.
+     *
+     * @see #updateEmptyQueryResult(SearchSessionId, List)
+     */
+    @MainThread
+    public void onRequestEmptyQueryResultUpdate(@NonNull SearchSessionId sessionId) {}
+
+    private void doUnregisterEmptyQueryResultUpdateCallback(@NonNull SearchSessionId sessionId,
+            @NonNull ISearchCallback callback) {
+        final ArrayList<CallbackWrapper> callbacks = mSessionEmptyQueryResultCallbacks.get(
+                sessionId);
+        if (callbacks == null) {
+            Slog.e(TAG, "Failed to unregister for updates for unknown session: " + sessionId);
+            return;
+        }
+
+        final CallbackWrapper wrapper = findCallbackWrapper(callbacks, callback);
+        removeCallbackWrapper(callbacks, wrapper);
+    }
+
+    /**
+     * Finds the callback wrapper for the given callback.
+     */
+    private CallbackWrapper findCallbackWrapper(ArrayList<CallbackWrapper> callbacks,
+            ISearchCallback callback) {
+        for (int i = callbacks.size() - 1; i >= 0; i--) {
+            if (callbacks.get(i).isCallback(callback)) {
+                return callbacks.get(i);
+            }
+        }
+        return null;
+    }
+
+    private void removeCallbackWrapper(@Nullable ArrayList<CallbackWrapper> callbacks,
+            @Nullable CallbackWrapper wrapper) {
+        if (callbacks == null || wrapper == null) {
+            return;
+        }
+        callbacks.remove(wrapper);
+        wrapper.destroy();
+        if (callbacks.isEmpty()) {
+            onStopUpdateEmptyQueryResult();
+        }
+    }
+
+    /**
+     * Called when there are no longer any empty query result callbacks registered. Service
+     * provider can choose to stop generating data to optimize for system health.
+     */
+    @MainThread
+    public void onStopUpdateEmptyQueryResult() {}
+
     private void doDestroy(@NonNull SearchSessionId sessionId) {
         super.onDestroy();
         onDestroy(sessionId);
@@ -172,14 +294,49 @@
     @MainThread
     public abstract void onDestroy(@NonNull SearchSessionId sessionId);
 
-    private static final class CallbackWrapper implements Consumer<List<SearchTarget>> {
+    /**
+     * Used by the service provider to send back results the client app. The can be called
+     * in response to {@link #onRequestEmptyQueryResultUpdate(SearchSessionId)} or proactively as
+     * a result of changes in zero state data.
+     */
+    public final void updateEmptyQueryResult(@NonNull SearchSessionId sessionId,
+            @NonNull List<SearchTarget> targets) {
+        List<CallbackWrapper> callbacks = mSessionEmptyQueryResultCallbacks.get(sessionId);
+        if (callbacks != null) {
+            for (CallbackWrapper callback : callbacks) {
+                callback.accept(targets);
+            }
+        }
+    }
+
+    private static final class CallbackWrapper implements Consumer<List<SearchTarget>>,
+            IBinder.DeathRecipient {
 
         private ISearchCallback mCallback;
+        private final Consumer<CallbackWrapper> mOnBinderDied;
 
-        CallbackWrapper(ISearchCallback callback) {
+        CallbackWrapper(ISearchCallback callback,
+                @Nullable Consumer<CallbackWrapper> onBinderDied) {
             mCallback = callback;
+            mOnBinderDied = onBinderDied;
+            if (mOnBinderDied != null) {
+                try {
+                    mCallback.asBinder().linkToDeath(this, 0);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to link to death:" + e);
+                }
+            }
         }
 
+        public boolean isCallback(@NonNull ISearchCallback callback) {
+            if (mCallback == null) {
+                Slog.e(TAG, "Callback is null, likely the binder has died.");
+                return false;
+            }
+            return mCallback.asBinder().equals(callback.asBinder());
+        }
+
+
         @Override
         public void accept(List<SearchTarget> searchTargets) {
             try {
@@ -193,5 +350,20 @@
                 Slog.e(TAG, "Error sending result:" + e);
             }
         }
+
+        public void destroy() {
+            if (mCallback != null && mOnBinderDied != null) {
+                mCallback.asBinder().unlinkToDeath(this, 0);
+            }
+        }
+
+        @Override
+        public void binderDied() {
+            destroy();
+            mCallback = null;
+            if (mOnBinderDied != null) {
+                mOnBinderDied.accept(this);
+            }
+        }
     }
 }
diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS
index 59a0c2e..ec44100 100644
--- a/core/java/android/service/voice/OWNERS
+++ b/core/java/android/service/voice/OWNERS
@@ -1,3 +1,7 @@
 # Bug component: 533220
 
 include /core/java/android/app/assist/OWNERS
+
+# The owner here should not be assist owner
+liangyuchen@google.com
+tuanng@google.com
diff --git a/core/java/android/service/voice/VisualQueryDetectionService.java b/core/java/android/service/voice/VisualQueryDetectionService.java
index fde0afb..2e455c2 100644
--- a/core/java/android/service/voice/VisualQueryDetectionService.java
+++ b/core/java/android/service/voice/VisualQueryDetectionService.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.media.AudioFormat;
+import android.media.AudioSystem;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.os.ParcelFileDescriptor;
@@ -129,7 +130,7 @@
 
         @Override
         public void updateAudioFlinger(IBinder audioFlinger) {
-            Log.v(TAG, "Ignore #updateAudioFlinger");
+            AudioSystem.setAudioFlingerBinder(audioFlinger);
         }
 
         @Override
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 44afb89..23513fad 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1242,7 +1242,7 @@
                             null /* ignoringVisibilityState */, config.isScreenRound(),
                             false /* alwaysConsumeSystemBars */, mLayout.softInputMode,
                             mLayout.flags, SYSTEM_UI_FLAG_VISIBLE, mLayout.type,
-                            config.windowConfiguration.getWindowingMode(), null /* typeSideMap */);
+                            config.windowConfiguration.getWindowingMode(), null /* idSideMap */);
 
                     if (!fixedSize) {
                         final Rect padding = mIWallpaperEngine.mDisplayPadding;
diff --git a/core/java/android/text/Highlights.java b/core/java/android/text/Highlights.java
index 356dfca..ac4a5f2 100644
--- a/core/java/android/text/Highlights.java
+++ b/core/java/android/text/Highlights.java
@@ -38,9 +38,9 @@
     }
 
     /**
-     * Returns a number of highlight.
+     * Returns the number of highlight.
      *
-     * @return a number of highlight.
+     * @return the number of highlight.
      *
      * @see Builder#addRange(Paint, int, int)
      * @see Builder#addRanges(Paint, int...)
@@ -53,7 +53,7 @@
      * Returns a paint used for the i-th highlight.
      *
      * @param index an index of the highlight. Must be between 0 and {@link #getSize()}
-     * @return a paint object
+     * @return the paint object
      *
      * @see Builder#addRange(Paint, int, int)
      * @see Builder#addRanges(Paint, int...)
@@ -72,7 +72,7 @@
      * [1, 2, 3, 4].
      *
      * @param index an index of the highlight. Must be between 0 and {@link #getSize()}
-     * @return a paint object
+     * @return the flattened ranges.
      *
      * @see Builder#addRange(Paint, int, int)
      * @see Builder#addRanges(Paint, int...)
@@ -90,6 +90,9 @@
         /**
          * Add single range highlight.
          *
+         * If the given range has overlaps with the already added ranges, the previous highlights
+         * are overdrawn by this range.
+         *
          * @param paint a paint object used for drawing highlight path.
          * @param start an inclusive offset of the text.
          * @param end an exclusive offset of the text.
@@ -111,6 +114,9 @@
         /**
          * Add multiple ranges highlight.
          *
+         * If the given ranges have overlap with the already added ranges, the previous highlights
+         * are overdrawn by this range.
+         *
          * @param paint a paint object used for drawing highlight path.
          * @param ranges a flatten ranges. The {@code 2 * i}-th element is an inclusive start offset
          *              of the {@code i}-th character. The {@code 2 * i + 1}-th element is an
diff --git a/core/java/android/tracing/OWNERS b/core/java/android/tracing/OWNERS
index 7d1b48b..079d4c5 100644
--- a/core/java/android/tracing/OWNERS
+++ b/core/java/android/tracing/OWNERS
@@ -1,2 +1,3 @@
 carmenjackson@google.com
+kevinjeon@google.com
 include platform/external/perfetto:/OWNERS
diff --git a/core/java/android/transparency/BinaryTransparencyManager.java b/core/java/android/transparency/BinaryTransparencyManager.java
index d77bbcc..c18adfc 100644
--- a/core/java/android/transparency/BinaryTransparencyManager.java
+++ b/core/java/android/transparency/BinaryTransparencyManager.java
@@ -67,24 +67,6 @@
     }
 
     /**
-     * Gets binary measurements of all installed APEXs, each packed in a Bundle.
-     * @return A List of {@link android.os.Bundle}s with the following keys:
-     *         {@link com.android.server.BinaryTransparencyService#BUNDLE_PACKAGE_INFO}
-     *         {@link com.android.server.BinaryTransparencyService#BUNDLE_CONTENT_DIGEST_ALGORITHM}
-     *         {@link com.android.server.BinaryTransparencyService#BUNDLE_CONTENT_DIGEST}
-     */
-    // TODO(b/259422958): Fix static constants referenced here - should be defined here
-    @NonNull
-    public List getApexInfo() {
-        try {
-            Slog.d(TAG, "Calling backend's getApexInfo()");
-            return mService.getApexInfo();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Collects the APEX information on the device.
      *
      * @param includeTestOnly Whether to include test only data in the returned ApexInfo.
@@ -116,4 +98,21 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Collects the silent installed MBA information on the device.
+     *
+     * @return A List containing the MBA info of silent installed.
+     * @hide
+     */
+    @NonNull
+    public List<IBinaryTransparencyService.AppInfo> collectAllSilentInstalledMbaInfo(
+            Bundle packagesToSkip) {
+        try {
+            Slog.d(TAG, "Calling backend's collectAllSilentInstalledMbaInfo()");
+            return mService.collectAllSilentInstalledMbaInfo(packagesToSkip);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 06fe523..ba9847e 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -76,6 +76,16 @@
     public static final String SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME =
             "settings_app_allow_dark_theme_activation_at_bedtime";
 
+    /**
+     * Flag to decouple bluetooth LE Audio Broadcast from Unicast
+     * If the flag is true, the broadcast feature will be enabled when the phone
+     * is connected to the BLE device.
+     * If the flag is false, it is not necessary to connect the BLE device.
+     * @hide
+     */
+    public static final String SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST =
+            "settings_need_connected_ble_device_for_broadcast";
+
     /** @hide */
     public static final String SETTINGS_AUTO_TEXT_WRAPPING = "settings_auto_text_wrapping";
 
@@ -199,21 +209,22 @@
         DEFAULT_FLAGS.put(SETTINGS_VOLUME_PANEL_IN_SYSTEMUI, "false");
         DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true");
         DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "true");
+        DEFAULT_FLAGS.put(SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, "true");
         DEFAULT_FLAGS.put(SETTINGS_AUTO_TEXT_WRAPPING, "false");
         DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_UI, "false");
         DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_SHORTCUT, "false");
         DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_MODIFIER_KEY, "false");
         DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD, "false");
         DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE, "false");
-        DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA, "false");
+        DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA, "true");
         DEFAULT_FLAGS.put(SETTINGS_ADB_METRICS_WRITER, "false");
-        DEFAULT_FLAGS.put(SETTINGS_SHOW_STYLUS_PREFERENCES, "false");
+        DEFAULT_FLAGS.put(SETTINGS_SHOW_STYLUS_PREFERENCES, "true");
         DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_ENROLLMENT, "false");
         DEFAULT_FLAGS.put(SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE, "false");
         DEFAULT_FLAGS.put(SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM, "false");
         DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "false");
         DEFAULT_FLAGS.put(SETTINGS_FLASH_ALERTS, "false");
-        DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "false");
+        DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "true");
         DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "false");
     }
 
diff --git a/core/java/android/util/RotationUtils.java b/core/java/android/util/RotationUtils.java
index 3e7c67e..f20767b 100644
--- a/core/java/android/util/RotationUtils.java
+++ b/core/java/android/util/RotationUtils.java
@@ -27,6 +27,7 @@
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
+import android.view.Surface;
 import android.view.Surface.Rotation;
 import android.view.SurfaceControl;
 
@@ -245,4 +246,23 @@
                 throw new IllegalArgumentException("Unknown rotation: " + rotation);
         }
     }
+
+    /**
+     * Reverses the rotation direction around the Z axis. Note that this method assumes all
+     * rotations are relative to {@link Surface.ROTATION_0}.
+     *
+     * @param rotation the original rotation.
+     * @return the new rotation that should be applied.
+     */
+    @Surface.Rotation
+    public static int reverseRotationDirectionAroundZAxis(@Surface.Rotation int rotation) {
+        // Flipping 270 and 90 has the same effect as changing the direction which rotation is
+        // applied.
+        if (rotation == Surface.ROTATION_90) {
+            rotation = Surface.ROTATION_270;
+        } else if (rotation == Surface.ROTATION_270) {
+            rotation = Surface.ROTATION_90;
+        }
+        return rotation;
+    }
 }
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index f299238..3cf56c0 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -1571,7 +1571,7 @@
                     parent = provider.createAccessibilityNodeInfo(virtualDescendantId);
                     if (parent == null) {
                         // Going up the parent relation we found a null predecessor,
-                        // so remove these disconnected nodes form the result.
+                        // so remove these disconnected nodes from the result.
                         final int currentResultSize = outInfos.size();
                         for (int i = currentResultSize - 1; i >= initialResultSize; i--) {
                             outInfos.remove(i);
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 91febcd..3dc79cf 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -270,10 +270,14 @@
     private static final int CALLBACK_LAST = CALLBACK_COMMIT;
 
     private Choreographer(Looper looper, int vsyncSource) {
+        this(looper, vsyncSource, /* layerHandle */ 0L);
+    }
+
+    private Choreographer(Looper looper, int vsyncSource, long layerHandle) {
         mLooper = looper;
         mHandler = new FrameHandler(looper);
         mDisplayEventReceiver = USE_VSYNC
-                ? new FrameDisplayEventReceiver(looper, vsyncSource)
+                ? new FrameDisplayEventReceiver(looper, vsyncSource, layerHandle)
                 : null;
         mLastFrameTimeNanos = Long.MIN_VALUE;
 
@@ -313,6 +317,26 @@
     }
 
     /**
+     * Gets the choreographer associated with the SurfaceControl.
+     *
+     * @param layerHandle to which the choreographer will be attached.
+     * @param looper      the choreographer is attached on this looper.
+     *
+     * @return The choreographer for the looper which is attached
+     * to the sourced SurfaceControl::mNativeHandle.
+     * @throws IllegalStateException if the looper sourced is null.
+     * @hide
+     */
+    @NonNull
+    static Choreographer getInstanceForSurfaceControl(long layerHandle,
+            @NonNull Looper looper) {
+        if (looper == null) {
+            throw new IllegalStateException("The current thread must have a looper!");
+        }
+        return new Choreographer(looper, VSYNC_SOURCE_APP, layerHandle);
+    }
+
+    /**
      * @return The Choreographer of the main thread, if it exists, or {@code null} otherwise.
      * @hide
      */
@@ -334,6 +358,15 @@
     }
 
     /**
+     * Dispose the DisplayEventReceiver on the Choreographer.
+     * @hide
+     */
+    @UnsupportedAppUsage
+    void invalidate() {
+        dispose();
+    }
+
+    /**
      * The amount of time, in milliseconds, between each frame of the animation.
      * <p>
      * This is a requested time that the animation will attempt to honor, but the actual delay
@@ -1166,8 +1199,8 @@
         private int mFrame;
         private VsyncEventData mLastVsyncEventData = new VsyncEventData();
 
-        public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
-            super(looper, vsyncSource, 0);
+        FrameDisplayEventReceiver(Looper looper, int vsyncSource, long layerHandle) {
+            super(looper, vsyncSource, /* eventRegistration */ 0, layerHandle);
         }
 
         // TODO(b/116025192): physicalDisplayId is ignored because SF only emits VSYNC events for
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 25863a6..6b1499f 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -360,6 +360,17 @@
     public static final int FLAG_STEAL_TOP_FOCUS_DISABLED = 1 << 12;
 
     /**
+     * Display flag: Indicates that the display is a rear display.
+     * <p>
+     * This flag identifies complementary displays that are facing away from the user.
+     * </p>
+     *
+     * @hide
+     * @see #getFlags()
+     */
+    public static final int FLAG_REAR = 1 << 13;
+
+    /**
      * Display flag: Indicates that the contents of the display should not be scaled
      * to fit the physical screen dimensions.  Used for development only to emulate
      * devices with smaller physicals screens while preserving density.
@@ -2497,5 +2508,24 @@
                     + ", mMaxAverageLuminance=" + mMaxAverageLuminance
                     + ", mMinLuminance=" + mMinLuminance + '}';
         }
+
+        /**
+         * @hide
+         */
+        @NonNull
+        public static String hdrTypeToString(int hdrType) {
+            switch (hdrType) {
+                case HDR_TYPE_DOLBY_VISION:
+                    return "HDR_TYPE_DOLBY_VISION";
+                case HDR_TYPE_HDR10:
+                    return "HDR_TYPE_HDR10";
+                case HDR_TYPE_HLG:
+                    return "HDR_TYPE_HLG";
+                case HDR_TYPE_HDR10_PLUS:
+                    return "HDR_TYPE_HDR10_PLUS";
+                default:
+                    return "HDR_TYPE_INVALID";
+            }
+        }
     }
 }
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index ce7606a0..edce001 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -27,6 +27,8 @@
 
 import dalvik.annotation.optimization.FastNative;
 
+import libcore.util.NativeAllocationRegistry;
+
 import java.lang.ref.WeakReference;
 
 /**
@@ -80,12 +82,18 @@
     private MessageQueue mMessageQueue;
 
     private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
-            MessageQueue messageQueue, int vsyncSource, int eventRegistration);
-    private static native void nativeDispose(long receiverPtr);
+            MessageQueue messageQueue, int vsyncSource, int eventRegistration, long layerHandle);
+    private static native long nativeGetDisplayEventReceiverFinalizer();
     @FastNative
     private static native void nativeScheduleVsync(long receiverPtr);
     private static native VsyncEventData nativeGetLatestVsyncEventData(long receiverPtr);
 
+    private static final NativeAllocationRegistry sNativeAllocationRegistry =
+            NativeAllocationRegistry.createMalloced(
+                    DisplayEventReceiver.class.getClassLoader(),
+                    nativeGetDisplayEventReceiverFinalizer());
+    private Runnable mFreeNativeResources;
+
     /**
      * Creates a display event receiver.
      *
@@ -93,7 +101,11 @@
      */
     @UnsupportedAppUsage
     public DisplayEventReceiver(Looper looper) {
-        this(looper, VSYNC_SOURCE_APP, 0);
+        this(looper, VSYNC_SOURCE_APP, /* eventRegistration */ 0, /* layerHandle */ 0L);
+    }
+
+    public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration) {
+        this(looper, vsyncSource, eventRegistration, /* layerHandle */ 0L);
     }
 
     /**
@@ -103,36 +115,27 @@
      * @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
      * @param eventRegistration Which events to dispatch. Must be a bitfield consist of the
      * EVENT_REGISTRATION_*_FLAG values.
+     * @param layerHandle Layer to which the current instance is attached to
      */
-    public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration) {
+    public DisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration,
+            long layerHandle) {
         if (looper == null) {
             throw new IllegalArgumentException("looper must not be null");
         }
 
         mMessageQueue = looper.getQueue();
         mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
-                vsyncSource, eventRegistration);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            dispose(true);
-        } finally {
-            super.finalize();
-        }
+                vsyncSource, eventRegistration, layerHandle);
+        mFreeNativeResources = sNativeAllocationRegistry.registerNativeAllocation(this,
+                mReceiverPtr);
     }
 
     /**
      * Disposes the receiver.
      */
     public void dispose() {
-        dispose(false);
-    }
-
-    private void dispose(boolean finalized) {
         if (mReceiverPtr != 0) {
-            nativeDispose(mReceiverPtr);
+            mFreeNativeResources.run();
             mReceiverPtr = 0;
         }
         mMessageQueue = null;
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index c2b6bc5..3a02c48 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -337,6 +337,9 @@
     @Nullable
     public DisplayShape displayShape;
 
+    @Nullable
+    public SurfaceControl.RefreshRateRange layoutLimitedRefreshRate;
+
     public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
         @Override
         public DisplayInfo createFromParcel(Parcel source) {
@@ -411,7 +414,8 @@
                 && brightnessDefault == other.brightnessDefault
                 && Objects.equals(roundedCorners, other.roundedCorners)
                 && installOrientation == other.installOrientation
-                && Objects.equals(displayShape, other.displayShape);
+                && Objects.equals(displayShape, other.displayShape)
+                && Objects.equals(layoutLimitedRefreshRate, other.layoutLimitedRefreshRate);
     }
 
     @Override
@@ -466,6 +470,7 @@
         roundedCorners = other.roundedCorners;
         installOrientation = other.installOrientation;
         displayShape = other.displayShape;
+        layoutLimitedRefreshRate = other.layoutLimitedRefreshRate;
     }
 
     public void readFromParcel(Parcel source) {
@@ -526,6 +531,7 @@
         }
         installOrientation = source.readInt();
         displayShape = source.readTypedObject(DisplayShape.CREATOR);
+        layoutLimitedRefreshRate = source.readTypedObject(SurfaceControl.RefreshRateRange.CREATOR);
     }
 
     @Override
@@ -584,6 +590,7 @@
         }
         dest.writeInt(installOrientation);
         dest.writeTypedObject(displayShape, flags);
+        dest.writeTypedObject(layoutLimitedRefreshRate, flags);
     }
 
     @Override
@@ -758,7 +765,7 @@
         sb.append(name);
         sb.append("\", displayId ");
         sb.append(displayId);
-        sb.append("\", displayGroupId ");
+        sb.append(", displayGroupId ");
         sb.append(displayGroupId);
         sb.append(flagsToString(flags));
         sb.append(", real ");
@@ -843,6 +850,8 @@
         sb.append(brightnessDefault);
         sb.append(", installOrientation ");
         sb.append(Surface.rotationToString(installOrientation));
+        sb.append(", layoutLimitedRefreshRate ");
+        sb.append(layoutLimitedRefreshRate);
         sb.append("}");
         return sb.toString();
     }
@@ -906,6 +915,9 @@
         if ((flags & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) {
             result.append(", FLAG_TOUCH_FEEDBACK_DISABLED");
         }
+        if ((flags & Display.FLAG_REAR) != 0) {
+            result.append(", FLAG_REAR_DISPLAY");
+        }
         return result.toString();
     }
 }
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index e89be47..4a3b8ac 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -123,7 +123,7 @@
 
         // TODO: ResultReceiver for IME.
         // TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag.
-        ImeTracker.get().onProgress(statsToken,
+        ImeTracker.forLogging().onProgress(statsToken,
                 ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_REQUEST_SHOW);
 
         if (getControl() == null) {
@@ -133,7 +133,8 @@
         // If we had a request before to show from IME (tracked with mImeRequestedShow), reaching
         // this code here means that we now got control, so we can start the animation immediately.
         // If client window is trying to control IME and IME is already visible, it is immediate.
-        if (fromIme || (mState.getSource(getId()).isVisible() && getControl() != null)) {
+        if (fromIme
+                || (mState.isSourceOrDefaultVisible(getId(), getType()) && getControl() != null)) {
             return ShowResult.SHOW_IMMEDIATELY;
         }
 
@@ -164,12 +165,13 @@
         //  - we do already have one, but we have control and use the passed in token
         //      for the insets animation already.
         if (statsToken == null || getControl() != null) {
-            statsToken = ImeTracker.get().onRequestHide(null /* component */, Process.myUid(),
+            statsToken = ImeTracker.forLogging().onRequestHide(null /* component */,
+                    Process.myUid(),
                     ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
                     SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
         }
 
-        ImeTracker.get().onProgress(statsToken,
+        ImeTracker.forLogging().onProgress(statsToken,
                 ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_NOTIFY_HIDDEN);
 
         getImm().notifyImeHidden(mController.getHost().getWindowToken(), statsToken);
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index b22a43e..720f569 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -448,6 +448,7 @@
      */
     public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
 
+    // Cap motion ranges to prevent attacks (b/25637534)
     private static final int MAX_RANGES = 1000;
 
     private static final int VIBRATOR_ID_ALL = -1;
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 309a94a..75f1666 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -33,12 +33,12 @@
 import static android.view.InsetsController.DEBUG;
 import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
 import static android.view.InsetsController.LayoutInsetsDuringAnimation;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.InsetsState.ISIDE_BOTTOM;
 import static android.view.InsetsState.ISIDE_FLOATING;
 import static android.view.InsetsState.ISIDE_LEFT;
 import static android.view.InsetsState.ISIDE_RIGHT;
 import static android.view.InsetsState.ISIDE_TOP;
-import static android.view.InsetsState.ITYPE_IME;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.inputmethod.ImeTracker.DEBUG_IME_VISIBILITY;
@@ -132,19 +132,19 @@
         mController = controller;
         mInitialInsetsState = new InsetsState(state, true /* copySources */);
         if (frame != null) {
-            final SparseIntArray typeSideMap = new SparseIntArray();
-            mCurrentInsets = getInsetsFromState(mInitialInsetsState, frame, null /* typeSideMap */);
+            final SparseIntArray idSideMap = new SparseIntArray();
+            mCurrentInsets = getInsetsFromState(mInitialInsetsState, frame, null /* idSideMap */);
             mHiddenInsets = calculateInsets(mInitialInsetsState, frame, controls, false /* shown */,
-                    null /* typeSideMap */);
+                    null /* idSideMap */);
             mShownInsets = calculateInsets(mInitialInsetsState, frame, controls, true /* shown */,
-                    typeSideMap);
+                    idSideMap);
             mHasZeroInsetsIme = mShownInsets.bottom == 0 && controlsType(WindowInsets.Type.ime());
             if (mHasZeroInsetsIme) {
                 // IME has shownInsets of ZERO, and can't map to a side by default.
                 // Map zero insets IME to bottom, making it a special case of bottom insets.
-                typeSideMap.put(ITYPE_IME, ISIDE_BOTTOM);
+                idSideMap.put(ID_IME, ISIDE_BOTTOM);
             }
-            buildSideControlsMap(typeSideMap, mSideControlsMap, controls);
+            buildSideControlsMap(idSideMap, mSideControlsMap, controls);
         } else {
             // Passing a null frame indicates the caller wants to play the insets animation anyway,
             // no matter the source provides insets to the frame or not.
@@ -399,27 +399,27 @@
     }
 
     private Insets getInsetsFromState(InsetsState state, Rect frame,
-            @Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
+            @Nullable @InternalInsetsSide SparseIntArray idSideMap) {
         return state.calculateInsets(frame, null /* ignoringVisibilityState */,
                 false /* isScreenRound */, false /* alwaysConsumeSystemBars */,
                 LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/,
                 0 /* legacyWindowFlags */, 0 /* legacySystemUiFlags */, TYPE_APPLICATION,
-                WINDOWING_MODE_UNDEFINED, typeSideMap).getInsets(mTypes);
+                WINDOWING_MODE_UNDEFINED, idSideMap).getInsets(mTypes);
     }
 
     /** Computes the insets relative to the given frame. */
     private Insets calculateInsets(InsetsState state, Rect frame,
             SparseArray<InsetsSourceControl> controls, boolean shown,
-            @Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
+            @Nullable @InternalInsetsSide SparseIntArray idSideMap) {
         for (int i = controls.size() - 1; i >= 0; i--) {
             final InsetsSourceControl control  = controls.valueAt(i);
             if (control == null) {
                 // control may be null if it got revoked.
                 continue;
             }
-            state.getSource(control.getId()).setVisible(shown);
+            state.setSourceVisible(control.getId(), shown);
         }
-        return getInsetsFromState(state, frame, typeSideMap);
+        return getInsetsFromState(state, frame, idSideMap);
     }
 
     /** Computes the insets from the insets hints of controls. */
@@ -435,7 +435,8 @@
                 // control may be null if it got revoked.
                 continue;
             }
-            if (state == null || state.getSource(control.getId()).isVisible()) {
+            if (state == null
+                    || state.isSourceOrDefaultVisible(control.getId(), control.getType())) {
                 insets = Insets.max(insets, control.getInsetsHint());
             }
         }
@@ -465,20 +466,23 @@
         // TODO: Implement behavior when inset spans over multiple types
         for (int i = controls.size() - 1; i >= 0; i--) {
             final InsetsSourceControl control = controls.valueAt(i);
-            final InsetsSource source = mInitialInsetsState.getSource(control.getId());
+            final InsetsSource source = mInitialInsetsState.peekSource(control.getId());
             final SurfaceControl leash = control.getLeash();
 
             mTmpMatrix.setTranslate(control.getSurfacePosition().x, control.getSurfacePosition().y);
-            mTmpFrame.set(source.getFrame());
+            if (source != null) {
+                mTmpFrame.set(source.getFrame());
+            }
             addTranslationToMatrix(side, offset, mTmpMatrix, mTmpFrame);
 
             final boolean visible = mHasZeroInsetsIme && side == ISIDE_BOTTOM
                     ? (mAnimationType == ANIMATION_TYPE_SHOW || !mFinished)
                     : inset != 0;
 
-            if (outState != null) {
-                outState.getSource(source.getId()).setVisible(visible);
-                outState.getSource(source.getId()).setFrame(mTmpFrame);
+            if (outState != null && source != null) {
+                outState.getOrCreateSource(source.getId(), source.getType())
+                        .setVisible(visible)
+                        .setFrame(mTmpFrame);
             }
 
             // If the system is controlling the insets source, the leash can be null.
@@ -517,12 +521,12 @@
         }
     }
 
-    private static void buildSideControlsMap(SparseIntArray typeSideMap,
+    private static void buildSideControlsMap(SparseIntArray idSideMap,
             SparseSetArray<InsetsSourceControl> sideControlsMap,
             SparseArray<InsetsSourceControl> controls) {
-        for (int i = typeSideMap.size() - 1; i >= 0; i--) {
-            final int type = typeSideMap.keyAt(i);
-            final int side = typeSideMap.valueAt(i);
+        for (int i = idSideMap.size() - 1; i >= 0; i--) {
+            final int type = idSideMap.keyAt(i);
+            final int side = idSideMap.valueAt(i);
             final InsetsSourceControl control = controls.get(type);
             if (control == null) {
                 // If the types that we are controlling are less than the types that the system has,
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 8e8e28a..d8bff1c 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -19,13 +19,14 @@
 import static android.os.Trace.TRACE_TAG_VIEW;
 import static android.view.InsetsControllerProto.CONTROL;
 import static android.view.InsetsControllerProto.STATE;
-import static android.view.InsetsState.ITYPE_CAPTION_BAR;
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
 import static android.view.WindowInsets.Type.FIRST;
 import static android.view.WindowInsets.Type.LAST;
 import static android.view.WindowInsets.Type.all;
+import static android.view.WindowInsets.Type.captionBar;
 import static android.view.WindowInsets.Type.ime;
+import static android.view.inputmethod.ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL;
 
 import android.animation.AnimationHandler;
 import android.animation.Animator;
@@ -35,6 +36,8 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityThread;
+import android.content.Context;
 import android.content.res.CompatibilityInfo;
 import android.graphics.Insets;
 import android.graphics.Rect;
@@ -44,13 +47,12 @@
 import android.os.Process;
 import android.os.Trace;
 import android.text.TextUtils;
-import android.util.ArraySet;
+import android.util.IntArray;
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
 import android.view.InsetsSourceConsumer.ShowResult;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.SurfaceControl.Transaction;
 import android.view.WindowInsets.Type;
 import android.view.WindowInsets.Type.InsetsType;
@@ -60,6 +62,7 @@
 import android.view.animation.LinearInterpolator;
 import android.view.animation.PathInterpolator;
 import android.view.inputmethod.ImeTracker;
+import android.view.inputmethod.ImeTracker.InputMethodJankContext;
 import android.view.inputmethod.InputMethodManager;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -186,6 +189,14 @@
         @Nullable
         String getRootViewTitle();
 
+        /**
+         * @return the context related to the rootView.
+         */
+        @Nullable
+        default Context getRootViewContext() {
+            return null;
+        }
+
         /** @see ViewRootImpl#dipToPx */
         int dipToPx(int dips);
 
@@ -249,6 +260,9 @@
     /** The amount IME will move up/down when animating in floating mode. */
     private static final int FLOATING_IME_BOTTOM_INSET_DP = -80;
 
+    private static final int ID_CAPTION_BAR =
+            InsetsSource.createId(null /* owner */, 0 /* index */, captionBar());
+
     static final boolean DEBUG = false;
     static final boolean WARN = false;
 
@@ -306,7 +320,7 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {ANIMATION_TYPE_NONE, ANIMATION_TYPE_SHOW, ANIMATION_TYPE_HIDE,
             ANIMATION_TYPE_USER, ANIMATION_TYPE_RESIZE})
-    @interface AnimationType {
+    public @interface AnimationType {
     }
 
     /**
@@ -321,6 +335,25 @@
     /** Logging listener. */
     private WindowInsetsAnimationControlListener mLoggingListener;
 
+    /** Context for {@link android.view.inputmethod.ImeTracker.ImeJankTracker} to monitor jank. */
+    private final InputMethodJankContext mJankContext = new InputMethodJankContext() {
+        @Override
+        public Context getDisplayContext() {
+            return mHost != null ? mHost.getRootViewContext() : null;
+        }
+
+        @Override
+        public SurfaceControl getTargetSurfaceControl() {
+            final InsetsSourceControl imeSourceControl = getImeSourceConsumer().getControl();
+            return imeSourceControl != null ? imeSourceControl.getLeash() : null;
+        }
+
+        @Override
+        public String getHostPackageName() {
+            return mHost != null ? mHost.getRootViewContext().getPackageName() : null;
+        }
+    };
+
     /**
      * The default implementation of listener, to be used by InsetsController and InsetsPolicy to
      * animate insets.
@@ -338,6 +371,7 @@
         private final boolean mDisable;
         private final int mFloatingImeBottomInset;
         private final WindowInsetsAnimationControlListener mLoggingListener;
+        private final InputMethodJankContext mInputMethodJankContext;
 
         private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
                 new ThreadLocal<AnimationHandler>() {
@@ -351,7 +385,8 @@
 
         public InternalAnimationControlListener(boolean show, boolean hasAnimationCallbacks,
                 @InsetsType int requestedTypes, @Behavior int behavior, boolean disable,
-                int floatingImeBottomInset, WindowInsetsAnimationControlListener loggingListener) {
+                int floatingImeBottomInset, WindowInsetsAnimationControlListener loggingListener,
+                @Nullable InputMethodJankContext jankContext) {
             mShow = show;
             mHasAnimationCallbacks = hasAnimationCallbacks;
             mRequestedTypes = requestedTypes;
@@ -360,6 +395,7 @@
             mDisable = disable;
             mFloatingImeBottomInset = floatingImeBottomInset;
             mLoggingListener = loggingListener;
+            mInputMethodJankContext = jankContext;
         }
 
         @Override
@@ -406,10 +442,26 @@
                         + insetsFraction);
             });
             mAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    if (mInputMethodJankContext == null) return;
+                    ImeTracker.forJank().onRequestAnimation(
+                            mInputMethodJankContext,
+                            mShow ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE,
+                            !mHasAnimationCallbacks);
+                }
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    if (mInputMethodJankContext == null) return;
+                    ImeTracker.forJank().onCancelAnimation();
+                }
 
                 @Override
                 public void onAnimationEnd(Animator animation) {
                     onAnimationFinish();
+                    if (mInputMethodJankContext == null) return;
+                    ImeTracker.forJank().onFinishAnimation();
                 }
             });
             if (!mHasAnimationCallbacks) {
@@ -621,6 +673,79 @@
     private final Runnable mInvokeControllableInsetsChangedListeners =
             this::invokeControllableInsetsChangedListeners;
 
+    private final InsetsState.OnTraverseCallbacks mRemoveGoneSources =
+            new InsetsState.OnTraverseCallbacks() {
+
+                private final IntArray mPendingRemoveIndexes = new IntArray();
+
+                @Override
+                public void onIdNotFoundInState2(int index1, InsetsSource source1) {
+                    if (!CAPTION_ON_SHELL && source1.getType() == captionBar()) {
+                        return;
+                    }
+
+                    // Don't change the indexes of the sources while traversing. Remove it later.
+                    mPendingRemoveIndexes.add(index1);
+
+                    // Remove the consumer as well except the IME one. IME consumer should always
+                    // be there since we need to communicate with InputMethodManager no matter we
+                    // have the source or not.
+                    if (source1.getType() != ime()) {
+                        mSourceConsumers.remove(source1.getId());
+                    }
+                }
+
+                @Override
+                public void onFinish(InsetsState state1, InsetsState state2) {
+                    for (int i = mPendingRemoveIndexes.size() - 1; i >= 0; i--) {
+                        state1.removeSourceAt(mPendingRemoveIndexes.get(i));
+                    }
+                    mPendingRemoveIndexes.clear();
+                }
+            };
+
+    private final InsetsState.OnTraverseCallbacks mStartResizingAnimationIfNeeded =
+            new InsetsState.OnTraverseCallbacks() {
+
+                private @InsetsType int mTypes;
+                private InsetsState mToState;
+
+                @Override
+                public void onStart(InsetsState state1, InsetsState state2) {
+                    mTypes = 0;
+                    mToState = null;
+                }
+
+                @Override
+                public void onIdMatch(InsetsSource source1, InsetsSource source2) {
+                    final @InsetsType int type = source1.getType();
+                    if ((type & Type.systemBars()) == 0
+                            || !source1.isVisible() || !source2.isVisible()
+                            || source1.getFrame().equals(source2.getFrame())
+                            || !(Rect.intersects(mFrame, source1.getFrame())
+                                    || Rect.intersects(mFrame, source2.getFrame()))) {
+                        return;
+                    }
+                    mTypes |= type;
+                    if (mToState == null) {
+                        mToState = new InsetsState();
+                    }
+                    mToState.addSource(new InsetsSource(source2));
+                }
+
+                @Override
+                public void onFinish(InsetsState state1, InsetsState state2) {
+                    if (mTypes == 0) {
+                        return;
+                    }
+                    cancelExistingControllers(mTypes);
+                    final InsetsAnimationControlRunner runner = new InsetsResizeAnimationRunner(
+                            mFrame, state1, mToState, RESIZE_INTERPOLATOR,
+                            ANIMATION_DURATION_RESIZE, mTypes, InsetsController.this);
+                    mRunningAnimations.add(new RunningAnimation(runner, runner.getAnimationType()));
+                }
+            };
+
     public InsetsController(Host host) {
         this(host, (controller, source) -> {
             if (source.getType() == ime()) {
@@ -671,7 +796,7 @@
             WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/,
                     mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(),
                     mLastLegacySoftInputMode, mLastLegacyWindowFlags, mLastLegacySystemUiFlags,
-                    mWindowType, mLastWindowingMode, null /* typeSideMap */);
+                    mWindowType, mLastWindowingMode, null /* idSideMap */);
             mHost.dispatchWindowInsetsAnimationProgress(insets,
                     Collections.unmodifiableList(runningAnimations));
             if (DEBUG) {
@@ -687,7 +812,7 @@
         };
 
         // Make mImeSourceConsumer always non-null.
-        mImeSourceConsumer = getSourceConsumer(new InsetsSource(ITYPE_IME, ime()));
+        mImeSourceConsumer = getSourceConsumer(new InsetsSource(ID_IME, ime()));
     }
 
     @VisibleForTesting
@@ -739,29 +864,21 @@
                 true /* excludeInvisibleIme */)) {
             if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged");
             mHost.notifyInsetsChanged();
-            startResizingAnimationIfNeeded(lastState);
+            if (lastState.getDisplayFrame().equals(mState.getDisplayFrame())) {
+                InsetsState.traverse(lastState, mState, mStartResizingAnimationIfNeeded);
+            }
         }
         return true;
     }
 
     private void updateState(InsetsState newState) {
         mState.set(newState, 0 /* types */);
-        for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
-            final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
-            final InsetsSource source = newState.peekSource(consumer.getId());
-            if (source == null && consumer != mImeSourceConsumer) {
-                // IME source consumer should always be there since we need to communicate with
-                // InputMethodManager no matter we have the source or not.
-                mSourceConsumers.removeAt(i);
-            }
-        }
         @InsetsType int existingTypes = 0;
         @InsetsType int visibleTypes = 0;
         @InsetsType int disabledUserAnimationTypes = 0;
         @InsetsType int[] cancelledUserAnimationTypes = {0};
-        for (int i = 0; i < InsetsState.SIZE; i++) {
-            InsetsSource source = newState.peekSource(i);
-            if (source == null) continue;
+        for (int i = 0, size = newState.sourceSize(); i < size; i++) {
+            final InsetsSource source = newState.sourceAt(i);
             @InsetsType int type = source.getType();
             @AnimationType int animationType = getAnimationType(type);
             if (!source.isUserControllable()) {
@@ -789,15 +906,7 @@
             }
             mVisibleTypes = visibleTypes;
         }
-        for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
-            // Only update the server side insets here.
-            if (!CAPTION_ON_SHELL && type == ITYPE_CAPTION_BAR) continue;
-            InsetsSource source = mState.peekSource(type);
-            if (source == null) continue;
-            if (newState.peekSource(type) == null) {
-                mState.removeSource(type);
-            }
-        }
+        InsetsState.traverse(mState, newState, mRemoveGoneSources);
 
         updateDisabledUserAnimationTypes(disabledUserAnimationTypes);
 
@@ -825,55 +934,20 @@
         if (CAPTION_ON_SHELL) {
             return false;
         }
-        if (mState.peekSource(ITYPE_CAPTION_BAR) == null
-                && mCaptionInsetsHeight == 0) {
+        final InsetsSource source = mState.peekSource(ID_CAPTION_BAR);
+        if (source == null && mCaptionInsetsHeight == 0) {
             return false;
         }
-        if (mState.peekSource(ITYPE_CAPTION_BAR) != null
-                && mCaptionInsetsHeight
-                == mState.peekSource(ITYPE_CAPTION_BAR).getFrame().height()) {
+        if (source != null && mCaptionInsetsHeight == source.getFrame().height()) {
             return false;
         }
 
         return true;
     }
 
-    private void startResizingAnimationIfNeeded(InsetsState fromState) {
-        if (!fromState.getDisplayFrame().equals(mState.getDisplayFrame())) {
-            return;
-        }
-        @InsetsType int types = 0;
-        InsetsState toState = null;
-        final ArraySet<Integer> internalTypes = InsetsState.toInternalType(Type.systemBars());
-        for (int i = internalTypes.size() - 1; i >= 0; i--) {
-            final @InternalInsetsType int type = internalTypes.valueAt(i);
-            final InsetsSource fromSource = fromState.peekSource(type);
-            final InsetsSource toSource = mState.peekSource(type);
-            if (fromSource != null && toSource != null
-                    && fromSource.isVisible() && toSource.isVisible()
-                    && !fromSource.getFrame().equals(toSource.getFrame())
-                    && (Rect.intersects(mFrame, fromSource.getFrame())
-                            || Rect.intersects(mFrame, toSource.getFrame()))) {
-                types |= toSource.getType();
-                if (toState == null) {
-                    toState = new InsetsState();
-                }
-                toState.addSource(new InsetsSource(toSource));
-            }
-        }
-        if (types == 0) {
-            return;
-        }
-        cancelExistingControllers(types);
-        final InsetsAnimationControlRunner runner = new InsetsResizeAnimationRunner(
-                mFrame, fromState, toState, RESIZE_INTERPOLATOR, ANIMATION_DURATION_RESIZE, types,
-                this);
-        mRunningAnimations.add(new RunningAnimation(runner, runner.getAnimationType()));
-    }
-
     /**
      * @see InsetsState#calculateInsets(Rect, InsetsState, boolean, boolean, int, int, int, int,
-     *      int, SparseIntArray)
+     *      int, android.util.SparseIntArray)
      */
     @VisibleForTesting
     public WindowInsets calculateInsets(boolean isScreenRound, boolean alwaysConsumeSystemBars,
@@ -886,7 +960,7 @@
         mLastLegacySystemUiFlags = legacySystemUiFlags;
         mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState*/,
                 isScreenRound, alwaysConsumeSystemBars, legacySoftInputMode, legacyWindowFlags,
-                legacySystemUiFlags, windowType, windowingMode, null /* typeSideMap */);
+                legacySystemUiFlags, windowType, windowingMode, null /* idSideMap */);
         return mLastInsets;
     }
 
@@ -981,7 +1055,7 @@
     public void show(@InsetsType int types) {
         ImeTracker.Token statsToken = null;
         if ((types & ime()) != 0) {
-            statsToken = ImeTracker.get().onRequestShow(null /* component */,
+            statsToken = ImeTracker.forLogging().onRequestShow(null /* component */,
                     Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
                     SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API);
         }
@@ -1006,6 +1080,9 @@
         }
         // Handle pending request ready in case there was one set.
         if (fromIme && mPendingImeControlRequest != null) {
+            if ((types & Type.ime()) != 0) {
+                ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication);
+            }
             handlePendingControlRequest(statsToken);
             return;
         }
@@ -1028,7 +1105,7 @@
                         "show ignored for type: %d animType: %d requestedVisible: %s",
                         type, animationType, requestedVisible));
                 if (isImeAnimation) {
-                    ImeTracker.get().onCancelled(statsToken,
+                    ImeTracker.forLogging().onCancelled(statsToken,
                             ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
                 }
                 continue;
@@ -1036,16 +1113,21 @@
             if (fromIme && animationType == ANIMATION_TYPE_USER) {
                 // App is already controlling the IME, don't cancel it.
                 if (isImeAnimation) {
-                    ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
+                    ImeTracker.forLogging().onFailed(
+                            statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
                 }
                 continue;
             }
             if (isImeAnimation) {
-                ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
+                ImeTracker.forLogging().onProgress(
+                        statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
             }
             typesReady |= type;
         }
         if (DEBUG) Log.d(TAG, "show typesReady: " + typesReady);
+        if (fromIme && (typesReady & Type.ime()) != 0) {
+            ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication);
+        }
         applyAnimation(typesReady, true /* show */, fromIme, statsToken);
     }
 
@@ -1074,7 +1156,7 @@
     public void hide(@InsetsType int types) {
         ImeTracker.Token statsToken = null;
         if ((types & ime()) != 0) {
-            statsToken = ImeTracker.get().onRequestHide(null /* component */,
+            statsToken = ImeTracker.forLogging().onRequestHide(null /* component */,
                     Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
                     SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
         }
@@ -1123,13 +1205,14 @@
                 // no-op: already hidden or animating out (because window visibility is
                 // applied before starting animation).
                 if (isImeAnimation) {
-                    ImeTracker.get().onCancelled(statsToken,
+                    ImeTracker.forLogging().onCancelled(statsToken,
                             ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
                 }
                 continue;
             }
             if (isImeAnimation) {
-                ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
+                ImeTracker.forLogging().onProgress(
+                        statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
             }
             typesReady |= type;
         }
@@ -1201,8 +1284,19 @@
             @AnimationType int animationType,
             @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
             boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) {
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION);
+        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION);
         if ((types & mTypesBeingCancelled) != 0) {
+            final boolean monitoredAnimation =
+                    animationType == ANIMATION_TYPE_SHOW || animationType == ANIMATION_TYPE_HIDE;
+            if (monitoredAnimation && (types & Type.ime()) != 0) {
+                if (animationType == ANIMATION_TYPE_SHOW) {
+                    ImeTracker.forLatency().onShowCancelled(statsToken,
+                            PHASE_CLIENT_ANIMATION_CANCEL, ActivityThread::currentApplication);
+                } else {
+                    ImeTracker.forLatency().onHideCancelled(statsToken,
+                            PHASE_CLIENT_ANIMATION_CANCEL, ActivityThread::currentApplication);
+                }
+            }
             throw new IllegalStateException("Cannot start a new insets animation of "
                     + Type.toString(types)
                     + " while an existing " + Type.toString(mTypesBeingCancelled)
@@ -1214,10 +1308,11 @@
             types &= ~mDisabledUserAnimationInsetsTypes;
 
             if ((disabledTypes & ime()) != 0) {
-                ImeTracker.get().onFailed(statsToken,
+                ImeTracker.forLogging().onFailed(statsToken,
                         ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
 
-                if (fromIme && !mState.getSource(mImeSourceConsumer.getId()).isVisible()) {
+                if (fromIme
+                        && !mState.isSourceOrDefaultVisible(mImeSourceConsumer.getId(), ime())) {
                     // We've requested IMM to show IME, but the IME is not controllable. We need to
                     // cancel the request.
                     setRequestedVisibleTypes(0 /* visibleTypes */, ime());
@@ -1235,7 +1330,8 @@
             Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0);
             return;
         }
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
+        ImeTracker.forLogging().onProgress(statsToken,
+                ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
         if (DEBUG) Log.d(TAG, "controlAnimation types: " + types);
         mLastStartedAnimTypes |= types;
 
@@ -1302,8 +1398,11 @@
         if ((typesReady & WindowInsets.Type.ime()) != 0) {
             ImeTracing.getInstance().triggerClientDump("InsetsAnimationControlImpl",
                     mHost.getInputMethodManager(), null /* icProto */);
+            if (animationType == ANIMATION_TYPE_HIDE) {
+                ImeTracker.forLatency().onHidden(statsToken, ActivityThread::currentApplication);
+            }
         }
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_RUNNING);
+        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_RUNNING);
         mRunningAnimations.add(new RunningAnimation(runner, animationType));
         if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: "
                 + useInsetsAnimationThread);
@@ -1343,7 +1442,8 @@
     private Pair<Integer, Boolean> collectSourceControls(boolean fromIme, @InsetsType int types,
             SparseArray<InsetsSourceControl> controls, @AnimationType int animationType,
             @Nullable ImeTracker.Token statsToken) {
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_COLLECT_SOURCE_CONTROLS);
+        ImeTracker.forLogging().onProgress(statsToken,
+                ImeTracker.PHASE_CLIENT_COLLECT_SOURCE_CONTROLS);
 
         int typesReady = 0;
         boolean imeReady = true;
@@ -1446,13 +1546,13 @@
         }
         final ImeTracker.Token statsToken = runner.getStatsToken();
         if (shown) {
-            ImeTracker.get().onProgress(statsToken,
+            ImeTracker.forLogging().onProgress(statsToken,
                     ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_SHOW);
-            ImeTracker.get().onShown(statsToken);
+            ImeTracker.forLogging().onShown(statsToken);
         } else {
-            ImeTracker.get().onProgress(statsToken,
+            ImeTracker.forLogging().onProgress(statsToken,
                     ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_HIDE);
-            ImeTracker.get().onHidden(statsToken);
+            ImeTracker.forLogging().onHidden(statsToken);
         }
         reportRequestedVisibleTypes();
     }
@@ -1478,13 +1578,13 @@
 
     private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) {
         if (invokeCallback) {
-            ImeTracker.get().onCancelled(control.getStatsToken(),
-                    ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
+            ImeTracker.forLogging().onCancelled(control.getStatsToken(),
+                    PHASE_CLIENT_ANIMATION_CANCEL);
             control.cancel();
         } else {
             // Succeeds if invokeCallback is false (i.e. when called from notifyFinished).
-            ImeTracker.get().onProgress(control.getStatsToken(),
-                    ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
+            ImeTracker.forLogging().onProgress(control.getStatsToken(),
+                    PHASE_CLIENT_ANIMATION_CANCEL);
         }
         if (DEBUG) {
             Log.d(TAG, TextUtils.formatSimple(
@@ -1649,7 +1749,7 @@
         final InternalAnimationControlListener listener = new InternalAnimationControlListener(
                 show, hasAnimationCallbacks, types, mHost.getSystemBarsBehavior(),
                 skipAnim || mAnimationsDisabled, mHost.dipToPx(FLOATING_IME_BOTTOM_INSET_DP),
-                mLoggingListener);
+                mLoggingListener, mJankContext);
 
         // We are about to playing the default animation (show/hide). Passing a null frame indicates
         // the controlled types should be animated regardless of the frame.
@@ -1757,10 +1857,10 @@
         if (mCaptionInsetsHeight != height) {
             mCaptionInsetsHeight = height;
             if (mCaptionInsetsHeight != 0) {
-                mState.getSource(ITYPE_CAPTION_BAR).setFrame(mFrame.left, mFrame.top,
-                        mFrame.right, mFrame.top + mCaptionInsetsHeight);
+                mState.getOrCreateSource(ID_CAPTION_BAR, captionBar()).setFrame(
+                        mFrame.left, mFrame.top, mFrame.right, mFrame.top + mCaptionInsetsHeight);
             } else {
-                mState.removeSource(ITYPE_CAPTION_BAR);
+                mState.removeSource(ID_CAPTION_BAR);
             }
             mHost.notifyInsetsChanged();
         }
diff --git a/core/java/android/view/InsetsResizeAnimationRunner.java b/core/java/android/view/InsetsResizeAnimationRunner.java
index cf64eedf..bffaeea 100644
--- a/core/java/android/view/InsetsResizeAnimationRunner.java
+++ b/core/java/android/view/InsetsResizeAnimationRunner.java
@@ -33,7 +33,6 @@
 import android.graphics.Rect;
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsAnimation.Bounds;
 import android.view.animation.Interpolator;
@@ -142,24 +141,23 @@
             return false;
         }
         final float fraction = mAnimation.getInterpolatedFraction();
-        for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
-            final InsetsSource fromSource = mFromState.peekSource(type);
-            final InsetsSource toSource = mToState.peekSource(type);
-            if (fromSource == null || toSource == null) {
-                continue;
+        InsetsState.traverse(mFromState, mToState, new InsetsState.OnTraverseCallbacks() {
+            @Override
+            public void onIdMatch(InsetsSource fromSource, InsetsSource toSource) {
+                final Rect fromFrame = fromSource.getFrame();
+                final Rect toFrame = toSource.getFrame();
+                final Rect frame = new Rect(
+                        (int) (fromFrame.left + fraction * (toFrame.left - fromFrame.left)),
+                        (int) (fromFrame.top + fraction * (toFrame.top - fromFrame.top)),
+                        (int) (fromFrame.right + fraction * (toFrame.right - fromFrame.right)),
+                        (int) (fromFrame.bottom + fraction * (toFrame.bottom - fromFrame.bottom)));
+                final InsetsSource source =
+                        new InsetsSource(fromSource.getId(), fromSource.getType());
+                source.setFrame(frame);
+                source.setVisible(toSource.isVisible());
+                outState.addSource(source);
             }
-            final Rect fromFrame = fromSource.getFrame();
-            final Rect toFrame = toSource.getFrame();
-            final Rect frame = new Rect(
-                    (int) (fromFrame.left + fraction * (toFrame.left - fromFrame.left)),
-                    (int) (fromFrame.top + fraction * (toFrame.top - fromFrame.top)),
-                    (int) (fromFrame.right + fraction * (toFrame.right - fromFrame.right)),
-                    (int) (fromFrame.bottom + fraction * (toFrame.bottom - fromFrame.bottom)));
-            final InsetsSource source = new InsetsSource(type, fromSource.getType());
-            source.setFrame(frame);
-            source.setVisible(toSource.isVisible());
-            outState.addSource(source);
-        }
+        });
         if (mFinished) {
             mController.notifyFinished(this, true /* shown */);
         }
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index f6b063d..17ab83c 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -21,7 +21,9 @@
 import static android.view.InsetsSourceProto.VISIBLE;
 import static android.view.InsetsSourceProto.VISIBLE_FRAME;
 import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
+import static android.view.WindowInsets.Type.ime;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Insets;
@@ -40,6 +42,9 @@
  */
 public class InsetsSource implements Parcelable {
 
+    /** The insets source ID of IME */
+    public static final int ID_IME = createId(null, 0, ime());
+
     /**
      * An unique integer to identify this source across processes.
      */
@@ -83,20 +88,24 @@
         mInsetsRoundedCornerFrame = other.mInsetsRoundedCornerFrame;
     }
 
-    public void setFrame(int left, int top, int right, int bottom) {
+    public InsetsSource setFrame(int left, int top, int right, int bottom) {
         mFrame.set(left, top, right, bottom);
+        return this;
     }
 
-    public void setFrame(Rect frame) {
+    public InsetsSource setFrame(Rect frame) {
         mFrame.set(frame);
+        return this;
     }
 
-    public void setVisibleFrame(@Nullable Rect visibleFrame) {
+    public InsetsSource setVisibleFrame(@Nullable Rect visibleFrame) {
         mVisibleFrame = visibleFrame != null ? new Rect(visibleFrame) : null;
+        return this;
     }
 
-    public void setVisible(boolean visible) {
+    public InsetsSource setVisible(boolean visible) {
         mVisible = visible;
+        return this;
     }
 
     public int getId() {
@@ -128,8 +137,9 @@
         return mInsetsRoundedCornerFrame;
     }
 
-    public void setInsetsRoundedCornerFrame(boolean insetsRoundedCornerFrame) {
+    public InsetsSource setInsetsRoundedCornerFrame(boolean insetsRoundedCornerFrame) {
         mInsetsRoundedCornerFrame = insetsRoundedCornerFrame;
+        return this;
     }
 
     /**
@@ -223,6 +233,29 @@
     }
 
     /**
+     * Creates an identifier of an {@link InsetsSource}.
+     *
+     * @param owner An object owned by the owner. Only the owner can modify its own sources.
+     * @param index An owner may have multiple sources with the same type. For example, the system
+     *              server might have multiple display cutout sources. This is used to identify
+     *              which one is which. The value must be in a range of [0, 2047].
+     * @param type The {@link WindowInsets.Type.InsetsType type} of the source.
+     * @return a unique integer as the identifier.
+     */
+    public static int createId(Object owner, @IntRange(from = 0, to = 2047) int index,
+            @InsetsType int type) {
+        if (index < 0 || index >= 2048) {
+            throw new IllegalArgumentException();
+        }
+        // owner takes top 16 bits;
+        // index takes 11 bits since the 6th bit;
+        // type takes bottom 5 bits.
+        return (((owner != null ? owner.hashCode() : 1) % (1 << 16)) << 16)
+                + (index << 5)
+                + WindowInsets.Type.indexOf(type);
+    }
+
+    /**
      * Export the state of {@link InsetsSource} into a protocol buffer output stream.
      *
      * @param proto   Stream to write the state to
@@ -241,7 +274,7 @@
 
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix);
-        pw.print("InsetsSource id="); pw.print(mId);
+        pw.print("InsetsSource id="); pw.print(Integer.toHexString(mId));
         pw.print(" type="); pw.print(WindowInsets.Type.toString(mType));
         pw.print(" frame="); pw.print(mFrame.toShortString());
         if (mVisibleFrame != null) {
@@ -258,7 +291,7 @@
     }
 
     /**
-     * @param excludeInvisibleImeFrames If {@link InsetsState#ITYPE_IME} frames should be ignored
+     * @param excludeInvisibleImeFrames If {@link WindowInsets.Type#ime()} frames should be ignored
      *                                  when IME is not visible.
      */
     public boolean equals(@Nullable Object o, boolean excludeInvisibleImeFrames) {
@@ -316,8 +349,7 @@
 
     @Override
     public String toString() {
-        return "InsetsSource: {"
-                + "mId=" + mId
+        return "InsetsSource: {" + Integer.toHexString(mId)
                 + " mType=" + WindowInsets.Type.toString(mType)
                 + " mFrame=" + mFrame.toShortString()
                 + " mVisible=" + mVisible
diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java
index c849cb5..7ea93f5 100644
--- a/core/java/android/view/InsetsSourceControl.java
+++ b/core/java/android/view/InsetsSourceControl.java
@@ -205,8 +205,7 @@
 
     @Override
     public String toString() {
-        return "InsetsSourceControl: {"
-                + "mId=" + mId
+        return "InsetsSourceControl: {" + Integer.toHexString(mId)
                 + " mType=" + WindowInsets.Type.toString(mType)
                 + (mInitiallyVisible ? " initiallyVisible" : "")
                 + " mSurfacePosition=" + mSurfacePosition
@@ -217,7 +216,7 @@
 
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix);
-        pw.print("InsetsSourceControl mId="); pw.print(mId);
+        pw.print("InsetsSourceControl mId="); pw.print(Integer.toHexString(mId));
         pw.print(" mType="); pw.print(WindowInsets.Type.toString(mType));
         pw.print(" mLeash="); pw.print(mLeash);
         pw.print(" mInitiallyVisible="); pw.print(mInitiallyVisible);
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 054d177..ba7d823 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -20,6 +20,7 @@
 import static android.view.InsetsStateProto.DISPLAY_FRAME;
 import static android.view.InsetsStateProto.SOURCES;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+import static android.view.WindowInsets.Type.captionBar;
 import static android.view.WindowInsets.Type.displayCutout;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.indexOf;
@@ -42,6 +43,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArraySet;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.proto.ProtoOutputStream;
 import android.view.WindowInsets.Type;
@@ -53,7 +55,6 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
 import java.util.Objects;
 import java.util.StringJoiner;
 
@@ -85,11 +86,6 @@
             ITYPE_TOP_TAPPABLE_ELEMENT,
             ITYPE_RIGHT_TAPPABLE_ELEMENT,
             ITYPE_BOTTOM_TAPPABLE_ELEMENT,
-            ITYPE_LEFT_DISPLAY_CUTOUT,
-            ITYPE_TOP_DISPLAY_CUTOUT,
-            ITYPE_RIGHT_DISPLAY_CUTOUT,
-            ITYPE_BOTTOM_DISPLAY_CUTOUT,
-            ITYPE_IME,
             ITYPE_CLIMATE_BAR,
             ITYPE_EXTRA_NAVIGATION_BAR,
             ITYPE_LEFT_GENERIC_OVERLAY,
@@ -99,15 +95,7 @@
     })
     public @interface InternalInsetsType {}
 
-    /**
-     * Special value to be used to by methods returning an {@link InternalInsetsType} to indicate
-     * that the objects/parameters aren't associated with an {@link InternalInsetsType}
-     */
-    public static final int ITYPE_INVALID = -1;
-
-    static final int FIRST_TYPE = 0;
-
-    public static final int ITYPE_STATUS_BAR = FIRST_TYPE;
+    public static final int ITYPE_STATUS_BAR = 0;
     public static final int ITYPE_NAVIGATION_BAR = 1;
     public static final int ITYPE_CAPTION_BAR = 2;
 
@@ -121,19 +109,11 @@
     public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9;
     public static final int ITYPE_RIGHT_MANDATORY_GESTURES = 10;
 
-    public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 11;
-    public static final int ITYPE_TOP_DISPLAY_CUTOUT = 12;
-    public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 13;
-    public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 14;
-
     public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 15;
     public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 16;
     public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 17;
     public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 18;
 
-    /** Input method window. */
-    public static final int ITYPE_IME = 19;
-
     /** Additional system decorations inset type. */
     public static final int ITYPE_CLIMATE_BAR = 20;
     public static final int ITYPE_EXTRA_NAVIGATION_BAR = 21;
@@ -144,16 +124,8 @@
     public static final int ITYPE_RIGHT_GENERIC_OVERLAY = 24;
     public static final int ITYPE_BOTTOM_GENERIC_OVERLAY = 25;
 
-    static final int LAST_TYPE = ITYPE_BOTTOM_GENERIC_OVERLAY;
-    public static final int SIZE = LAST_TYPE + 1;
-
-    // Derived types
-
-    /** A shelf is the same as the navigation bar. */
-    public static final int ITYPE_SHELF = ITYPE_NAVIGATION_BAR;
-
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "IINSETS_SIDE", value = {
+    @IntDef(prefix = "ISIDE", value = {
             ISIDE_LEFT,
             ISIDE_TOP,
             ISIDE_RIGHT,
@@ -169,7 +141,7 @@
     static final int ISIDE_FLOATING = 4;
     static final int ISIDE_UNKNOWN = 5;
 
-    private final InsetsSource[] mSources = new InsetsSource[SIZE];
+    private final SparseArray<InsetsSource> mSources;
 
     /**
      * The frame of the display these sources are relative to.
@@ -201,13 +173,15 @@
     private DisplayShape mDisplayShape = DisplayShape.NONE;
 
     public InsetsState() {
+        mSources = new SparseArray<>();
     }
 
     public InsetsState(InsetsState copy) {
-        set(copy);
+        this(copy, false /* copySources */);
     }
 
     public InsetsState(InsetsState copy, boolean copySources) {
+        mSources = new SparseArray<>(copy.mSources.size());
         set(copy, copySources);
     }
 
@@ -224,36 +198,29 @@
             boolean isScreenRound, boolean alwaysConsumeSystemBars,
             int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags,
             int windowType, @WindowConfiguration.WindowingMode int windowingMode,
-            @Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
+            @Nullable @InternalInsetsSide SparseIntArray idSideMap) {
         Insets[] typeInsetsMap = new Insets[Type.SIZE];
         Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
         boolean[] typeVisibilityMap = new boolean[Type.SIZE];
         final Rect relativeFrame = new Rect(frame);
         final Rect relativeFrameMax = new Rect(frame);
-        for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
-            InsetsSource source = mSources[type];
-            if (source == null) {
-                int index = indexOf(toPublicType(type));
-                if (typeInsetsMap[index] == null) {
-                    typeInsetsMap[index] = Insets.NONE;
-                }
-                continue;
-            }
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            final InsetsSource source = mSources.valueAt(i);
 
             processSource(source, relativeFrame, false /* ignoreVisibility */, typeInsetsMap,
-                    typeSideMap, typeVisibilityMap);
+                    idSideMap, typeVisibilityMap);
 
             // IME won't be reported in max insets as the size depends on the EditorInfo of the IME
             // target.
             if (source.getType() != WindowInsets.Type.ime()) {
                 InsetsSource ignoringVisibilitySource = ignoringVisibilityState != null
-                        ? ignoringVisibilityState.getSource(type)
+                        ? ignoringVisibilityState.peekSource(source.getId())
                         : source;
                 if (ignoringVisibilitySource == null) {
                     continue;
                 }
                 processSource(ignoringVisibilitySource, relativeFrameMax,
-                        true /* ignoreVisibility */, typeMaxInsetsMap, null /* typeSideMap */,
+                        true /* ignoreVisibility */, typeMaxInsetsMap, null /* idSideMap */,
                         null /* typeVisibilityMap */);
             }
         }
@@ -306,8 +273,9 @@
         // If mRoundedCornerFrame is set, we should calculate the new RoundedCorners based on this
         // frame.
         final Rect roundedCornerFrame = new Rect(mRoundedCornerFrame);
-        for (InsetsSource source : mSources) {
-            if (source != null && source.getInsetsRoundedCornerFrame()) {
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            final InsetsSource source = mSources.valueAt(i);
+            if (source.getInsetsRoundedCornerFrame()) {
                 final Insets insets = source.calculateInsets(roundedCornerFrame, false);
                 roundedCornerFrame.inset(insets);
             }
@@ -351,13 +319,9 @@
 
     public Insets calculateInsets(Rect frame, @InsetsType int types, boolean ignoreVisibility) {
         Insets insets = Insets.NONE;
-        for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
-            InsetsSource source = mSources[type];
-            if (source == null) {
-                continue;
-            }
-            int publicType = InsetsState.toPublicType(type);
-            if ((publicType & types) == 0) {
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            final InsetsSource source = mSources.valueAt(i);
+            if ((source.getType() & types) == 0) {
                 continue;
             }
             insets = Insets.max(source.calculateInsets(frame, ignoreVisibility), insets);
@@ -368,13 +332,9 @@
     public Insets calculateInsets(Rect frame, @InsetsType int types,
             @InsetsType int requestedVisibleTypes) {
         Insets insets = Insets.NONE;
-        for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
-            InsetsSource source = mSources[type];
-            if (source == null) {
-                continue;
-            }
-            int publicType = InsetsState.toPublicType(type);
-            if ((publicType & types & requestedVisibleTypes) == 0) {
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            final InsetsSource source = mSources.valueAt(i);
+            if ((source.getType() & types & requestedVisibleTypes) == 0) {
                 continue;
             }
             insets = Insets.max(source.calculateInsets(frame, true), insets);
@@ -392,13 +352,9 @@
                 ? systemBars() | ime()
                 : systemBars();
         Insets insets = Insets.NONE;
-        for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
-            InsetsSource source = mSources[type];
-            if (source == null) {
-                continue;
-            }
-            final int publicType = InsetsState.toPublicType(type);
-            if ((publicType & visibleInsetsTypes) == 0) {
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            final InsetsSource source = mSources.valueAt(i);
+            if ((source.getType() & visibleInsetsTypes) == 0) {
                 continue;
             }
             insets = Insets.max(source.calculateVisibleInsets(frame), insets);
@@ -416,13 +372,10 @@
     @InsetsType
     public int calculateUncontrollableInsetsFromFrame(Rect frame) {
         int blocked = 0;
-        for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
-            InsetsSource source = mSources[type];
-            if (source == null) {
-                continue;
-            }
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            final InsetsSource source = mSources.valueAt(i);
             if (!canControlSource(frame, source)) {
-                blocked |= toPublicType(type);
+                blocked |= source.getType();
             }
         }
         return blocked;
@@ -438,12 +391,12 @@
     }
 
     private void processSource(InsetsSource source, Rect relativeFrame, boolean ignoreVisibility,
-            Insets[] typeInsetsMap, @Nullable @InternalInsetsSide SparseIntArray typeSideMap,
+            Insets[] typeInsetsMap, @Nullable @InternalInsetsSide SparseIntArray idSideMap,
             @Nullable boolean[] typeVisibilityMap) {
         Insets insets = source.calculateInsets(relativeFrame, ignoreVisibility);
 
         final int type = source.getType();
-        processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
+        processSourceAsPublicType(source, typeInsetsMap, idSideMap, typeVisibilityMap,
                 insets, type);
 
         if (type == Type.MANDATORY_SYSTEM_GESTURES) {
@@ -452,24 +405,24 @@
             //       Type.systemGestureInsets() as NORMAL | MANDATORY, but then we lose the
             //       ability to set systemGestureInsets() independently from
             //       mandatorySystemGestureInsets() in the Builder.
-            processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
+            processSourceAsPublicType(source, typeInsetsMap, idSideMap, typeVisibilityMap,
                     insets, Type.SYSTEM_GESTURES);
         }
         if (type == Type.CAPTION_BAR) {
             // Caption should also be gesture and tappable elements. This should not be needed when
             // the caption is added from the shell, as the shell can add other types at the same
             // time.
-            processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
+            processSourceAsPublicType(source, typeInsetsMap, idSideMap, typeVisibilityMap,
                     insets, Type.SYSTEM_GESTURES);
-            processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
+            processSourceAsPublicType(source, typeInsetsMap, idSideMap, typeVisibilityMap,
                     insets, Type.MANDATORY_SYSTEM_GESTURES);
-            processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
+            processSourceAsPublicType(source, typeInsetsMap, idSideMap, typeVisibilityMap,
                     insets, Type.TAPPABLE_ELEMENT);
         }
     }
 
     private void processSourceAsPublicType(InsetsSource source, Insets[] typeInsetsMap,
-            @InternalInsetsSide @Nullable SparseIntArray typeSideMap,
+            @InternalInsetsSide @Nullable SparseIntArray idSideMap,
             @Nullable boolean[] typeVisibilityMap, Insets insets, int type) {
         int index = indexOf(type);
         Insets existing = typeInsetsMap[index];
@@ -483,10 +436,10 @@
             typeVisibilityMap[index] = source.isVisible();
         }
 
-        if (typeSideMap != null) {
+        if (idSideMap != null) {
             @InternalInsetsSide int insetSide = getInsetSide(insets);
             if (insetSide != ISIDE_UNKNOWN) {
-                typeSideMap.put(source.getId(), insetSide);
+                idSideMap.put(source.getId(), insetSide);
             }
         }
     }
@@ -514,31 +467,60 @@
         return ISIDE_UNKNOWN;
     }
 
-    public InsetsSource getSource(@InternalInsetsType int type) {
-        InsetsSource source = mSources[type];
+    /**
+     * Gets the source mapped from the ID, or creates one if no such mapping has been made.
+     */
+    public InsetsSource getOrCreateSource(int id, int type) {
+        InsetsSource source = mSources.get(id);
         if (source != null) {
             return source;
         }
-        source = new InsetsSource(type, toPublicType(type));
-        mSources[type] = source;
+        source = new InsetsSource(id, type);
+        mSources.put(id, source);
         return source;
     }
 
-    public @Nullable InsetsSource peekSource(@InternalInsetsType int type) {
-        return mSources[type];
+    /**
+     * Gets the source mapped from the ID, or <code>null</code> if no such mapping has been made.
+     */
+    public @Nullable InsetsSource peekSource(int id) {
+        return mSources.get(id);
     }
 
     /**
-     * Returns the source visibility or the default visibility if the source doesn't exist. This is
-     * useful if when treating this object as a request.
+     * Given an index in the range <code>0...sourceSize()-1</code>, returns the source ID from the
+     * <code>index</code>th ID-source mapping that this state stores.
+     */
+    public int sourceIdAt(int index) {
+        return mSources.keyAt(index);
+    }
+
+    /**
+     * Given an index in the range <code>0...sourceSize()-1</code>, returns the source from the
+     * <code>index</code>th ID-source mapping that this state stores.
+     */
+    public InsetsSource sourceAt(int index) {
+        return mSources.valueAt(index);
+    }
+
+    /**
+     * Returns the amount of the sources.
+     */
+    public int sourceSize() {
+        return mSources.size();
+    }
+
+    /**
+     * Returns if the source is visible or the type is default visible and the source doesn't exist.
      *
-     * @param type The {@link InternalInsetsType} to query.
+     * @param id The ID of the source.
+     * @param type The {@link InsetsType} to see if it is default visible.
      * @return {@code true} if the source is visible or the type is default visible and the source
      *         doesn't exist.
      */
-    public boolean getSourceOrDefaultVisibility(@InternalInsetsType int type) {
-        final InsetsSource source = mSources[type];
-        return source != null ? source.isVisible() : getDefaultVisibility(type);
+    public boolean isSourceOrDefaultVisible(int id, @InsetsType int type) {
+        final InsetsSource source = mSources.get(id);
+        return source != null ? source.isVisible() : (type & Type.defaultVisible()) != 0;
     }
 
     public void setDisplayFrame(Rect frame) {
@@ -612,28 +594,31 @@
     }
 
     /**
-     * Modifies the state of this class to exclude a certain type to make it ready for dispatching
-     * to the client.
+     * Removes the source which has the ID from this state, if there was any.
      *
-     * @param type The {@link InternalInsetsType} of the source to remove
-     * @return {@code true} if this InsetsState was modified; {@code false} otherwise.
+     * @param id The ID of the source to remove.
      */
-    public boolean removeSource(@InternalInsetsType int type) {
-        if (mSources[type] == null) {
-            return false;
-        }
-        mSources[type] = null;
-        return true;
+    public void removeSource(int id) {
+        mSources.delete(id);
+    }
+
+    /**
+     * Removes the source at the specified index.
+     *
+     * @param index The index of the source to remove.
+     */
+    public void removeSourceAt(int index) {
+        mSources.removeAt(index);
     }
 
     /**
      * A shortcut for setting the visibility of the source.
      *
-     * @param type The {@link InternalInsetsType} of the source to set the visibility
+     * @param id The ID of the source to set the visibility
      * @param visible {@code true} for visible
      */
-    public void setSourceVisible(@InternalInsetsType int type, boolean visible) {
-        InsetsSource source = mSources[type];
+    public void setSourceVisible(int id, boolean visible) {
+        final InsetsSource source = mSources.get(id);
         if (source != null) {
             source.setVisible(visible);
         }
@@ -651,14 +636,12 @@
         mRoundedCornerFrame.scale(scale);
         mPrivacyIndicatorBounds = mPrivacyIndicatorBounds.scale(scale);
         mDisplayShape = mDisplayShape.setScale(scale);
-        for (int i = 0; i < SIZE; i++) {
-            final InsetsSource source = mSources[i];
-            if (source != null) {
-                source.getFrame().scale(scale);
-                final Rect visibleFrame = source.getVisibleFrame();
-                if (visibleFrame != null) {
-                    visibleFrame.scale(scale);
-                }
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            final InsetsSource source = mSources.valueAt(i);
+            source.getFrame().scale(scale);
+            final Rect visibleFrame = source.getVisibleFrame();
+            if (visibleFrame != null) {
+                visibleFrame.scale(scale);
             }
         }
     }
@@ -674,15 +657,12 @@
         mRoundedCornerFrame.set(other.mRoundedCornerFrame);
         mPrivacyIndicatorBounds = other.getPrivacyIndicatorBounds();
         mDisplayShape = other.getDisplayShape();
-        if (copySources) {
-            for (int i = 0; i < SIZE; i++) {
-                InsetsSource source = other.mSources[i];
-                mSources[i] = source != null ? new InsetsSource(source) : null;
-            }
-        } else {
-            for (int i = 0; i < SIZE; i++) {
-                mSources[i] = other.mSources[i];
-            }
+        mSources.clear();
+        for (int i = 0, size = other.mSources.size(); i < size; i++) {
+            final InsetsSource otherSource = other.mSources.valueAt(i);
+            mSources.append(otherSource.getId(), copySources
+                    ? new InsetsSource(otherSource)
+                    : otherSource);
         }
     }
 
@@ -700,15 +680,25 @@
         mRoundedCornerFrame.set(other.mRoundedCornerFrame);
         mPrivacyIndicatorBounds = other.getPrivacyIndicatorBounds();
         mDisplayShape = other.getDisplayShape();
-        final ArraySet<Integer> t = toInternalType(types);
-        for (int i = t.size() - 1; i >= 0; i--) {
-            final int type = t.valueAt(i);
-            mSources[type] = other.mSources[type];
+        if (types == 0) {
+            return;
+        }
+        for (int i = mSources.size() - 1; i >= 0; i--) {
+            final InsetsSource source = mSources.valueAt(i);
+            if ((source.getType() & types) != 0) {
+                mSources.removeAt(i);
+            }
+        }
+        for (int i = other.mSources.size() - 1; i >= 0; i--) {
+            final InsetsSource otherSource = other.mSources.valueAt(i);
+            if ((otherSource.getType() & types) != 0) {
+                mSources.put(otherSource.getId(), otherSource);
+            }
         }
     }
 
     public void addSource(InsetsSource source) {
-        mSources[source.getId()] = source;
+        mSources.put(source.getId(), source);
     }
 
     public static boolean clearsCompatInsets(int windowType, int windowFlags, int windowingMode) {
@@ -748,15 +738,6 @@
             result.add(ITYPE_RIGHT_MANDATORY_GESTURES);
             result.add(ITYPE_BOTTOM_MANDATORY_GESTURES);
         }
-        if ((types & Type.DISPLAY_CUTOUT) != 0) {
-            result.add(ITYPE_LEFT_DISPLAY_CUTOUT);
-            result.add(ITYPE_TOP_DISPLAY_CUTOUT);
-            result.add(ITYPE_RIGHT_DISPLAY_CUTOUT);
-            result.add(ITYPE_BOTTOM_DISPLAY_CUTOUT);
-        }
-        if ((types & Type.IME) != 0) {
-            result.add(ITYPE_IME);
-        }
         return result;
     }
 
@@ -780,8 +761,6 @@
                 return Type.SYSTEM_OVERLAYS;
             case ITYPE_CAPTION_BAR:
                 return Type.CAPTION_BAR;
-            case ITYPE_IME:
-                return Type.IME;
             case ITYPE_TOP_MANDATORY_GESTURES:
             case ITYPE_BOTTOM_MANDATORY_GESTURES:
             case ITYPE_LEFT_MANDATORY_GESTURES:
@@ -797,33 +776,11 @@
             case ITYPE_RIGHT_TAPPABLE_ELEMENT:
             case ITYPE_BOTTOM_TAPPABLE_ELEMENT:
                 return Type.TAPPABLE_ELEMENT;
-            case ITYPE_LEFT_DISPLAY_CUTOUT:
-            case ITYPE_TOP_DISPLAY_CUTOUT:
-            case ITYPE_RIGHT_DISPLAY_CUTOUT:
-            case ITYPE_BOTTOM_DISPLAY_CUTOUT:
-                return Type.DISPLAY_CUTOUT;
             default:
                 throw new IllegalArgumentException("Unknown type: " + type);
         }
     }
 
-    public static boolean getDefaultVisibility(@InternalInsetsType int type) {
-        return type != ITYPE_IME;
-    }
-
-    public static boolean containsType(@InternalInsetsType int[] types,
-            @InternalInsetsType int type) {
-        if (types == null) {
-            return false;
-        }
-        for (int t : types) {
-            if (t == type) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     public void dump(String prefix, PrintWriter pw) {
         final String newPrefix = prefix + "  ";
         pw.println(prefix + "InsetsState");
@@ -833,16 +790,14 @@
         pw.println(newPrefix + "mRoundedCornerFrame=" + mRoundedCornerFrame);
         pw.println(newPrefix + "mPrivacyIndicatorBounds=" + mPrivacyIndicatorBounds);
         pw.println(newPrefix + "mDisplayShape=" + mDisplayShape);
-        for (int i = 0; i < SIZE; i++) {
-            InsetsSource source = mSources[i];
-            if (source == null) continue;
-            source.dump(newPrefix + "  ", pw);
+        for (int i = 0, size = mSources.size(); i < size; i++) {
+            mSources.valueAt(i).dump(newPrefix + "  ", pw);
         }
     }
 
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
-        InsetsSource source = mSources[ITYPE_IME];
+        final InsetsSource source = mSources.get(InsetsSource.ID_IME);
         if (source != null) {
             source.dumpDebug(proto, SOURCES);
         }
@@ -883,16 +838,6 @@
                 return "ITYPE_RIGHT_TAPPABLE_ELEMENT";
             case ITYPE_BOTTOM_TAPPABLE_ELEMENT:
                 return "ITYPE_BOTTOM_TAPPABLE_ELEMENT";
-            case ITYPE_LEFT_DISPLAY_CUTOUT:
-                return "ITYPE_LEFT_DISPLAY_CUTOUT";
-            case ITYPE_TOP_DISPLAY_CUTOUT:
-                return "ITYPE_TOP_DISPLAY_CUTOUT";
-            case ITYPE_RIGHT_DISPLAY_CUTOUT:
-                return "ITYPE_RIGHT_DISPLAY_CUTOUT";
-            case ITYPE_BOTTOM_DISPLAY_CUTOUT:
-                return "ITYPE_BOTTOM_DISPLAY_CUTOUT";
-            case ITYPE_IME:
-                return "ITYPE_IME";
             case ITYPE_CLIMATE_BAR:
                 return "ITYPE_CLIMATE_BAR";
             case ITYPE_EXTRA_NAVIGATION_BAR:
@@ -921,8 +866,8 @@
      * excluded.
      * @param excludingCaptionInsets {@code true} if we want to compare two InsetsState objects but
      *                                           ignore the caption insets source value.
-     * @param excludeInvisibleImeFrames If {@link #ITYPE_IME} frames should be ignored when IME is
-     *                                  not visible.
+     * @param excludeInvisibleImeFrames If {@link WindowInsets.Type#ime()} frames should be ignored
+     *                                  when IME is not visible.
      * @return {@code true} if the two InsetsState objects are equal, {@code false} otherwise.
      */
     @VisibleForTesting
@@ -941,38 +886,56 @@
                 || !mDisplayShape.equals(state.mDisplayShape)) {
             return false;
         }
-        for (int i = 0; i < SIZE; i++) {
-            if (excludingCaptionInsets) {
-                if (i == ITYPE_CAPTION_BAR) continue;
+
+        final SparseArray<InsetsSource> thisSources = mSources;
+        final SparseArray<InsetsSource> thatSources = state.mSources;
+        if (!excludingCaptionInsets && !excludeInvisibleImeFrames) {
+            return thisSources.contentEquals(thatSources);
+        } else {
+            final int thisSize = thisSources.size();
+            final int thatSize = thatSources.size();
+            int thisIndex = 0;
+            int thatIndex = 0;
+            while (thisIndex < thisSize && thatIndex < thatSize) {
+                // Seek to the next non-excluding source of ours.
+                InsetsSource thisSource = thisSources.valueAt(thisIndex);
+                while (thisSource != null
+                        && (excludingCaptionInsets && thisSource.getType() == captionBar()
+                                || excludeInvisibleImeFrames && thisSource.getType() == ime()
+                                        && !thisSource.isVisible())) {
+                    thisIndex++;
+                    thisSource = thisIndex < thisSize ? thisSources.valueAt(thisIndex) : null;
+                }
+
+                // Seek to the next non-excluding source of theirs.
+                InsetsSource thatSource = thatSources.valueAt(thatIndex);
+                while (thatSource != null
+                        && (excludingCaptionInsets && thatSource.getType() == captionBar()
+                                || excludeInvisibleImeFrames && thatSource.getType() == ime()
+                                        && !thatSource.isVisible())) {
+                    thatIndex++;
+                    thatSource = thatIndex < thatSize ? thatSources.valueAt(thatIndex) : null;
+                }
+
+                if (!Objects.equals(thisSource, thatSource)) {
+                    return false;
+                }
+
+                thisIndex++;
+                thatIndex++;
             }
-            InsetsSource source = mSources[i];
-            InsetsSource otherSource = state.mSources[i];
-            if (source == null && otherSource == null) {
-                continue;
-            }
-            if (excludeInvisibleImeFrames && i == ITYPE_IME
-                    && ((source == null && !otherSource.isVisible())
-                            || (otherSource == null && !source.isVisible()))) {
-                continue;
-            }
-            if (source == null || otherSource == null) {
-                return false;
-            }
-            if (!otherSource.equals(source, excludeInvisibleImeFrames)) {
-                return false;
-            }
+            return thisIndex >= thisSize && thatIndex >= thatSize;
         }
-        return true;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mDisplayFrame, mDisplayCutout, Arrays.hashCode(mSources),
+        return Objects.hash(mDisplayFrame, mDisplayCutout, mSources.contentHashCode(),
                 mRoundedCorners, mPrivacyIndicatorBounds, mRoundedCornerFrame, mDisplayShape);
     }
 
     public InsetsState(Parcel in) {
-        readFromParcel(in);
+        mSources = readFromParcel(in);
     }
 
     @Override
@@ -984,14 +947,18 @@
     public void writeToParcel(Parcel dest, int flags) {
         mDisplayFrame.writeToParcel(dest, flags);
         mDisplayCutout.writeToParcel(dest, flags);
-        dest.writeTypedArray(mSources, 0 /* parcelableFlags */);
         dest.writeTypedObject(mRoundedCorners, flags);
         mRoundedCornerFrame.writeToParcel(dest, flags);
         dest.writeTypedObject(mPrivacyIndicatorBounds, flags);
         dest.writeTypedObject(mDisplayShape, flags);
+        final int size = mSources.size();
+        dest.writeInt(size);
+        for (int i = 0; i < size; i++) {
+            dest.writeTypedObject(mSources.valueAt(i), flags);
+        }
     }
 
-    public static final @NonNull Creator<InsetsState> CREATOR = new Creator<InsetsState>() {
+    public static final @NonNull Creator<InsetsState> CREATOR = new Creator<>() {
 
         public InsetsState createFromParcel(Parcel in) {
             return new InsetsState(in);
@@ -1002,24 +969,34 @@
         }
     };
 
-    public void readFromParcel(Parcel in) {
+    public SparseArray<InsetsSource> readFromParcel(Parcel in) {
         mDisplayFrame.readFromParcel(in);
         mDisplayCutout.readFromParcel(in);
-        in.readTypedArray(mSources, InsetsSource.CREATOR);
         mRoundedCorners = in.readTypedObject(RoundedCorners.CREATOR);
         mRoundedCornerFrame.readFromParcel(in);
         mPrivacyIndicatorBounds = in.readTypedObject(PrivacyIndicatorBounds.CREATOR);
         mDisplayShape = in.readTypedObject(DisplayShape.CREATOR);
+        final int size = in.readInt();
+        final SparseArray<InsetsSource> sources;
+        if (mSources == null) {
+            // We are constructing this InsetsState.
+            sources = new SparseArray<>(size);
+        } else {
+            sources = mSources;
+            sources.clear();
+        }
+        for (int i = 0; i < size; i++) {
+            final InsetsSource source = in.readTypedObject(InsetsSource.CREATOR);
+            sources.append(source.getId(), source);
+        }
+        return sources;
     }
 
     @Override
     public String toString() {
-        StringJoiner joiner = new StringJoiner(", ");
-        for (int i = 0; i < SIZE; i++) {
-            InsetsSource source = mSources[i];
-            if (source != null) {
-                joiner.add(source.toString());
-            }
+        final StringJoiner joiner = new StringJoiner(", ");
+        for (int i = 0, size = mSources.size(); i < size; i++) {
+            joiner.add(mSources.valueAt(i).toString());
         }
         return "InsetsState: {"
                 + "mDisplayFrame=" + mDisplayFrame
@@ -1031,5 +1008,112 @@
                 + ", mSources= { " + joiner
                 + " }";
     }
+
+    /**
+     * Traverses sources in two {@link InsetsState}s and calls back when events defined in
+     * {@link OnTraverseCallbacks} happen. This is optimized for {@link SparseArray} that we avoid
+     * triggering the binary search while getting the key or the value.
+     *
+     * This can be used to copy attributes of sources from one InsetsState to the other one, or to
+     * remove sources existing in one InsetsState but not in the other one.
+     *
+     * @param state1 The first {@link InsetsState} to be traversed.
+     * @param state2 The second {@link InsetsState} to be traversed.
+     * @param cb The {@link OnTraverseCallbacks} to call back to the caller.
+     */
+    public static void traverse(InsetsState state1, InsetsState state2, OnTraverseCallbacks cb) {
+        cb.onStart(state1, state2);
+        final int size1 = state1.sourceSize();
+        final int size2 = state2.sourceSize();
+        int index1 = 0;
+        int index2 = 0;
+        while (index1 < size1 && index2 < size2) {
+            int id1 = state1.sourceIdAt(index1);
+            int id2 = state2.sourceIdAt(index2);
+            while (id1 != id2) {
+                if (id1 < id2) {
+                    cb.onIdNotFoundInState2(index1, state1.sourceAt(index1));
+                    index1++;
+                    if (index1 < size1) {
+                        id1 = state1.sourceIdAt(index1);
+                    } else {
+                        break;
+                    }
+                } else {
+                    cb.onIdNotFoundInState1(index2, state2.sourceAt(index2));
+                    index2++;
+                    if (index2 < size2) {
+                        id2 = state2.sourceIdAt(index2);
+                    } else {
+                        break;
+                    }
+                }
+            }
+            if (index1 >= size1 || index2 >= size2) {
+                break;
+            }
+            final InsetsSource source1 = state1.sourceAt(index1);
+            final InsetsSource source2 = state2.sourceAt(index2);
+            cb.onIdMatch(source1, source2);
+            index1++;
+            index2++;
+        }
+        while (index2 < size2) {
+            cb.onIdNotFoundInState1(index2, state2.sourceAt(index2));
+            index2++;
+        }
+        while (index1 < size1) {
+            cb.onIdNotFoundInState2(index1, state1.sourceAt(index1));
+            index1++;
+        }
+        cb.onFinish(state1, state2);
+    }
+
+    /**
+     * Used with {@link #traverse(InsetsState, InsetsState, OnTraverseCallbacks)} to call back when
+     * certain events happen.
+     */
+    public interface OnTraverseCallbacks {
+
+        /**
+         * Called at the beginning of the traverse.
+         *
+         * @param state1 same as the state1 supplied to {@link #traverse}
+         * @param state2 same as the state2 supplied to {@link #traverse}
+         */
+        default void onStart(InsetsState state1, InsetsState state2) { }
+
+        /**
+         * Called when finding two IDs from two InsetsStates are the same.
+         *
+         * @param source1 the source in state1.
+         * @param source2 the source in state2.
+         */
+        default void onIdMatch(InsetsSource source1, InsetsSource source2) { }
+
+        /**
+         * Called when finding an ID in state2 but not in state1.
+         *
+         * @param index2 the index of the ID in state2.
+         * @param source2 the source which has the ID in state2.
+         */
+        default void onIdNotFoundInState1(int index2, InsetsSource source2) { }
+
+        /**
+         * Called when finding an ID in state1 but not in state2.
+         *
+         * @param index1 the index of the ID in state1.
+         * @param source1 the source which has the ID in state1.
+         */
+        default void onIdNotFoundInState2(int index1, InsetsSource source1) { }
+
+        /**
+         * Called at the end of the traverse.
+         *
+         * @param state1 same as the state1 supplied to {@link #traverse}
+         * @param state2 same as the state2 supplied to {@link #traverse}
+         */
+        default void onFinish(InsetsState state1, InsetsState state2) { }
+    }
 }
 
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 54e1a53..8663013 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -64,6 +64,7 @@
 import android.opengl.EGLSync;
 import android.os.Build;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
@@ -463,6 +464,10 @@
     public long mNativeObject;
     private long mNativeHandle;
 
+    private final Object mChoreographerLock = new Object();
+    @GuardedBy("mChoreographerLock")
+    private Choreographer mChoreographer;
+
     // TODO: Move width/height to native and fix locking through out.
     private final Object mLock = new Object();
     @GuardedBy("mLock")
@@ -1269,6 +1274,59 @@
     }
 
     /**
+     * Returns the associated {@link Choreographer} instance with the
+     * current instance of the SurfaceControl.
+     * Must be called from a thread that already has a {@link android.os.Looper}
+     * associated with it.
+     * If there is no {@link Choreographer} associated with the SurfaceControl then a new instance
+     * of the {@link Choreographer} is created.
+     *
+     * @hide
+     */
+    @TestApi
+    public @NonNull Choreographer getChoreographer() {
+        return getChoreographer(Looper.myLooper());
+    }
+
+    /**
+     * Returns the associated {@link Choreographer} instance with the
+     * current instance of the SurfaceControl.
+     * If there is no {@link Choreographer} associated with the SurfaceControl then a new instance
+     * of the {@link Choreographer} is created.
+     *
+     * @param looper the choreographer is attached on this looper
+     *
+     * @hide
+     */
+    @TestApi
+    public @NonNull Choreographer getChoreographer(@NonNull Looper looper) {
+        checkNotReleased();
+        synchronized (mChoreographerLock) {
+            if (mChoreographer != null) {
+                return mChoreographer;
+            }
+
+            mChoreographer = Choreographer.getInstanceForSurfaceControl(mNativeHandle, looper);
+            return mChoreographer;
+        }
+    }
+
+    /**
+     * Returns true if {@link Choreographer} is present otherwise false.
+     * To check the validity use {@link #isValid} on the SurfaceControl, a valid SurfaceControl with
+     * choreographer will have the valid Choreographer.
+     *
+     * @hide
+     */
+    @TestApi
+    @UnsupportedAppUsage
+    public boolean hasChoreographer() {
+        synchronized (mChoreographerLock) {
+            return mChoreographer != null;
+        }
+    }
+
+    /**
      * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
      * android.view.SurfaceControlProto}.
      *
@@ -1325,6 +1383,12 @@
             mNativeObject = 0;
             mNativeHandle = 0;
             mCloseGuard.close();
+            synchronized (mChoreographerLock) {
+                if (mChoreographer != null) {
+                    mChoreographer.invalidate();
+                    mChoreographer = null;
+                }
+            }
         }
     }
 
@@ -1692,7 +1756,7 @@
      * Information about the min and max refresh rate DM would like to set the display to.
      * @hide
      */
-    public static final class RefreshRateRange {
+    public static final class RefreshRateRange implements Parcelable {
         public static final String TAG = "RefreshRateRange";
 
         // The tolerance within which we consider something approximately equals.
@@ -1761,6 +1825,35 @@
             this.min = other.min;
             this.max = other.max;
         }
+
+        /**
+         * Writes the RefreshRateRange to parce
+         *
+         * @param dest parcel to write the transaction to
+         */
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
+            dest.writeFloat(min);
+            dest.writeFloat(max);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final @NonNull Creator<RefreshRateRange> CREATOR =
+                new Creator<RefreshRateRange>() {
+                    @Override
+                    public RefreshRateRange createFromParcel(Parcel in) {
+                        return new RefreshRateRange(in.readFloat(), in.readFloat());
+                    }
+
+                    @Override
+                    public RefreshRateRange[] newArray(int size) {
+                        return new RefreshRateRange[size];
+                    }
+                };
     }
 
     /**
@@ -2411,10 +2504,10 @@
      * {@link Transaction#setTrustedPresentationCallback(SurfaceControl,
      * TrustedPresentationThresholds, Executor, Consumer)}
      */
-    public static class TrustedPresentationThresholds {
-        private float mMinAlpha;
-        private float mMinFractionRendered;
-        private int mStabilityRequirementMs;
+    public static final class TrustedPresentationThresholds {
+        private final float mMinAlpha;
+        private final float mMinFractionRendered;
+        private final int mStabilityRequirementMs;
 
         /**
          * Creates a TrustedPresentationThresholds that's used when calling
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1eb87c9..0bce710 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -20,6 +20,7 @@
 import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER;
 import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -51,6 +52,8 @@
 
 import com.android.internal.view.SurfaceCallbackHelper;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.locks.ReentrantLock;
@@ -117,6 +120,36 @@
  * may not blend properly as a consequence of not applying alpha to the surface content directly.
  */
 public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback {
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"SURFACE_LIFECYCLE_"},
+            value = {SURFACE_LIFECYCLE_DEFAULT,
+                     SURFACE_LIFECYCLE_FOLLOWS_VISIBILITY,
+                     SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT})
+    public @interface SurfaceLifecycleStrategy {}
+
+    /**
+     * Default lifecycle of the Surface owned by this SurfaceView.
+     *
+     * The default lifecycle matches {@link #SURFACE_LIFECYCLE_FOLLOWS_VISIBILITY}.
+     */
+    public static final int SURFACE_LIFECYCLE_DEFAULT = 0;
+
+    /**
+     * The Surface lifecycle is tied to SurfaceView visibility.
+     *
+     * The Surface is created when the SurfaceView becomes visible, and is destroyed when the
+     * SurfaceView is no longer visible.
+     */
+    public static final int SURFACE_LIFECYCLE_FOLLOWS_VISIBILITY = 1;
+
+    /**
+     * The Surface lifecycle is tied to SurfaceView attachment.
+     * The Surface is created when the SurfaceView first becomes attached, but is not destroyed
+     * until this SurfaceView has been detached from the current window.
+     */
+    public static final int SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT = 2;
+
     private static final String TAG = "SurfaceView";
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_POSITION = false;
@@ -151,6 +184,11 @@
     SurfaceControl mBackgroundControl;
     private boolean mDisableBackgroundLayer = false;
 
+    @SurfaceLifecycleStrategy
+    private int mRequestedSurfaceLifecycleStrategy = SURFACE_LIFECYCLE_DEFAULT;
+    @SurfaceLifecycleStrategy
+    private int mSurfaceLifecycleStrategy = SURFACE_LIFECYCLE_DEFAULT;
+
     /**
      * We use this lock to protect access to mSurfaceControl. Both are accessed on the UI
      * thread and the render thread via RenderNode.PositionUpdateListener#positionLost.
@@ -413,6 +451,7 @@
             observer.removeOnPreDrawListener(mDrawListener);
             mGlobalListenersAdded = false;
         }
+        if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " Detaching SV");
 
         mRequestedVisible = false;
 
@@ -699,6 +738,20 @@
         }
     }
 
+    /**
+     * Controls the lifecycle of the Surface owned by this SurfaceView.
+     *
+     * <p>By default, the lifecycycle strategy employed by the SurfaceView is
+     * {@link #SURFACE_LIFECYCLE_DEFAULT}.
+     *
+     * @param lifecycleStrategy The strategy for the lifecycle of the Surface owned by this
+     * SurfaceView.
+     */
+    public void setSurfaceLifecycle(@SurfaceLifecycleStrategy int lifecycleStrategy) {
+        mRequestedSurfaceLifecycleStrategy = lifecycleStrategy;
+        updateSurface();
+    }
+
     private void updateOpaqueFlag() {
         if (!PixelFormat.formatHasAlpha(mRequestedFormat)) {
             mSurfaceFlags |= SurfaceControl.OPAQUE;
@@ -780,7 +833,7 @@
 
         mSurfaceLock.lock();
         try {
-            mDrawingStopped = !mVisible;
+            mDrawingStopped = !surfaceShouldExist();
 
             if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                     + "Cur surface: " + mSurface);
@@ -887,6 +940,20 @@
         return realSizeChanged;
     }
 
+    private boolean requiresSurfaceControlCreation(boolean formatChanged, boolean visibleChanged) {
+        if (mSurfaceLifecycleStrategy == SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT) {
+            return (mSurfaceControl == null || formatChanged) && mAttachedToWindow;
+        }
+
+        return (mSurfaceControl == null || formatChanged || visibleChanged) && mRequestedVisible;
+    }
+
+    private boolean surfaceShouldExist() {
+        final boolean respectVisibility =
+                mSurfaceLifecycleStrategy != SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT;
+        return mVisible || (!respectVisibility && mAttachedToWindow);
+    }
+
     /** @hide */
     protected void updateSurface() {
         if (!mHaveFrame) {
@@ -921,8 +988,7 @@
         final boolean formatChanged = mFormat != mRequestedFormat;
         final boolean visibleChanged = mVisible != mRequestedVisible;
         final boolean alphaChanged = mAlpha != alpha;
-        final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged)
-                && mRequestedVisible;
+        final boolean creating = requiresSurfaceControlCreation(formatChanged, visibleChanged);
         final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
         final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility;
         getLocationInWindow(mLocation);
@@ -933,10 +999,13 @@
         final boolean hintChanged = (viewRoot.getBufferTransformHint() != mTransformHint)
                 && mRequestedVisible;
         final boolean relativeZChanged = mSubLayer != mRequestedSubLayer;
+        final boolean surfaceLifecycleStrategyChanged =
+                mSurfaceLifecycleStrategy != mRequestedSurfaceLifecycleStrategy;
 
         if (creating || formatChanged || sizeChanged || visibleChanged
                 || alphaChanged || windowVisibleChanged || positionChanged
-                || layoutSizeChanged || hintChanged || relativeZChanged) {
+                || layoutSizeChanged || hintChanged || relativeZChanged || !mAttachedToWindow
+                || surfaceLifecycleStrategyChanged) {
 
             if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                     + "Changes: creating=" + creating
@@ -945,7 +1014,10 @@
                     + " hint=" + hintChanged
                     + " visible=" + visibleChanged
                     + " left=" + (mWindowSpaceLeft != mLocation[0])
-                    + " top=" + (mWindowSpaceTop != mLocation[1]));
+                    + " top=" + (mWindowSpaceTop != mLocation[1])
+                    + " z=" + relativeZChanged
+                    + " attached=" + mAttachedToWindow
+                    + " lifecycleStrategy=" + surfaceLifecycleStrategyChanged);
 
             try {
                 mVisible = mRequestedVisible;
@@ -959,6 +1031,9 @@
                 mTransformHint = viewRoot.getBufferTransformHint();
                 mSubLayer = mRequestedSubLayer;
 
+                final int previousSurfaceLifecycleStrategy = mSurfaceLifecycleStrategy;
+                mSurfaceLifecycleStrategy = mRequestedSurfaceLifecycleStrategy;
+
                 mScreenRect.left = mWindowSpaceLeft;
                 mScreenRect.top = mWindowSpaceTop;
                 mScreenRect.right = mWindowSpaceLeft + getWidth();
@@ -1000,15 +1075,27 @@
                     SurfaceHolder.Callback[] callbacks = null;
 
                     final boolean surfaceChanged = creating;
-                    if (mSurfaceCreated && (surfaceChanged || (!mVisible && visibleChanged))) {
-                        mSurfaceCreated = false;
-                        notifySurfaceDestroyed();
+                    final boolean respectVisibility =
+                            mSurfaceLifecycleStrategy != SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT;
+                    final boolean previouslyDidNotRespectVisibility =
+                            previousSurfaceLifecycleStrategy
+                                    == SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT;
+                    final boolean lifecycleNewlyRespectsVisibility = respectVisibility
+                            && previouslyDidNotRespectVisibility;
+                    if (mSurfaceCreated) {
+                        if (surfaceChanged || (!respectVisibility && !mAttachedToWindow)
+                                || (respectVisibility && !mVisible
+                                        && (visibleChanged || lifecycleNewlyRespectsVisibility))) {
+                            mSurfaceCreated = false;
+                            notifySurfaceDestroyed();
+                        }
                     }
 
                     copySurface(creating /* surfaceControlCreated */, sizeChanged);
 
-                    if (mVisible && mSurface.isValid()) {
-                        if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
+                    if (surfaceShouldExist() && mSurface.isValid()) {
+                        if (!mSurfaceCreated
+                                && (surfaceChanged || (respectVisibility && visibleChanged))) {
                             mSurfaceCreated = true;
                             mIsCreating = true;
                             if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
@@ -1019,7 +1106,7 @@
                             }
                         }
                         if (creating || formatChanged || sizeChanged || hintChanged
-                                || visibleChanged || realSizeChanged) {
+                                || (respectVisibility && visibleChanged) || realSizeChanged) {
                             if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
                                     + "surfaceChanged -- format=" + mFormat
                                     + " w=" + myWidth + " h=" + myHeight);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 9c6e823..2db2132 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -572,17 +572,10 @@
     }
 
     @Override
-    public void setSurfaceControl(@Nullable SurfaceControl surfaceControl) {
-        super.setSurfaceControl(surfaceControl);
+    public void setSurfaceControl(@Nullable SurfaceControl surfaceControl,
+            @Nullable BLASTBufferQueue blastBufferQueue) {
+        super.setSurfaceControl(surfaceControl, blastBufferQueue);
         mWebViewOverlayProvider.setSurfaceControl(surfaceControl);
-        updateWebViewOverlayCallbacks();
-    }
-
-    /**
-     * Sets the BLASTBufferQueue being used for rendering. This is required to be specified
-     * for WebView overlay support
-     */
-    public void setBlastBufferQueue(@Nullable BLASTBufferQueue blastBufferQueue) {
         mWebViewOverlayProvider.setBLASTBufferQueue(blastBufferQueue);
         updateWebViewOverlayCallbacks();
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9fa6c05..20f6baf 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import static android.content.res.Resources.ID_NULL;
+import static android.os.Trace.TRACE_TAG_APP;
 import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
@@ -998,6 +999,22 @@
     private static boolean sAcceptZeroSizeDragShadow;
 
     /**
+     * When true, measure and layout passes of all the newly attached views will be logged with
+     * {@link Trace}, so we can better debug jank due to complex view hierarchies.
+     */
+    private static boolean sTraceLayoutSteps;
+
+    /**
+     * When not null, emits a {@link Trace} instant event and the stacktrace every time a relayout
+     * of a class having this name happens.
+     */
+    private static String sTraceRequestLayoutClass;
+
+    /** Used to avoid computing the full strings each time when layout tracing is enabled. */
+    @Nullable
+    private ViewTraversalTracingStrings mTracingStrings;
+
+    /**
      * Prior to R, {@link #dispatchApplyWindowInsets} had an issue:
      * <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
      * entire view hierarchy in prefix order, including siblings as well as siblings of parents
@@ -3583,6 +3600,9 @@
      *                  1               PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
      *                 1                PFLAG4_DRAG_A11Y_STARTED
      *                1                 PFLAG4_AUTO_HANDWRITING_INITIATION_ENABLED
+     *               1                  PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER
+     *              1                   PFLAG4_TRAVERSAL_TRACING_ENABLED
+     *             1                    PFLAG4_RELAYOUT_TRACING_ENABLED
      * |-------|-------|-------|-------|
      */
 
@@ -3669,6 +3689,18 @@
      */
     private static final int PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER = 0x000020000;
 
+    /**
+     * When set, measure and layout passes of this view will be logged with {@link Trace}, so we
+     * can better debug jank due to complex view hierarchies.
+     */
+    private static final int PFLAG4_TRAVERSAL_TRACING_ENABLED = 0x000040000;
+
+    /**
+     * When set, emits a {@link Trace} instant event and stacktrace every time a requestLayout of
+     * this class happens.
+     */
+    private static final int PFLAG4_RELAYOUT_TRACING_ENABLED = 0x000080000;
+
     /* End of masks for mPrivateFlags4 */
 
     /** @hide */
@@ -6653,6 +6685,15 @@
         out.append(mRight);
         out.append(',');
         out.append(mBottom);
+        appendId(out);
+        if (mAutofillId != null) {
+            out.append(" aid="); out.append(mAutofillId);
+        }
+        out.append("}");
+        return out.toString();
+    }
+
+    void appendId(StringBuilder out) {
         final int id = getId();
         if (id != NO_ID) {
             out.append(" #");
@@ -6684,11 +6725,6 @@
                 }
             }
         }
-        if (mAutofillId != null) {
-            out.append(" aid="); out.append(mAutofillId);
-        }
-        out.append("}");
-        return out.toString();
     }
 
     /**
@@ -14083,7 +14119,7 @@
         // working solution.
         View source = this;
         while (true) {
-            if (source.includeForAccessibility()) {
+            if (source.includeForAccessibility(false)) {
                 source.sendAccessibilityEvent(eventType);
                 return;
             }
@@ -14437,11 +14473,12 @@
             // importance, since we'll need to check it later to make sure.
             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
-            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
+            final boolean oldIncludeForAccessibility =
+                    maySkipNotify && includeForAccessibility(false);
             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
-            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
+            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility(false)) {
                 notifySubtreeAccessibilityStateChangedIfNeeded();
             } else {
                 notifyViewAccessibilityStateChangedIfNeeded(
@@ -14573,28 +14610,53 @@
     }
 
     /**
-     * Whether to regard this view for accessibility. A view is regarded for
-     * accessibility if it is important for accessibility or the querying
-     * accessibility service has explicitly requested that view not
-     * important for accessibility are regarded.
-     *
-     * @return Whether to regard the view for accessibility.
-     *
+     * @see #includeForAccessibility(boolean)
      * @hide
      */
     @UnsupportedAppUsage
     public boolean includeForAccessibility() {
-        if (mAttachInfo != null) {
+        return includeForAccessibility(true);
+    }
+
+    /**
+     * Whether to regard this view for accessibility.
+     *
+     * <p>
+     * If this decision is used for generating the accessibility node tree then this returns false
+     * for {@link #isAccessibilityDataPrivate()} views queried by non-accessibility tools.
+     * </p>
+     * <p>
+     * Otherwise, a view is regarded for accessibility if:
+     * <li>the view returns true for {@link #isImportantForAccessibility()}, or</li>
+     * <li>the querying accessibility service has explicitly requested that views not important for
+     * accessibility are regarded by setting
+     * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS}</li>
+     * </p>
+     *
+     * @param forNodeTree True if the result of this function will be used for generating a node
+     *                    tree, otherwise false (like when sending {@link AccessibilityEvent}s).
+     * @return Whether to regard the view for accessibility.
+     * @hide
+     */
+    public boolean includeForAccessibility(boolean forNodeTree) {
+        if (mAttachInfo == null) {
+            return false;
+        }
+
+        if (forNodeTree) {
+            // The AccessibilityDataPrivate property should not effect whether this View is
+            // included for consideration when sending AccessibilityEvents. Events copy their
+            // source View's AccessibilityDataPrivate value, and then filtering is done when
+            // AccessibilityManagerService propagates events to each recipient AccessibilityService.
             if (!AccessibilityManager.getInstance(mContext).isRequestFromAccessibilityTool()
                     && isAccessibilityDataPrivate()) {
                 return false;
             }
-
-            return (mAttachInfo.mAccessibilityFetchFlags
-                    & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
-                    || isImportantForAccessibility();
         }
-        return false;
+
+        return (mAttachInfo.mAccessibilityFetchFlags
+                & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
+                || isImportantForAccessibility();
     }
 
     /**
@@ -17142,7 +17204,8 @@
     void setFlags(int flags, int mask) {
         final boolean accessibilityEnabled =
                 AccessibilityManager.getInstance(mContext).isEnabled();
-        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
+        final boolean oldIncludeForAccessibility =
+                accessibilityEnabled && includeForAccessibility(false);
 
         int old = mViewFlags;
         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
@@ -17368,7 +17431,7 @@
             if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
                     || (changed & CONTEXT_CLICKABLE) != 0) {
-                if (oldIncludeForAccessibility != includeForAccessibility()) {
+                if (oldIncludeForAccessibility != includeForAccessibility(false)) {
                     notifySubtreeAccessibilityStateChangedIfNeeded();
                 } else {
                     notifyViewAccessibilityStateChangedIfNeeded(
@@ -21154,6 +21217,14 @@
         if (isFocused()) {
             notifyFocusChangeToImeFocusController(true /* hasFocus */);
         }
+
+        if (sTraceLayoutSteps) {
+            setTraversalTracingEnabled(true);
+        }
+        if (sTraceRequestLayoutClass != null
+                && sTraceRequestLayoutClass.equals(getClass().getSimpleName())) {
+            setRelayoutTracingEnabled(true);
+        }
     }
 
     /**
@@ -24053,6 +24124,30 @@
         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
     }
 
+    /**
+     * Enable measure/layout debugging on traces.
+     *
+     * @see Trace
+     * @hide
+     */
+    public static void setTraceLayoutSteps(boolean traceLayoutSteps) {
+        sTraceLayoutSteps = traceLayoutSteps;
+    }
+
+    /**
+     * Enable request layout tracing classes with {@code s} simple name.
+     * <p>
+     * When set, a {@link Trace} instant event and a log with the stacktrace is emitted every
+     * time a requestLayout of a class matching {@code s} name happens.
+     * This applies only to views attached from this point onwards.
+     *
+     * @see Trace#instant(long, String)
+     * @hide
+     */
+    public static void setTracedRequestLayoutClassClass(String s) {
+        sTraceRequestLayoutClass = s;
+    }
+
     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
         Insets parentInsets = mParent instanceof View ?
                 ((View) mParent).getOpticalInsets() : Insets.NONE;
@@ -24087,7 +24182,13 @@
     @SuppressWarnings({"unchecked"})
     public void layout(int l, int t, int r, int b) {
         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
+            if (isTraversalTracingEnabled()) {
+                Trace.beginSection(mTracingStrings.onMeasureBeforeLayout);
+            }
             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
+            if (isTraversalTracingEnabled()) {
+                Trace.endSection();
+            }
             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
         }
 
@@ -24100,7 +24201,13 @@
                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
 
         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
+            if (isTraversalTracingEnabled()) {
+                Trace.beginSection(mTracingStrings.onLayout);
+            }
             onLayout(changed, l, t, r, b);
+            if (isTraversalTracingEnabled()) {
+                Trace.endSection();
+            }
 
             if (shouldDrawRoundScrollbar()) {
                 if(mRoundScrollbarRenderer == null) {
@@ -26660,6 +26767,25 @@
         return (viewRoot != null && viewRoot.isInLayout());
     }
 
+    /** To be used only for debugging purposes. */
+    private void printStackStrace(String name) {
+        Log.d(VIEW_LOG_TAG, "---- ST:" + name);
+
+        StringBuilder sb = new StringBuilder();
+        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
+        int startIndex = 1;
+        int endIndex = Math.min(stackTraceElements.length, startIndex + 20); // max 20 entries.
+        for (int i = startIndex; i < endIndex; i++) {
+            StackTraceElement s = stackTraceElements[i];
+            sb.append(s.getMethodName())
+                    .append("(")
+                    .append(s.getFileName())
+                    .append(":")
+                    .append(s.getLineNumber())
+                    .append(") <- ");
+        }
+        Log.d(VIEW_LOG_TAG, name + ": " + sb);
+    }
     /**
      * Call this when something has changed which has invalidated the
      * layout of this view. This will schedule a layout pass of the view
@@ -26673,6 +26799,12 @@
      */
     @CallSuper
     public void requestLayout() {
+        if (isRelayoutTracingEnabled()) {
+            Trace.instantForTrack(TRACE_TAG_APP, "requestLayoutTracing",
+                    mTracingStrings.classSimpleName);
+            printStackStrace(mTracingStrings.requestLayoutStacktracePrefix);
+        }
+
         if (mMeasureCache != null) mMeasureCache.clear();
 
         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
@@ -26766,8 +26898,14 @@
 
             int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
             if (cacheIndex < 0 || sIgnoreMeasureCache) {
+                if (isTraversalTracingEnabled()) {
+                    Trace.beginSection(mTracingStrings.onMeasure);
+                }
                 // measure ourselves, this should set the measured dimension flag back
                 onMeasure(widthMeasureSpec, heightMeasureSpec);
+                if (isTraversalTracingEnabled()) {
+                    Trace.endSection();
+                }
                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
             } else {
                 long value = mMeasureCache.valueAt(cacheIndex);
@@ -32005,6 +32143,38 @@
                 .isStylusHandwritingAvailable();
     }
 
+    private void setTraversalTracingEnabled(boolean enabled) {
+        if (enabled) {
+            if (mTracingStrings == null) {
+                mTracingStrings = new ViewTraversalTracingStrings(this);
+            }
+            mPrivateFlags4 |= PFLAG4_TRAVERSAL_TRACING_ENABLED;
+        } else {
+            mPrivateFlags4 &= ~PFLAG4_TRAVERSAL_TRACING_ENABLED;
+        }
+    }
+
+    private boolean isTraversalTracingEnabled() {
+        return (mPrivateFlags4 & PFLAG4_TRAVERSAL_TRACING_ENABLED)
+                == PFLAG4_TRAVERSAL_TRACING_ENABLED;
+    }
+
+    private void setRelayoutTracingEnabled(boolean enabled) {
+        if (enabled) {
+            if (mTracingStrings == null) {
+                mTracingStrings = new ViewTraversalTracingStrings(this);
+            }
+            mPrivateFlags4 |= PFLAG4_RELAYOUT_TRACING_ENABLED;
+        } else {
+            mPrivateFlags4 &= ~PFLAG4_RELAYOUT_TRACING_ENABLED;
+        }
+    }
+
+    private boolean isRelayoutTracingEnabled() {
+        return (mPrivateFlags4 & PFLAG4_RELAYOUT_TRACING_ENABLED)
+                == PFLAG4_RELAYOUT_TRACING_ENABLED;
+    }
+
     /**
      * Collects a {@link ViewTranslationRequest} which represents the content to be translated in
      * the view.
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index f51d9ba..c96d298 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -27,6 +27,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.hardware.input.InputManager;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -232,6 +233,12 @@
      */
     private static final int MAXIMUM_FLING_VELOCITY = 8000;
 
+    /** Value used as a minimum fling velocity, when fling is not supported. */
+    private static final int NO_FLING_MIN_VELOCITY = Integer.MAX_VALUE;
+
+    /** Value used as a maximum fling velocity, when fling is not supported. */
+    private static final int NO_FLING_MAX_VELOCITY = Integer.MIN_VALUE;
+
     /**
      * Delay before dispatching a recurring accessibility event in milliseconds.
      * This delay guarantees that a recurring event will be send at most once
@@ -333,6 +340,8 @@
     private final int mFadingEdgeLength;
     private final int mMinimumFlingVelocity;
     private final int mMaximumFlingVelocity;
+    private final int mMinimumRotaryEncoderFlingVelocity;
+    private final int mMaximumRotaryEncoderFlingVelocity;
     private final int mScrollbarSize;
     private final int mTouchSlop;
     private final int mHandwritingSlop;
@@ -378,6 +387,8 @@
         mFadingEdgeLength = FADING_EDGE_LENGTH;
         mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY;
         mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY;
+        mMinimumRotaryEncoderFlingVelocity = MINIMUM_FLING_VELOCITY;
+        mMaximumRotaryEncoderFlingVelocity = MAXIMUM_FLING_VELOCITY;
         mScrollbarSize = SCROLL_BAR_SIZE;
         mTouchSlop = TOUCH_SLOP;
         mHandwritingSlop = HANDWRITING_SLOP;
@@ -504,6 +515,19 @@
                 com.android.internal.R.dimen.config_viewMinFlingVelocity);
         mMaximumFlingVelocity = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.config_viewMaxFlingVelocity);
+
+        int configMinRotaryEncoderFlingVelocity = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.config_viewMinRotaryEncoderFlingVelocity);
+        int configMaxRotaryEncoderFlingVelocity = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.config_viewMaxRotaryEncoderFlingVelocity);
+        if (configMinRotaryEncoderFlingVelocity < 0 || configMaxRotaryEncoderFlingVelocity < 0) {
+            mMinimumRotaryEncoderFlingVelocity = NO_FLING_MIN_VELOCITY;
+            mMaximumRotaryEncoderFlingVelocity = NO_FLING_MAX_VELOCITY;
+        } else {
+            mMinimumRotaryEncoderFlingVelocity = configMinRotaryEncoderFlingVelocity;
+            mMaximumRotaryEncoderFlingVelocity = configMaxRotaryEncoderFlingVelocity;
+        }
+
         mGlobalActionsKeyTimeout = res.getInteger(
                 com.android.internal.R.integer.config_globalActionsKeyTimeout);
 
@@ -1077,6 +1101,98 @@
     }
 
     /**
+     * Minimum absolute value of velocity to initiate a fling for a motion generated by an
+     * {@link InputDevice} with an id of {@code inputDeviceId}, from an input {@code source} and on
+     * a given motion event {@code axis}.
+     *
+     * <p>Before utilizing this method to get a minimum fling velocity for a motion generated by the
+     * input device, scale the velocity of the motion events generated by the input device to pixels
+     * per second.
+     *
+     * <p>For instance, if you tracked {@link MotionEvent#AXIS_SCROLL} vertical velocities generated
+     * from a {@link InputDevice#SOURCE_ROTARY_ENCODER}, the velocity returned from
+     * {@link VelocityTracker} will be in the units with which the axis values were reported in the
+     * motion event. Before comparing that velocity against the minimum fling velocity specified
+     * here, make sure that the {@link MotionEvent#AXIS_SCROLL} velocity from the tracker is
+     * calculated in "units per second" (see {@link VelocityTracker#computeCurrentVelocity(int)},
+     * {@link VelocityTracker#computeCurrentVelocity(int, float)} to adjust your velocity
+     * computations to "per second"), and use {@link #getScaledVerticalScrollFactor} to change this
+     * velocity value to "pixels/second".
+     *
+     * <p>If the provided {@code inputDeviceId} is not valid, or if the input device whose ID is
+     * provided does not support the given motion event source and/or axis, this method will return
+     * {@code Integer.MAX_VALUE}.
+     *
+     * <h3>Obtaining the correct arguments for this method call</h3>
+     * <p><b>inputDeviceId</b>: if calling this method in response to a {@link MotionEvent}, use
+     * the device ID that is reported by the event, which can be obtained using
+     * {@link MotionEvent#getDeviceId()}. Otherwise, use a valid ID that is obtained from
+     * {@link InputDevice#getId()}, or from an {@link InputManager} instance
+     * ({@link InputManager#getInputDeviceIds()} gives all the valid input device IDs).
+     *
+     * <p><b>axis</b>: a {@link MotionEvent} may report data for multiple axes, and each axis may
+     * have multiple data points for different pointers. Use the axis for which you obtained the
+     * velocity for ({@link VelocityTracker} lets you calculate velocities for a specific axis. Use
+     * the axis for which you calculated velocity). You can use
+     * {@link InputDevice#getMotionRanges()} to get all the {@link InputDevice.MotionRange}s for the
+     * {@link InputDevice}, from which you can derive all the valid axes for the device.
+     *
+     * <p><b>source</b>: use {@link MotionEvent#getSource()} if calling this method in response to a
+     * {@link MotionEvent}. Otherwise, use a valid source for the {@link InputDevice}. You can use
+     * {@link InputDevice#getMotionRanges()} to get all the {@link InputDevice.MotionRange}s for the
+     * {@link InputDevice}, from which you can derive all the valid sources for the device.
+     *
+     *
+     * <p>This method optimizes calls over multiple input device IDs, so caching the return value of
+     * the method is not necessary if you are handling multiple input devices.
+     *
+     * @param inputDeviceId the ID of the {@link InputDevice} that generated the motion triggering
+     *          fling.
+     * @param axis the axis on which the motion triggering the fling happened. This axis should be
+     *          a valid axis that can be reported by the provided input device from the provided
+     *          input device source.
+     * @param source the input source of the motion causing fling. This source should be a valid
+     *          source for the {@link InputDevice} whose ID is {@code inputDeviceId}.
+     *
+     * @return the minimum velocity, in pixels/second, to trigger fling.
+     *
+     * @see InputDevice#getMotionRange(int, int)
+     * @see InputDevice#getMotionRanges()
+     * @see VelocityTracker#getAxisVelocity(int, int)
+     * @see VelocityTracker#getAxisVelocity(int)
+     */
+    public int getScaledMinimumFlingVelocity(int inputDeviceId, int axis, int source) {
+        if (!isInputDeviceInfoValid(inputDeviceId, axis, source)) return NO_FLING_MIN_VELOCITY;
+
+        if (source == InputDevice.SOURCE_ROTARY_ENCODER) return mMinimumRotaryEncoderFlingVelocity;
+
+        return mMinimumFlingVelocity;
+    }
+
+    /**
+     * Maximum absolute value of velocity to initiate a fling for a motion generated by an
+     * {@link InputDevice} with an id of {@code inputDeviceId}, from an input {@code source} and on
+     * a given motion event {@code axis}.
+     *
+     * <p>Similar to {@link #getScaledMinimumFlingVelocity(int, int, int)}, but for maximum fling
+     * velocity, instead of minimum. Also, unlike that method which returns
+     * {@code Integer.MAX_VALUE} for bad input device ID, source and/or motion event axis inputs,
+     * this method returns {@code Integer.MIN_VALUE} for such bad inputs.
+     */
+    public int getScaledMaximumFlingVelocity(int inputDeviceId, int axis, int source) {
+        if (!isInputDeviceInfoValid(inputDeviceId, axis, source)) return NO_FLING_MAX_VELOCITY;
+
+        if (source == InputDevice.SOURCE_ROTARY_ENCODER) return mMaximumRotaryEncoderFlingVelocity;
+
+        return mMaximumFlingVelocity;
+    }
+
+    private static boolean isInputDeviceInfoValid(int id, int axis, int source) {
+        InputDevice device = InputManager.getInstance().getInputDevice(id);
+        return device != null && device.getMotionRange(axis, source) != null;
+    }
+
+    /**
      * Check if shortcuts should be displayed in menus.
      *
      * @return {@code True} if shortcuts should be displayed in menus.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0e4ac01..73d4471 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3532,7 +3532,7 @@
     @Override
     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
         boolean handled = false;
-        if (includeForAccessibility()) {
+        if (includeForAccessibility(false)) {
             handled = super.dispatchPopulateAccessibilityEventInternal(event);
             if (handled) {
                 return handled;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9119ea4..b1a5802 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -22,7 +22,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.InputDevice.SOURCE_CLASS_NONE;
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.View.PFLAG_DRAW_ANIMATION;
 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
@@ -291,7 +291,7 @@
      * @hide
      */
     public static final boolean CAPTION_ON_SHELL =
-            SystemProperties.getBoolean("persist.wm.debug.caption_on_shell", false);
+            SystemProperties.getBoolean("persist.wm.debug.caption_on_shell", true);
 
     /**
      * Whether the client should compute the window frame on its own.
@@ -683,6 +683,10 @@
 
     private BLASTBufferQueue mBlastBufferQueue;
 
+    private boolean mUpdateSdrHdrRatioInfo = false;
+    private float mDesiredSdrHdrRatio = 1f;
+    private float mRenderSdrHdrRatio = 1f;
+
     /**
      * Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to
      * the surface insets. This surface is created only if a client requests it via {@link
@@ -705,6 +709,7 @@
 
     // These are accessed by multiple threads.
     final Rect mWinFrame; // frame given by window manager.
+    private final Rect mLastLayoutFrame;
     Rect mOverrideInsetsFrame;
 
     final Rect mPendingBackDropFrame = new Rect();
@@ -764,7 +769,12 @@
     private long mFpsPrevTime = -1;
     private int mFpsNumFrames;
 
-    private int mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
+    /**
+     * The resolved pointer icon type requested by this window.
+     * A null value indicates the resolved pointer icon has not yet been calculated.
+     */
+    @Nullable
+    private Integer mPointerIconType = null;
     private PointerIcon mCustomPointerIcon = null;
 
     /**
@@ -947,6 +957,7 @@
         mHeight = -1;
         mDirty = new Rect();
         mWinFrame = new Rect();
+        mLastLayoutFrame = new Rect();
         mWindow = new W(this);
         mLeashToken = new Binder();
         mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
@@ -1311,7 +1322,7 @@
                         UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH,
                         mInsetsController.getRequestedVisibleTypes(), 1f /* compactScale */,
                         mTmpFrames);
-                setFrame(mTmpFrames.frame);
+                setFrame(mTmpFrames.frame, true /* withinRelayout */);
                 registerBackCallbackOnWindow();
                 if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
                 if (res < WindowManagerGlobal.ADD_OKAY) {
@@ -1627,18 +1638,16 @@
                 final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
                         || insets.top != 0 || insets.bottom != 0;
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
-                mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
+                final ThreadedRenderer renderer = ThreadedRenderer.create(mContext, translucent,
                         attrs.getTitle().toString());
+                mAttachInfo.mThreadedRenderer = renderer;
+                renderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
                 updateColorModeIfNeeded(attrs.getColorMode());
                 updateForceDarkMode();
-                if (mAttachInfo.mThreadedRenderer != null) {
-                    mAttachInfo.mHardwareAccelerated =
-                            mAttachInfo.mHardwareAccelerationRequested = true;
-                    if (mHardwareRendererObserver != null) {
-                        mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
-                    }
-                    mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
-                    mAttachInfo.mThreadedRenderer.setBlastBufferQueue(mBlastBufferQueue);
+                mAttachInfo.mHardwareAccelerated = true;
+                mAttachInfo.mHardwareAccelerationRequested = true;
+                if (mHardwareRendererObserver != null) {
+                    renderer.addObserver(mHardwareRendererObserver);
                 }
             }
         }
@@ -1840,7 +1849,7 @@
             onMovedToDisplay(displayId, mLastConfigurationFromResources);
         }
 
-        setFrame(frame);
+        setFrame(frame, false /* withinRelayout */);
         mTmpFrames.displayFrame.set(displayFrame);
         if (mTmpFrames.attachedFrame != null && attachedFrame != null) {
             mTmpFrames.attachedFrame.set(attachedFrame);
@@ -2264,8 +2273,7 @@
         }
 
         if (mAttachInfo.mThreadedRenderer != null) {
-            mAttachInfo.mThreadedRenderer.setSurfaceControl(null);
-            mAttachInfo.mThreadedRenderer.setBlastBufferQueue(null);
+            mAttachInfo.mThreadedRenderer.setSurfaceControl(null, null);
         }
     }
 
@@ -4828,6 +4836,13 @@
 
                 useAsyncReport = true;
 
+                if (mUpdateSdrHdrRatioInfo) {
+                    mUpdateSdrHdrRatioInfo = false;
+                    applyTransactionOnDraw(mTransaction.setExtendedRangeBrightness(
+                            getSurfaceControl(), mRenderSdrHdrRatio, mDesiredSdrHdrRatio));
+                    mAttachInfo.mThreadedRenderer.setTargetSdrHdrRatio(mRenderSdrHdrRatio);
+                }
+
                 if (forceDraw) {
                     mAttachInfo.mThreadedRenderer.forceDrawNextFrame();
                 }
@@ -5361,7 +5376,20 @@
                 && !getConfiguration().isScreenWideColorGamut()) {
             colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
         }
-        mAttachInfo.mThreadedRenderer.setColorMode(colorMode);
+        float desiredRatio = mAttachInfo.mThreadedRenderer.setColorMode(colorMode);
+        if (desiredRatio != mDesiredSdrHdrRatio) {
+            mDesiredSdrHdrRatio = desiredRatio;
+            mUpdateSdrHdrRatioInfo = true;
+        }
+    }
+
+    /** happylint */
+    public void setTargetSdrHdrRatio(float ratio) {
+        if (mRenderSdrHdrRatio != ratio) {
+            mRenderSdrHdrRatio = ratio;
+            mUpdateSdrHdrRatioInfo = true;
+            invalidate();
+        }
     }
 
     @Override
@@ -5787,7 +5815,7 @@
                 }
                 case MSG_SHOW_INSETS: {
                     final ImeTracker.Token statsToken = (ImeTracker.Token) msg.obj;
-                    ImeTracker.get().onProgress(statsToken,
+                    ImeTracker.forLogging().onProgress(statsToken,
                             ImeTracker.PHASE_CLIENT_HANDLE_SHOW_INSETS);
                     if (mView == null) {
                         Log.e(TAG,
@@ -5800,7 +5828,7 @@
                 }
                 case MSG_HIDE_INSETS: {
                     final ImeTracker.Token statsToken = (ImeTracker.Token) msg.obj;
-                    ImeTracker.get().onProgress(statsToken,
+                    ImeTracker.forLogging().onProgress(statsToken,
                             ImeTracker.PHASE_CLIENT_HANDLE_HIDE_INSETS);
                     mInsetsController.hide(msg.arg1, msg.arg2 == 1, statsToken);
                     break;
@@ -5815,7 +5843,7 @@
                         mTmpFrames.frame.right = l + w;
                         mTmpFrames.frame.top = t;
                         mTmpFrames.frame.bottom = t + h;
-                        setFrame(mTmpFrames.frame);
+                        setFrame(mTmpFrames.frame, false /* withinRelayout */);
                         maybeHandleWindowMove(mWinFrame);
                     }
                     break;
@@ -6868,13 +6896,13 @@
                         || event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
                     // Other apps or the window manager may change the icon type outside of
                     // this app, therefore the icon type has to be reset on enter/exit event.
-                    mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
+                    mPointerIconType = null;
                 }
 
                 if (event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) {
                     if (!updatePointerIcon(event) &&
                             event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) {
-                        mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
+                        mPointerIconType = null;
                     }
                 }
             }
@@ -6913,7 +6941,7 @@
     }
 
     private void resetPointerIcon(MotionEvent event) {
-        mPointerIconType = PointerIcon.TYPE_NOT_SPECIFIED;
+        mPointerIconType = null;
         updatePointerIcon(event);
     }
 
@@ -6943,9 +6971,9 @@
         }
 
         final int pointerType = (pointerIcon != null) ?
-                pointerIcon.getType() : PointerIcon.TYPE_DEFAULT;
+                pointerIcon.getType() : PointerIcon.TYPE_NOT_SPECIFIED;
 
-        if (mPointerIconType != pointerType) {
+        if (mPointerIconType == null || mPointerIconType != pointerType) {
             mPointerIconType = pointerType;
             mCustomPointerIcon = null;
             if (mPointerIconType != PointerIcon.TYPE_CUSTOM) {
@@ -8322,7 +8350,7 @@
             // If the position and the size of the frame are both changed, it will trigger a BLAST
             // sync, and we still need to call relayout to obtain the syncSeqId. Otherwise, we just
             // need to send attributes via relayoutAsync.
-            final Rect oldFrame = mWinFrame;
+            final Rect oldFrame = mLastLayoutFrame;
             final Rect newFrame = mTmpFrames.frame;
             final boolean positionChanged =
                     newFrame.top != oldFrame.top || newFrame.left != oldFrame.left;
@@ -8435,8 +8463,7 @@
                 updateBlastSurfaceIfNeeded();
             }
             if (mAttachInfo.mThreadedRenderer != null) {
-                mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
-                mAttachInfo.mThreadedRenderer.setBlastBufferQueue(mBlastBufferQueue);
+                mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
             }
             if (mPreviousTransformHint != transformHint) {
                 mPreviousTransformHint = transformHint;
@@ -8453,7 +8480,7 @@
             params.restore();
         }
 
-        setFrame(mTmpFrames.frame);
+        setFrame(mTmpFrames.frame, true /* withinRelayout */);
         return relayoutResult;
     }
 
@@ -8488,8 +8515,18 @@
         mIsSurfaceOpaque = opaque;
     }
 
-    private void setFrame(Rect frame) {
+    /**
+     * Set the mWinFrame of this window.
+     * @param frame the new frame of this window.
+     * @param withinRelayout {@code true} if this setting is within the relayout, or is the initial
+     *                       setting. That will make sure in the relayout process, we always compare
+     *                       the window frame with the last processed window frame.
+     */
+    private void setFrame(Rect frame, boolean withinRelayout) {
         mWinFrame.set(frame);
+        if (withinRelayout) {
+            mLastLayoutFrame.set(frame);
+        }
 
         final WindowConfiguration winConfig = getCompatWindowConfiguration();
         mPendingBackDropFrame.set(mPendingDragResizing && !winConfig.useWindowFrameForBackdrop()
@@ -8736,6 +8773,8 @@
 
         mInsetsController.dump(prefix, writer);
 
+        mOnBackInvokedDispatcher.dump(prefix, writer);
+
         writer.println(prefix + "View Hierarchy:");
         dumpViewHierarchy(innerPrefix, writer, mView);
     }
@@ -8937,7 +8976,7 @@
         if (mTranslator != null) {
             mTranslator.translateInsetsStateInScreenToAppWindow(insetsState);
         }
-        if (insetsState.getSourceOrDefaultVisibility(ITYPE_IME)) {
+        if (insetsState.isSourceOrDefaultVisible(ID_IME, Type.ime())) {
             ImeTracing.getInstance().triggerClientDump("ViewRootImpl#dispatchResized",
                     getInsetsController().getHost().getInputMethodManager(), null /* icProto */);
         }
@@ -8969,7 +9008,7 @@
             mTranslator.translateInsetsStateInScreenToAppWindow(insetsState);
             mTranslator.translateSourceControlsInScreenToAppWindow(activeControls);
         }
-        if (insetsState != null && insetsState.getSourceOrDefaultVisibility(ITYPE_IME)) {
+        if (insetsState != null && insetsState.isSourceOrDefaultVisible(ID_IME, Type.ime())) {
             ImeTracing.getInstance().triggerClientDump("ViewRootImpl#dispatchInsetsControlChanged",
                     getInsetsController().getHost().getInputMethodManager(), null /* icProto */);
         }
@@ -10368,10 +10407,10 @@
                         null /* icProto */);
             }
             if (viewAncestor != null) {
-                ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
+                ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
                 viewAncestor.showInsets(types, fromIme, statsToken);
             } else {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
+                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
             }
         }
 
@@ -10385,10 +10424,10 @@
                         null /* icProto */);
             }
             if (viewAncestor != null) {
-                ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
+                ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
                 viewAncestor.hideInsets(types, fromIme, statsToken);
             } else {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
+                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
             }
         }
 
@@ -11408,33 +11447,25 @@
         });
     }
 
-    private class VRISurfaceSyncGroup extends SurfaceSyncGroup {
-        VRISurfaceSyncGroup(String name) {
-            super(name);
-        }
-
-        @Override
-        public void onSyncReady() {
-            Runnable runnable = () -> {
-                mNumPausedForSync--;
-                if (!mIsInTraversal && mNumPausedForSync == 0) {
-                    scheduleTraversals();
-                }
-            };
-
-            if (Thread.currentThread() == mThread) {
-                runnable.run();
-            } else {
-                mHandler.post(runnable);
-            }
-        }
-    }
-
     @Override
     public SurfaceSyncGroup getOrCreateSurfaceSyncGroup() {
         boolean newSyncGroup = false;
         if (mActiveSurfaceSyncGroup == null) {
-            mActiveSurfaceSyncGroup = new VRISurfaceSyncGroup(mTag);
+            mActiveSurfaceSyncGroup = new SurfaceSyncGroup(mTag);
+            mActiveSurfaceSyncGroup.setAddedToSyncListener(() -> {
+                Runnable runnable = () -> {
+                    mNumPausedForSync--;
+                    if (!mIsInTraversal && mNumPausedForSync == 0) {
+                        scheduleTraversals();
+                    }
+                };
+
+                if (Thread.currentThread() == mThread) {
+                    runnable.run();
+                } else {
+                    mHandler.post(runnable);
+                }
+            });
             updateSyncInProgressCount(mActiveSurfaceSyncGroup);
             newSyncGroup = true;
         }
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index c59d83e..a2708ee 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -21,6 +21,7 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
 
 import android.annotation.NonNull;
+import android.content.Context;
 import android.content.res.CompatibilityInfo;
 import android.os.Handler;
 import android.os.IBinder;
@@ -246,6 +247,11 @@
     }
 
     @Override
+    public Context getRootViewContext() {
+        return mViewRoot != null ? mViewRoot.mContext : null;
+    }
+
+    @Override
     public int dipToPx(int dips) {
         if (mViewRoot != null) {
             return mViewRoot.dipToPx(dips);
diff --git a/core/java/android/view/ViewTraversalTracingStrings.java b/core/java/android/view/ViewTraversalTracingStrings.java
new file mode 100644
index 0000000..7dde87b
--- /dev/null
+++ b/core/java/android/view/ViewTraversalTracingStrings.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.os.Trace;
+
+/**
+ * Keeps and caches strings used to trace {@link View} traversals.
+ * <p>
+ * This is done to avoid expensive computations of them every time, which can improve performance.
+ */
+class ViewTraversalTracingStrings {
+
+    /** {@link Trace} tag used to mark {@link View#onMeasure(int, int)}. */
+    public final String onMeasure;
+
+    /** {@link Trace} tag used to mark {@link View#onLayout(boolean, int, int, int, int)}. */
+    public final String onLayout;
+
+    /** Caches the view simple name to avoid re-computations. */
+    public final String classSimpleName;
+
+    /** Prefix for request layout stacktraces output in logs. */
+    public final String requestLayoutStacktracePrefix;
+
+    /** {@link Trace} tag used to mark {@link View#onMeasure(int, int)} happening before layout. */
+    public final String onMeasureBeforeLayout;
+
+    /**
+     * @param v {@link View} from where to get the class name.
+     */
+    ViewTraversalTracingStrings(View v) {
+        String className = v.getClass().getSimpleName();
+        classSimpleName = className;
+        onMeasureBeforeLayout = getTraceName("onMeasureBeforeLayout", className, v);
+        onMeasure = getTraceName("onMeasure", className, v);
+        onLayout = getTraceName("onLayout", className, v);
+        requestLayoutStacktracePrefix = "requestLayout " + className;
+    }
+
+    private String getTraceName(String sectionName, String className, View v) {
+        StringBuilder out = new StringBuilder();
+        out.append(sectionName);
+        out.append(" ");
+        out.append(className);
+        v.appendId(out);
+        return out.substring(0, Math.min(out.length() - 1, Trace.MAX_SECTION_NAME_LEN - 1));
+    }
+}
diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java
index 7077804..3b8298e 100644
--- a/core/java/android/view/WindowLayout.java
+++ b/core/java/android/view/WindowLayout.java
@@ -16,10 +16,10 @@
 
 package android.view;
 
-import static android.view.InsetsState.ITYPE_IME;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.systemBars;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
@@ -89,7 +89,7 @@
         if (attachedWindowFrame == null) {
             outParentFrame.set(outDisplayFrame);
             if ((pfl & PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME) != 0) {
-                final InsetsSource source = state.peekSource(ITYPE_IME);
+                final InsetsSource source = state.peekSource(ID_IME);
                 if (source != null) {
                     outParentFrame.inset(source.calculateInsets(
                             outParentFrame, false /* ignoreVisibility */));
@@ -109,14 +109,6 @@
             // Ensure that windows with a non-ALWAYS display cutout mode are laid out in
             // the cutout safe zone.
             final Rect displayFrame = state.getDisplayFrame();
-            final InsetsSource statusBarSource = state.peekSource(ITYPE_STATUS_BAR);
-            if (statusBarSource != null && displayCutoutSafe.top > displayFrame.top) {
-                // Make sure that the zone we're avoiding for the cutout is at least as tall as the
-                // status bar; otherwise fullscreen apps will end up cutting halfway into the status
-                // bar.
-                displayCutoutSafeExceptMaybeBars.top =
-                        Math.max(statusBarSource.getFrame().bottom, displayCutoutSafe.top);
-            }
             if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
                 if (displayFrame.width() < displayFrame.height()) {
                     displayCutoutSafeExceptMaybeBars.top = MIN_Y;
@@ -131,7 +123,7 @@
                     && (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
                     || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) {
                 final Insets systemBarsInsets = state.calculateInsets(
-                        displayFrame, WindowInsets.Type.systemBars(), requestedVisibleTypes);
+                        displayFrame, systemBars(), requestedVisibleTypes);
                 if (systemBarsInsets.left > 0) {
                     displayCutoutSafeExceptMaybeBars.left = MIN_X;
                 }
@@ -145,12 +137,11 @@
                     displayCutoutSafeExceptMaybeBars.bottom = MAX_Y;
                 }
             }
-            if (type == TYPE_INPUT_METHOD) {
-                final InsetsSource navSource = state.peekSource(ITYPE_NAVIGATION_BAR);
-                if (navSource != null && navSource.calculateInsets(displayFrame, true).bottom > 0) {
-                    // The IME can always extend under the bottom cutout if the navbar is there.
-                    displayCutoutSafeExceptMaybeBars.bottom = MAX_Y;
-                }
+            if (type == TYPE_INPUT_METHOD
+                    && displayCutoutSafeExceptMaybeBars.bottom != MAX_Y
+                    && state.calculateInsets(displayFrame, navigationBars(), true).bottom > 0) {
+                // The IME can always extend under the bottom cutout if the navbar is there.
+                displayCutoutSafeExceptMaybeBars.bottom = MAX_Y;
             }
             final boolean attachedInParent = attachedWindowFrame != null && !layoutInScreen;
 
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9bec409..0f68cd0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -815,8 +815,8 @@
     }
 
     /**
-     * Activity level {@link android.content.pm.PackageManager.Property PackageManager
-     * .Property} for an app to inform the system that the activity can be opted-in or opted-out
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager
+     * .Property} for an app to inform the system that the app can be opted-in or opted-out
      * from the compatibility treatment that avoids {@link
      * android.app.Activity#setRequestedOrientation} loops. The loop can be trigerred by
      * ignoreRequestedOrientation display setting enabled on the device or by the landscape natural
@@ -834,17 +834,17 @@
      *     <li>Camera compatibility force rotation treatment is active for the package.
      * </ul>
      *
-     * <p>Setting this property to {@code false} informs the system that the activity must be
+     * <p>Setting this property to {@code false} informs the system that the app must be
      * opted-out from the compatibility treatment even if the device manufacturer has opted the app
      * into the treatment.
      *
      * <p><b>Syntax:</b>
      * <pre>
-     * &lt;activity&gt;
+     * &lt;application&gt;
      *   &lt;property
      *     android:name="android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION"
      *     android:value="true|false"/&gt;
-     * &lt;/activity&gt;
+     * &lt;/application&gt;
      * </pre>
      *
      * @hide
@@ -854,8 +854,45 @@
             "android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION";
 
     /**
-     * Activity level {@link android.content.pm.PackageManager.Property PackageManager
-     * .Property} for an app to inform the system that the activity should be excluded from the
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager
+     * .Property} for an app to inform the system that the application can be opted-in or opted-out
+     * from the compatibility treatment that enables sending a fake focus event for unfocused
+     * resumed split screen activities. This is needed because some game engines wait to get
+     * focus before drawing the content of the app which isn't guaranteed by default in multi-window
+     * modes.
+     *
+     * <p>Device manufacturers can enable this treatment using their discretion on a per-device
+     * basis to improve display compatibility. The treatment also needs to be specifically enabled
+     * on a per-app basis afterwards. This can either be done by device manufacturers or developers.
+     *
+     * <p>With this property set to {@code true}, the system will apply the treatment only if the
+     * device manufacturer had previously enabled it on the device. A fake focus event will be sent
+     * to the app after it is resumed only if the app is in split-screen.
+     *
+     * <p>Setting this property to {@code false} informs the system that the activity must be
+     * opted-out from the compatibility treatment even if the device manufacturer has opted the app
+     * into the treatment.
+     *
+     * <p>If the property remains unset the system will apply the treatment only if it had
+     * previously been enabled both at the device and app level by the device manufacturer.
+     *
+     * <p><b>Syntax:</b>
+     * <pre>
+     * &lt;application&gt;
+     *   &lt;property
+     *     android:name="android.window.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS"
+     *     android:value="true|false"/&gt;
+     * &lt;/application&gt;
+     * </pre>
+     *
+     * @hide
+     */
+    // TODO(b/263984287): Make this public API.
+    String PROPERTY_COMPAT_ENABLE_FAKE_FOCUS = "android.window.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS";
+
+    /**
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager
+     * .Property} for an app to inform the system that the app should be excluded from the
      * camera compatibility force rotation treatment.
      *
      * <p>The camera compatibility treatment aligns orientations of portrait app window and natural
@@ -880,11 +917,11 @@
      *
      * <p><b>Syntax:</b>
      * <pre>
-     * &lt;activity&gt;
+     * &lt;application&gt;
      *   &lt;property
      *     android:name="android.window.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION"
      *     android:value="true|false"/&gt;
-     * &lt;/activity&gt;
+     * &lt;/application&gt;
      * </pre>
      *
      * @hide
@@ -894,8 +931,8 @@
             "android.window.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION";
 
     /**
-     * Activity level {@link android.content.pm.PackageManager.Property PackageManager
-     * .Property} for an app to inform the system that the activity should be excluded
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager
+     * .Property} for an app to inform the system that the app should be excluded
      * from the activity "refresh" after the camera compatibility force rotation treatment.
      *
      * <p>The camera compatibility treatment aligns orientations of portrait app window and natural
@@ -927,11 +964,11 @@
      *
      * <p><b>Syntax:</b>
      * <pre>
-     * &lt;activity&gt;
+     * &lt;application&gt;
      *   &lt;property
      *     android:name="android.window.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH"
      *     android:value="true|false"/&gt;
-     * &lt;/activity&gt;
+     * &lt;/application&gt;
      * </pre>
      *
      * @hide
@@ -941,7 +978,7 @@
             "android.window.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH";
 
     /**
-     * Activity level {@link android.content.pm.PackageManager.Property PackageManager
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager
      * .Property} for an app to inform the system that the activity should be or shouldn't be
      * "refreshed" after the camera compatibility force rotation treatment using "paused ->
      * resumed" cycle rather than "stopped -> resumed".
@@ -977,11 +1014,11 @@
      *
      * <p><b>Syntax:</b>
      * <pre>
-     * &lt;activity&gt;
+     * &lt;application&gt;
      *   &lt;property
      *     android:name="android.window.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE"
      *     android:value="true|false"/&gt;
-     * &lt;/activity&gt;
+     * &lt;/application&gt;
      * </pre>
      *
      * @hide
@@ -991,23 +1028,23 @@
             "android.window.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE";
 
     /**
-     * Activity level {@link android.content.pm.PackageManager.Property PackageManager
-     * .Property} for an app to inform the system that the activity should be excluded from the
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager
+     * .Property} for an app to inform the system that the app should be excluded from the
      * compatibility override for orientation set by the device manufacturer.
      *
      * <p>With this property set to {@code true} or unset, device manufacturers can override
-     * orientation for the activity using their discretion to improve display compatibility.
+     * orientation for the app using their discretion to improve display compatibility.
      *
      * <p>With this property set to {@code false}, device manufactured per-app override for
      * orientation won't be applied.
      *
      * <p><b>Syntax:</b>
      * <pre>
-     * &lt;activity&gt;
+     * &lt;application&gt;
      *   &lt;property
      *     android:name="android.window.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE"
      *     android:value="true|false"/&gt;
-     * &lt;/activity&gt;
+     * &lt;/application&gt;
      * </pre>
      *
      * @hide
@@ -1017,8 +1054,8 @@
             "android.window.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE";
 
     /**
-     * Activity level {@link android.content.pm.PackageManager.Property PackageManager
-     * .Property} for an app to inform the system that the activity should be opted-out from the
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager
+     * .Property} for an app to inform the system that the app should be opted-out from the
      * compatibility override that fixes display orientation to landscape natural orientation when
      * an activity is fullscreen.
      *
@@ -1048,11 +1085,11 @@
      *
      * <p><b>Syntax:</b>
      * <pre>
-     * &lt;activity&gt;
+     * &lt;application&gt;
      *   &lt;property
      *     android:name="android.window.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE"
      *     android:value="true|false"/&gt;
-     * &lt;/activity&gt;
+     * &lt;/application&gt;
      * </pre>
      *
      * @hide
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 3ce419e..7969518 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -186,6 +186,18 @@
      */
     public static final int ACCESSIBILITY_SHORTCUT_KEY = 1;
 
+    /** @hide */
+    public static final int FLASH_REASON_CALL = 1;
+
+    /** @hide */
+    public static final int FLASH_REASON_ALARM = 2;
+
+    /** @hide */
+    public static final int FLASH_REASON_NOTIFICATION = 3;
+
+    /** @hide */
+    public static final int FLASH_REASON_PREVIEW = 4;
+
     /**
      * Annotations for the shortcut type.
      * @hide
@@ -210,6 +222,19 @@
     public @interface ContentFlag {}
 
     /**
+     * Annotations for reason of Flash notification.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "FLASH_REASON_" }, value = {
+            FLASH_REASON_CALL,
+            FLASH_REASON_ALARM,
+            FLASH_REASON_NOTIFICATION,
+            FLASH_REASON_PREVIEW
+    })
+    public @interface FlashNotificationReason {}
+
+    /**
      * Use this flag to indicate the content of a UI that times out contains icons.
      *
      * @see #getRecommendedTimeoutMillis(int, int)
@@ -317,6 +342,13 @@
     private SparseArray<List<AccessibilityRequestPreparer>> mRequestPreparerLists;
 
     /**
+     * Binder for flash notification.
+     *
+     * @see #startFlashNotificationSequence(Context, int)
+     */
+    private final Binder mBinder = new Binder();
+
+    /**
      * Listener for the system accessibility state. To listen for changes to the
      * accessibility state on the device, implement this interface and register
      * it with the system by calling {@link #addAccessibilityStateChangeListener}.
@@ -2096,6 +2128,95 @@
         }
     }
 
+    /**
+     * Start sequence (infinite) type of flash notification. Use
+     * {@code Context.getOpPackageName()} as the identifier of this flash notification.
+     * The notification can be cancelled later by calling {@link #stopFlashNotificationSequence}
+     * with same {@code Context.getOpPackageName()}.
+     * If the binder associated with this {@link AccessibilityManager} instance dies then the
+     * sequence will stop automatically. It is strongly recommended to call
+     * {@link #stopFlashNotificationSequence} within a reasonable amount of time after calling
+     * this method.
+     *
+     * @param context The context in which this manager operates.
+     * @param reason The triggering reason of flash notification.
+     * @return {@code true} if flash notification works properly.
+     * @hide
+     */
+    public boolean startFlashNotificationSequence(@NonNull Context context,
+            @FlashNotificationReason int reason) {
+        final IAccessibilityManager service;
+        synchronized (mLock) {
+            service = getServiceLocked();
+            if (service == null) {
+                return false;
+            }
+        }
+
+        try {
+            return service.startFlashNotificationSequence(context.getOpPackageName(),
+                    reason, mBinder);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error while start flash notification sequence", re);
+            return false;
+        }
+    }
+
+    /**
+     * Stop sequence (infinite) type of flash notification. The flash notification with
+     * {@code Context.getOpPackageName()} as identifier will be stopped if exist.
+     * It is strongly recommended to call this method within a reasonable amount of time after
+     * calling {@link #startFlashNotificationSequence} method.
+     *
+     * @param context The context in which this manager operates.
+     * @return {@code true} if flash notification stops properly.
+     * @hide
+     */
+    public boolean stopFlashNotificationSequence(@NonNull Context context) {
+        final IAccessibilityManager service;
+        synchronized (mLock) {
+            service = getServiceLocked();
+            if (service == null) {
+                return false;
+            }
+        }
+
+        try {
+            return service.stopFlashNotificationSequence(context.getOpPackageName());
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error while stop flash notification sequence", re);
+            return false;
+        }
+    }
+
+    /**
+     * Start event (finite) type of flash notification.
+     *
+     * @param context The context in which this manager operates.
+     * @param reason The triggering reason of flash notification.
+     * @param reasonPkg The package that trigger the flash notification.
+     * @return {@code true} if flash notification works properly.
+     * @hide
+     */
+    public boolean startFlashNotificationEvent(@NonNull Context context,
+            @FlashNotificationReason int reason, @Nullable String reasonPkg) {
+        final IAccessibilityManager service;
+        synchronized (mLock) {
+            service = getServiceLocked();
+            if (service == null) {
+                return false;
+            }
+        }
+
+        try {
+            return service.startFlashNotificationEvent(context.getOpPackageName(),
+                    reason, reasonPkg);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error while start flash notification event", re);
+            return false;
+        }
+    }
+
     private IAccessibilityManager getServiceLocked() {
         if (mService == null) {
             tryConnectToServiceLocked(null);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 5629e0f..d88cdf1 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -1817,13 +1817,12 @@
      * </p>
      *
      * @see AccessibilityEvent#getContentChangeTypes for all content change types.
-     * @param minDurationBetweenContentChanges the minimum duration between content change events.
+     * @param duration the minimum duration between content change events.
      *                                         Negative duration would be treated as zero.
      */
-    public void setMinDurationBetweenContentChanges(
-            @NonNull Duration minDurationBetweenContentChanges) {
+    public void setMinDurationBetweenContentChanges(@NonNull Duration duration) {
         enforceNotSealed();
-        mMinDurationBetweenContentChanges = minDurationBetweenContentChanges.toMillis();
+        mMinDurationBetweenContentChanges = duration.toMillis();
     }
 
     /**
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index c2d899a..098e97c 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -120,4 +120,8 @@
     void injectInputEventToInputFilter(in InputEvent event);
 
     float getUiContrast();
+
+    boolean startFlashNotificationSequence(String opPkg, int reason, IBinder token);
+    boolean stopFlashNotificationSequence(String opPkg);
+    boolean startFlashNotificationEvent(String opPkg, int reason, String reasonPkg);
 }
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 7d1dc76..c8c910d 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -28,6 +28,7 @@
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.Xml;
+import android.view.InflateException;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -137,16 +138,9 @@
         try {
             parser = context.getResources().getAnimation(id);
             return createAnimationFromXml(context, parser);
-        } catch (XmlPullParserException ex) {
-            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
-            rnf.initCause(ex);
-            throw rnf;
-        } catch (IOException ex) {
-            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
-            rnf.initCause(ex);
-            throw rnf;
+        } catch (XmlPullParserException | IOException | InflateException ex) {
+            throw new NotFoundException(
+                    "Can't load animation resource ID #0x" + Integer.toHexString(id), ex);
         } finally {
             if (parser != null) parser.close();
         }
@@ -159,8 +153,9 @@
     }
 
     @UnsupportedAppUsage
-    private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
-            AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
+    private static Animation createAnimationFromXml(
+            Context c, XmlPullParser parser, AnimationSet parent, AttributeSet attrs)
+            throws XmlPullParserException, IOException, InflateException {
 
         Animation anim = null;
 
@@ -168,8 +163,8 @@
         int type;
         int depth = parser.getDepth();
 
-        while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
-               && type != XmlPullParser.END_DOCUMENT) {
+        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
+                && type != XmlPullParser.END_DOCUMENT) {
 
             if (type != XmlPullParser.START_TAG) {
                 continue;
@@ -193,7 +188,7 @@
             } else if (name.equals("extend")) {
                 anim = new ExtendAnimation(c, attrs);
             } else {
-                throw new RuntimeException("Unknown animation name: " + parser.getName());
+                throw new InflateException("Unknown animation name: " + parser.getName());
             }
 
             if (parent != null) {
@@ -220,29 +215,24 @@
         try {
             parser = context.getResources().getAnimation(id);
             return createLayoutAnimationFromXml(context, parser);
-        } catch (XmlPullParserException ex) {
-            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
-            rnf.initCause(ex);
-            throw rnf;
-        } catch (IOException ex) {
-            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
-            rnf.initCause(ex);
-            throw rnf;
+        } catch (XmlPullParserException | IOException | InflateException ex) {
+            throw new NotFoundException(
+                    "Can't load animation resource ID #0x" + Integer.toHexString(id), ex);
         } finally {
             if (parser != null) parser.close();
         }
     }
 
-    private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
-            XmlPullParser parser) throws XmlPullParserException, IOException {
+    private static LayoutAnimationController createLayoutAnimationFromXml(
+            Context c, XmlPullParser parser)
+            throws XmlPullParserException, IOException, InflateException {
 
         return createLayoutAnimationFromXml(c, parser, Xml.asAttributeSet(parser));
     }
 
-    private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
-            XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException {
+    private static LayoutAnimationController createLayoutAnimationFromXml(
+            Context c, XmlPullParser parser, AttributeSet attrs)
+            throws XmlPullParserException, IOException, InflateException {
 
         LayoutAnimationController controller = null;
 
@@ -263,7 +253,7 @@
             } else if ("gridLayoutAnimation".equals(name)) {
                 controller = new GridLayoutAnimationController(c, attrs);
             } else {
-                throw new RuntimeException("Unknown layout animation name: " + name);
+                throw new InflateException("Unknown layout animation name: " + name);
             }
         }
 
@@ -342,16 +332,9 @@
         try {
             parser = context.getResources().getAnimation(id);
             return createInterpolatorFromXml(context.getResources(), context.getTheme(), parser);
-        } catch (XmlPullParserException ex) {
-            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
-            rnf.initCause(ex);
-            throw rnf;
-        } catch (IOException ex) {
-            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
-            rnf.initCause(ex);
-            throw rnf;
+        } catch (XmlPullParserException | IOException | InflateException ex) {
+            throw new NotFoundException(
+                    "Can't load animation resource ID #0x" + Integer.toHexString(id), ex);
         } finally {
             if (parser != null) parser.close();
         }
@@ -372,25 +355,20 @@
         try {
             parser = res.getAnimation(id);
             return createInterpolatorFromXml(res, theme, parser);
-        } catch (XmlPullParserException ex) {
-            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
-            rnf.initCause(ex);
-            throw rnf;
-        } catch (IOException ex) {
-            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
-                    Integer.toHexString(id));
-            rnf.initCause(ex);
-            throw rnf;
+        } catch (XmlPullParserException | IOException | InflateException ex) {
+            throw new NotFoundException(
+                    "Can't load animation resource ID #0x" + Integer.toHexString(id), ex);
         } finally {
-            if (parser != null)
+            if (parser != null) {
                 parser.close();
+            }
         }
 
     }
 
-    private static Interpolator createInterpolatorFromXml(Resources res, Theme theme, XmlPullParser parser)
-            throws XmlPullParserException, IOException {
+    private static Interpolator createInterpolatorFromXml(
+            Resources res, Theme theme, XmlPullParser parser)
+            throws XmlPullParserException, IOException, InflateException {
 
         BaseInterpolator interpolator = null;
 
@@ -430,7 +408,7 @@
             } else if (name.equals("pathInterpolator")) {
                 interpolator = new PathInterpolator(res, theme, attrs);
             } else {
-                throw new RuntimeException("Unknown interpolator name: " + parser.getName());
+                throw new InflateException("Unknown interpolator name: " + parser.getName());
             }
         }
         return interpolator;
diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java
index cba399f..e7c610b 100644
--- a/core/java/android/view/autofill/AutofillFeatureFlags.java
+++ b/core/java/android/view/autofill/AutofillFeatureFlags.java
@@ -145,19 +145,13 @@
      * <p>For example, a list with only 1 package would be, {@code Package1:;}. A list with one
      * denied activity {@code Activity1} under {@code Package1} and a full denied package
      * {@code Package2} would be {@code Package1:Activity1;Package2:;}
-     *
-     * @hide
      */
-    @TestApi
     public static final String DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW =
             "package_deny_list_for_unimportant_view";
 
     /**
      * Whether the heuristics check for view is enabled
-     *
-     * @hide
      */
-    @TestApi
     public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW =
             "trigger_fill_request_on_unimportant_view";
 
@@ -169,15 +163,24 @@
      *
      * <p> For example, a imeAction list could be "2,3,4", corresponding to ime_action definition
      * in {@link android.view.inputmethod.EditorInfo.java}</p>
-     *
-     * @hide
      */
-    @TestApi
     @SuppressLint("IntentName")
     public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS =
             "non_autofillable_ime_action_ids";
     // END AUTOFILL FOR ALL APPS FLAGS //
 
+
+    // START AUTOFILL PCC CLASSIFICATION FLAGS
+
+    /**
+     * Sets the fill dialog feature enabled or not.
+     */
+    public static final String DEVICE_CONFIG_AUTOFILL_PCC_CLASSIFICATION_ENABLED =
+            "pcc_classification_enabled";
+
+    // END AUTOFILL PCC CLASSIFICATION FLAGS
+
+
     /**
      * Sets a value of delay time to show up the inline tooltip view.
      *
@@ -191,6 +194,7 @@
     private static final boolean DEFAULT_HAS_FILL_DIALOG_UI_FEATURE = false;
     private static final String DEFAULT_FILL_DIALOG_ENABLED_HINTS = "";
 
+
     // CREDENTIAL MANAGER DEFAULTS
     // Credential manager is enabled by default so as to allow testing by app developers
     private static final boolean DEFAULT_CREDENTIAL_MANAGER_ENABLED = true;
@@ -199,6 +203,13 @@
     private static final boolean DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_SAVE_DIALOG = false;
     // END CREDENTIAL MANAGER DEFAULTS
 
+
+    // AUTOFILL PCC CLASSIFICATION FLAGS DEFAULTS
+    // Default for whether the pcc classification is enabled for autofill.
+    private static final boolean DEFAULT_AUTOFILL_PCC_CLASSIFICATION_ENABLED = false;
+    // END AUTOFILL PCC CLASSIFICATION FLAGS DEFAULTS
+
+
     private AutofillFeatureFlags() {};
 
     /**
@@ -302,4 +313,23 @@
             DeviceConfig.NAMESPACE_AUTOFILL,
             DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW, "");
     }
+
+
+    // START AUTOFILL PCC CLASSIFICATION FUNCTIONS
+
+    /**
+     * Whether Autofill PCC Detection is enabled.
+     *
+     * @hide
+     */
+    public static boolean isAutofillPccClassificationEnabled() {
+        // TODO(b/266379948): Add condition for checking whether device has PCC first
+
+        return DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_AUTOFILL,
+                DEVICE_CONFIG_AUTOFILL_PCC_CLASSIFICATION_ENABLED,
+                DEFAULT_AUTOFILL_PCC_CLASSIFICATION_ENABLED);
+    }
+
+    // END AUTOFILL PCC CLASSIFICATION FUNCTIONS
 }
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index b5764c5..bdc7333 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -19,6 +19,7 @@
 import static android.service.autofill.FillRequest.FLAG_IME_SHOWING;
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
+import static android.service.autofill.FillRequest.FLAG_PCC_DETECTION;
 import static android.service.autofill.FillRequest.FLAG_RESET_FILL_DIALOG_STATE;
 import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG;
 import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
@@ -1312,6 +1313,22 @@
             return;
         }
 
+        // Start session with PCC flag to get assist structure and send field classification request
+        // to PCC classification service.
+        if (AutofillFeatureFlags.isAutofillPccClassificationEnabled()) {
+            synchronized (mLock) {
+                final boolean clientAdded = tryAddServiceClientIfNeededLocked();
+                if (clientAdded){
+                    startSessionLocked(/* id= */ AutofillId.NO_AUTOFILL_ID,
+                        /* bounds= */ null, /* value= */ null, /* flags= */ FLAG_PCC_DETECTION);
+                } else {
+                    if (sVerbose) {
+                        Log.v(TAG, "not starting session: no service client");
+                    }
+                }
+            }
+        }
+
         if (mIsFillDialogEnabled
                 || ArrayUtils.containsAny(autofillHints, mFillDialogEnabledHints)) {
             if (sDebug) {
diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java
index 3b6ec80..e5a99ff 100644
--- a/core/java/android/view/inputmethod/ImeTracker.java
+++ b/core/java/android/view/inputmethod/ImeTracker.java
@@ -16,24 +16,36 @@
 
 package android.view.inputmethod;
 
+import static com.android.internal.inputmethod.InputMethodDebug.softInputDisplayReasonToString;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_IME_INSETS_ANIMATION;
+import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_HIDDEN;
+import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_SHOWN;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityThread;
+import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemProperties;
 import android.util.Log;
+import android.view.InsetsController.AnimationType;
+import android.view.SurfaceControl;
 
 import com.android.internal.inputmethod.InputMethodDebug;
 import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.jank.InteractionJankMonitor.Configuration;
+import com.android.internal.util.LatencyTracker;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.Field;
 import java.util.Arrays;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Random;
 import java.util.stream.Collectors;
@@ -385,15 +397,35 @@
     void onHidden(@Nullable Token token);
 
     /**
-     * Get the singleton instance of this class.
+     * Get the singleton request tracker instance.
      *
-     * @return the singleton instance of this class
+     * @return the singleton request tracker instance
      */
     @NonNull
-    static ImeTracker get() {
+    static ImeTracker forLogging() {
         return LOGGER;
     }
 
+    /**
+     * Get the singleton jank tracker instance.
+     *
+     * @return the singleton jank tracker instance
+     */
+    @NonNull
+    static ImeJankTracker forJank() {
+        return JANK_TRACKER;
+    }
+
+    /**
+     * Get the singleton latency tracker instance.
+     *
+     * @return the singleton latency tracker instance
+     */
+    @NonNull
+    static ImeLatencyTracker forLatency() {
+        return LATENCY_TRACKER;
+    }
+
     /** The singleton IME tracker instance. */
     @NonNull
     ImeTracker LOGGER = new ImeTracker() {
@@ -489,6 +521,12 @@
         }
     };
 
+    /** The singleton IME tracker instance for instrumenting jank metrics. */
+    ImeJankTracker JANK_TRACKER = new ImeJankTracker();
+
+    /** The singleton IME tracker instance for instrumenting latency metrics. */
+    ImeLatencyTracker LATENCY_TRACKER = new ImeLatencyTracker();
+
     /** A token that tracks the progress of an IME request. */
     class Token implements Parcelable {
 
@@ -592,4 +630,162 @@
             }
         }
     }
+
+    /**
+     * Context related to {@link InteractionJankMonitor}.
+     */
+    interface InputMethodJankContext {
+        /**
+         * @return a context associated with a display
+         */
+        Context getDisplayContext();
+
+        /**
+         * @return a SurfaceControl that is going to be monitored
+         */
+        SurfaceControl getTargetSurfaceControl();
+
+        /**
+         * @return the package name of the host
+         */
+        String getHostPackageName();
+    }
+
+    /**
+     * Context related to {@link LatencyTracker}.
+     */
+    interface InputMethodLatencyContext {
+        /**
+         * @return a context associated with current application
+         */
+        Context getAppContext();
+    }
+
+    /**
+     * A tracker instance which is in charge of communicating with {@link InteractionJankMonitor}.
+     * This class disallows instantiating from outside, use {@link #forJank()} to get the singleton.
+     */
+    final class ImeJankTracker {
+
+        /**
+         * This class disallows instantiating from outside.
+         */
+        private ImeJankTracker() {
+        }
+
+        /**
+         * Called when the animation, which is going to be monitored, starts.
+         *
+         * @param jankContext context which is needed by {@link InteractionJankMonitor}
+         * @param animType {@link AnimationType}
+         * @param useSeparatedThread {@code true} if the animation is handled by the app,
+         *                           {@code false} if the animation will be scheduled on the
+         *                           {@link android.view.InsetsAnimationThread}
+         */
+        public void onRequestAnimation(@NonNull InputMethodJankContext jankContext,
+                @AnimationType int animType, boolean useSeparatedThread) {
+            if (jankContext.getDisplayContext() == null
+                    || jankContext.getTargetSurfaceControl() == null) {
+                return;
+            }
+            final Configuration.Builder builder = Configuration.Builder.withSurface(
+                            CUJ_IME_INSETS_ANIMATION,
+                            jankContext.getDisplayContext(),
+                            jankContext.getTargetSurfaceControl())
+                    .setTag(String.format(Locale.US, "%d@%d@%s", animType,
+                            useSeparatedThread ? 0 : 1, jankContext.getHostPackageName()));
+            InteractionJankMonitor.getInstance().begin(builder);
+        }
+
+        /**
+         * Called when the animation, which is going to be monitored, cancels.
+         */
+        public void onCancelAnimation() {
+            InteractionJankMonitor.getInstance().cancel(CUJ_IME_INSETS_ANIMATION);
+        }
+
+        /**
+         * Called when the animation, which is going to be monitored, ends.
+         */
+        public void onFinishAnimation() {
+            InteractionJankMonitor.getInstance().end(CUJ_IME_INSETS_ANIMATION);
+        }
+    }
+
+    /**
+     * A tracker instance which is in charge of communicating with {@link LatencyTracker}.
+     * This class disallows instantiating from outside, use {@link #forLatency()}
+     * to get the singleton.
+     */
+    final class ImeLatencyTracker {
+
+        /**
+         * This class disallows instantiating from outside.
+         */
+        private ImeLatencyTracker() {
+        }
+
+        private boolean shouldMonitorLatency(@SoftInputShowHideReason int reason) {
+            return reason == SoftInputShowHideReason.SHOW_SOFT_INPUT
+                    || reason == SoftInputShowHideReason.HIDE_SOFT_INPUT
+                    || reason == SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API
+                    || reason == SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API
+                    || reason == SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME
+                    || reason == SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_IME;
+        }
+
+        public void onRequestShow(@Nullable Token token, @Origin int origin,
+                @SoftInputShowHideReason int reason,
+                @NonNull InputMethodLatencyContext latencyContext) {
+            if (!shouldMonitorLatency(reason)) return;
+            LatencyTracker.getInstance(latencyContext.getAppContext())
+                    .onActionStart(
+                            ACTION_REQUEST_IME_SHOWN,
+                            softInputDisplayReasonToString(reason));
+        }
+
+        public void onRequestHide(@Nullable Token token, @Origin int origin,
+                @SoftInputShowHideReason int reason,
+                @NonNull InputMethodLatencyContext latencyContext) {
+            if (!shouldMonitorLatency(reason)) return;
+            LatencyTracker.getInstance(latencyContext.getAppContext())
+                    .onActionStart(
+                            ACTION_REQUEST_IME_HIDDEN,
+                            softInputDisplayReasonToString(reason));
+        }
+
+        public void onShowFailed(@Nullable Token token, @Phase int phase,
+                @NonNull InputMethodLatencyContext latencyContext) {
+            onShowCancelled(token, phase, latencyContext);
+        }
+
+        public void onHideFailed(@Nullable Token token, @Phase int phase,
+                @NonNull InputMethodLatencyContext latencyContext) {
+            onHideCancelled(token, phase, latencyContext);
+        }
+
+        public void onShowCancelled(@Nullable Token token, @Phase int phase,
+                @NonNull InputMethodLatencyContext latencyContext) {
+            LatencyTracker.getInstance(latencyContext.getAppContext())
+                    .onActionCancel(ACTION_REQUEST_IME_SHOWN);
+        }
+
+        public void onHideCancelled(@Nullable Token token, @Phase int phase,
+                @NonNull InputMethodLatencyContext latencyContext) {
+            LatencyTracker.getInstance(latencyContext.getAppContext())
+                    .onActionCancel(ACTION_REQUEST_IME_HIDDEN);
+        }
+
+        public void onShown(@Nullable Token token,
+                @NonNull InputMethodLatencyContext latencyContext) {
+            LatencyTracker.getInstance(latencyContext.getAppContext())
+                    .onActionEnd(ACTION_REQUEST_IME_SHOWN);
+        }
+
+        public void onHidden(@Nullable Token token,
+                @NonNull InputMethodLatencyContext latencyContext) {
+            LatencyTracker.getInstance(latencyContext.getAppContext())
+                    .onActionEnd(ACTION_REQUEST_IME_HIDDEN);
+        }
+    }
 }
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index 5e323fa..8f270f5 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -361,6 +361,16 @@
      * @throws NullPointerException if the target is {@code null}.
      */
     @Override
+    public boolean requestCursorUpdates(@CursorUpdateMode int cursorUpdateMode,
+            @CursorUpdateFilter int cursorUpdateFilter) {
+        return mTarget.requestCursorUpdates(cursorUpdateMode, cursorUpdateFilter);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
+    @Override
     public void requestTextBoundsInfo(
             @NonNull RectF bounds, @NonNull @CallbackExecutor Executor executor,
             @NonNull Consumer<TextBoundsInfoResult> consumer) {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 99bd02d..642182b 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2045,10 +2045,11 @@
     private boolean showSoftInput(View view, @Nullable ImeTracker.Token statsToken, int flags,
             ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
         if (statsToken == null) {
-            statsToken = ImeTracker.get().onRequestShow(null /* component */,
+            statsToken = ImeTracker.forLogging().onRequestShow(null /* component */,
                     Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT, reason);
         }
-
+        ImeTracker.forLatency().onRequestShow(statsToken, ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
+                reason, ActivityThread::currentApplication);
         ImeTracing.getInstance().triggerClientDump("InputMethodManager#showSoftInput", this,
                 null /* icProto */);
         // Re-dispatch if there is a context mismatch.
@@ -2060,12 +2061,15 @@
         checkFocus();
         synchronized (mH) {
             if (!hasServedByInputMethodLocked(view)) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+                ImeTracker.forLatency().onShowFailed(
+                        statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED,
+                        ActivityThread::currentApplication);
                 Log.w(TAG, "Ignoring showSoftInput() as view=" + view + " is not served.");
                 return false;
             }
 
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
 
             // Makes sure to call ImeInsetsSourceConsumer#onShowRequested on the UI thread.
             // TODO(b/229426865): call WindowInsetsController#show instead.
@@ -2095,20 +2099,20 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
     public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
         synchronized (mH) {
-            final ImeTracker.Token statsToken = ImeTracker.get().onRequestShow(null /* component */,
-                    Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
+            final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestShow(
+                    null /* component */, Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
                     SoftInputShowHideReason.SHOW_SOFT_INPUT);
 
             Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be"
                     + " removed soon. If you are using androidx.appcompat.widget.SearchView,"
                     + " please update to version 26.0 or newer version.");
             if (mCurRootView == null || mCurRootView.getView() == null) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
                 Log.w(TAG, "No current root view, ignoring showSoftInputUnchecked()");
                 return;
             }
 
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
 
             // Makes sure to call ImeInsetsSourceConsumer#onShowRequested on the UI thread.
             // TODO(b/229426865): call WindowInsetsController#show instead.
@@ -2186,20 +2190,24 @@
 
     private boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
             ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
-        final ImeTracker.Token statsToken = ImeTracker.get().onRequestHide(null /* component */,
-                Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT, reason);
-
+        final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestHide(
+                null /* component */, Process.myUid(),
+                ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT, reason);
+        ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
+                reason, ActivityThread::currentApplication);
         ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromWindow",
                 this, null /* icProto */);
         checkFocus();
         synchronized (mH) {
             final View servedView = getServedViewLocked();
             if (servedView == null || servedView.getWindowToken() != windowToken) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+                ImeTracker.forLatency().onHideFailed(statsToken,
+                        ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
                 return false;
             }
 
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
 
             return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, statsToken,
                     flags, resultReceiver, reason);
@@ -2835,18 +2843,22 @@
 
     @UnsupportedAppUsage
     void closeCurrentInput() {
-        final ImeTracker.Token statsToken = ImeTracker.get().onRequestHide(null /* component */,
-                Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
+        final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestHide(
+                null /* component */, Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
                 SoftInputShowHideReason.HIDE_SOFT_INPUT);
+        ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
+                SoftInputShowHideReason.HIDE_SOFT_INPUT, ActivityThread::currentApplication);
 
         synchronized (mH) {
             if (mCurRootView == null || mCurRootView.getView() == null) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+                ImeTracker.forLatency().onHideFailed(statsToken,
+                        ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
                 Log.w(TAG, "No current root view, ignoring closeCurrentInput()");
                 return;
             }
 
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
 
             IInputMethodManagerGlobalInvoker.hideSoftInput(
                     mClient,
@@ -2905,11 +2917,13 @@
         synchronized (mH) {
             final View servedView = getServedViewLocked();
             if (servedView == null || servedView.getWindowToken() != windowToken) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
+                ImeTracker.forLogging().onFailed(statsToken,
+                        ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
                 return false;
             }
 
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
+            ImeTracker.forLogging().onProgress(statsToken,
+                    ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
 
             showSoftInput(servedView, statsToken, 0 /* flags */, null /* resultReceiver */,
                     SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API);
@@ -2927,21 +2941,25 @@
      */
     public void notifyImeHidden(IBinder windowToken, @Nullable ImeTracker.Token statsToken) {
         if (statsToken == null) {
-            statsToken = ImeTracker.get().onRequestHide(null /* component */,
+            statsToken = ImeTracker.forLogging().onRequestHide(null /* component */,
                     Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
                     SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
         }
-
+        ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
+                SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API,
+                ActivityThread::currentApplication);
         ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this,
                 null /* icProto */);
         synchronized (mH) {
             if (!isImeSessionAvailableLocked() || mCurRootView == null
                     || mCurRootView.getWindowToken() != windowToken) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+                ImeTracker.forLatency().onHideFailed(statsToken,
+                        ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
                 return;
             }
 
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
 
             IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, statsToken,
                     0 /* flags */, null /* resultReceiver */,
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 1e1b9ba..adeb889 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -471,7 +471,7 @@
     AbsPositionScroller mPositionScroller;
 
     /**
-     * The offset in pixels form the top of the AdapterView to the top
+     * The offset in pixels from the top of the AdapterView to the top
      * of the currently selected view. Used to save and restore state.
      */
     int mSelectedTop = 0;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index f4a8639..136846a 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -37,6 +37,7 @@
 import android.content.UndoOwner;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -101,6 +102,7 @@
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.InputDevice;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -185,20 +187,34 @@
     // Tag used when the Editor maintains its own separate UndoManager.
     private static final String UNDO_OWNER_TAG = "Editor";
 
-    // Ordering constants used to place the Action Mode or context menu items in their menu.
-    private static final int MENU_ITEM_ORDER_ASSIST = 0;
-    private static final int MENU_ITEM_ORDER_UNDO = 2;
-    private static final int MENU_ITEM_ORDER_REDO = 3;
-    private static final int MENU_ITEM_ORDER_CUT = 4;
-    private static final int MENU_ITEM_ORDER_COPY = 5;
-    private static final int MENU_ITEM_ORDER_PASTE = 6;
-    private static final int MENU_ITEM_ORDER_SHARE = 7;
-    private static final int MENU_ITEM_ORDER_SELECT_ALL = 8;
-    private static final int MENU_ITEM_ORDER_REPLACE = 9;
-    private static final int MENU_ITEM_ORDER_AUTOFILL = 10;
-    private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 11;
-    private static final int MENU_ITEM_ORDER_SECONDARY_ASSIST_ACTIONS_START = 50;
-    private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 100;
+    // Ordering constants used to place the Action Mode items in their menu.
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_ASSIST = 0;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_CUT = 4;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_COPY = 5;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_PASTE = 6;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_SHARE = 7;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_SELECT_ALL = 8;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_REPLACE = 9;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_AUTOFILL = 10;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 11;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_SECONDARY_ASSIST_ACTIONS_START = 50;
+    private static final int ACTION_MODE_MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 100;
+
+    // Ordering constants used to place the Context Menu items in their menu.
+    private static final int CONTEXT_MENU_ITEM_ORDER_UNDO = 2;
+    private static final int CONTEXT_MENU_ITEM_ORDER_REDO = 3;
+    private static final int CONTEXT_MENU_ITEM_ORDER_CUT = 4;
+    private static final int CONTEXT_MENU_ITEM_ORDER_COPY = 5;
+    private static final int CONTEXT_MENU_ITEM_ORDER_PASTE = 6;
+    private static final int CONTEXT_MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 7;
+    private static final int CONTEXT_MENU_ITEM_ORDER_SELECT_ALL = 8;
+    private static final int CONTEXT_MENU_ITEM_ORDER_SHARE = 9;
+    private static final int CONTEXT_MENU_ITEM_ORDER_AUTOFILL = 10;
+    private static final int CONTEXT_MENU_ITEM_ORDER_REPLACE = 11;
+
+    private static final int CONTEXT_MENU_GROUP_UNDO_REDO = Menu.FIRST;
+    private static final int CONTEXT_MENU_GROUP_CLIPBOARD = Menu.FIRST + 1;
+    private static final int CONTEXT_MENU_GROUP_MISC = Menu.FIRST + 2;
 
     private static final int FLAG_MISSPELLED_OR_GRAMMAR_ERROR =
             SuggestionSpan.FLAG_MISSPELLED | SuggestionSpan.FLAG_GRAMMAR_ERROR;
@@ -3112,8 +3128,8 @@
             for (int i = 0; i < suggestionInfoArray.length; i++) {
                 suggestionInfoArray[i] = new SuggestionInfo();
             }
-            final SubMenu subMenu = menu.addSubMenu(Menu.NONE, Menu.NONE, MENU_ITEM_ORDER_REPLACE,
-                    com.android.internal.R.string.replace);
+            final SubMenu subMenu = menu.addSubMenu(Menu.NONE, Menu.NONE,
+                    CONTEXT_MENU_ITEM_ORDER_REPLACE, com.android.internal.R.string.replace);
             final int numItems = mSuggestionHelper.getSuggestionInfo(suggestionInfoArray, null);
             for (int i = 0; i < numItems; i++) {
                 final SuggestionInfo info = suggestionInfoArray[i];
@@ -3128,45 +3144,54 @@
             }
         }
 
-        menu.add(Menu.NONE, TextView.ID_UNDO, MENU_ITEM_ORDER_UNDO,
+        final int keyboard = mTextView.getResources().getConfiguration().keyboard;
+        menu.setQwertyMode(keyboard == Configuration.KEYBOARD_QWERTY);
+
+        menu.setGroupDividerEnabled(true);
+
+        menu.add(CONTEXT_MENU_GROUP_UNDO_REDO, TextView.ID_UNDO, CONTEXT_MENU_ITEM_ORDER_UNDO,
                 com.android.internal.R.string.undo)
                 .setAlphabeticShortcut('z')
                 .setOnMenuItemClickListener(mOnContextMenuItemClickListener)
                 .setEnabled(mTextView.canUndo());
-        menu.add(Menu.NONE, TextView.ID_REDO, MENU_ITEM_ORDER_REDO,
+        menu.add(CONTEXT_MENU_GROUP_UNDO_REDO, TextView.ID_REDO, CONTEXT_MENU_ITEM_ORDER_REDO,
                 com.android.internal.R.string.redo)
+                .setAlphabeticShortcut('z', KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON)
                 .setOnMenuItemClickListener(mOnContextMenuItemClickListener)
                 .setEnabled(mTextView.canRedo());
 
-        menu.add(Menu.NONE, TextView.ID_CUT, MENU_ITEM_ORDER_CUT,
+        menu.add(CONTEXT_MENU_GROUP_CLIPBOARD, TextView.ID_CUT, CONTEXT_MENU_ITEM_ORDER_CUT,
                 com.android.internal.R.string.cut)
                 .setAlphabeticShortcut('x')
                 .setOnMenuItemClickListener(mOnContextMenuItemClickListener)
                 .setEnabled(mTextView.canCut());
-        menu.add(Menu.NONE, TextView.ID_COPY, MENU_ITEM_ORDER_COPY,
+        menu.add(CONTEXT_MENU_GROUP_CLIPBOARD, TextView.ID_COPY, CONTEXT_MENU_ITEM_ORDER_COPY,
                 com.android.internal.R.string.copy)
                 .setAlphabeticShortcut('c')
                 .setOnMenuItemClickListener(mOnContextMenuItemClickListener)
                 .setEnabled(mTextView.canCopy());
-        menu.add(Menu.NONE, TextView.ID_PASTE, MENU_ITEM_ORDER_PASTE,
+        menu.add(CONTEXT_MENU_GROUP_CLIPBOARD, TextView.ID_PASTE, CONTEXT_MENU_ITEM_ORDER_PASTE,
                 com.android.internal.R.string.paste)
                 .setAlphabeticShortcut('v')
                 .setEnabled(mTextView.canPaste())
                 .setOnMenuItemClickListener(mOnContextMenuItemClickListener);
-        menu.add(Menu.NONE, TextView.ID_PASTE_AS_PLAIN_TEXT, MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT,
+        menu.add(CONTEXT_MENU_GROUP_CLIPBOARD, TextView.ID_PASTE_AS_PLAIN_TEXT,
+                        CONTEXT_MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT,
                 com.android.internal.R.string.paste_as_plain_text)
+                .setAlphabeticShortcut('v', KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON)
                 .setEnabled(mTextView.canPasteAsPlainText())
                 .setOnMenuItemClickListener(mOnContextMenuItemClickListener);
-        menu.add(Menu.NONE, TextView.ID_SHARE, MENU_ITEM_ORDER_SHARE,
-                com.android.internal.R.string.share)
-                .setEnabled(mTextView.canShare())
-                .setOnMenuItemClickListener(mOnContextMenuItemClickListener);
-        menu.add(Menu.NONE, TextView.ID_SELECT_ALL, MENU_ITEM_ORDER_SELECT_ALL,
-                com.android.internal.R.string.selectAll)
+        menu.add(CONTEXT_MENU_GROUP_CLIPBOARD, TextView.ID_SELECT_ALL,
+                        CONTEXT_MENU_ITEM_ORDER_SELECT_ALL, com.android.internal.R.string.selectAll)
                 .setAlphabeticShortcut('a')
                 .setEnabled(mTextView.canSelectAllText())
                 .setOnMenuItemClickListener(mOnContextMenuItemClickListener);
-        menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
+
+        menu.add(CONTEXT_MENU_GROUP_MISC, TextView.ID_SHARE, CONTEXT_MENU_ITEM_ORDER_SHARE,
+                com.android.internal.R.string.share)
+                .setEnabled(mTextView.canShare())
+                .setOnMenuItemClickListener(mOnContextMenuItemClickListener);
+        menu.add(CONTEXT_MENU_GROUP_MISC, TextView.ID_AUTOFILL, CONTEXT_MENU_ITEM_ORDER_AUTOFILL,
                 android.R.string.autofill)
                 .setEnabled(mTextView.canRequestAutofill())
                 .setOnMenuItemClickListener(mOnContextMenuItemClickListener);
@@ -4348,28 +4373,28 @@
 
         private void populateMenuWithItems(Menu menu) {
             if (mTextView.canCut()) {
-                menu.add(Menu.NONE, TextView.ID_CUT, MENU_ITEM_ORDER_CUT,
+                menu.add(Menu.NONE, TextView.ID_CUT, ACTION_MODE_MENU_ITEM_ORDER_CUT,
                         com.android.internal.R.string.cut)
                                 .setAlphabeticShortcut('x')
                                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
             }
 
             if (mTextView.canCopy()) {
-                menu.add(Menu.NONE, TextView.ID_COPY, MENU_ITEM_ORDER_COPY,
+                menu.add(Menu.NONE, TextView.ID_COPY, ACTION_MODE_MENU_ITEM_ORDER_COPY,
                         com.android.internal.R.string.copy)
                                 .setAlphabeticShortcut('c')
                                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
             }
 
             if (mTextView.canPaste()) {
-                menu.add(Menu.NONE, TextView.ID_PASTE, MENU_ITEM_ORDER_PASTE,
+                menu.add(Menu.NONE, TextView.ID_PASTE, ACTION_MODE_MENU_ITEM_ORDER_PASTE,
                         com.android.internal.R.string.paste)
                                 .setAlphabeticShortcut('v')
                                 .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
             }
 
             if (mTextView.canShare()) {
-                menu.add(Menu.NONE, TextView.ID_SHARE, MENU_ITEM_ORDER_SHARE,
+                menu.add(Menu.NONE, TextView.ID_SHARE, ACTION_MODE_MENU_ITEM_ORDER_SHARE,
                         com.android.internal.R.string.share)
                         .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
             }
@@ -4377,7 +4402,7 @@
             if (mTextView.canRequestAutofill()) {
                 final String selected = mTextView.getSelectedText();
                 if (selected == null || selected.isEmpty()) {
-                    menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
+                    menu.add(Menu.NONE, TextView.ID_AUTOFILL, ACTION_MODE_MENU_ITEM_ORDER_AUTOFILL,
                             com.android.internal.R.string.autofill)
                             .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
                 }
@@ -4387,7 +4412,7 @@
                 menu.add(
                         Menu.NONE,
                         TextView.ID_PASTE_AS_PLAIN_TEXT,
-                        MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT,
+                                ACTION_MODE_MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT,
                         com.android.internal.R.string.paste_as_plain_text)
                         .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
             }
@@ -4414,7 +4439,7 @@
             boolean canSelectAll = mTextView.canSelectAllText();
             boolean selectAllItemExists = menu.findItem(TextView.ID_SELECT_ALL) != null;
             if (canSelectAll && !selectAllItemExists) {
-                menu.add(Menu.NONE, TextView.ID_SELECT_ALL, MENU_ITEM_ORDER_SELECT_ALL,
+                menu.add(Menu.NONE, TextView.ID_SELECT_ALL, ACTION_MODE_MENU_ITEM_ORDER_SELECT_ALL,
                         com.android.internal.R.string.selectAll)
                     .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
             } else if (!canSelectAll && selectAllItemExists) {
@@ -4426,7 +4451,7 @@
             boolean canReplace = mTextView.isSuggestionsEnabled() && shouldOfferToShowSuggestions();
             boolean replaceItemExists = menu.findItem(TextView.ID_REPLACE) != null;
             if (canReplace && !replaceItemExists) {
-                menu.add(Menu.NONE, TextView.ID_REPLACE, MENU_ITEM_ORDER_REPLACE,
+                menu.add(Menu.NONE, TextView.ID_REPLACE, ACTION_MODE_MENU_ITEM_ORDER_REPLACE,
                         com.android.internal.R.string.replace)
                     .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
             } else if (!canReplace && replaceItemExists) {
@@ -4452,12 +4477,12 @@
                 // Primary assist action (Always shown).
                 final MenuItem item = addAssistMenuItem(menu,
                         textClassification.getActions().get(0), TextView.ID_ASSIST,
-                        MENU_ITEM_ORDER_ASSIST, MenuItem.SHOW_AS_ACTION_ALWAYS);
+                        ACTION_MODE_MENU_ITEM_ORDER_ASSIST, MenuItem.SHOW_AS_ACTION_ALWAYS);
                 item.setIntent(textClassification.getIntent());
             } else if (hasLegacyAssistItem(textClassification)) {
                 // Legacy primary assist action (Always shown).
                 final MenuItem item = menu.add(
-                        TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST,
+                        TextView.ID_ASSIST, TextView.ID_ASSIST, ACTION_MODE_MENU_ITEM_ORDER_ASSIST,
                         textClassification.getLabel())
                         .setIcon(textClassification.getIcon())
                         .setIntent(textClassification.getIntent());
@@ -4471,7 +4496,7 @@
             for (int i = 1; i < count; i++) {
                 // Secondary assist action (Never shown).
                 addAssistMenuItem(menu, textClassification.getActions().get(i), Menu.NONE,
-                        MENU_ITEM_ORDER_SECONDARY_ASSIST_ACTIONS_START + i - 1,
+                        ACTION_MODE_MENU_ITEM_ORDER_SECONDARY_ASSIST_ACTIONS_START + i - 1,
                         MenuItem.SHOW_AS_ACTION_NEVER);
             }
             mPrevTextClassification = textClassification;
@@ -4785,12 +4810,14 @@
                 }
 
                 if (includeVisibleLineBounds) {
-                    Rect visibleRect = new Rect();
-                    if (mTextView.getLocalVisibleRect(visibleRect)) {
+                    final Rect visibleRect = new Rect();
+                    if (mTextView.getContentVisibleRect(visibleRect)) {
+                        // Subtract the viewportToContentVerticalOffset to convert the view
+                        // coordinates to layout coordinates.
                         final float visibleTop =
-                                visibleRect.top + viewportToContentVerticalOffset;
+                                visibleRect.top - viewportToContentVerticalOffset;
                         final float visibleBottom =
-                                visibleRect.bottom + viewportToContentVerticalOffset;
+                                visibleRect.bottom - viewportToContentVerticalOffset;
                         final int firstLine =
                                 layout.getLineForVertical((int) Math.floor(visibleTop));
                         final int lastLine =
@@ -4803,7 +4830,7 @@
                                     + viewportToContentVerticalOffset;
                             final float right = layout.getLineRight(line)
                                     + viewportToContentHorizontalOffset;
-                            final float bottom = layout.getLineBottom(line)
+                            final float bottom = layout.getLineBottom(line, false)
                                     + viewportToContentVerticalOffset;
                             builder.addVisibleLineBounds(left, top, right, bottom);
                         }
@@ -7914,7 +7941,7 @@
             for (int i = 0; i < size; i++) {
                 final ResolveInfo resolveInfo = mSupportedActivities.get(i);
                 menu.add(Menu.NONE, Menu.NONE,
-                        Editor.MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START + i,
+                        Editor.ACTION_MODE_MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START + i,
                         getLabel(resolveInfo))
                         .setIntent(createProcessTextIntentForResolveInfo(resolveInfo))
                         .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6e36a03..77df1f1 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -108,6 +108,7 @@
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Layout;
+import android.text.NoCopySpan;
 import android.text.ParcelableSpan;
 import android.text.PrecomputedText;
 import android.text.SegmentFinder;
@@ -905,6 +906,8 @@
     private Scroller mScroller;
     private TextPaint mTempTextPaint;
 
+    private Object mTempCursor;
+
     @UnsupportedAppUsage
     private BoringLayout.Metrics mBoring;
     @UnsupportedAppUsage
@@ -6502,7 +6505,7 @@
     }
 
     boolean hasGesturePreviewHighlight() {
-        return mGesturePreviewHighlightStart > 0;
+        return mGesturePreviewHighlightStart >= 0;
     }
 
     /**
@@ -10060,10 +10063,8 @@
         }
         int offset = mLayout.getOffsetForHorizontal(line, point.x);
         String textToInsert = gesture.getTextToInsert();
-        getEditableText().insert(offset, textToInsert);
-        Selection.setSelection(getEditableText(), offset + textToInsert.length());
+        return tryInsertTextForHandwritingGesture(offset, textToInsert, gesture);
         // TODO(b/243980426): Insert extra spaces if necessary.
-        return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
     }
 
     /** @hide */
@@ -10163,12 +10164,11 @@
         if (startOffset < endOffset) {
             getEditableText().delete(startOffset, endOffset);
             Selection.setSelection(getEditableText(), startOffset);
+            return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
         } else {
             // No whitespace found, so insert a space.
-            getEditableText().insert(startOffset, " ");
-            Selection.setSelection(getEditableText(), startOffset + 1);
+            return tryInsertTextForHandwritingGesture(startOffset, " ", gesture);
         }
-        return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
     }
 
     /** @hide */
@@ -10229,8 +10229,7 @@
             // The point is not within lineMargin of a line.
             return -1;
         }
-        if (point.x < mLayout.getLineLeft(line) - lineMargin
-                || point.x > mLayout.getLineRight(line) + lineMargin) {
+        if (point.x < -lineMargin || point.x > mLayout.getWidth() + lineMargin) {
             // The point is not within lineMargin of a line.
             return -1;
         }
@@ -10252,6 +10251,32 @@
                 area, segmentFinder, Layout.INCLUSION_STRATEGY_CONTAINS_CENTER);
     }
 
+    private int tryInsertTextForHandwritingGesture(
+            int offset, String textToInsert, HandwritingGesture gesture) {
+        // A temporary cursor span is placed at the insertion offset. The span will be pushed
+        // forward when text is inserted, then the real cursor can be placed after the inserted
+        // text. A temporary cursor span is used in order to avoid modifying the real selection span
+        // in the case that the text is filtered out.
+        Editable editableText = getEditableText();
+        if (mTempCursor == null) {
+            mTempCursor = new NoCopySpan.Concrete();
+        }
+        editableText.setSpan(mTempCursor, offset, offset, Spanned.SPAN_POINT_POINT);
+
+        editableText.insert(offset, textToInsert);
+
+        int newOffset = editableText.getSpanStart(mTempCursor);
+        editableText.removeSpan(mTempCursor);
+        if (newOffset == offset) {
+            // The inserted text was filtered out.
+            return handleGestureFailure(gesture);
+        } else {
+            // Place the cursor after the inserted text.
+            Selection.setSelection(editableText, newOffset);
+            return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
+        }
+    }
+
     private Pattern getWhitespacePattern() {
         if (mWhitespacePattern == null) {
             mWhitespacePattern = Pattern.compile("\\s+");
@@ -13627,6 +13652,27 @@
     }
 
     /**
+     * Helper method to set {@code rect} to the text content's non-clipped area in the view's
+     * coordinates.
+     *
+     * @return true if at least part of the text content is visible; false if the text content is
+     * completely clipped or translated out of the visible area.
+     */
+    boolean getContentVisibleRect(Rect rect) {
+        if (!getLocalVisibleRect(rect)) {
+            return false;
+        }
+        // getLocalVisibleRect returns a rect relative to the unscrolled left top corner of the
+        // view. In other words, the returned rectangle's origin point is (-scrollX, -scrollY) in
+        // view's coordinates. So we need to offset it with the negative scrolled amount to convert
+        // it to view's coordinate.
+        rect.offset(-getScrollX(), -getScrollY());
+        // Clip the view's visible rect with the text layout's visible rect.
+        return rect.intersect(getCompoundPaddingLeft(), getCompoundPaddingTop(),
+                getWidth() - getCompoundPaddingRight(), getHeight() - getCompoundPaddingBottom());
+    }
+
+    /**
      * Populate requested character bounds in a {@link CursorAnchorInfo.Builder}
      *
      * @param builder The builder to populate
@@ -13646,10 +13692,9 @@
             return;
         }
         final Rect rect = new Rect();
-        getLocalVisibleRect(rect);
+        getContentVisibleRect(rect);
         final RectF visibleRect = new RectF(rect);
 
-
         final float[] characterBounds = getCharacterBounds(startIndex, endIndex,
                 viewportToContentHorizontalOffset, viewportToContentVerticalOffset);
         final int limit = endIndex - startIndex;
diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java
index 535dc4e..c270053 100644
--- a/core/java/android/window/DisplayWindowPolicyController.java
+++ b/core/java/android/window/DisplayWindowPolicyController.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 
 import android.annotation.NonNull;
+import android.annotation.UserIdInt;
 import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -137,7 +138,7 @@
     /**
      * This is called when the top activity of the display is changed.
      */
-    public void onTopActivityChanged(ComponentName topActivity, int uid) {}
+    public void onTopActivityChanged(ComponentName topActivity, int uid, @UserIdInt int userId) {}
 
     /**
      * This is called when the apps that contains running activities on the display has changed.
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
index a0bd7f7..9ef6880 100644
--- a/core/java/android/window/ImeOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -82,8 +82,13 @@
             @NonNull OnBackInvokedCallback callback) {
         final Bundle bundle = new Bundle();
         // Always invoke back for ime without checking the window focus.
+        // We use strong reference in the binder wrapper to avoid accidentally GC the callback.
+        // This is necessary because the callback is sent to and registered from
+        // the app process, which may treat the IME callback as weakly referenced. This will not
+        // cause a memory leak because the app side already clears the reference correctly.
         final IOnBackInvokedCallback iCallback =
-                new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(callback);
+                new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(
+                        callback, false /* useWeakRef */);
         bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder());
         bundle.putInt(RESULT_KEY_PRIORITY, priority);
         bundle.putInt(RESULT_KEY_ID, callback.hashCode());
@@ -211,6 +216,12 @@
         IOnBackInvokedCallback getIOnBackInvokedCallback() {
             return mIOnBackInvokedCallback;
         }
+
+        @Override
+        public String toString() {
+            return "ImeCallback=ImeOnBackInvokedCallback@" + mId
+                    + " Callback=" + mIOnBackInvokedCallback;
+        }
     }
 
     /**
diff --git a/core/java/android/window/ProxyOnBackInvokedDispatcher.java b/core/java/android/window/ProxyOnBackInvokedDispatcher.java
index 09d8b0f..56c05b2 100644
--- a/core/java/android/window/ProxyOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ProxyOnBackInvokedDispatcher.java
@@ -180,16 +180,7 @@
                 return;
             }
             clearCallbacksOnDispatcher();
-            if (actualDispatcher instanceof ProxyOnBackInvokedDispatcher) {
-                // We don't want to nest ProxyDispatchers, so if we are given on, we unwrap its
-                // actual dispatcher.
-                // This can happen when an Activity is recreated but the Window is preserved (e.g.
-                // when going from split-screen back to single screen)
-                mActualDispatcher =
-                        ((ProxyOnBackInvokedDispatcher) actualDispatcher).mActualDispatcher;
-            } else {
-                mActualDispatcher = actualDispatcher;
-            }
+            mActualDispatcher = actualDispatcher;
             transferCallbacksToDispatcher();
         }
     }
diff --git a/core/java/android/window/SurfaceSyncGroup.java b/core/java/android/window/SurfaceSyncGroup.java
index 2e55041..78de954 100644
--- a/core/java/android/window/SurfaceSyncGroup.java
+++ b/core/java/android/window/SurfaceSyncGroup.java
@@ -53,7 +53,7 @@
  * see the <a href="https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/window/SurfaceSyncGroup.md">SurfaceSyncGroup documentation</a>
  * </p>
  */
-public class SurfaceSyncGroup {
+public final class SurfaceSyncGroup {
     private static final String TAG = "SurfaceSyncGroup";
     private static final boolean DEBUG = false;
 
@@ -101,6 +101,9 @@
      */
     public final ISurfaceSyncGroup mISurfaceSyncGroup = new ISurfaceSyncGroupImpl();
 
+    @GuardedBy("mLock")
+    private Runnable mAddedToSyncListener;
+
     /**
      * Token to identify this SurfaceSyncGroup. This is used to register the SurfaceSyncGroup in
      * WindowManager. This token is also sent to other processes' SurfaceSyncGroup that want to be
@@ -447,12 +450,15 @@
     }
 
     /**
-     * Invoked when the SurfaceSyncGroup has been added to another SurfaceSyncGroup and is ready
-     * to proceed.
+     * Add a Runnable to be invoked when the SurfaceSyncGroup has been added to another
+     * SurfaceSyncGroup. This is useful to know when it's safe to proceed rendering.
      *
      * @hide
      */
-    public void onSyncReady() {
+    public void setAddedToSyncListener(Runnable addedToSyncListener) {
+        synchronized (mLock) {
+            mAddedToSyncListener = addedToSyncListener;
+        }
     }
 
     private boolean addSyncToWm(IBinder token, boolean parentSyncGroupMerge,
@@ -525,12 +531,15 @@
         if (DEBUG) {
             Log.d(TAG, "setTransactionCallbackFromParent " + mName);
         }
-        boolean finished = false;
+
         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
             Trace.traceBegin(Trace.TRACE_TAG_VIEW,
                     "setTransactionCallbackFromParent " + mName + " callback="
                             + transactionReadyCallback.hashCode());
         }
+
+        boolean finished = false;
+        Runnable addedToSyncListener = null;
         synchronized (mLock) {
             if (mFinished) {
                 finished = true;
@@ -577,6 +586,7 @@
                         Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                     }
                 };
+                addedToSyncListener = mAddedToSyncListener;
             }
         }
 
@@ -587,8 +597,8 @@
                 transactionReadyCallback.onTransactionReady(null);
             } catch (RemoteException e) {
             }
-        } else {
-            onSyncReady();
+        } else if (addedToSyncListener != null) {
+            addedToSyncListener.run();
         }
         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
diff --git a/core/java/android/window/TaskFragmentTransaction.java b/core/java/android/window/TaskFragmentTransaction.java
index 7667743..3c5d60d 100644
--- a/core/java/android/window/TaskFragmentTransaction.java
+++ b/core/java/android/window/TaskFragmentTransaction.java
@@ -128,7 +128,7 @@
     /** Change type: the status of the TaskFragment is changed. */
     public static final int TYPE_TASK_FRAGMENT_INFO_CHANGED = 2;
 
-    /** Change type: the TaskFragment is removed form the hierarchy. */
+    /** Change type: the TaskFragment is removed from the hierarchy. */
     public static final int TYPE_TASK_FRAGMENT_VANISHED = 3;
 
     /** Change type: the status of the parent leaf Task is changed. */
diff --git a/core/java/android/window/WindowMetricsController.java b/core/java/android/window/WindowMetricsController.java
index 11bd47d..3478b0f 100644
--- a/core/java/android/window/WindowMetricsController.java
+++ b/core/java/android/window/WindowMetricsController.java
@@ -56,7 +56,7 @@
 public final class WindowMetricsController {
     // TODO(b/151908239): Remove and always enable this if it is stable.
     private static final boolean LAZY_WINDOW_INSETS = android.os.SystemProperties.getBoolean(
-            "persist.wm.debug.win_metrics_lazy_insets", false);
+            "persist.wm.debug.win_metrics_lazy_insets", true);
     private final Context mContext;
 
     public WindowMetricsController(@NonNull Context context) {
@@ -127,7 +127,7 @@
                     isScreenRound, alwaysConsumeSystemBars, SOFT_INPUT_ADJUST_NOTHING,
                     0 /* flags */, SYSTEM_UI_FLAG_VISIBLE,
                     WindowManager.LayoutParams.INVALID_WINDOW_TYPE, windowingMode,
-                    null /* typeSideMap */);
+                    null /* idSideMap */);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 7a5510c..a8c2b2f 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -29,6 +29,7 @@
 import android.view.IWindow;
 import android.view.IWindowSession;
 
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -232,11 +233,55 @@
         return Checker.isOnBackInvokedCallbackEnabled(mChecker.getContext());
     }
 
+    /**
+     * Dump information about this WindowOnBackInvokedDispatcher
+     * @param prefix the prefix that will be prepended to each line of the produced output
+     * @param writer the writer that will receive the resulting text
+     */
+    public void dump(String prefix, PrintWriter writer) {
+        String innerPrefix = prefix + "    ";
+        writer.println(prefix + "WindowOnBackDispatcher:");
+        if (mAllCallbacks.isEmpty()) {
+            writer.println(prefix + "<None>");
+            return;
+        }
+
+        writer.println(innerPrefix + "Top Callback: " + getTopCallback());
+        writer.println(innerPrefix + "Callbacks: ");
+        mAllCallbacks.forEach((callback, priority) -> {
+            writer.println(innerPrefix + "  Callback: " + callback + " Priority=" + priority);
+        });
+    }
+
     static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
-        private final WeakReference<OnBackInvokedCallback> mCallback;
+        static class CallbackRef {
+            final WeakReference<OnBackInvokedCallback> mWeakRef;
+            final OnBackInvokedCallback mStrongRef;
+            CallbackRef(@NonNull OnBackInvokedCallback callback, boolean useWeakRef) {
+                if (useWeakRef) {
+                    mWeakRef = new WeakReference<>(callback);
+                    mStrongRef = null;
+                } else {
+                    mStrongRef = callback;
+                    mWeakRef = null;
+                }
+            }
+
+            OnBackInvokedCallback get() {
+                if (mStrongRef != null) {
+                    return mStrongRef;
+                }
+                return mWeakRef.get();
+            }
+        }
+        final CallbackRef mCallbackRef;
 
         OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback) {
-            mCallback = new WeakReference<>(callback);
+            mCallbackRef = new CallbackRef(callback, true /* useWeakRef */);
+        }
+
+        OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback, boolean useWeakRef) {
+            mCallbackRef = new CallbackRef(callback, useWeakRef);
         }
 
         @Override
@@ -279,8 +324,9 @@
         public void onBackInvoked() throws RemoteException {
             Handler.getMain().post(() -> {
                 mProgressAnimator.reset();
-                final OnBackInvokedCallback callback = mCallback.get();
+                final OnBackInvokedCallback callback = mCallbackRef.get();
                 if (callback == null) {
+                    Log.d(TAG, "Trying to call onBackInvoked() on a null callback reference.");
                     return;
                 }
                 callback.onBackInvoked();
@@ -289,7 +335,7 @@
 
         @Nullable
         private OnBackAnimationCallback getBackAnimationCallback() {
-            OnBackInvokedCallback callback = mCallback.get();
+            OnBackInvokedCallback callback = mCallbackRef.get();
             return callback instanceof OnBackAnimationCallback ? (OnBackAnimationCallback) callback
                     : null;
         }
diff --git a/core/java/com/android/internal/accessibility/common/MagnificationConstants.java b/core/java/com/android/internal/accessibility/common/MagnificationConstants.java
new file mode 100644
index 0000000..94c230b
--- /dev/null
+++ b/core/java/com/android/internal/accessibility/common/MagnificationConstants.java
@@ -0,0 +1,30 @@
+/*
+ * 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.internal.accessibility.common;
+
+/**
+ * Collection of common constants for accessibility shortcut.
+ */
+public final class MagnificationConstants {
+    private MagnificationConstants() {}
+
+    /**
+     * The min value for the magnification persisted scale. We assume if the scale is lower than
+     * the min value, there will be no obvious magnification effect.
+     */
+    public static final float PERSISTED_SCALE_MIN_VALUE = 1.3f;
+}
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index f843318..fc5cb4b 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -229,6 +229,35 @@
         }
     }
 
+    /**
+     * Enables visual detection service.
+     *
+     * @param listener to receive visual attention gained/lost events.
+     */
+    public void enableVisualQueryDetection(
+            IVisualQueryDetectionAttentionListener listener) {
+        try {
+            if (mVoiceInteractionManagerService != null) {
+                mVoiceInteractionManagerService.enableVisualQueryDetection(listener);
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to register visual query detection attention listener", e);
+        }
+    }
+
+    /**
+     * Disables visual query detection.
+     */
+    public void disableVisualQueryDetection() {
+        try {
+            if (mVoiceInteractionManagerService != null) {
+                mVoiceInteractionManagerService.disableVisualQueryDetection();
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to register visual query detection attention listener", e);
+        }
+    }
+
     @UnsupportedAppUsage
     public ComponentName getAssistComponentForUser(int userId) {
         final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index f257f1c..7c237e69 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2525,8 +2525,7 @@
             List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
             boolean filterLastUsed, UserHandle userHandle) {
         ChooserListAdapter chooserListAdapter = createChooserListAdapter(context, payloadIntents,
-                initialIntents, rList, filterLastUsed,
-                createListController(userHandle));
+                initialIntents, rList, filterLastUsed, userHandle);
         AppPredictor.Callback appPredictorCallback = createAppPredictorCallback(chooserListAdapter);
         AppPredictor appPredictor = setupAppPredictorForUser(userHandle, appPredictorCallback);
         chooserListAdapter.setAppPredictor(appPredictor);
@@ -2536,12 +2535,18 @@
 
     @VisibleForTesting
     public ChooserListAdapter createChooserListAdapter(Context context,
-            List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
-            boolean filterLastUsed, ResolverListController resolverListController) {
+            List<Intent> payloadIntents,
+            Intent[] initialIntents,
+            List<ResolveInfo> rList,
+            boolean filterLastUsed,
+            UserHandle userHandle) {
+        UserHandle initialIntentsUserSpace = isLaunchedAsCloneProfile()
+                && userHandle.equals(getPersonalProfileUserHandle())
+                ? getCloneProfileUserHandle() : userHandle;
         return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
-                filterLastUsed, resolverListController, this,
+                filterLastUsed, createListController(userHandle), this,
                 this, context.getPackageManager(),
-                getChooserActivityLogger());
+                getChooserActivityLogger(), initialIntentsUserSpace);
     }
 
     @VisibleForTesting
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index e0568cf..1eecb41 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -105,6 +105,9 @@
     private AppPredictor mAppPredictor;
     private AppPredictor.Callback mAppPredictorCallback;
 
+    // Represents the UserSpace in which the Initial Intents should be resolved.
+    private final UserHandle mInitialIntentsUserSpace;
+
     // For pinned direct share labels, if the text spans multiple lines, the TextView will consume
     // the full width, even if the characters actually take up less than that. Measure the actual
     // line widths and constrain the View's width based upon that so that the pin doesn't end up
@@ -142,11 +145,12 @@
             ChooserListCommunicator chooserListCommunicator,
             SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator,
             PackageManager packageManager,
-            ChooserActivityLogger chooserActivityLogger) {
+            ChooserActivityLogger chooserActivityLogger,
+            UserHandle initialIntentsUserSpace) {
         // Don't send the initial intents through the shared ResolverActivity path,
         // we want to separate them into a different section.
         super(context, payloadIntents, null, rList, filterLastUsed,
-                resolverListController, chooserListCommunicator, false);
+                resolverListController, chooserListCommunicator, false, initialIntentsUserSpace);
 
         mMaxShortcutTargetsPerApp =
                 context.getResources().getInteger(R.integer.config_maxShortcutTargetsPerApp);
@@ -154,6 +158,7 @@
         createPlaceHolders();
         mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator;
         mChooserActivityLogger = chooserActivityLogger;
+        mInitialIntentsUserSpace = initialIntentsUserSpace;
 
         if (initialIntents != null) {
             for (int i = 0; i < initialIntents.length; i++) {
@@ -197,12 +202,12 @@
                     ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                     ri.icon = li.getIconResource();
                     ri.iconResourceId = ri.icon;
-                    ri.userHandle = getUserHandle();
                 }
                 if (userManager.isManagedProfile()) {
                     ri.noResourceId = true;
                     ri.icon = 0;
                 }
+                ri.userHandle = mInitialIntentsUserSpace;
                 mCallerTargets.add(new DisplayResolveInfo(ii, ri, ii, makePresentationGetter(ri)));
                 if (mCallerTargets.size() == MAX_SUGGESTED_APP_TARGETS) break;
             }
@@ -351,6 +356,10 @@
                 // Consolidate multiple targets from same app.
                 Map<String, DisplayResolveInfo> consolidated = new HashMap<>();
                 for (DisplayResolveInfo info : allTargets) {
+                    if (info.getResolveInfo().userHandle == null) {
+                        Log.e(TAG, "ResolveInfo with null UserHandle found: "
+                                + info.getResolveInfo());
+                    }
                     String resolvedTarget = info.getResolvedComponentName().getPackageName()
                             + '#' + info.getDisplayLabel()
                             + '#' + ResolverActivity.getResolveInfoUserHandle(
diff --git a/core/java/com/android/internal/app/ISoundTriggerSession.aidl b/core/java/com/android/internal/app/ISoundTriggerSession.aidl
index a1ba558..3269ffc 100644
--- a/core/java/com/android/internal/app/ISoundTriggerSession.aidl
+++ b/core/java/com/android/internal/app/ISoundTriggerSession.aidl
@@ -36,7 +36,8 @@
 
     void deleteSoundModel(in ParcelUuid soundModelId);
 
-    int startRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback,
+    int startRecognition(in SoundTrigger.GenericSoundModel soundModel,
+         in IRecognitionStatusCallback callback,
          in SoundTrigger.RecognitionConfig config, boolean runInBatterySaver);
 
     int stopRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback);
diff --git a/core/java/com/android/internal/app/IVisualQueryDetectionAttentionListener.aidl b/core/java/com/android/internal/app/IVisualQueryDetectionAttentionListener.aidl
new file mode 100644
index 0000000..3e48da7
--- /dev/null
+++ b/core/java/com/android/internal/app/IVisualQueryDetectionAttentionListener.aidl
@@ -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.internal.app;
+
+/**
+ * Allows sysui to notify users the assistant is ready to take a query without notifying the
+ * assistant app.
+ */
+oneway interface IVisualQueryDetectionAttentionListener {
+   /**
+    * Called when attention signal is sent.
+    */
+   void onAttentionGained();
+
+   /**
+    * Called when a attention signal is lost.
+    */
+   void onAttentionLost();
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 88d6425..619b420 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -39,6 +39,7 @@
 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractionSoundTriggerSession;
 import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.app.IVisualQueryDetectionAttentionListener;
 
 interface IVoiceInteractionManagerService {
     void showSession(in Bundle sessionArgs, int flags, String attributionTag);
@@ -300,6 +301,12 @@
      */
     void shutdownHotwordDetectionService();
 
+    @EnforcePermission("ACCESS_VOICE_INTERACTION_SERVICE")
+    void enableVisualQueryDetection(in IVisualQueryDetectionAttentionListener Listener);
+
+    @EnforcePermission("ACCESS_VOICE_INTERACTION_SERVICE")
+    void disableVisualQueryDetection();
+
     void startPerceiving(in IVisualQueryDetectionVoiceInteractionCallback callback);
 
     void stopPerceiving();
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index 3619c7b..685bd9a 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -277,8 +277,7 @@
             inflater.inflate(R.menu.language_selection_list, menu);
 
             final MenuItem searchMenuItem = menu.findItem(R.id.locale_search_menu);
-            if (mLocalePickerCollector.hasSpecificPackageName()
-                    && mOnActionExpandListener != null) {
+            if (mOnActionExpandListener != null) {
                 searchMenuItem.setOnActionExpandListener(mOnActionExpandListener);
             }
 
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index bcff907..b0a4b54 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -141,8 +141,9 @@
         @UnsupportedAppUsage
         public String getFullNameNative() {
             if (mFullNameNative == null) {
+                Locale locale = mLocale.stripExtensions();
                 mFullNameNative =
-                        LocaleHelper.getDisplayName(mLocale, mLocale, true /* sentence case */);
+                        LocaleHelper.getDisplayName(locale, locale, true /* sentence case */);
             }
             return mFullNameNative;
         }
@@ -563,6 +564,22 @@
         String id = locale.toLanguageTag();
         LocaleInfo result;
         if (!sLocaleCache.containsKey(id)) {
+            // Locale preferences can modify the language tag to current system languages, so we
+            // need to check the input locale without extra u extension except numbering system.
+            Locale filteredLocale = new Locale.Builder()
+                    .setLocale(locale.stripExtensions())
+                    .setUnicodeLocaleKeyword("nu", locale.getUnicodeLocaleType("nu"))
+                    .build();
+            if (sLocaleCache.containsKey(filteredLocale.toLanguageTag())) {
+                result = new LocaleInfo(locale);
+                LocaleInfo localeInfo = sLocaleCache.get(filteredLocale.toLanguageTag());
+                // This locale is included in supported locales, so follow the settings
+                // of supported locales.
+                result.mIsPseudo = localeInfo.mIsPseudo;
+                result.mIsTranslated = localeInfo.mIsTranslated;
+                result.mSuggestionFlags = localeInfo.mSuggestionFlags;
+                return result;
+            }
             result = new LocaleInfo(locale);
             sLocaleCache.put(id, result);
         } else {
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index 56da8e0..69660ae 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -11,6 +11,7 @@
 per-file *Assist* = file:/core/java/android/service/voice/OWNERS
 per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
 per-file *Voice* = file:/core/java/android/service/voice/OWNERS
+per-file *VisualQuery* = file:/core/java/android/service/voice/OWNERS
 
 # System language settings
 per-file *Locale* = file:platform/packages/apps/Settings:/src/com/android/settings/localepicker/OWNERS
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 992e243..d6a515a 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -33,6 +33,8 @@
 import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
+
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.annotation.UiThread;
@@ -780,7 +782,7 @@
         return getCloneProfileUserHandle() != null;
     }
 
-    private boolean isLaunchedAsCloneProfile() {
+    protected final boolean isLaunchedAsCloneProfile() {
         return hasCloneProfile()
                 && (UserHandle.myUserId() == getCloneProfileUserHandle().getIdentifier());
     }
@@ -1517,9 +1519,7 @@
         safelyStartActivityAsUser(cti, user, null);
     }
 
-    // TODO: Make method public final.
-    @VisibleForTesting
-    protected void safelyStartActivityAsUser(
+    protected final void safelyStartActivityAsUser(
             TargetInfo cti, UserHandle user, @Nullable Bundle options) {
         // We're dispatching intents that might be coming from legacy apps, so
         // don't kill ourselves.
@@ -1609,9 +1609,12 @@
         Intent startIntent = getIntent();
         boolean isAudioCaptureDevice =
                 startIntent.getBooleanExtra(EXTRA_IS_AUDIO_CAPTURE_DEVICE, false);
+        UserHandle initialIntentsUserSpace = isLaunchedAsCloneProfile()
+                && userHandle.equals(getPersonalProfileUserHandle())
+                ? getCloneProfileUserHandle() : userHandle;
         return new ResolverListAdapter(context, payloadIntents, initialIntents, rList,
                 filterLastUsed, createListController(userHandle), this,
-                isAudioCaptureDevice);
+                isAudioCaptureDevice, initialIntentsUserSpace);
     }
 
     @VisibleForTesting
@@ -2536,19 +2539,17 @@
     }
 
     /**
-     * This function is temporary in nature, and its usages will be replaced with just
-     * resolveInfo.userHandle, once it is available, once sharesheet is stable.
-     */
-    public static UserHandle getResolveInfoUserHandle(ResolveInfo resolveInfo,
-            UserHandle predictedHandle) {
-        return resolveInfo.userHandle;
-    }
-
-    /**
      * Returns the {@link List} of {@link UserHandle} to pass on to the
      * {@link ResolverRankerServiceResolverComparator} as per the provided {@code userHandle}.
      */
-    protected final List<UserHandle> getResolverRankerServiceUserHandleList(UserHandle userHandle) {
+    @VisibleForTesting(visibility = PROTECTED)
+    public final List<UserHandle> getResolverRankerServiceUserHandleList(UserHandle userHandle) {
+        return getResolverRankerServiceUserHandleListInternal(userHandle);
+    }
+
+    @VisibleForTesting
+    protected List<UserHandle> getResolverRankerServiceUserHandleListInternal(UserHandle
+            userHandle) {
         List<UserHandle> userList = new ArrayList<>();
         userList.add(userHandle);
         // Add clonedProfileUserHandle to the list only if we are:
@@ -2560,4 +2561,16 @@
         }
         return userList;
     }
+
+    /**
+     * This function is temporary in nature, and its usages will be replaced with just
+     * resolveInfo.userHandle, once it is available, once sharesheet is stable.
+     */
+    public static UserHandle getResolveInfoUserHandle(ResolveInfo resolveInfo,
+            UserHandle predictedHandle) {
+        if (resolveInfo.userHandle == null) {
+            Log.e(TAG, "ResolveInfo with null UserHandle found: " + resolveInfo);
+        }
+        return resolveInfo.userHandle;
+    }
 }
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index 2df2b2b..18c8eb4 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -91,13 +91,16 @@
     private boolean mIsTabLoaded;
     private final Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>();
     private final Map<DisplayResolveInfo, LoadLabelTask> mLabelLoaders = new HashMap<>();
+    // Represents the UserSpace in which the Initial Intents should be resolved.
+    private final UserHandle mInitialIntentsUserSpace;
 
     public ResolverListAdapter(Context context, List<Intent> payloadIntents,
             Intent[] initialIntents, List<ResolveInfo> rList,
             boolean filterLastUsed,
             ResolverListController resolverListController,
             ResolverListCommunicator resolverListCommunicator,
-            boolean isAudioCaptureDevice) {
+            boolean isAudioCaptureDevice,
+            UserHandle initialIntentsUserSpace) {
         mContext = context;
         mIntents = payloadIntents;
         mInitialIntents = initialIntents;
@@ -111,6 +114,11 @@
         mIsAudioCaptureDevice = isAudioCaptureDevice;
         final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
         mIconDpi = am.getLauncherLargeIconDensity();
+        mInitialIntentsUserSpace = initialIntentsUserSpace;
+    }
+
+    public ResolverListController getResolverListController() {
+        return mResolverListController;
     }
 
     public void handlePackagesChanged() {
@@ -439,13 +447,13 @@
                         ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                         ri.icon = li.getIconResource();
                         ri.iconResourceId = ri.icon;
-                        ri.userHandle = getUserHandle();
                     }
                     if (userManager.isManagedProfile()) {
                         ri.noResourceId = true;
                         ri.icon = 0;
                     }
 
+                    ri.userHandle = mInitialIntentsUserSpace;
                     addResolveInfo(new DisplayResolveInfo(ii, ri,
                             ri.loadLabel(mPm), null, ii, makePresentationGetter(ri)));
                 }
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index b9373be..1084c71 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -562,6 +562,13 @@
             "task_manager_show_user_visible_jobs";
 
     /**
+     * (boolean) Whether the task manager should tell JobScheduler it's about to ask for an
+     * app stop.
+     */
+    public static final String TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP =
+            "task_manager_inform_job_scheduler_of_pending_app_stop";
+
+    /**
      * (boolean) Whether to show notification volume control slider separate from ring.
      */
     public static final String VOLUME_SEPARATE_NOTIFICATION = "volume_separate_notification";
diff --git a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
new file mode 100644
index 0000000..f724e55
--- /dev/null
+++ b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
@@ -0,0 +1,183 @@
+/**
+ * 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.internal.config.sysui;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Provides a central definition of debug SystemUI's SystemProperties flags, and their defaults.
+ *
+ * The main feature of this class is that it encodes a system-wide default for each flag which can
+ *  be updated by engineers with a single-line CL.
+ *
+ * NOTE: Because flag values returned by this class are not cached, it is important that developers
+ *  understand the intricacies of changing values and how that applies to their own code.
+ *  Generally, the best practice is to set the property, and then restart the device so that any
+ *  processes with stale state can be updated.  However, if your code has no state derived from the
+ *  flag value and queries it any time behavior is relevant, then it may be safe to change the flag
+ *  and not immediately reboot.
+ *
+ * To enable flags in debuggable builds, use the following commands:
+ *
+ * $ adb shell setprop persist.sysui.whatever_the_flag true
+ * $ adb reboot
+ *
+ * @hide
+ */
+public class SystemUiSystemPropertiesFlags {
+
+    /** The interface used for resolving SystemUI SystemProperties Flags to booleans. */
+    public interface FlagResolver {
+        /** Is the flag enabled? */
+        boolean isEnabled(Flag flag);
+    }
+
+    /** The primary, immutable resolver returned by getResolver() */
+    private static final FlagResolver
+            MAIN_RESOLVER =
+            Build.IS_DEBUGGABLE ? new DebugResolver() : new ProdResolver();
+
+    /**
+     * On debuggable builds, this can be set to override the resolver returned by getResolver().
+     * This can be useful to override flags when testing components that do not allow injecting the
+     * SystemUiPropertiesFlags resolver they use.
+     * Always set this to null when tests tear down.
+     */
+    @VisibleForTesting
+    public static FlagResolver TEST_RESOLVER = null;
+
+    /** Get the resolver for this device configuration. */
+    public static FlagResolver getResolver() {
+        if (Build.IS_DEBUGGABLE && TEST_RESOLVER != null) {
+            Log.i("SystemUiSystemPropertiesFlags", "Returning debug resolver " + TEST_RESOLVER);
+            return TEST_RESOLVER;
+        }
+        return MAIN_RESOLVER;
+    }
+
+    /** The teamfood flag allows multiple features to be opted into at once. */
+    public static final Flag TEAMFOOD = devFlag("persist.sysui.teamfood");
+
+    /**
+     * Flags related to notification features
+     */
+    public static final class NotificationFlags {
+
+        /**
+         * FOR DEVELOPMENT / TESTING ONLY!!!
+         * Forcibly demote *ALL* FSI notifications as if no apps have the app op permission.
+         */
+        public static final Flag FSI_FORCE_DEMOTE =
+                devFlag("persist.sysui.notification.fsi_force_demote");
+
+        /** Gating the ability for users to dismiss ongoing event notifications */
+        public static final Flag ALLOW_DISMISS_ONGOING =
+                devFlag("persist.sysui.notification.ongoing_dismissal");
+
+        /** Gating the redaction of OTP notifications on the lockscreen */
+        public static final Flag OTP_REDACTION =
+                devFlag("persist.sysui.notification.otp_redaction");
+
+    }
+
+    //// == Everything below this line is the implementation == ////
+
+    /**
+     * Creates a flag that is enabled by default in debuggable builds.
+     * It can be enabled by setting this flag's SystemProperty to 1.
+     *
+     * This flag is ALWAYS disabled in release builds.
+     */
+    @VisibleForTesting
+    public static Flag devFlag(String name) {
+        return new Flag(name, false, null);
+    }
+
+    /**
+     * Creates a flag that is disabled by default in debuggable builds.
+     * It can be enabled or force-disabled by setting this flag's SystemProperty to 1 or 0.
+     * If this flag's SystemProperty is not set, the flag can be enabled by setting the
+     * TEAMFOOD flag's SystemProperty to 1.
+     *
+     * This flag is ALWAYS disabled in release builds.
+     */
+    @VisibleForTesting
+    public static Flag teamfoodFlag(String name) {
+        return new Flag(name, false, TEAMFOOD);
+    }
+
+    /**
+     * Creates a flag that is enabled by default in debuggable builds.
+     * It can be enabled by setting this flag's SystemProperty to 0.
+     *
+     * This flag is ALWAYS enabled in release builds.
+     */
+    @VisibleForTesting
+    public static Flag releasedFlag(String name) {
+        return new Flag(name, true, null);
+    }
+
+    /** Represents a developer-switchable gate for a feature. */
+    public static final class Flag {
+        public final String mSysPropKey;
+        public final boolean mDefaultValue;
+        @Nullable
+        public final Flag mDebugDefault;
+
+        /** constructs a new flag.  only visible for testing the class */
+        @VisibleForTesting
+        public Flag(@NonNull String sysPropKey, boolean defaultValue, @Nullable Flag debugDefault) {
+            mSysPropKey = sysPropKey;
+            mDefaultValue = defaultValue;
+            mDebugDefault = debugDefault;
+        }
+    }
+
+    /** Implementation of the interface used in release builds. */
+    @VisibleForTesting
+    public static final class ProdResolver implements
+            FlagResolver {
+        @Override
+        public boolean isEnabled(Flag flag) {
+            return flag.mDefaultValue;
+        }
+    }
+
+    /** Implementation of the interface used in debuggable builds. */
+    @VisibleForTesting
+    public static class DebugResolver implements FlagResolver {
+        @Override
+        public final boolean isEnabled(Flag flag) {
+            if (flag.mDebugDefault == null) {
+                return getBoolean(flag.mSysPropKey, flag.mDefaultValue);
+            }
+            return getBoolean(flag.mSysPropKey, isEnabled(flag.mDebugDefault));
+        }
+
+        /** Look up the value; overridable for tests to avoid needing to set SystemProperties */
+        @VisibleForTesting
+        public boolean getBoolean(String key, boolean defaultValue) {
+            return SystemProperties.getBoolean(key, defaultValue);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/expresslog/Histogram.java b/core/java/com/android/internal/expresslog/Histogram.java
new file mode 100644
index 0000000..fe950c4
--- /dev/null
+++ b/core/java/com/android/internal/expresslog/Histogram.java
@@ -0,0 +1,107 @@
+/*
+ * 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.internal.expresslog;
+
+import android.annotation.NonNull;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+/** CounterHistogram encapsulates StatsD write API calls */
+public final class Histogram {
+
+    private final long mMetricIdHash;
+    private final BinOptions mBinOptions;
+
+    public Histogram(@NonNull String metricId, @NonNull BinOptions binOptions) {
+        mMetricIdHash = Utils.hashString(metricId);
+        mBinOptions = binOptions;
+    }
+
+    /**
+     * Logs increment sample count for automatically calculated bin
+     *
+     * @hide
+     */
+    public void logSample(float sample) {
+        final int binIndex = mBinOptions.getBinForSample(sample);
+        FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash,
+                /*count*/ 1, binIndex);
+    }
+
+    /** Used by CounterHistogram to map data sample to corresponding bin */
+    public interface BinOptions {
+        /**
+         * Returns bins count to be used by counter histogram
+         *
+         * @return bins count used to initialize Options, including overflow & underflow bins
+         * @hide
+         */
+        int getBinsCount();
+
+        /**
+         * @return zero based index
+         * Calculates bin index for the input sample value
+         * index == 0 stands for underflow
+         * index == getBinsCount() - 1 stands for overflow
+         * @hide
+         */
+        int getBinForSample(float sample);
+    }
+
+    /** Used by CounterHistogram to map data sample to corresponding bin for on uniform bins */
+    public static final class UniformOptions implements BinOptions {
+
+        private final int mBinCount;
+        private final float mMinValue;
+        private final float mExclusiveMaxValue;
+        private final float mBinSize;
+
+        public UniformOptions(int binCount, float minValue, float exclusiveMaxValue) {
+            if (binCount < 1) {
+                throw new IllegalArgumentException("Bin count should be positive number");
+            }
+
+            if (exclusiveMaxValue <= minValue) {
+                throw new IllegalArgumentException("Bins range invalid (maxValue < minValue)");
+            }
+
+            mMinValue = minValue;
+            mExclusiveMaxValue = exclusiveMaxValue;
+            mBinSize = (mExclusiveMaxValue - minValue) / binCount;
+
+            // Implicitly add 2 for the extra undeflow & overflow bins
+            mBinCount = binCount + 2;
+        }
+
+        @Override
+        public int getBinsCount() {
+            return mBinCount;
+        }
+
+        @Override
+        public int getBinForSample(float sample) {
+            if (sample < mMinValue) {
+                // goes to underflow
+                return 0;
+            } else if (sample >= mExclusiveMaxValue) {
+                // goes to overflow
+                return mBinCount - 1;
+            }
+            return (int) ((sample - mMinValue) / mBinSize + 1);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/expresslog/TEST_MAPPING b/core/java/com/android/internal/expresslog/TEST_MAPPING
new file mode 100644
index 0000000..c9b0cf8
--- /dev/null
+++ b/core/java/com/android/internal/expresslog/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "ExpressLogTests",
+      "options": [
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/jank/EventLogTags.logtags b/core/java/com/android/internal/jank/EventLogTags.logtags
index 6139bce..7af5d8f 100644
--- a/core/java/com/android/internal/jank/EventLogTags.logtags
+++ b/core/java/com/android/internal/jank/EventLogTags.logtags
@@ -3,8 +3,8 @@
 option java_package com.android.internal.jank;
 
 # Marks a request to start tracing a CUJ. Doesn't mean the request was executed.
-37001 jank_cuj_events_begin_request (CUJ Type|1|5)
+37001 jank_cuj_events_begin_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Ns|2|3)
 # Marks a request to end tracing a CUJ. Doesn't mean the request was executed.
-37002 jank_cuj_events_end_request (CUJ Type|1|5)
+37002 jank_cuj_events_end_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
 # Marks a request to cancel tracing a CUJ. Doesn't mean the request was executed.
-37003 jank_cuj_events_cancel_request (CUJ Type|1|5)
+37003 jank_cuj_events_cancel_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index d9e9a5f..62f1599 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -16,11 +16,15 @@
 
 package com.android.internal.jank;
 
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import static com.android.internal.jank.FrameTracker.REASON_CANCEL_NORMAL;
 import static com.android.internal.jank.FrameTracker.REASON_CANCEL_TIMEOUT;
 import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL;
 import static com.android.internal.jank.FrameTracker.REASON_END_UNKNOWN;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__BIOMETRIC_PROMPT_TRANSITION;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
@@ -89,17 +93,20 @@
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__VOLUME_CONTROL;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WALLPAPER_TRANSITION;
 
+import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.UiThread;
 import android.annotation.WorkerThread;
+import android.app.ActivityThread;
 import android.content.Context;
 import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.HandlerThread;
+import android.os.SystemClock;
 import android.provider.DeviceConfig;
-import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
@@ -232,6 +239,7 @@
     public static final int CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS = 66;
     public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67;
     public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68;
+    public static final int CUJ_IME_INSETS_ANIMATION = 69;
 
     private static final int NO_STATSD_LOGGING = -1;
 
@@ -309,6 +317,7 @@
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS,
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE,
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
+            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION,
     };
 
     private static class InstanceHolder {
@@ -401,7 +410,8 @@
             CUJ_RECENTS_SCROLLING,
             CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS,
             CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
-            CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME
+            CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
+            CUJ_IME_INSETS_ANIMATION,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface CujType {
@@ -422,29 +432,37 @@
      * @param worker the worker thread for the callbacks
      */
     @VisibleForTesting
+    @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
     public InteractionJankMonitor(@NonNull HandlerThread worker) {
-        // Check permission early.
-        Settings.Config.enforceReadPermission(
-            DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR);
-
         mRunningTrackers = new SparseArray<>();
         mTimeoutActions = new SparseArray<>();
         mWorker = worker;
         mWorker.start();
-        mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
         mDisplayResolutionTracker = new DisplayResolutionTracker(worker.getThreadHandler());
-
-        // Post initialization to the background in case we're running on the main
-        // thread.
-        mWorker.getThreadHandler().post(
-                () -> mPropertiesChangedListener.onPropertiesChanged(
-                        DeviceConfig.getProperties(
-                                DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR)));
-        DeviceConfig.addOnPropertiesChangedListener(
-                DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR,
-                new HandlerExecutor(mWorker.getThreadHandler()),
-                mPropertiesChangedListener);
+        mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
         mEnabled = DEFAULT_ENABLED;
+
+        final Context context = ActivityThread.currentApplication();
+        if (context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) == PERMISSION_GRANTED) {
+            // Post initialization to the background in case we're running on the main thread.
+            mWorker.getThreadHandler().post(
+                    () -> mPropertiesChangedListener.onPropertiesChanged(
+                            DeviceConfig.getProperties(
+                                    DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR)));
+            DeviceConfig.addOnPropertiesChangedListener(
+                    DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR,
+                    new HandlerExecutor(mWorker.getThreadHandler()),
+                    mPropertiesChangedListener);
+        } else {
+            if (DEBUG) {
+                Log.d(TAG, "Initialized the InteractionJankMonitor."
+                        + " (No READ_DEVICE_CONFIG permission to change configs)"
+                        + " enabled=" + mEnabled + ", interval=" + mSamplingInterval
+                        + ", missedFrameThreshold=" + mTraceThresholdMissedFrames
+                        + ", frameTimeThreshold=" + mTraceThresholdFrameTimeMillis
+                        + ", package=" + context.getPackageName());
+            }
+        }
     }
 
     /**
@@ -556,7 +574,8 @@
     public boolean begin(@NonNull Configuration.Builder builder) {
         try {
             final Configuration config = builder.build();
-            EventLogTags.writeJankCujEventsBeginRequest(config.mCujType);
+            EventLogTags.writeJankCujEventsBeginRequest(
+                    config.mCujType, SystemClock.elapsedRealtimeNanos(), SystemClock.uptimeNanos());
             final TrackerResult result = new TrackerResult();
             final boolean success = config.getHandler().runWithScissors(
                     () -> result.mResult = beginInternal(config), EXECUTOR_TASK_TIMEOUT);
@@ -630,7 +649,8 @@
      * @return boolean true if the tracker is ended successfully, false otherwise.
      */
     public boolean end(@CujType int cujType) {
-        EventLogTags.writeJankCujEventsEndRequest(cujType);
+        EventLogTags.writeJankCujEventsEndRequest(cujType, SystemClock.elapsedRealtimeNanos(),
+                SystemClock.uptimeNanos());
         FrameTracker tracker = getTracker(cujType);
         // Skip this call since we haven't started a trace yet.
         if (tracker == null) return false;
@@ -668,7 +688,8 @@
      * @return boolean true if the tracker is cancelled successfully, false otherwise.
      */
     public boolean cancel(@CujType int cujType) {
-        EventLogTags.writeJankCujEventsCancelRequest(cujType);
+        EventLogTags.writeJankCujEventsCancelRequest(cujType, SystemClock.elapsedRealtimeNanos(),
+                SystemClock.uptimeNanos());
         return cancel(cujType, REASON_CANCEL_NORMAL);
     }
 
@@ -923,6 +944,8 @@
                 return "LAUNCHER_CLOSE_ALL_APPS_SWIPE";
             case CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME:
                 return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
+            case CUJ_IME_INSETS_ANIMATION:
+                return "IME_INSETS_ANIMATION";
         }
         return "UNKNOWN";
     }
@@ -1178,7 +1201,7 @@
          */
         @VisibleForTesting
         public int getDisplayId() {
-            return (mSurfaceOnly ? mContext.getDisplay() : mView.getDisplay()).getDisplayId();
+            return (mSurfaceOnly ? mContext : mView.getContext()).getDisplayId();
         }
     }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 9e176e3..f7e1d57 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -274,20 +274,6 @@
         initHistoryBuffer();
     }
 
-    /**
-     * Creates a read-only wrapper for the supplied writable history.
-     */
-    public BatteryStatsHistory(BatteryStatsHistory writableHistory) {
-        this(Parcel.obtain(), writableHistory.mSystemDir, 0, 0, null, null, null, writableHistory);
-        mMutable = false;
-
-        synchronized (mWritableHistory) {
-            // Make a copy of battery history to avoid concurrent modification.
-            mHistoryBuffer.appendFrom(mWritableHistory.mHistoryBuffer, 0,
-                    mWritableHistory.mHistoryBuffer.dataSize());
-        }
-    }
-
     @VisibleForTesting
     public BatteryStatsHistory(Parcel historyBuffer, File systemDir,
             int maxHistoryFiles, int maxHistoryBufferSize,
@@ -308,6 +294,9 @@
         mTracer = tracer;
         mClock = clock;
         mWritableHistory = writableHistory;
+        if (mWritableHistory != null) {
+            mMutable = false;
+        }
 
         mHistoryDir = new File(systemDir, HISTORY_DIR);
         mHistoryDir.mkdirs();
@@ -415,7 +404,14 @@
      * in the system directory, so it is not safe while actively writing history.
      */
     public BatteryStatsHistory copy() {
-        return new BatteryStatsHistory(this);
+        synchronized (this) {
+            // Make a copy of battery history to avoid concurrent modification.
+            Parcel historyBufferCopy = Parcel.obtain();
+            historyBufferCopy.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
+
+            return new BatteryStatsHistory(historyBufferCopy, mSystemDir, 0, 0, null, null, null,
+                    this);
+        }
     }
 
     /**
diff --git a/core/java/com/android/internal/os/IBinaryTransparencyService.aidl b/core/java/com/android/internal/os/IBinaryTransparencyService.aidl
index e782aa7..c8340ac 100644
--- a/core/java/com/android/internal/os/IBinaryTransparencyService.aidl
+++ b/core/java/com/android/internal/os/IBinaryTransparencyService.aidl
@@ -28,8 +28,6 @@
 interface IBinaryTransparencyService {
     String getSignedImageInfo();
 
-    List getApexInfo();
-
     void recordMeasurementsForAllPackages();
 
     parcelable ApexInfo {
@@ -60,4 +58,5 @@
     /** Test only */
     List<ApexInfo> collectAllApexInfo(boolean includeTestOnly);
     List<AppInfo> collectAllUpdatedPreloadInfo(in Bundle packagesToSkip);
+    List<AppInfo> collectAllSilentInstalledMbaInfo(in Bundle packagesToSkip);
 }
\ No newline at end of file
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index c6aca44..1875ecf 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -378,8 +378,12 @@
             // window, as we'll be skipping the addView in handleResumeActivity(), and
             // the token will not be updated as for a new window.
             getAttributes().token = preservedWindow.getAttributes().token;
-            mProxyOnBackInvokedDispatcher.setActualDispatcher(
-                    preservedWindow.getOnBackInvokedDispatcher());
+            final ViewRootImpl viewRoot = mDecor.getViewRootImpl();
+            if (viewRoot != null) {
+                // Clear the old callbacks and attach to the new window.
+                viewRoot.getOnBackInvokedDispatcher().clear();
+                onViewRootImplSet(viewRoot);
+            }
         }
         // Even though the device doesn't support picture-in-picture mode,
         // an user can force using it through developer options.
@@ -1938,9 +1942,9 @@
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_DOWN:
             case KeyEvent.KEYCODE_VOLUME_MUTE: {
-                // If we have a session send it the volume command, otherwise
-                // use the suggested stream.
-                if (mMediaController != null) {
+                // If we have a session and no active phone call send it the volume command,
+                // otherwise use the suggested stream.
+                if (mMediaController != null && !isActivePhoneCallKnown()) {
                     getMediaSessionManager().dispatchVolumeKeyEventToSessionAsSystemService(event,
                             mMediaController.getSessionToken());
                 } else {
@@ -1991,6 +1995,18 @@
         return false;
     }
 
+    private boolean isActivePhoneCallKnown() {
+        boolean isActivePhoneCallKnown = false;
+        AudioManager audioManager =
+                (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+        int audioManagerMode = audioManager.getMode();
+        if (audioManagerMode == AudioManager.MODE_IN_CALL
+                || audioManagerMode == AudioManager.MODE_IN_COMMUNICATION) {
+            isActivePhoneCallKnown = true;
+        }
+        return isActivePhoneCallKnown;
+    }
+
     private KeyguardManager getKeyguardManager() {
         if (mKeyguardManager == null) {
             mKeyguardManager = (KeyguardManager) getContext().getSystemService(
diff --git a/core/java/com/android/internal/security/VerityUtils.java b/core/java/com/android/internal/security/VerityUtils.java
index 786941f..74a9d16 100644
--- a/core/java/com/android/internal/security/VerityUtils.java
+++ b/core/java/com/android/internal/security/VerityUtils.java
@@ -81,6 +81,15 @@
         }
     }
 
+    /** Enables fs-verity for an open file without signature. */
+    public static void setUpFsverity(int fd) throws IOException {
+        int errno = enableFsverityForFdNative(fd);
+        if (errno != 0) {
+            throw new IOException("Failed to enable fs-verity on FD(" + fd + "): "
+                    + Os.strerror(errno));
+        }
+    }
+
     /** Returns whether the file has fs-verity enabled. */
     public static boolean hasFsverity(@NonNull String filePath) {
         int retval = statxForFsverityNative(filePath);
@@ -211,6 +220,7 @@
     }
 
     private static native int enableFsverityNative(@NonNull String filePath);
+    private static native int enableFsverityForFdNative(int fd);
     private static native int measureFsverityNative(@NonNull String filePath,
             @NonNull byte[] digest);
     private static native int statxForFsverityNative(@NonNull String filePath);
diff --git a/core/java/com/android/internal/statusbar/AppClipsServiceConnector.java b/core/java/com/android/internal/statusbar/AppClipsServiceConnector.java
new file mode 100644
index 0000000..287b85f
--- /dev/null
+++ b/core/java/com/android/internal/statusbar/AppClipsServiceConnector.java
@@ -0,0 +1,99 @@
+/*
+ * 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.internal.statusbar;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * A helper class to communicate with the App Clips service running in SystemUI.
+ */
+public class AppClipsServiceConnector {
+
+    private static final String TAG = AppClipsServiceConnector.class.getSimpleName();
+
+    private final Context mContext;
+    private final Handler mHandler;
+
+    public AppClipsServiceConnector(Context context) {
+        mContext = context;
+        HandlerThread handlerThread = new HandlerThread(TAG);
+        handlerThread.start();
+        mHandler = handlerThread.getThreadHandler();
+    }
+
+    /**
+     * @return true if the task represented by {@code taskId} can launch App Clips screenshot flow,
+     * false otherwise.
+     */
+    public boolean canLaunchCaptureContentActivityForNote(int taskId) {
+        try {
+            CompletableFuture<Boolean> future = new CompletableFuture<>();
+            connectToServiceAndProcessRequest(taskId, future);
+            return future.get();
+        } catch (Exception e) {
+            Log.d(TAG, "Exception from service\n" + e);
+        }
+
+        return false;
+    }
+
+    private void connectToServiceAndProcessRequest(int taskId, CompletableFuture<Boolean> future) {
+        ServiceConnection serviceConnection = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                try {
+                    future.complete(IAppClipsService.Stub.asInterface(
+                            service).canLaunchCaptureContentActivityForNote(taskId));
+                } catch (Exception e) {
+                    Log.d(TAG, "Exception from service\n" + e);
+                }
+                future.complete(false);
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                if (!future.isDone()) {
+                    future.complete(false);
+                }
+            }
+        };
+
+        final ComponentName serviceComponent = ComponentName.unflattenFromString(
+                mContext.getResources().getString(
+                        com.android.internal.R.string.config_screenshotAppClipsServiceComponent));
+        final Intent serviceIntent = new Intent();
+        serviceIntent.setComponent(serviceComponent);
+
+        boolean bindService = mContext.bindServiceAsUser(serviceIntent, serviceConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, mHandler,
+                mContext.getUser());
+
+        // Complete the future early if service not bound.
+        if (!bindService) {
+            future.complete(false);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/statusbar/IAppClipsService.aidl b/core/java/com/android/internal/statusbar/IAppClipsService.aidl
new file mode 100644
index 0000000..013d0d3
--- /dev/null
+++ b/core/java/com/android/internal/statusbar/IAppClipsService.aidl
@@ -0,0 +1,26 @@
+/**
+ * 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.internal.statusbar;
+
+/**
+ * A service that runs in SystemUI and helps determine if App Clips flow is supported in the
+ * current state of device. This service needs to run in SystemUI in order to communicate with the
+ * instance of app bubbles.
+ */
+interface IAppClipsService {
+    boolean canLaunchCaptureContentActivityForNote(in int taskId);
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 1c85ca2..b529a10 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -214,11 +214,11 @@
      * bar and navigation bar which are temporarily visible to the user.
      *
      * @param displayId the ID of the display to notify.
-     * @param types the internal insets types of the bars are about to show transiently.
+     * @param types the insets types of the bars are about to show transiently.
      * @param isGestureOnSystemBar whether the gesture to show the transient bar was a gesture on
      *        one of the bars itself.
      */
-    void showTransient(int displayId, in int[] types, boolean isGestureOnSystemBar);
+    void showTransient(int displayId, int types, boolean isGestureOnSystemBar);
 
     /**
      * Notifies System UI to abort the transient state of system bars, which prevents the bars being
@@ -226,9 +226,9 @@
      * bars again.
      *
      * @param displayId the ID of the display to notify.
-     * @param types the internal insets types of the bars are about to abort the transient state.
+     * @param types the insets types of the bars are about to abort the transient state.
      */
-    void abortTransient(int displayId, in int[] types);
+    void abortTransient(int displayId, int types);
 
     /**
      * Show a warning that the device is about to go to sleep due to user inactivity.
diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
index 54221ce..4f827cd 100644
--- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
+++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.statusbar;
 
-import android.annotation.NonNull;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -41,15 +40,14 @@
     public final int mBehavior;
     public final int mRequestedVisibleTypes;
     public final String mPackageName;
-    public final int[] mTransientBarTypes;
+    public final int mTransientBarTypes;
     public final LetterboxDetails[] mLetterboxDetails;
 
     public RegisterStatusBarResult(ArrayMap<String, StatusBarIcon> icons, int disabledFlags1,
             int appearance, AppearanceRegion[] appearanceRegions, int imeWindowVis,
             int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2, IBinder imeToken,
             boolean navbarColorManagedByIme, int behavior, int requestedVisibleTypes,
-            String packageName, @NonNull int[] transientBarTypes,
-            LetterboxDetails[] letterboxDetails) {
+            String packageName, int transientBarTypes, LetterboxDetails[] letterboxDetails) {
         mIcons = new ArrayMap<>(icons);
         mDisabledFlags1 = disabledFlags1;
         mAppearance = appearance;
@@ -87,7 +85,7 @@
         dest.writeInt(mBehavior);
         dest.writeInt(mRequestedVisibleTypes);
         dest.writeString(mPackageName);
-        dest.writeIntArray(mTransientBarTypes);
+        dest.writeInt(mTransientBarTypes);
         dest.writeParcelableArray(mLetterboxDetails, flags);
     }
 
@@ -113,7 +111,7 @@
                     final int behavior = source.readInt();
                     final int requestedVisibleTypes = source.readInt();
                     final String packageName = source.readString();
-                    final int[] transientBarTypes = source.createIntArray();
+                    final int transientBarTypes = source.readInt();
                     final LetterboxDetails[] letterboxDetails =
                             source.readParcelableArray(null, LetterboxDetails.class);
                     return new RegisterStatusBarResult(icons, disabledFlags1, appearance,
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index afb526a..2d5bb6c 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -14,7 +14,10 @@
 
 package com.android.internal.util;
 
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Trace.TRACE_TAG_APP;
+import static android.provider.DeviceConfig.NAMESPACE_LATENCY_TRACKER;
 
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL_UNLOCKED;
@@ -24,6 +27,8 @@
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FOLD_TO_AOD;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOAD_SHARE_SHEET;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOCKSCREEN_UNLOCK;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_CAMERA_CHECK;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_SENSOR;
@@ -42,9 +47,12 @@
 import static com.android.internal.util.LatencyTracker.ActionProperties.SAMPLE_INTERVAL_SUFFIX;
 import static com.android.internal.util.LatencyTracker.ActionProperties.TRACE_THRESHOLD_SUFFIX;
 
+import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.app.ActivityThread;
 import android.content.Context;
 import android.os.Build;
 import android.os.ConditionVariable;
@@ -187,6 +195,16 @@
      */
     public static final int ACTION_SHOW_VOICE_INTERACTION = 19;
 
+    /**
+     * Time it takes to request IME shown animation.
+     */
+    public static final int ACTION_REQUEST_IME_SHOWN = 20;
+
+    /**
+     * Time it takes to request IME hidden animation.
+     */
+    public static final int ACTION_REQUEST_IME_HIDDEN = 21;
+
     private static final int[] ACTIONS_ALL = {
         ACTION_EXPAND_PANEL,
         ACTION_TOGGLE_RECENTS,
@@ -208,6 +226,8 @@
         ACTION_SHOW_SELECTION_TOOLBAR,
         ACTION_FOLD_TO_AOD,
         ACTION_SHOW_VOICE_INTERACTION,
+        ACTION_REQUEST_IME_SHOWN,
+        ACTION_REQUEST_IME_HIDDEN,
     };
 
     /** @hide */
@@ -232,6 +252,8 @@
         ACTION_SHOW_SELECTION_TOOLBAR,
         ACTION_FOLD_TO_AOD,
         ACTION_SHOW_VOICE_INTERACTION,
+        ACTION_REQUEST_IME_SHOWN,
+        ACTION_REQUEST_IME_HIDDEN,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Action {
@@ -259,6 +281,8 @@
             UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_SELECTION_TOOLBAR,
             UIACTION_LATENCY_REPORTED__ACTION__ACTION_FOLD_TO_AOD,
             UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION,
+            UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN,
+            UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN,
     };
 
     private static LatencyTracker sLatencyTracker;
@@ -284,15 +308,30 @@
         return sLatencyTracker;
     }
 
+    @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
     @VisibleForTesting
     public LatencyTracker() {
         mEnabled = DEFAULT_ENABLED;
 
-        // Post initialization to the background in case we're running on the main thread.
-        BackgroundThread.getHandler().post(() -> this.updateProperties(
-                DeviceConfig.getProperties(DeviceConfig.NAMESPACE_LATENCY_TRACKER)));
-        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_LATENCY_TRACKER,
-                BackgroundThread.getExecutor(), this::updateProperties);
+        final Context context = ActivityThread.currentApplication();
+        if (context != null
+                && context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) == PERMISSION_GRANTED) {
+            // Post initialization to the background in case we're running on the main thread.
+            BackgroundThread.getHandler().post(() -> this.updateProperties(
+                    DeviceConfig.getProperties(NAMESPACE_LATENCY_TRACKER)));
+            DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_LATENCY_TRACKER,
+                    BackgroundThread.getExecutor(), this::updateProperties);
+        } else {
+            if (DEBUG) {
+                if (context == null) {
+                    Log.d(TAG, "No application for " + ActivityThread.currentActivityThread());
+                } else {
+                    Log.d(TAG, "Initialized the LatencyTracker."
+                            + " (No READ_DEVICE_CONFIG permission to change configs)"
+                            + " enabled=" + mEnabled + ", package=" + context.getPackageName());
+                }
+            }
+        }
     }
 
     private void updateProperties(DeviceConfig.Properties properties) {
@@ -368,6 +407,10 @@
                 return "ACTION_FOLD_TO_AOD";
             case UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION:
                 return "ACTION_SHOW_VOICE_INTERACTION";
+            case UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN:
+                return "ACTION_REQUEST_IME_SHOWN";
+            case UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN:
+                return "ACTION_REQUEST_IME_HIDDEN";
             default:
                 throw new IllegalArgumentException("Invalid action");
         }
diff --git a/core/java/com/android/internal/util/ScreenshotRequest.java b/core/java/com/android/internal/util/ScreenshotRequest.java
index 1902f80..c8b7def 100644
--- a/core/java/com/android/internal/util/ScreenshotRequest.java
+++ b/core/java/com/android/internal/util/ScreenshotRequest.java
@@ -173,6 +173,9 @@
         public Builder(
                 @WindowManager.ScreenshotType int type,
                 @WindowManager.ScreenshotSource int source) {
+            if (type != TAKE_SCREENSHOT_FULLSCREEN && type != TAKE_SCREENSHOT_PROVIDED_IMAGE) {
+                throw new IllegalArgumentException("Invalid screenshot type requested!");
+            }
             mType = type;
             mSource = source;
         }
diff --git a/core/java/com/android/internal/util/TraceBuffer.java b/core/java/com/android/internal/util/TraceBuffer.java
index fe8a59e..bfcd65d 100644
--- a/core/java/com/android/internal/util/TraceBuffer.java
+++ b/core/java/com/android/internal/util/TraceBuffer.java
@@ -193,7 +193,7 @@
     }
 
     /**
-     * Removes all elements form the buffer
+     * Removes all elements from the buffer
      */
     public void resetBuffer() {
         synchronized (mBufferLock) {
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index e56c381..5c3759f 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -1,10 +1,7 @@
 package com.android.internal.widget;
 
-import static android.provider.DeviceConfig.NAMESPACE_AUTO_PIN_CONFIRMATION;
-
 import android.annotation.NonNull;
 import android.os.AsyncTask;
-import android.provider.DeviceConfig;
 
 import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
 
@@ -120,8 +117,7 @@
             @Override
             protected void onPostExecute(Boolean result) {
                 callback.onChecked(result, mThrottleTimeout);
-                if (DeviceConfig.getBoolean(NAMESPACE_AUTO_PIN_CONFIRMATION,
-                        "enable_auto_pin_confirmation", false)) {
+                if (LockPatternUtils.isAutoPinConfirmFeatureAvailable()) {
                     utils.setPinLength(userId, credentialCopy.size());
                 }
                 credentialCopy.zeroize();
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2f51479..4d820ac 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -681,7 +681,7 @@
      * @return true, if deviceConfig flag is set to true or the flag is not propagated and
      * defaultValue is true.
      */
-    public boolean isAutoPinConfirmFeatureAvailable() {
+    public static boolean isAutoPinConfirmFeatureAvailable() {
         return DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_AUTO_PIN_CONFIRMATION,
                 FLAG_ENABLE_AUTO_PIN_CONFIRMATION,
diff --git a/core/java/com/android/internal/widget/RecyclerView.java b/core/java/com/android/internal/widget/RecyclerView.java
index e27557a..4a74d5f 100644
--- a/core/java/com/android/internal/widget/RecyclerView.java
+++ b/core/java/com/android/internal/widget/RecyclerView.java
@@ -10087,7 +10087,7 @@
         static final int FLAG_IGNORE = 1 << 7;
 
         /**
-         * When the View is detached form the parent, we set this flag so that we can take correct
+         * When the View is detached from the parent, we set this flag so that we can take correct
          * action when we need to remove it or add it back.
          */
         static final int FLAG_TMP_DETACHED = 1 << 8;
diff --git a/core/java/com/android/server/backup/ShortcutBackupHelper.java b/core/java/com/android/server/backup/ShortcutBackupHelper.java
index 0b3f2ae..3c4b622 100644
--- a/core/java/com/android/server/backup/ShortcutBackupHelper.java
+++ b/core/java/com/android/server/backup/ShortcutBackupHelper.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.content.pm.IShortcutService;
 import android.os.ServiceManager;
-import android.os.UserHandle;
 import android.util.Slog;
 
 public class ShortcutBackupHelper extends BlobBackupHelper {
@@ -28,8 +27,11 @@
 
     private static final String KEY_USER_FILE = "shortcutuser.xml";
 
-    public ShortcutBackupHelper() {
+    private final int mUserId;
+
+    public ShortcutBackupHelper(int userId) {
         super(BLOB_VERSION, KEY_USER_FILE);
+        mUserId = userId;
     }
 
     private IShortcutService getShortcutService() {
@@ -42,7 +44,7 @@
         switch (key) {
             case KEY_USER_FILE:
                 try {
-                    return getShortcutService().getBackupPayload(UserHandle.USER_SYSTEM);
+                    return getShortcutService().getBackupPayload(mUserId);
                 } catch (Exception e) {
                     Slog.wtf(TAG, "Backup failed", e);
                 }
@@ -58,7 +60,7 @@
         switch (key) {
             case KEY_USER_FILE:
                 try {
-                    getShortcutService().applyRestore(payload, UserHandle.USER_SYSTEM);
+                    getShortcutService().applyRestore(payload, mUserId);
                 } catch (Exception e) {
                     Slog.wtf(TAG, "Restore failed", e);
                 }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 82f414b..b79c540 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -40,6 +40,12 @@
 
     cppflags: ["-Wno-conversion-null"],
 
+    product_variables: {
+        eng: {
+            cflags: ["-DNO_RESET_STACK_PROTECTOR"],
+        },
+    },
+
     cpp_std: "gnu++20",
 
     srcs: [
diff --git a/core/jni/LayoutlibLoader.cpp b/core/jni/LayoutlibLoader.cpp
index d7cbf74..200ddef 100644
--- a/core/jni/LayoutlibLoader.cpp
+++ b/core/jni/LayoutlibLoader.cpp
@@ -27,6 +27,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "android_view_InputDevice.h"
 #include "core_jni_helpers.h"
 #include "jni.h"
 #ifdef _WIN32
@@ -100,6 +101,7 @@
 extern int register_android_util_jar_StrictJarFile(JNIEnv* env);
 extern int register_android_view_KeyCharacterMap(JNIEnv* env);
 extern int register_android_view_KeyEvent(JNIEnv* env);
+extern int register_android_view_InputDevice(JNIEnv* env);
 extern int register_android_view_MotionEvent(JNIEnv* env);
 extern int register_android_view_ThreadedRenderer(JNIEnv* env);
 extern int register_android_graphics_HardwareBufferRenderer(JNIEnv* env);
@@ -142,6 +144,7 @@
         {"android.util.jar.StrictJarFile", REG_JNI(register_android_util_jar_StrictJarFile)},
         {"android.view.KeyCharacterMap", REG_JNI(register_android_view_KeyCharacterMap)},
         {"android.view.KeyEvent", REG_JNI(register_android_view_KeyEvent)},
+        {"android.view.InputDevice", REG_JNI(register_android_view_InputDevice)},
         {"android.view.MotionEvent", REG_JNI(register_android_view_MotionEvent)},
         {"android.view.VelocityTracker", REG_JNI(register_android_view_VelocityTracker)},
         {"com.android.internal.util.VirtualRefBasePtr",
@@ -320,6 +323,41 @@
     return true;
 }
 
+// Creates an array of InputDevice from key character map files
+static void init_keyboard(JNIEnv* env, const vector<string>& keyboardPaths) {
+    jclass inputDevice = FindClassOrDie(env, "android/view/InputDevice");
+    jobjectArray inputDevicesArray =
+            env->NewObjectArray(keyboardPaths.size(), inputDevice, nullptr);
+    int keyboardId = 1;
+
+    for (const string& path : keyboardPaths) {
+        base::Result<std::shared_ptr<KeyCharacterMap>> charMap =
+                KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE);
+
+        InputDeviceInfo info = InputDeviceInfo();
+        info.initialize(keyboardId, 0, 0, InputDeviceIdentifier(),
+                        "keyboard " + std::to_string(keyboardId), true, false, 0);
+        info.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+        info.setKeyCharacterMap(*charMap);
+
+        jobject inputDeviceObj = android_view_InputDevice_create(env, info);
+        if (inputDeviceObj) {
+            env->SetObjectArrayElement(inputDevicesArray, keyboardId - 1, inputDeviceObj);
+            env->DeleteLocalRef(inputDeviceObj);
+        }
+        keyboardId++;
+    }
+
+    if (bridge == nullptr) {
+        bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
+        bridge = MakeGlobalRefOrDie(env, bridge);
+    }
+    jmethodID setInputManager = GetStaticMethodIDOrDie(env, bridge, "setInputManager",
+                                                       "([Landroid/view/InputDevice;)V");
+    env->CallStaticVoidMethod(bridge, setInputManager, inputDevicesArray);
+    env->DeleteLocalRef(inputDevicesArray);
+}
+
 } // namespace android
 
 using namespace android;
@@ -411,6 +449,13 @@
     // Use English locale for number format to ensure correct parsing of floats when using strtof
     setlocale(LC_NUMERIC, "en_US.UTF-8");
 
+    auto keyboardPathsString =
+            (jstring)env->CallStaticObjectMethod(system, getPropertyMethod,
+                                                 env->NewStringUTF("keyboard_paths"),
+                                                 env->NewStringUTF(""));
+    vector<string> keyboardPaths = parseCsv(env, keyboardPathsString);
+    init_keyboard(env, keyboardPaths);
+
     return JNI_VERSION_1_6;
 }
 
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index a8d8a43..b09a9c3 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -65,7 +65,7 @@
 public:
     NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
                                const sp<MessageQueue>& messageQueue, jint vsyncSource,
-                               jint eventRegistration);
+                               jint eventRegistration, jlong layerHandle);
 
     void dispose();
 
@@ -88,11 +88,15 @@
 
 NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
                                                        const sp<MessageQueue>& messageQueue,
-                                                       jint vsyncSource, jint eventRegistration)
+                                                       jint vsyncSource, jint eventRegistration,
+                                                       jlong layerHandle)
       : DisplayEventDispatcher(messageQueue->getLooper(),
                                static_cast<gui::ISurfaceComposer::VsyncSource>(vsyncSource),
                                static_cast<gui::ISurfaceComposer::EventRegistration>(
-                                       eventRegistration)),
+                                       eventRegistration),
+                               layerHandle != 0 ? sp<IBinder>::fromExisting(
+                                                          reinterpret_cast<IBinder*>(layerHandle))
+                                                : nullptr),
         mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
         mMessageQueue(messageQueue) {
     ALOGV("receiver %p ~ Initializing display event receiver.", this);
@@ -214,7 +218,7 @@
 }
 
 static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj,
-                        jint vsyncSource, jint eventRegistration) {
+                        jint vsyncSource, jint eventRegistration, jlong layerHandle) {
     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
     if (messageQueue == NULL) {
         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
@@ -223,7 +227,7 @@
 
     sp<NativeDisplayEventReceiver> receiver =
             new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource,
-                                           eventRegistration);
+                                           eventRegistration, layerHandle);
     status_t status = receiver->initialize();
     if (status) {
         String8 message;
@@ -236,13 +240,15 @@
     return reinterpret_cast<jlong>(receiver.get());
 }
 
-static void nativeDispose(JNIEnv* env, jclass clazz, jlong receiverPtr) {
-    NativeDisplayEventReceiver* receiver =
-            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
+static void release(NativeDisplayEventReceiver* receiver) {
     receiver->dispose();
     receiver->decStrong(gDisplayEventReceiverClassInfo.clazz); // drop reference held by the object
 }
 
+static jlong nativeGetDisplayEventReceiverFinalizer(JNIEnv*, jclass) {
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&release));
+}
+
 static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
     sp<NativeDisplayEventReceiver> receiver =
             reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
@@ -268,9 +274,10 @@
 
 static const JNINativeMethod gMethods[] = {
         /* name, signature, funcPtr */
-        {"nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;II)J",
+        {"nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;IIJ)J",
          (void*)nativeInit},
-        {"nativeDispose", "(J)V", (void*)nativeDispose},
+        {"nativeGetDisplayEventReceiverFinalizer", "()J",
+         (void*)nativeGetDisplayEventReceiverFinalizer},
         // @FastNative
         {"nativeScheduleVsync", "(J)V", (void*)nativeScheduleVsync},
         {"nativeGetLatestVsyncEventData", "(J)Landroid/view/DisplayEventReceiver$VsyncEventData;",
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 6a92581..5965e17 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -2302,7 +2302,7 @@
       setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
     }
 
-#if defined(__BIONIC__)
+#if defined(__BIONIC__) && !defined(NO_RESET_STACK_PROTECTOR)
     // Reset the stack guard for the new process.
     android_reset_stack_guards();
 #endif
diff --git a/core/jni/com_android_internal_security_VerityUtils.cpp b/core/jni/com_android_internal_security_VerityUtils.cpp
index 3e5689b..4a9e2d4 100644
--- a/core/jni/com_android_internal_security_VerityUtils.cpp
+++ b/core/jni/com_android_internal_security_VerityUtils.cpp
@@ -38,13 +38,8 @@
 
 namespace {
 
-int enableFsverity(JNIEnv *env, jobject /* clazz */, jstring filePath) {
-    ScopedUtfChars path(env, filePath);
-    if (path.c_str() == nullptr) {
-        return EINVAL;
-    }
-    ::android::base::unique_fd rfd(open(path.c_str(), O_RDONLY | O_CLOEXEC));
-    if (rfd.get() < 0) {
+int enableFsverityForFd(JNIEnv *env, jobject clazz, jint fd) {
+    if (fd < 0) {
         return errno;
     }
 
@@ -55,12 +50,21 @@
     arg.salt_size = 0;
     arg.salt_ptr = reinterpret_cast<uintptr_t>(nullptr);
 
-    if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, &arg) < 0) {
+    if (ioctl(fd, FS_IOC_ENABLE_VERITY, &arg) < 0) {
         return errno;
     }
     return 0;
 }
 
+int enableFsverity(JNIEnv *env, jobject clazz, jstring filePath) {
+    ScopedUtfChars path(env, filePath);
+    if (path.c_str() == nullptr) {
+        return EINVAL;
+    }
+    ::android::base::unique_fd rfd(open(path.c_str(), O_RDONLY | O_CLOEXEC));
+    return enableFsverityForFd(env, clazz, rfd.get());
+}
+
 // Returns whether the file has fs-verity enabled.
 // 0 if it is not present, 1 if is present, and -errno if there was an error.
 int statxForFsverity(JNIEnv *env, jobject /* clazz */, jstring filePath) {
@@ -126,6 +130,7 @@
 }
 const JNINativeMethod sMethods[] = {
         {"enableFsverityNative", "(Ljava/lang/String;)I", (void *)enableFsverity},
+        {"enableFsverityForFdNative", "(I)I", (void *)enableFsverityForFd},
         {"statxForFsverityNative", "(Ljava/lang/String;)I", (void *)statxForFsverity},
         {"measureFsverityNative", "(Ljava/lang/String;[B)I", (void *)measureFsverity},
 };
diff --git a/core/proto/android/os/system_properties.proto b/core/proto/android/os/system_properties.proto
index 4f3eeb0..84c82e0 100644
--- a/core/proto/android/os/system_properties.proto
+++ b/core/proto/android/os/system_properties.proto
@@ -514,7 +514,10 @@
 
         optional string gfx_driver_whitelist_0 = 45;
 
-        // Next Tag: 46
+        optional bool  egl_blobcache_multifile = 46;
+        optional int32 egl_blobcache_multifile_limit = 47;
+
+        // Next Tag: 48
     }
     optional Ro ro = 21;
 
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index fd0d9c5..128de8b 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -88,6 +88,9 @@
 
     optional SettingProto assisted_gps_enabled = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto audio_safe_volume_state = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto audio_safe_csd_current_value = 157 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto audio_safe_csd_next_warning = 158 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto audio_safe_csd_dose_records = 159 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
     reserved 17; // Used to be autofill_compat_mode_allowed_packages
 
@@ -1087,5 +1090,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 157;
+    // Next tag = 160;
 }
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index ea0ec79..68267db 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -89,6 +89,7 @@
         // Setting for accessibility magnification for following typing.
         optional SettingProto accessibility_magnification_follow_typing_enabled = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto contrast_level = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto accessibility_magnification_always_on_enabled = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Accessibility accessibility = 2;
 
diff --git a/core/proto/android/server/windowmanagertransitiontrace.proto b/core/proto/android/server/windowmanagertransitiontrace.proto
index 4161f65..ab87384 100644
--- a/core/proto/android/server/windowmanagertransitiontrace.proto
+++ b/core/proto/android/server/windowmanagertransitiontrace.proto
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-syntax = "proto3";
+syntax = "proto2";
 
 package com.android.server.wm.shell;
 
@@ -36,13 +36,30 @@
     MAGIC_NUMBER_H = 0x45434152;  /* RACE (little-endian ASCII) */
   }
 
-  fixed64 magic_number = 1;  /* Must be the first field, set to value in MagicNumber */
-  int64 timestamp = 2; /* The timestamp of when the trace was started. */
-  repeated Transition transition = 3;
+  required fixed64 magic_number = 1;  /* Must be the first field, set to value in MagicNumber */
+  repeated Transition sent_transitions = 2;
+
+  // Additional debugging info only collected and dumped when explicitly requested to trace
+  repeated TransitionState transition_states = 3;
+  repeated TransitionInfo transition_info = 4;
 }
 
 message Transition {
+  optional int32 id = 1; // Not dumped in always on tracing
+  required uint64 start_transaction_id = 2;
+  required uint64 finish_transaction_id = 3;
+  required int64 create_time_ns = 4;
+  required int64 send_time_ns = 5;
+  repeated Target targets = 6;
+}
 
+message Target {
+  required int32 mode = 1;
+  required int32 layer_id = 2;
+  optional int32 window_id = 3;  // Not dumped in always on tracing
+}
+
+message TransitionState {
   enum State {
     COLLECTING = 0;
     PENDING = -1;
@@ -52,19 +69,29 @@
     FINISHED = 4;
   }
 
-  int32 id = 1;
-  int32 transition_type = 2;
-  int64 timestamp = 3;
-  State state = 5;
-  int32 flags = 6;
-  repeated ChangeInfo change = 7;
-  uint64 start_transaction_id = 8;
-  uint64 finish_transaction_id = 9;
+  required int64 time_ns = 1;
+  required int32 transition_id = 2;
+  required int32 transition_type = 3;
+  required State state = 4;
+  required int32 flags = 5;
+  repeated ChangeInfo change = 6;
+  repeated com.android.server.wm.IdentifierProto participants = 7;
 }
 
 message ChangeInfo {
-  com.android.server.wm.IdentifierProto window_identifier = 1;
-  int32 transit_mode = 2;
-  bool has_changed = 3;
-  int32 change_flags = 4;
+  required com.android.server.wm.IdentifierProto window_identifier = 1;
+  required int32 transit_mode = 2;
+  required bool has_changed = 3;
+  required int32 change_flags = 4;
+  required int32 windowing_mode = 5;
+}
+
+message TransitionInfo {
+  required int32 transition_id = 1;
+  repeated TransitionInfoChange change = 2;
+}
+
+message TransitionInfoChange {
+  required int32 layer_id = 1;
+  required int32 mode = 2;
 }
diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto
index 607fd10..8889320 100644
--- a/core/proto/android/service/usb.proto
+++ b/core/proto/android/service/usb.proto
@@ -45,7 +45,7 @@
 message UsbHandlerProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    /* Same as android.hardware.usb.gadget.V1_0.GadgetFunction.* */
+    /* Same as android.hardware.usb.gadget.GadgetFunction.* */
     enum Function {
         FUNCTION_ADB = 1;
         FUNCTION_ACCESSORY = 2;
@@ -54,6 +54,7 @@
         FUNCTION_PTP = 16;
         FUNCTION_RNDIS = 32;
         FUNCTION_AUDIO_SOURCE = 64;
+        FUNCTION_UVC = 128;
     }
 
     repeated Function current_functions = 1;
@@ -284,7 +285,8 @@
 
     optional int32 cards_parser = 1;
     repeated UsbAlsaDeviceProto alsa_devices = 2;
-    repeated UsbMidiDeviceProto midi_devices = 3;
+    reserved 3; // previously midi_devices, now unused
+    repeated UsbAlsaMidiDeviceProto alsa_midi_devices = 4;
 }
 
 message UsbAlsaDeviceProto {
@@ -299,7 +301,7 @@
     optional string address = 6;
 }
 
-message UsbMidiDeviceProto {
+message UsbAlsaMidiDeviceProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional int32 card = 1;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 81c7fba..0b6b0a1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1751,7 +1751,7 @@
     <!-- Allows an application to access wrist temperature data from the watch sensors.
          If you're requesting this permission, you must also request
          {@link #BODY_SENSORS_WRIST_TEMPERATURE}. Requesting this permission by itself doesn't
-         give you heart rate body sensors access.
+         give you wrist temperature body sensors access.
          <p class="note"><strong>Note: </strong> This permission is for Wear OS only.
          <p>Protection level: dangerous
 
@@ -2579,6 +2579,14 @@
     <!-- ==================================================== -->
     <eat-comment />
 
+    <!-- Allows an application to capture screen content to perform a screenshot using the intent
+         action {@link android.content.Intent#ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE}.
+         <p>Protection level: internal|role
+         <p>Intended for use by ROLE_NOTES only.
+    -->
+    <permission android:name="android.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE"
+        android:protectionLevel="internal|role" />
+
     <!-- Allows an application to get notified when a screen capture of its windows is attempted.
          <p>Protection level: normal
     -->
@@ -4534,6 +4542,15 @@
     <permission android:name="android.permission.BIND_AUTOFILL_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by a
+         {@link android.service.assist.classification.FieldClassificationService},
+         to ensure that only the system can bind to it.
+         @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.BIND_FIELD_CLASSIFICATION_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- Must be required by a CredentialProviderService to ensure that only the
          system can bind to it.
          <p>Protection level: signature
@@ -6657,7 +6674,7 @@
     <permission android:name="android.permission.USE_FULL_SCREEN_INTENT"
                 android:label="@string/permlab_fullScreenIntent"
                 android:description="@string/permdesc_fullScreenIntent"
-                android:protectionLevel="normal" />
+                android:protectionLevel="normal|appop" />
 
     <!-- @SystemApi Allows requesting the framework broadcast the
          {@link Intent#ACTION_DEVICE_CUSTOMIZATION_READY} intent.
@@ -6921,8 +6938,8 @@
 
     <!-- Allows an assistive application to perform actions on behalf of users inside of
          applications.
-         <p>For now, this permission is only granted to system applications fulfilling the
-         ASSISTANT role.
+         <p>For now, this permission is only granted to the Assistant application selected by
+         the user.
          <p>Protection level: internal|role
     -->
     <permission android:name="android.permission.EXECUTE_APP_ACTION"
diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml
index cb4462c..53a6836 100644
--- a/core/res/res/drawable-nodpi/stat_sys_adb.xml
+++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2022 The Android Open Source Project
+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.
@@ -13,78 +13,42 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-<vector android:width="24dp" android:height="24dp"
-        android:viewportWidth="24" android:viewportHeight="24"
-        xmlns:android="http://schemas.android.com/apk/res/android">
-  <path android:pathData="
-        M22.45 11.94
-        l-.58-.21
-        a1.19 1.19 0 0 1-.26-2.12
-        l.51-.34
-        a1.2 1.2 0 0 0-.83-2.19
-        l-.61.08
-        a1.2 1.2 0 0 1-1.21-1.76
-        l.29-.54
-        A1.2 1.2 0 0 0 18 3.31
-        l-.5.36
-        a1.21 1.21 0 0 1-1.9-1
-        v-.61
-        a1.2 1.2 0 0 0-2.27-.56
-        l-.26.5
-        a1.2 1.2 0 0 1-2.14 0
-        l-.28-.54
-        a1.2 1.2 0 0 0-2.27.56
-        v.61
-        a1.21 1.21 0 0 1-1.9 1
-        L6 3.31
-        a1.2 1.2 0 0 0-1.76 1.55
-        l.29.54
-        a1.2 1.2 0 0 1-1.21 1.76
-        l-.61-.08
-        a1.2 1.2 0 0 0-.83 2.19
-        l.51.34
-        a1.19 1.19 0 0 1-.26 2.12
-        l-.58.21
-        a1.21 1.21 0 0 0 .29 2.33
-        l.61.06
-        a1.2 1.2 0 0 1 .76 2
-        l-.42.46
-        a1.2 1.2 0 0 0 1.33 1.92
-        l.57-.22
-        a1.21 1.21 0 0 1 1.61 1.42
-        l-.16.59
-        a1.2 1.2 0 0 0 2.07 1.09
-        l.4-.47
-        a1.2 1.2 0 0 1 2.08.51
-        l.14.6
-        a1.2 1.2 0 0 0 2.34 0
-        l.14-.6
-        a1.2 1.2 0 0 1 2.08-.51
-        l.4.47
-        a1.2 1.2 0 0 0 2.07-1.09
-        l-.16-.59
-        a1.21 1.21 0 0 1 1.61-1.42
-        l.57.22
-        a1.2 1.2 0 0 0 1.33-1.92
-        l-.42-.46
-        a1.2 1.2 0 0 1 .76-2
-        l.61-.06
-        a1.21 1.21 0 0 0 .29-2.33
-        z
-        M12 19
-        a7 7 0 1 1 7-7 7 7 0 0 1-7 7
-        z
-        "
-        android:fillColor="#000000" />
-  <path android:pathData="
-        M9 7.75
-        a.75.75 0 1 0 0 1.5.75.75 0 1 0 0-1.5
-        z
-        M15 7.75
-        a.75.75 0 1 0 0 1.5.75.75 0 1 0 0-1.5
-        z
-        "
-        android:fillColor="#000000" />
-  <path android:strokeColor="#000000" android:strokeMiterLimit="10" android:strokeWidth="2"
-        android:pathData="M4 12h16M12 12v8" />
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:name="ring"
+        android:pathData="M 12 21 C 16.971 21 21 16.971 21 12 C 21 7.029 16.971 3 12 3 C 7.029 3 3 7.029 3 12 C 3 16.971 7.029 21 12 21 Z"
+        android:fillColor="#00000000"
+        android:strokeColor="#ffffff"
+        android:strokeWidth="2"/>
+    <group android:name="group">
+        <clip-path
+            android:pathData="M 20.5 12 C 20.5 16.694 16.694 20.5 12 20.5 C 7.306 20.5 3.5 16.694 3.5 12 C 3.5 7.306 7.306 3.5 12 3.5 C 16.694 3.5 20.5 7.306 20.5 12 Z"/>
+        <path
+            android:pathData="M 14.812 9.023 C 13.014 9.707 11.027 9.707 9.229 9.023 L 8.265 10.693 C 8.06 11.048 7.605 11.17 7.25 10.964 C 6.895 10.759 6.773 10.305 6.978 9.949 L 7.899 8.355 C 5.988 7.137 4.702 5.084 4.502 2.695 L 4.456 2.153 L 19.584 2.153 L 19.539 2.695 C 19.339 5.084 18.052 7.137 16.142 8.355 L 17.067 9.958 C 17.259 10.307 17.142 10.746 16.801 10.952 C 16.45 11.165 15.993 11.052 15.781 10.701 L 15.775 10.693 L 14.812 9.023 Z"
+            android:fillColor="#ffffff"/>
+        <group android:name="stars">
+            <path android:pathData="
+                M 7,14  h1v1h-1z
+                M 13,15 h1v1h-1z
+                M 14,11 h1v1h-1z
+
+                M 11,17 h0.5v0.5h-0.5z
+                M 10,15 h0.5v0.5h-0.5z
+                M 13,18 h0.5v0.5h-0.5z
+                M 17,15 h0.5v0.5h-0.5z
+                M 15,14 h0.5v0.5h-0.5z
+                M 18,12 h0.5v0.5h-0.5z
+                M 5,13  h0.5v0.5h-0.5z
+                M 5,10  h0.5v0.5h-0.5z
+                M 9,11  h0.5v0.5h-0.5z
+                M 8,17  h0.5v0.5h-0.5z
+                M 12,12 h0.5v0.5h-0.5z
+            " android:fillColor="#ffffff"/>
+        </group>
+    </group>
 </vector>
diff --git a/core/res/res/drawable/ic_clone_badge.xml b/core/res/res/drawable/ic_clone_badge.xml
new file mode 100644
index 0000000..1682425
--- /dev/null
+++ b/core/res/res/drawable/ic_clone_badge.xml
@@ -0,0 +1,29 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path
+        android:pathData="M22,9.5C22,13.642 18.642,17 14.5,17C10.358,17 7,13.642 7,9.5C7,5.358 10.358,2 14.5,2C18.642,2 22,5.358 22,9.5Z"
+        android:fillColor="@android:color/system_neutral2_800"/>
+    <path
+        android:pathData="M9.5,20.333C12.722,20.333 15.333,17.722 15.333,14.5C15.333,11.278 12.722,8.667 9.5,8.667C6.278,8.667 3.667,11.278 3.667,14.5C3.667,17.722 6.278,20.333 9.5,20.333ZM9.5,22C13.642,22 17,18.642 17,14.5C17,10.358 13.642,7 9.5,7C5.358,7 2,10.358 2,14.5C2,18.642 5.358,22 9.5,22Z"
+        android:fillColor="@android:color/system_neutral2_800"
+        android:fillType="evenOdd"/>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_clone_icon_badge.xml b/core/res/res/drawable/ic_clone_icon_badge.xml
new file mode 100644
index 0000000..e4eabc8
--- /dev/null
+++ b/core/res/res/drawable/ic_clone_icon_badge.xml
@@ -0,0 +1,35 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="64dp"
+        android:height="64dp"
+        android:viewportWidth="64"
+        android:viewportHeight="64">
+<group
+    android:scaleX=".66"
+    android:scaleY=".66"
+    android:translateX="42"
+    android:translateY="42">
+    <path
+        android:pathData="M22,9.5C22,13.642 18.642,17 14.5,17C10.358,17 7,13.642 7,9.5C7,5.358 10.358,2 14.5,2C18.642,2 22,5.358 22,9.5Z"
+        android:fillColor="@android:color/system_neutral2_800"/>
+    <path
+        android:pathData="M9.5,20.333C12.722,20.333 15.333,17.722 15.333,14.5C15.333,11.278 12.722,8.667 9.5,8.667C6.278,8.667 3.667,11.278 3.667,14.5C3.667,17.722 6.278,20.333 9.5,20.333ZM9.5,22C13.642,22 17,18.642 17,14.5C17,10.358 13.642,7 9.5,7C5.358,7 2,10.358 2,14.5C2,18.642 5.358,22 9.5,22Z"
+        android:fillColor="@android:color/system_neutral2_800"
+        android:fillType="evenOdd"/>
+</group>
+</vector>
diff --git a/core/res/res/drawable/ic_dual_screen.xml b/core/res/res/drawable/ic_dual_screen.xml
new file mode 100644
index 0000000..26d97b7
--- /dev/null
+++ b/core/res/res/drawable/ic_dual_screen.xml
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M11,35.9 L25,41.5Q25,41.5 25,41.5Q25,41.5 25,41.5V12.1Q25,12.1 25,12.1Q25,12.1 25,12.1L11,6.5V35.9Q11,35.9 11,35.9Q11,35.9 11,35.9ZM9.9,38.65Q9.05,38.3 8.525,37.575Q8,36.85 8,35.9V7Q8,5.75 8.875,4.875Q9.75,4 11,4L26,9.3Q26.9,9.6 27.45,10.375Q28,11.15 28,12.1V41.5Q28,43.1 26.675,43.975Q25.35,44.85 23.9,44.25ZM25,38V35H37Q37,35 37,35Q37,35 37,35V7Q37,7 37,7Q37,7 37,7H11V4H37Q38.25,4 39.125,4.875Q40,5.75 40,7V35Q40,36.25 39.125,37.125Q38.25,38 37,38ZM11,35.9Q11,35.9 11,35.9Q11,35.9 11,35.9V6.5Q11,6.5 11,6.5Q11,6.5 11,6.5V35.9Q11,35.9 11,35.9Q11,35.9 11,35.9Z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_thermostat.xml b/core/res/res/drawable/ic_thermostat.xml
new file mode 100644
index 0000000..23e5792
--- /dev/null
+++ b/core/res/res/drawable/ic_thermostat.xml
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M26.15,19V16H37.65V19ZM26.15,13V10H42.15V13ZM14.8,41.95Q11.05,41.95 8.375,39.275Q5.7,36.6 5.7,32.85Q5.7,30.45 6.9,28.325Q8.1,26.2 10.2,24.9V10.6Q10.2,8.7 11.55,7.35Q12.9,6 14.8,6Q16.7,6 18.05,7.35Q19.4,8.7 19.4,10.6V24.9Q21.5,26.2 22.7,28.325Q23.9,30.45 23.9,32.85Q23.9,36.6 21.225,39.275Q18.55,41.95 14.8,41.95ZM8.7,32.85H20.9Q20.9,31.1 19.95,29.4Q19,27.7 17.4,27L16.4,26.55V10.6Q16.4,9.9 15.95,9.45Q15.5,9 14.8,9Q14.1,9 13.65,9.45Q13.2,9.9 13.2,10.6V26.55L12.2,27Q10.45,27.8 9.575,29.45Q8.7,31.1 8.7,32.85Z"/>
+</vector>
diff --git a/core/res/res/values-af-watch/strings.xml b/core/res/res/values-af-watch/strings.xml
index c6c87e2..21ba346 100644
--- a/core/res/res/values-af-watch/strings.xml
+++ b/core/res/res/values-af-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Program <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensors"</string>
 </resources>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 76a4da0..f1cd6b2 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Gee die program toegang tot liggaamsensordata, soos polsslag, temperatuur en bloedsuurstofpersentasie, terwyl die program gebruik word."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Kry toegang tot liggaamsensordata, soos polsslag, terwyl program op agtergrond is"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Gee die program toegang tot liggaamsensordata, soos polsslag, temperatuur en bloedsuurstofpersentasie, terwyl dit op die agtergrond is."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Het toegang tot liggaamsensordata oor polstermperatuur terwyl die app gebruik word."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Gee die app toegang tot liggaamsensordata oor polstermperatuur terwyl die app gebruik word."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Het toegang tot liggaamsensordata oor polstermperatuur terwyl die app op die agtergrond is."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Gee die app toegang tot liggaamsensordata oor polstermperatuur terwyl die app op die agtergrond is."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Lees kalendergebeurtenisse en -besonderhede"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Hierdie program kan alle kalendergebeurtenisse lees wat op jou tablet geberg is of jou kalenderdata stoor."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Hierdie program kan alle kalendergeleenthede wat op jou Android TV-toestel geberg is, lees of jou kalenderdata stoor."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android begin tans …"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet begin tans …"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Toestel begin tans …"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimeer tans berging."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Voltooi tans stelselopdatering …"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> gradeer tans op …"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimeer program <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Berei tans <xliff:g id="APPNAME">%1$s</xliff:g> voor."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Begin programme."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Voltooi herlaai."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Bekyk tans volskerm"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Swiep van bo na onder as jy wil uitgaan."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Het dit"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Draai vir ’n beter aansig"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Verlaat gedeelde skerm vir ’n beter aansig"</string>
     <string name="done_label" msgid="7283767013231718521">"Klaar"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Ure se sirkelglyer"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Minute se sirkelglyer"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloon <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vra PIN voordat jy ontspeld"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vra ontsluitpatroon voordat jy ontspeld"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vra wagwoord voordat jy ontspeld"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Laat ’n metgeselapp toe om voorgronddienste van agtergrond af te begin"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofoon is beskikbaar"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofoon is geblokkeer"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am-watch/strings.xml b/core/res/res/values-am-watch/strings.xml
index d46557a..ad9b696 100644
--- a/core/res/res/values-am-watch/strings.xml
+++ b/core/res/res/values-am-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g> መተግበሪያ ከ<xliff:g id="NUMBER_1">%2$d</xliff:g>።"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"አነፍናፊዎች"</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 39e010e..49e0128 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"መተግበሪያው በጥቅም ላይ ሳለ የሰውነት ዳሳሽ የአንጓ የሙቀት መጠን ውሂብን ይድረስ።"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"መተግበሪያው በጥቅም ላይ ሳለ መተግበሪያው የሰውነት ዳሳሽ የአንጓ የሙቀት መጠን ውሂብን እንዲደርስ ይፈቅድለታል።"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"መተግበሪያው ዳራ ውስጥ ሳለ የሰውነት ዳሳሽ የአንጓ የሙቀት መጠን ውሂብን ይድረስ።"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"መተግበሪያው በዳራ ውስጥ ሳለ መተግበሪያው የሰውነት ዳሳሽ የአንጓ የሙቀት መጠን ውሂብን እንዲደርስ ይፈቅድለታል።"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android በመጀመር ላይ ነው…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ጡባዊ በመጀመር ላይ ነው…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"መሣሪያ በመጀመር ላይ ነው…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"ማከማቻን በማመቻቸት ላይ።"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"የስርዓት ዝማኔን በመጨረስ ላይ…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> በማላቅ ላይ…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"መተግበሪያዎች በአግባቡ በመጠቀም ላይ <xliff:g id="NUMBER_0">%1$d</xliff:g> ከ <xliff:g id="NUMBER_1">%2$d</xliff:g> ፡፡"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>ን ማዘጋጀት።"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"መተግበሪያዎችን በማስጀመር ላይ፡፡"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"አጨራረስ ማስነሻ፡፡"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"ሙሉ ገጽ በማሳየት ላይ"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"ለመውጣት፣ ከላይ ወደታች ጠረግ ያድርጉ።"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"ገባኝ"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ለተሻለ ዕይታ ያሽከርክሩ"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ለተሻለ ዕይታ የተከፈለ ማያ ገጽን ትተው ይውጡ"</string>
     <string name="done_label" msgid="7283767013231718521">"ተከናውኗል"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"የሰዓታት ክብ ተንሸራታች"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"የደቂቃዎች ክብ ተንሸራታች"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2ኛ ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3ኛ ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ከመንቀል በፊት ፒን ጠይቅ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ከመንቀል በፊት የማስከፈቻ ስርዓተ-ጥለት ጠይቅ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ከመንቀል በፊት የይለፍ ቃል ጠይቅ"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"አጃቢ መተግበሪያ ከዳራ የፊት አገልግሎቶችን እንዲጀምር ያስችላል።"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ማይክሮፎን ይገኛል"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ማይክሮፎን ታግዷል"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar-watch/strings.xml b/core/res/res/values-ar-watch/strings.xml
index 3bc89f6..a8ca4cc 100644
--- a/core/res/res/values-ar-watch/strings.xml
+++ b/core/res/res/values-ar-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"التطبيق <xliff:g id="NUMBER_0">%1$d</xliff:g> من <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"أجهزة الاستشعار"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 5a64dbe..6f48e90 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -462,14 +462,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"الوصول إلى بيانات درجة حرارة المعصم من خلال جهاز استشعار الجسم عندما يكون التطبيق قيد الاستخدام"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"يسمح هذا الإذن للتطبيق بالوصول إلى بيانات درجة حرارة المعصم من خلال جهاز استشعار الجسم، وذلك عندما يكون التطبيق قيد الاستخدام."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"الوصول إلى بيانات درجة حرارة المعصم من خلال جهاز استشعار الجسم عندما يكون التطبيق مفعّلاً في الخلفية"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"يسمح هذا الإذن للتطبيق بالوصول إلى بيانات درجة حرارة المعصم من خلال جهاز استشعار الجسم، وذلك عندما يكون التطبيق مفعّلاً في الخلفية."</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>
@@ -1253,10 +1249,7 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"‏جارٍ تشغيل Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"جارٍ بدء تشغيل الجهاز اللوحي…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"جارٍ بدء تشغيل الجهاز…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"جارٍ تحسين مساحة التخزين."</string>
-    <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"جارٍ إنهاء تحديث النظام…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"جارٍ ترقية <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"جارٍ تحسين التطبيق <xliff:g id="NUMBER_0">%1$d</xliff:g> من <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"جارٍ تحضير <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"بدء التطبيقات."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"جارٍ إعادة التشغيل."</string>
@@ -1854,6 +1847,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"جارٍ العرض بملء الشاشة"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"للخروج، مرر بسرعة من أعلى إلى أسفل."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"حسنًا"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"يمكنك تدوير الجهاز لرؤية شاشة معاينة الكاميرا بشكل أوضح."</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"يمكنك الخروج من وضع \"تقسيم الشاشة\" لرؤية شاشة معاينة الكاميرا بشكل أوضح."</string>
     <string name="done_label" msgid="7283767013231718521">"تم"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"شريط التمرير الدائري للساعات"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"شريط التمرير الدائري للدقائق"</string>
@@ -1865,6 +1860,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> المخصص للعمل"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"العمل الثاني <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"العمل الثالث <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"طلب إدخال رقم التعريف الشخصي قبل إزالة التثبيت"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"طلب إدخال النقش الخاص بإلغاء القفل قبل إزالة التثبيت"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"طلب إدخال كلمة المرور قبل إزالة التثبيت"</string>
@@ -2319,4 +2316,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"يسمح هذا الإذن للتطبيق المصاحب ببدء الخدمات التي تعمل في المقدّمة من الخلفية."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"الميكروفون متاح."</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"تم حظر الميكروفون."</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-as-watch/strings.xml b/core/res/res/values-as-watch/strings.xml
index f72042e..5dc8863 100644
--- a/core/res/res/values-as-watch/strings.xml
+++ b/core/res/res/values-as-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g>টা এপৰ ভিতৰত <xliff:g id="NUMBER_0">%1$d</xliff:g>টা"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"ছেন্সৰসমূহ"</string>
 </resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 608e628..db655af 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"এপ্‌টো ব্যৱহাৰ হৈ থকাৰ সময়ত শৰীৰৰ ছেন্সৰ জৰিয়তে মণিবন্ধৰ উষ্ণতাৰ ডেটা এক্সেছ কৰে।"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"এপ্‌টো ব্যৱহাৰ হৈ থকাৰ সময়ত এপ্‌টোক শৰীৰৰ ছেন্সৰ জৰিয়তে মণিবন্ধৰ উষ্ণতাৰ ডেটা এক্সেছ কৰাৰ অনুমতি দিয়ে।"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"এপ্‌টো নেপথ্যত থকাৰ সময়ত শৰীৰৰ ছেন্সৰ জৰিয়তে মণিবন্ধৰ উষ্ণতাৰ ডেটা এক্সেছ কৰে।"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"এপ্‌টো নেপথ্যত থকাৰ সময়ত এপ্‌টোক শৰীৰৰ ছেন্সৰ জৰিয়তে মণিবন্ধৰ উষ্ণতাৰ ডেটা এক্সেছ কৰাৰ অনুমতি দিয়ে।"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android আৰম্ভ কৰি থকা হৈছে…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"টেবলেটটো আৰম্ভ হৈছে…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ডিভাইচটো আৰম্ভ হৈছে…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"ষ্ট’ৰেজ অপ্টিমাইজ কৰি থকা হৈছে।"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"ছিষ্টেম আপডে’ট সম্পূৰ্ণ কৰা হৈছে…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক আপগ্ৰেড কৰি থকা হৈছে…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g>ৰ ভিতৰত <xliff:g id="NUMBER_0">%1$d</xliff:g> এপ্ অপ্টিমাইজ কৰি থকা হৈছে৷"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>সাজু কৰি থকা হৈছে।"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"আৰম্ভ হৈ থকা এপসমূহ।"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"বুট কাৰ্য সমাপ্ত কৰিছে।"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"স্ক্ৰীন পূৰ্ণৰূপত চাই আছে"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"বাহিৰ হ\'বলৈ ওপৰৰপৰা তললৈ ছোৱাইপ কৰক।"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"বুজি পালোঁ"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ভালকৈ চাবলৈ ঘূৰাওক"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ভালকৈ চাবলৈ বিভাজিত স্ক্ৰীনৰ পৰা বাহিৰ হওক"</string>
     <string name="done_label" msgid="7283767013231718521">"সম্পন্ন কৰা হ’ল"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"ঘড়ীৰ বৃত্তাকাৰ শ্লাইডাৰ"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"মিনিটৰ বৃত্তাকাৰ শ্লাইডাৰ"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"কৰ্মস্থান <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"২য় কার্য <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"৩য় কার্য <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"ক্ল’ন <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"আনপিন কৰাৰ পূৰ্বে পিন দিবলৈ কওক"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"আনপিন কৰাৰ পূৰ্বে আনলক আৰ্হি দিবলৈ কওক"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"আনপিন কৰাৰ পূৰ্বে পাছৱৰ্ড দিবলৈ কওক"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"এটা সহযোগী এপক নেপথ্যৰ পৰা অগ্ৰভূমি সেৱাসমূহ আৰম্ভ কৰিবলৈ দিয়ে।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"মাইক্ৰ’ফ’নটো উপলব্ধ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"মাইক্ৰ’ফ’নটো অৱৰোধ কৰি থোৱা আছে"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-az-watch/strings.xml b/core/res/res/values-az-watch/strings.xml
index dbd2337..cf1b7a5 100644
--- a/core/res/res/values-az-watch/strings.xml
+++ b/core/res/res/values-az-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Tətbiq <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensorlar"</string>
 </resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 40af5eb..6dded33 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Tətbiqə istifadə zamanı ürək döyüntüsü, temperatur və qanda oksigen faizi kimi bədən sensoru datasına giriş icazəsi verir."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Arxa fonda olarkən ürək döyüntüsü kimi bədən sensoru datasına giriş"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Tətbiqə arxa fonda olarkən ürək döyüntüsü, temperatur və qanda oksigen faizi kimi bədən sensoru datasına giriş icazəsi verir."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Tətbiq istifadə edilərkən bədən sensoru bilək temperaturu datasına giriş."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Tətbiq istifadə edilərkən tətbiqin bədən sensoru bilək temperaturu datasına girişinə imkan verir."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Tətbiq arxa fonda olarkən bədən sensoru bilək temperaturu datasına giriş."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Tətbiq arxa fonda olarkən tətbiqin bədən sensoru bilək temperaturu datasına girişinə imkan verir."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Təqvim təqdirləri və detallarını oxuyun"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Bu tətbiq planşetdə yerləşdirilmiş və təqvim datasında yadda saxlanmış bütün təqvim tədbirlərini oxuya bilər."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Bu tətbiq Android TV cihazında saxlanılan bütün təqvim tədbirlərini oxuya, həmçinin təqvim datasını paylaşa və ya yadda saxlaya bilər."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android işə başlayır..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Planşet başlayır…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Cihaz başlayır…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Yaddaş optimallaşdırılır."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Sistem güncəlləmələri tamamlanır…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> təkmilləşdirilir…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> əddədən <xliff:g id="NUMBER_0">%1$d</xliff:g> tətbiq optimallaşır."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> proqramının hazırlanması."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Tətbiqlər başladılır."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Yükləmə başa çatır."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Tam ekrana baxış"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Çıxmaq üçün yuxarıdan aşağı sürüşdürün."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Anladım"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Daha yaxşı görünüş üçün fırladın"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Daha yaxşı görünüş üçün bölünmüş ekrandan çıxın"</string>
     <string name="done_label" msgid="7283767013231718521">"Hazırdır"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Dairəvi saat slayderi"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Dairəvi dəqiqə slayderi"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-ci İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-cü İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Kopyalayın: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ayırmadan öncə PIN istənilsin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Qrafik açar istənilsin"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ayırmadan öncə parol istənilsin"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Kompanyon tətbiqinə ön fon xidmətlərini arxa fondan başlatmaq icazəsi verir."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon əlçatandır"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon blok edilib"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-b+sr+Latn-watch/strings.xml b/core/res/res/values-b+sr+Latn-watch/strings.xml
index 699c148..da58726 100644
--- a/core/res/res/values-b+sr+Latn-watch/strings.xml
+++ b/core/res/res/values-b+sr+Latn-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplikacija <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Senzori"</string>
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 0f39f41..e052f83 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Dozvoljava aplikaciji da pristupa podacima senzora za telo, kao što su puls, temperatura i procenat kiseonika u krvi dok se aplikacija koristi."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Pristup podacima senzora za telo, kao što je puls, u pozadini"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Dozvoljava aplikaciji da pristupa podacima senzora za telo, kao što su puls, temperatura i procenat kiseonika u krvi dok je aplikacija u pozadini."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Pristupajte podacima o temperaturi sa senzora za telo na ručnom zglobu dok se aplikacija koristi."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Dozvoljava aplikaciji da pristupa podacima o temperaturi sa senzora za telo na ručnom zglobu dok se aplikacija koristi."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Pristupajte podacima o temperaturi sa senzora za telo na ručnom zglobu dok je aplikacija u pozadini."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Dozvoljava aplikaciji da pristupa podacima o temperaturi sa senzora za telo na ručnom zglobu dok je aplikacija u pozadini."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Čitanje događaja i podataka iz kalendara"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Ova aplikacija može da čita sve događaje iz kalendara koje čuvate na tabletu, kao i da deli ili čuva podatke iz kalendara."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ova aplikacija može da čita sve događaje iz kalendara koje čuvate na Android TV uređaju, kao i da deli ili čuva podatke iz kalendara."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android se pokreće…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet se pokreće…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Uređaj se pokreće…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Memorija se optimizuje."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Ažuriranje sistema se dovršava…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> se nadograđuje…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimizovanje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Priprema se <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Pokretanje aplikacija."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Završavanje pokretanja."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Prikazuje se ceo ekran"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Da biste izašli, prevucite nadole odozgo."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Važi"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotirajte radi boljeg prikaza"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Izađite iz podeljenog ekrana radi boljeg prikaza"</string>
     <string name="done_label" msgid="7283767013231718521">"Gotovo"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Kružni klizač za sate"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Kružni klizač za minute"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> na poslu"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. poslovni imejl <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloniraj <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži šablon za otključavanje pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži lozinku pre otkačinjanja"</string>
@@ -2316,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Dozvoljava pratećoj aplikaciji da pokrene usluge u prvom planu iz pozadine."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je dostupan"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je blokiran"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dvojni ekran"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dvojni ekran je uključen"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi oba ekrana za prikazivanje sadržaja"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Uređaj je previše zagrejan"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvojni ekran je nedostupan jer je telefon previše zagrejan"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Isključi"</string>
 </resources>
diff --git a/core/res/res/values-be-watch/strings.xml b/core/res/res/values-be-watch/strings.xml
index 73e6643..75e6307 100644
--- a/core/res/res/values-be-watch/strings.xml
+++ b/core/res/res/values-be-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Праграма <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Датчыкі"</string>
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 6d1135f..f0ecb5f 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -460,14 +460,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Доступ праграмы ў час яе выкарыстання да даных пра тэмпературу з датчыка цела, які знаходзіцца на запясці."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Праграма ў час яе выкарыстання будзе мець доступ да даных пра тэмпературу з датчыка цела, які знаходзіцца на запясці."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Доступ праграмы ў фонавым рэжыме да даных пра тэмпературу з датчыка цела, які знаходзіцца на запясці."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Праграма ў час яе працы ў фонавым рэжыме будзе мець доступ да даных пра тэмпературу з датчыка цела, які знаходзіцца на запясці."</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>
@@ -1251,10 +1247,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android запускаецца..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Запуск планшэта…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Запуск прылады…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Аптымізацыя сховішча."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Завяршэнне абнаўлення сістэмы…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> абнаўляецца…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Аптымізацыя прыкладання <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Падрыхтоўка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск прыкладанняў."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Завяршэнне загрузкі."</string>
@@ -1852,6 +1846,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Прагляд у поўнаэкранным рэжыме"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Для выхаду правядзіце зверху ўніз."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Зразумела"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Павярнуць для лепшага прагляду"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Выйсці з рэжыму падзеленага экрана для лепшага прагляду"</string>
     <string name="done_label" msgid="7283767013231718521">"Гатова"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Кругавы паўзунок гадзін"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Кругавы паўзунок хвілін"</string>
@@ -1863,6 +1859,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (праца)"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Другая праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Трэцяя праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запытваць PIN-код перад адмацаваннем"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запытваць узор разблакіроўкі перад адмацаваннем"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запытваць пароль перад адмацаваннем"</string>
@@ -2317,4 +2315,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Спадарожная праграма зможа запускаць актыўныя сэрвісы з фонавага рэжыму."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Мікрафон даступны"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Мікрафон заблакіраваны"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg-watch/strings.xml b/core/res/res/values-bg-watch/strings.xml
index b5554ca..7977f66 100644
--- a/core/res/res/values-bg-watch/strings.xml
+++ b/core/res/res/values-bg-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Прилож. <xliff:g id="NUMBER_0">%1$d</xliff:g> от <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Сензори"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index cfe18d4..141da1d 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Достъп до данните за температурата, измерена на китката от сензорите за тяло, докато приложението се използва."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Дава на приложението достъп до данните за температурата, измерена на китката от сензорите за тяло. Разрешението е в сила, докато приложението се използва."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Достъп до данните за температурата, измерена на китката от сензорите за тяло, докато приложението работи на заден план."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Дава на приложението достъп до данните за температурата, измерена на китката от сензорите за тяло. Разрешението е в сила, докато приложението работи на заден план."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android се стартира…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Таблетът се стартира…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Устройството се стартира…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Хранилището се оптимизира."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Системната актуализация завършва…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> се надстройва…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Оптимизира се приложение <xliff:g id="NUMBER_0">%1$d</xliff:g> от <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> се подготвя."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Приложенията се стартират."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Зареждането завършва."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Изглед на цял екран"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"За изход плъзнете пръст надолу от горната част."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Разбрах"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Завъртете за по-добър изглед"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Излезте от разделения екран за по-добър изглед"</string>
     <string name="done_label" msgid="7283767013231718521">"Готово"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Кръгов плъзгач за часовете"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Кръгов плъзгач за минутите"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> за работа"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Втори служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Трети служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запитване за ПИН код преди освобождаване"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запитване за фигура за отключване преди освобождаване"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запитване за парола преди освобождаване"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Разрешава на дадено придружаващо приложение да стартира услуги на преден план, докато се изпълнява на заден план."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофонът е налице"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофонът е блокиран"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bn-watch/strings.xml b/core/res/res/values-bn-watch/strings.xml
index 3d02cea..c98d372 100644
--- a/core/res/res/values-bn-watch/strings.xml
+++ b/core/res/res/values-bn-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g>টির মধ্যে <xliff:g id="NUMBER_0">%1$d</xliff:g>টি অ্যাপ্লিকেশান"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"সেন্সরগুলি"</string>
 </resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index e02d75d..969729c 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"অ্যাপ ব্যবহার করার সময়, দেহের তাপমাত্রা সংক্রান্ত বডি সেন্সর ডেটা অ্যাক্সেস করা।"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"অ্যাপ ব্যবহার করার সময়, দেহের তাপমাত্রা সংক্রান্ত বডি সেন্সর ডেটা অ্যাক্সেস করার ক্ষেত্রে অ্যাপকে অনুমতি দেয়।"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"অ্যাপ ব্যাকগ্রাউন্ডে চলার সময়, দেহের তাপমাত্রা সংক্রান্ত বডি সেন্সর ডেটা অ্যাক্সেস করা।"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"অ্যাপ ব্যাকগ্রাউন্ডে চলার সময়, দেহের তাপমাত্রা সংক্রান্ত বডি সেন্সর ডেটা অ্যাক্সেস করার ক্ষেত্রে অ্যাপকে অনুমতি দেয়।"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android চালু হচ্ছে…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ট্যাবলেট চালু করা হচ্ছে…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ডিভাইস চালু করা হচ্ছে…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"স্টোরেজ অপ্টিমাইজ করা হচ্ছে৷"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"সিস্টেম আপডেট শেষ করা হচ্ছে…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> আপগ্রেড করা হচ্ছে…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g>টির মধ্যে <xliff:g id="NUMBER_0">%1$d</xliff:g>টি অ্যাপ্লিকেশান অপ্টিমাইজ করা হচ্ছে৷"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> প্রস্তুত করা হচ্ছে৷"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"অ্যাপ্লিকেশানগুলি শুরু করা হচ্ছে৷"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"চালু করা সম্পূর্ণ হচ্ছে৷"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"পূর্ণ স্ক্রিনে দেখা হচ্ছে"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"প্রস্থান করতে উপর থেকে নিচের দিকে সোয়াইপ করুন"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"বুঝেছি"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"আরও ভাল ক্যামেরা ভিউ পাওয়ার জন্য ঘোরান"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"আরও ভাল ক্যামেরা ভিউ পাওয়ার জন্য স্প্লিট স্ক্রিন থেকে বেরিয়ে আসুন"</string>
     <string name="done_label" msgid="7283767013231718521">"সম্পন্ন হয়েছে"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"বৃত্তাকার ঘণ্টা নির্বাচকের স্লাইডার"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"বৃত্তাকার মিনিট নির্বাচকের স্লাইডার"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"কর্মক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"দ্বিতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"তৃতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> ক্লোন"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"আনপিন করার আগে পিন চান"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"আনপিন করার আগে আনলক প্যাটার্ন চান"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"আনপিন করার আগে পাসওয়ার্ড চান"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"কম্প্যানিয়ন অ্যাপকে, ব্যাকগ্রাউন্ড থেকে ফোরগ্রাউন্ড পরিষেবা চালু করার অনুমতি দেয়।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"মাইক্রোফোন উপলভ্য আছে"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"মাইক্রোফোন ব্লক করা হয়েছে"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ডুয়াল স্ক্রিন"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"\'ডুয়াল স্ক্রিন\' চালু করা আছে"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"কন্টেন্ট দেখানোর জন্য <xliff:g id="APP_NAME">%1$s</xliff:g> দুটি ডিসপ্লে ব্যবহার করছে"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ডিভাইস খুব গরম হয়ে গেছে"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"আপনার ফোন খুব বেশি গরম হয়ে যাচ্ছে বলে \'ডুয়াল স্ক্রিন\' উপলভ্য নেই"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"বন্ধ করুন"</string>
 </resources>
diff --git a/core/res/res/values-bs-watch/strings.xml b/core/res/res/values-bs-watch/strings.xml
index f51d3bf..da58726 100644
--- a/core/res/res/values-bs-watch/strings.xml
+++ b/core/res/res/values-bs-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. aplikac. od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Senzori"</string>
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 3c1925b..5f79517 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Dozvoljava aplikaciji dok se koristi da pristupa podacima tjelesnih senzora kao što su puls, temperatura i postotak kisika u krvi."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Pristup podacima tjelesnih senzora, kao što je puls, dok je u pozadini"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Dozvoljava aplikaciji dok je u pozadini da pristupa podacima tjelesnih senzora kao što su puls, temperatura i postotak kisika u krvi."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Pristup podacima tjelesnog senzora o temperaturi zgloba šake dok se aplikacija koristi."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Dozvoljava aplikaciji dok se koristi da pristupa podacima tjelesnog senzora o temperaturi zgloba šake."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Pristup podacima tjelesnog senzora o temperaturi zgloba šake dok je aplikacija u pozadini."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Dozvoljava aplikaciji dok je u pozadini da pristupa podacima tjelesnog senzora o temperaturi zgloba šake."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Čitanje događaja kalendara i detalja"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Ova aplikacija može čitati sve događaje u kalendaru pohranjene na vašem tabletu i sačuvati podatke kalendara."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ova aplikacija može čitati sve događaje u kalendaru na vašem Android TV uređaju i dijeliti ili sačuvati podatke kalendara."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android se pokreće..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Pokretanje tableta…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Pokretanje uređaja…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimiziranje pohrane."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Dovršavanje ažuriranja sistema…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> se nadograđuje…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimiziranje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Pripremanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Pokretanje aplikacija."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Pokretanje pri kraju."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Prikazuje se cijeli ekran"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Da izađete, prevucite odozgo nadolje."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Razumijem"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotirajte za bolji prikaz"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Izađite iz podijeljenog ekrana za bolji prikaz"</string>
     <string name="done_label" msgid="7283767013231718521">"Gotovo"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Kružni klizač za odabir sata"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Kružni klizač za minute"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloniranje aplikacije <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN prije nego se otkači"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži uzorak za otključavanje prije poništavanja kačenja"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži lozinku prije nego se otkači"</string>
@@ -2316,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Dozvoljava pratećoj aplikaciji da iz pozadine pokrene usluge u prvom planu."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je dostupan"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je blokiran"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dupli ekran"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dupli ekran je uključen"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> koristi oba ekrana za prikazivanje sadržaja"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Uređaj je previše zagrijan"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dupli ekran nije dostupan je se telefon previše zagrijava"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Isključi"</string>
 </resources>
diff --git a/core/res/res/values-ca-watch/strings.xml b/core/res/res/values-ca-watch/strings.xml
index 7bb483a..21ba346 100644
--- a/core/res/res/values-ca-watch/strings.xml
+++ b/core/res/res/values-ca-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplicació <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensors"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 41496a5..842dffa 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permet que l\'aplicació accedeixi a les dades del sensor corporal, com ara la freqüència cardíaca, la temperatura i el percentatge d\'oxigen a la sang, mentre s\'utilitza."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Accedir a dades del sensor corporal, com la freqüència cardíaca, en segon pla"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permet que l\'aplicació accedeixi a les dades del sensor corporal, com ara la freqüència cardíaca, la temperatura i el percentatge d\'oxigen a la sang, mentre es troba en segon pla."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Accedir a les dades de la temperatura del canell del sensor corporal mentre s\'utilitza l\'aplicació."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permet que l\'aplicació accedeixi a les dades de la temperatura del canell del sensor corporal mentre s\'utilitza l\'aplicació."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Accedir a les dades de la temperatura del canell del sensor corporal mentre l\'aplicació es troba en segon pla."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permet que l\'aplicació accedeixi a les dades de la temperatura del canell del sensor corporal mentre l\'aplicació es troba en segon pla."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Aquesta aplicació pot llegir els esdeveniments i la informació del calendari"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Aquesta aplicació pot llegir tots els esdeveniments del calendari emmagatzemats a la tauleta i compartir o desar les dades del teu calendari."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Aquesta aplicació pot llegir tots els esdeveniments del calendari emmagatzemats al dispositiu Android TV i compartir o desar les dades del calendari."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"S\'està iniciant Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"S\'està iniciant la tauleta…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"S\'està iniciant el dispositiu…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"S\'està optimitzant l\'emmagatzematge."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Completant l\'actualització del sistema…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"S\'està actualitzant <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"S\'està optimitzant l\'aplicació <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"S\'està preparant <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"S\'estan iniciant les aplicacions."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"S\'està finalitzant l\'actualització."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Mode de pantalla completa"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Per sortir, llisca cap avall des de la part superior."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Entesos"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gira per a una millor visualització"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Surt de la pantalla dividida per a una millor visualització"</string>
     <string name="done_label" msgid="7283767013231718521">"Fet"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Control circular de les hores"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Control circular dels minuts"</string>
@@ -1862,6 +1858,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2n <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3r <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Sol·licita el PIN per deixar de fixar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Sol·licita el patró de desbloqueig per deixar de fixar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demana la contrasenya per deixar de fixar"</string>
@@ -2316,4 +2314,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permet que una aplicació complementària iniciï serveis en primer pla des d\'un segon pla."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"El micròfon està disponible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"El micròfon està bloquejat"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs-watch/strings.xml b/core/res/res/values-cs-watch/strings.xml
index c94cc4d..6c9d718 100644
--- a/core/res/res/values-cs-watch/strings.xml
+++ b/core/res/res/values-cs-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Senzory"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 2e2c3e2..6a5f6c3 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -460,14 +460,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Poskytuje aplikaci přístup k datům z tělesných senzorů, jako je tepová frekvence, teplota a procento nasycení krve kyslíkem, během používání aplikace."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Přístup k datům z tělesných senzorů, jako je tepová frekvence, při běhu na pozadí"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Poskytuje aplikaci přístup k datům z tělesných senzorů, jako je tepová frekvence, teplota a procento nasycení krve kyslíkem, při běhu na pozadí."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Má přístup k údajům o teplotě zápěstí z tělesného senzoru během používání aplikace."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Poskytuje aplikaci přístup k údajům o teplotě zápěstí z tělesného senzoru během používání aplikace."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Má přístup k údajům o teplotě zápěstí z tělesného senzoru při běhu na pozadí."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Poskytuje aplikaci přístup k údajům o teplotě zápěstí z tělesného senzoru při běhu na pozadí."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Čtení událostí v kalendáři včetně podrobností"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Tato aplikace může číst všechny události v kalendáři uložené v tabletu a sdílet či ukládat data kalendáře."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Tato aplikace může číst všechny události v kalendáři uložené v zařízení Android TV a sdílet či ukládat data kalendáře."</string>
@@ -1251,10 +1247,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Spouštění systému Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet se spouští…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Zařízení se spouští…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Probíhá optimalizace úložiště."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Dokončování aktualizace systému…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> se upgraduje…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimalizování aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Příprava aplikace <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Spouštění aplikací."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Dokončování inicializace."</string>
@@ -1852,6 +1846,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Zobrazení celé obrazovky"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Režim ukončíte přejetím prstem shora dolů."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Rozumím"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Otočte obrazovku, abyste lépe viděli"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Ukončete režim rozdělené obrazovky, abyste lépe viděli"</string>
     <string name="done_label" msgid="7283767013231718521">"Hotovo"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Kruhový posuvník hodin"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Kruhový posuvník minut"</string>
@@ -1863,6 +1859,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Pracovní <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Před uvolněním požádat o PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Před uvolněním požádat o bezpečnostní gesto"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Před odepnutím požádat o heslo"</string>
@@ -2317,4 +2315,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Umožňuje doprovodné aplikaci spouštět z pozadí služby v popředí."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je dostupný"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je zablokován"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da-watch/strings.xml b/core/res/res/values-da-watch/strings.xml
index 498fce1..fa296b6 100644
--- a/core/res/res/values-da-watch/strings.xml
+++ b/core/res/res/values-da-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensorer"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 7bd5556..f8aec8b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Tillader, at appen kan få adgang til kropssensordata, f.eks. pulsen, temperaturen og iltmætningen af blodet, mens appen er i brug."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Få adgang til kropssensordata, f.eks. pulsen, mens appen er i baggrunden"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Tillader, at appen kan få adgang til kropssensordata, f.eks. pulsen, temperaturen og iltmætningen af blodet, mens appen er i baggrunden."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Få adgang til temperaturdata for kropssensoren på håndleddet, mens appen er i brug."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Tillader, at appen kan få adgang til temperaturdata for kropssensoren på håndleddet, mens appen er i brug."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Få adgang til temperaturdata for kropssensoren på håndleddet, mens appen er i baggrunden."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Tillader, at appen kan få adgang til temperaturdata for kropssensoren på håndleddet, mens appen er i baggrunden."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Læs kalenderbegivenheder og -info"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Denne app kan læse alle kalenderbegivenheder, der er gemt på din tablet, og dele eller gemme dine kalenderdata."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Denne app kan læse alle kalenderbegivenheder, der er gemt på din Android TV-enhed, og dele eller gemme dine kalenderdata."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android starter..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Denne tablet starter…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Enheden starter…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Lageret optimeres."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Afslutter systemopdatering…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> opgraderer…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimerer app <xliff:g id="NUMBER_0">%1$d</xliff:g> ud af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Åbner dine apps."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Gennemfører start."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visning i fuld skærm"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Stryg ned fra toppen for at afslutte."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK, det er forstået"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Roter, og få en bedre visning"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Afslut opdelt skærm, og få en bedre visning"</string>
     <string name="done_label" msgid="7283767013231718521">"Udfør"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Cirkulær timevælger"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Cirkulær minutvælger"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> – arbejde"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Klon af <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Bed om pinkode inden frigørelse"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Bed om oplåsningsmønster ved deaktivering"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Bed om adgangskode inden frigørelse"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Tillader, at en medfølgende app kan starte tjenester i forgrunden via tilladelser til tjenester i baggrunden."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofonen er tilgængelig"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofonen er blokeret"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de-watch/strings.xml b/core/res/res/values-de-watch/strings.xml
index c910425..3f693a9 100644
--- a/core/res/res/values-de-watch/strings.xml
+++ b/core/res/res/values-de-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> von <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensoren"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index bf79e13..837be87 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Ermöglicht der App den Zugriff auf Daten des Körpersensors, etwa solche zur Herzfrequenz, zur Temperatur und zum Blutsauerstoffanteil, während die App in Benutzung ist."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Zugriff auf Daten des Körpersensors, etwa Herzfrequenz, wenn im Hintergrund"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Ermöglicht der App den Zugriff auf Daten des Körpersensors, etwa solche zur Herzfrequenz, zur Temperatur und zum Blutsauerstoffanteil, während die App im Hintergrund ist."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Auf Daten des Körpersensors zur Hauttemperatur am Handgelenk zugreifen, während die App verwendet wird."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Ermöglicht der App, auf Daten des Körpersensors zur Hauttemperatur am Handgelenk zuzugreifen, während die App verwendet wird."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Auf Daten des Körpersensors zur Hauttemperatur am Handgelenk zugreifen, während die App im Hintergrund ausgeführt wird."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Ermöglicht der App, auf Daten des Körpersensors zur Hauttemperatur am Handgelenk zuzugreifen, während die App im Hintergrund ausgeführt wird."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Kalendertermine und Details lesen"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Diese App kann alle auf deinem Tablet gespeicherten Kalendertermine lesen und deine Kalenderdaten teilen oder speichern."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Diese App kann alle auf deinem Android TV-Gerät gespeicherten Kalendertermine lesen und die Kalenderdaten teilen oder speichern."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android wird gestartet…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet wird gestartet…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Gerät wird gestartet…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Speicher wird optimiert"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Systemupdate wird beendet…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Für <xliff:g id="APPLICATION">%1$s</xliff:g> wird gerade ein Upgrade ausgeführt…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> von <xliff:g id="NUMBER_1">%2$d</xliff:g> wird optimiert..."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> wird vorbereitet"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Apps werden gestartet..."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Start wird abgeschlossen..."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Vollbildmodus wird aktiviert"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Zum Beenden von oben nach unten wischen"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Ok"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Drehen, um die Ansicht zu verbessern"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Modus für geteilten Bildschirm beenden, um die Ansicht zu verbessern"</string>
     <string name="done_label" msgid="7283767013231718521">"Fertig"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Kreisförmiger Schieberegler für Stunden"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Kreisförmiger Schieberegler für Minuten"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vor dem Beenden nach PIN fragen"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vor dem Beenden nach Entsperrungsmuster fragen"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vor dem Beenden nach Passwort fragen"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Ermöglicht einer Companion-App, Dienste im Vordergrund aus dem Hintergrund zu starten."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon ist verfügbar"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon ist blockiert"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el-watch/strings.xml b/core/res/res/values-el-watch/strings.xml
index f0d7621..4d5b10d 100644
--- a/core/res/res/values-el-watch/strings.xml
+++ b/core/res/res/values-el-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Εφαρμογή <xliff:g id="NUMBER_0">%1$d</xliff:g> από <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Αισθητήρες"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e17f78f..f0879b48 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -301,7 +301,7 @@
     <string name="permgrouplab_calendar" msgid="6426860926123033230">"Ημερολόγιο"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"έχει πρόσβαση στο ημερολόγιό σας"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
-    <string name="permgroupdesc_sms" msgid="5726462398070064542">"στέλνει και να διαβάζει μηνύματα SMS"</string>
+    <string name="permgroupdesc_sms" msgid="5726462398070064542">"στέλνει και διαβάζει μηνύματα SMS"</string>
     <string name="permgrouplab_storage" msgid="17339216290379241">"Αρχεία"</string>
     <string name="permgroupdesc_storage" msgid="5378659041354582769">"πρόσβαση στα αρχεία της συσκευής σας"</string>
     <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"Μουσική και ήχος"</string>
@@ -309,7 +309,7 @@
     <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Φωτογραφίες και βίντεο"</string>
     <string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"πρόσβαση στις φωτογραφίες και τα βίντεο στη συσκευή σας"</string>
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"Μικρόφωνο"</string>
-    <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ηχογραφεί"</string>
+    <string name="permgroupdesc_microphone" msgid="1047786732792487722">"ηχογράφηση"</string>
     <string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Σωματική δραστ/τητα"</string>
     <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"πρόσβαση στη σωματική σας δραστηριότητα"</string>
     <string name="permgrouplab_camera" msgid="9090413408963547706">"Κάμερα"</string>
@@ -319,7 +319,7 @@
     <string name="permgrouplab_calllog" msgid="7926834372073550288">"Αρχεία καταγρ. κλήσ."</string>
     <string name="permgroupdesc_calllog" msgid="2026996642917801803">"ανάγνωση και εγγραφή αρχείου καταγραφής τηλεφωνικών κλήσεων"</string>
     <string name="permgrouplab_phone" msgid="570318944091926620">"Τηλέφωνο"</string>
-    <string name="permgroupdesc_phone" msgid="270048070781478204">"πραγματοποιεί και να διαχειρίζεται τηλ/κές κλήσεις"</string>
+    <string name="permgroupdesc_phone" msgid="270048070781478204">"πραγματοποιεί και διαχειρίζεται τηλ/κές κλήσεις"</string>
     <string name="permgrouplab_sensors" msgid="9134046949784064495">"Αισθητήρες σώματος"</string>
     <string name="permgroupdesc_sensors" msgid="2610631290633747752">"πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας"</string>
     <string name="permgrouplab_notifications" msgid="5472972361980668884">"Ειδοποιήσεις"</string>
@@ -366,7 +366,7 @@
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων που έχουν μεταδοθεί μέσω κινητού τηλεφώνου και έχουν ληφθεί από τη συσκευή σας. Ειδοποιήσεις που μεταδίδονται μέσω κινητού παραδίδονται σε ορισμένες τοποθεσίες για να σας προειδοποιήσουν για καταστάσεις έκτακτης ανάγκης. Κακόβουλες εφαρμογές ενδέχεται να παρεμποδίσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μετάδοσης μέσω κινητού σχετικά με μια επείγουσα κατάσταση."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"διαβάζει ροές δεδομένων στις οποίες έχετε εγγραφεί"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"Επιτρέπει στην εφαρμογή τη λήψη λεπτομερειών σχετικά με τις τρέχουσες συγχρονισμένες ροές δεδομένων."</string>
-    <string name="permlab_sendSms" msgid="7757368721742014252">"στέλνει και να διαβάζει μηνύματα SMS"</string>
+    <string name="permlab_sendSms" msgid="7757368721742014252">"στέλνει και διαβάζει μηνύματα SMS"</string>
     <string name="permdesc_sendSms" msgid="6757089798435130769">"Επιτρέπει στην εφαρμογή των αποστολή μηνυμάτων SMS. Αυτό μπορεί να προκαλέσει μη αναμενόμενες χρεώσεις. Οι κακόβουλες εφαρμογές ενδέχεται να σας κοστίσουν χρήματα, αποστέλλοντας μηνύματα χωρίς την έγκρισή σας."</string>
     <string name="permlab_readSms" msgid="5164176626258800297">"διαβάζει τα μηνύματα κειμένου (SMS ή MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"Αυτή η εφαρμογή μπορεί να διαβάσει όλα τα μηνύματα SMS (κειμένου) που είναι αποθηκευμένα στο tablet που χρησιμοποιείτε."</string>
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Πρόσβαση στα δεδομένα θερμοκρασίας καρπού του αισθητήρα σώματος όταν η εφαρμογή είναι σε χρήση."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Επιτρέπει στην εφαρμογή να αποκτήσει πρόσβαση στα δεδομένα θερμοκρασίας καρπού του αισθητήρα σώματος όταν η εφαρμογή είναι σε χρήση."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Πρόσβαση στα δεδομένα θερμοκρασίας καρπού του αισθητήρα σώματος όταν η εφαρμογή βρίσκεται στο παρασκήνιο."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Επιτρέπει στην εφαρμογή να αποκτήσει πρόσβαση στα δεδομένα θερμοκρασίας καρπού του αισθητήρα σώματος όταν η εφαρμογή βρίσκεται στο παρασκήνιο."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Ανάγνωση συμβάντων ημερολογίου και λεπτομερειών"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Αυτή η εφαρμογή μπορεί να διαβάσει όλα τα συμβάντα ημερολογίου που είναι αποθηκευμένα στο tablet που χρησιμοποιείτε και να μοιραστεί ή να αποθηκεύσει τα δεδομένα ημερολογίου σας."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Αυτή η εφαρμογή μπορεί να διαβάσει όλα τα συμβάντα ημερολογίου που είναι αποθηκευμένα στη συσκευή Android TV και να μοιραστεί ή να αποθηκεύσει τα δεδομένα ημερολογίου σας."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Εκκίνηση Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Εκκίνηση tablet…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Εκκίνηση συσκευής…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Βελτιστοποίηση αποθηκευτικού χώρου."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Ολοκλήρωση ενημέρωσης συστήματος…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> αναβαθμίζεται…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Βελτιστοποίηση της εφαρμογής <xliff:g id="NUMBER_0">%1$d</xliff:g> από <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Προετοιμασία <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Έναρξη εφαρμογών."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Ολοκλήρωση εκκίνησης."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Προβολή σε πλήρη οθόνη"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Για έξοδο, σύρετε προς τα κάτω από το επάνω μέρος."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Το κατάλαβα"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Περιστρέψτε την οθόνη για καλύτερη προβολή"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Εξέλθετε από τον διαχωρισμό οθόνης για καλύτερη προβολή"</string>
     <string name="done_label" msgid="7283767013231718521">"Τέλος"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Κυκλικό ρυθμιστικό ωρών"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Κυκλικό ρυθμιστικό λεπτών"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Εργασία <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 2"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 3"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Κλώνος <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Να γίνεται ερώτηση για το PIN, πριν από το ξεκαρφίτσωμα"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Να γίνεται ερώτηση για το μοτίβο ξεκλειδώματος, πριν από το ξεκαρφίτσωμα"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Επιτρέπει σε μια συνοδευτική εφαρμογή να εκκινεί υπηρεσίες στο προσκήνιο από το παρασκήνιο."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Το μικρόφωνο είναι διαθέσιμο"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Το μικρόφωνο έχει αποκλειστεί"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rAU-watch/strings.xml b/core/res/res/values-en-rAU-watch/strings.xml
index c738395..21ba346 100644
--- a/core/res/res/values-en-rAU-watch/strings.xml
+++ b/core/res/res/values-en-rAU-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensors"</string>
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 04cdfd9..35ce885 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Allows the app to access body sensor data, such as heart rate, temperature and blood oxygen percentage, while the app is in use."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Access body sensor data, like heart rate, while in the background"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Allows the app to access body sensor data, such as heart rate, temperature and blood oxygen percentage, while the app is in the background."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Access body sensor wrist temperature data while the app is in use."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Allows the app to access body sensor wrist temperature data, while the app is in use."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Access body sensor wrist temperature data while the app is in the background."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Allows the app to access body sensor wrist temperature data, while the app is in the background."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Read calendar events and details"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"This app can read all calendar events stored on your tablet and share or save your calendar data."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"This app can read all calendar events stored on your Android TV device and share or save your calendar data."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android is starting…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet is starting…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Device is starting…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimising storage."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Finishing system update…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> is upgrading…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Viewing full screen"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"To exit, swipe down from the top."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Got it"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotate for a better view"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Exit split screen for a better view"</string>
     <string name="done_label" msgid="7283767013231718521">"Done"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Hours circular slider"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Minutes circular slider"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Allows a companion app to start foreground services from background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microphone is available"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microphone is blocked"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is on"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Device is too warm"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dual Screen is unavailable because your phone is getting too warm"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Turn off"</string>
 </resources>
diff --git a/core/res/res/values-en-rCA-watch/strings.xml b/core/res/res/values-en-rCA-watch/strings.xml
index c738395..21ba346 100644
--- a/core/res/res/values-en-rCA-watch/strings.xml
+++ b/core/res/res/values-en-rCA-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensors"</string>
 </resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index cbe8013..f1a64d0 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Allows the app to access body sensor data, such as heart rate, temperature, and blood oxygen percentage, while the app is in use."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Access body sensor data, like heart rate, while in the background"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Allows the app to access body sensor data, such as heart rate, temperature, and blood oxygen percentage, while the app is in the background."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Access body sensor wrist temperature data while the app is in use."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Allows the app to access body sensor wrist temperature data, while the app is in use."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Access body sensor wrist temperature data while the app is in the background."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Allows the app to access body sensor wrist temperature data, while the app is in the background."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Read calendar events and details"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"This app can read all calendar events stored on your tablet and share or save your calendar data."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"This app can read all calendar events stored on your Android TV device and share or save your calendar data."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android is starting…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet is starting…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Device is starting…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimizing storage."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Finishing system update…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> is upgrading…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimizing app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Viewing full screen"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"To exit, swipe down from the top."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Got it"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotate for a better view"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Exit split screen for a better view"</string>
     <string name="done_label" msgid="7283767013231718521">"Done"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Hours circular slider"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Minutes circular slider"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Allows a companion app to start foreground services from background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microphone is available"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microphone is blocked"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen is on"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Device is too warm"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dual Screen is unavailable because your phone is getting too warm"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Turn off"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB-watch/strings.xml b/core/res/res/values-en-rGB-watch/strings.xml
index c738395..21ba346 100644
--- a/core/res/res/values-en-rGB-watch/strings.xml
+++ b/core/res/res/values-en-rGB-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensors"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index a43067a..02214d9 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Allows the app to access body sensor data, such as heart rate, temperature and blood oxygen percentage, while the app is in use."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Access body sensor data, like heart rate, while in the background"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Allows the app to access body sensor data, such as heart rate, temperature and blood oxygen percentage, while the app is in the background."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Access body sensor wrist temperature data while the app is in use."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Allows the app to access body sensor wrist temperature data, while the app is in use."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Access body sensor wrist temperature data while the app is in the background."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Allows the app to access body sensor wrist temperature data, while the app is in the background."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Read calendar events and details"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"This app can read all calendar events stored on your tablet and share or save your calendar data."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"This app can read all calendar events stored on your Android TV device and share or save your calendar data."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android is starting…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet is starting…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Device is starting…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimising storage."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Finishing system update…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> is upgrading…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Viewing full screen"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"To exit, swipe down from the top."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Got it"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotate for a better view"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Exit split screen for a better view"</string>
     <string name="done_label" msgid="7283767013231718521">"Done"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Hours circular slider"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Minutes circular slider"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Allows a companion app to start foreground services from background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microphone is available"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microphone is blocked"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is on"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Device is too warm"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dual Screen is unavailable because your phone is getting too warm"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Turn off"</string>
 </resources>
diff --git a/core/res/res/values-en-rIN-watch/strings.xml b/core/res/res/values-en-rIN-watch/strings.xml
index c738395..21ba346 100644
--- a/core/res/res/values-en-rIN-watch/strings.xml
+++ b/core/res/res/values-en-rIN-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensors"</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 02bea3d..26f73f6 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Allows the app to access body sensor data, such as heart rate, temperature and blood oxygen percentage, while the app is in use."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Access body sensor data, like heart rate, while in the background"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Allows the app to access body sensor data, such as heart rate, temperature and blood oxygen percentage, while the app is in the background."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Access body sensor wrist temperature data while the app is in use."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Allows the app to access body sensor wrist temperature data, while the app is in use."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Access body sensor wrist temperature data while the app is in the background."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Allows the app to access body sensor wrist temperature data, while the app is in the background."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Read calendar events and details"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"This app can read all calendar events stored on your tablet and share or save your calendar data."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"This app can read all calendar events stored on your Android TV device and share or save your calendar data."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android is starting…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet is starting…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Device is starting…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimising storage."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Finishing system update…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> is upgrading…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Viewing full screen"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"To exit, swipe down from the top."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Got it"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotate for a better view"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Exit split screen for a better view"</string>
     <string name="done_label" msgid="7283767013231718521">"Done"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Hours circular slider"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Minutes circular slider"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Ask for password before unpinning"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Allows a companion app to start foreground services from background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microphone is available"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microphone is blocked"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is on"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Device is too warm"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dual Screen is unavailable because your phone is getting too warm"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Turn off"</string>
 </resources>
diff --git a/core/res/res/values-en-rXC-watch/strings.xml b/core/res/res/values-en-rXC-watch/strings.xml
index 6d029e2..4ed361d 100644
--- a/core/res/res/values-en-rXC-watch/strings.xml
+++ b/core/res/res/values-en-rXC-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎App ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ of ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎Sensors‎‏‎‎‏‎"</string>
 </resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index d111611..ab87ab3 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎Allows the app to access body sensor data, such as heart rate, temperature, and blood oxygen percentage, while the app is in use.‎‏‎‎‏‎"</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‎‎Access body sensor data, like heart rate, while in the background‎‏‎‎‏‎"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎Allows the app to access body sensor data, such as heart rate, temperature, and blood oxygen percentage, while the app is in the background.‎‏‎‎‏‎"</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‎‎‏‎Access body sensor wrist temperature data while the app is in use.‎‏‎‎‏‎"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎Allows the app to access body sensor wrist temperature data, while the app is in use.‎‏‎‎‏‎"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎‎‎Access body sensor wrist temperature data while the app is in the background.‎‏‎‎‏‎"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‎‏‎‎‏‏‎Allows the app to access body sensor wrist temperature data, while the app is in the background.‎‏‎‎‏‎"</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎‎‎‎Read calendar events and details‎‏‎‎‏‎"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎This app can read all calendar events stored on your tablet and share or save your calendar data.‎‏‎‎‏‎"</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎This app can read all calendar events stored on your Android TV device and share or save your calendar data.‎‏‎‎‏‎"</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎Android is starting…‎‏‎‎‏‎"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‏‏‏‏‎‏‎‎‏‎‎‎‎Tablet is starting…‎‏‎‎‏‎"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‏‏‎‏‎Device is starting…‎‏‎‎‏‎"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‎Optimizing storage.‎‏‎‎‏‎"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‏‎‏‏‎‎‏‎Finishing system update…‎‏‎‎‏‎"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‎‎‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is upgrading…‎‏‎‎‏‎"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎Optimizing app ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ of ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‏‎‎‎Preparing ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‎Starting apps.‎‏‎‎‏‎"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎Finishing boot.‎‏‎‎‏‎"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‏‎Viewing full screen‎‏‎‎‏‎"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‎‎To exit, swipe down from the top.‎‏‎‎‏‎"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‎Got it‎‏‎‎‏‎"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎Rotate for a better view‎‏‎‎‏‎"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎Exit split screen for a better view‎‏‎‎‏‎"</string>
     <string name="done_label" msgid="7283767013231718521">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎Done‎‏‎‎‏‎"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎Hours circular slider‎‏‎‎‏‎"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‎‎Minutes circular slider‎‏‎‎‏‎"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎Work ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎2nd Work ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‏‎3rd Work ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎Clone ‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎Ask for PIN before unpinning‎‏‎‎‏‎"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎Ask for unlock pattern before unpinning‎‏‎‎‏‎"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎Ask for password before unpinning‎‏‎‎‏‎"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‎Allows a companion app to start foreground services from background.‎‏‎‎‏‎"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎Microphone is available‎‏‎‎‏‎"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎Microphone is blocked‎‏‎‎‏‎"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎Dual screen‎‏‎‎‏‎"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎Dual screen is on‎‏‎‎‏‎"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using both displays to show content‎‏‎‎‏‎"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‎Device is too warm‎‏‎‎‏‎"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎Dual Screen is unavailable because your phone is getting too warm‎‏‎‎‏‎"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‎Turn off‎‏‎‎‏‎"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS-watch/strings.xml b/core/res/res/values-es-rUS-watch/strings.xml
index adaa477..dea270b 100644
--- a/core/res/res/values-es-rUS-watch/strings.xml
+++ b/core/res/res/values-es-rUS-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensores"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index dad0231..0a749df 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite que la app acceda a datos del sensor corporal, como el ritmo cardíaco, la temperatura y el porcentaje de oxígeno en sangre, mientras la app está en uso."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Accede a datos del sensor corporal, como el ritmo cardíaco, en segundo plano"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permite que la app acceda a datos del sensor corporal, como el ritmo cardíaco, la temperatura y el porcentaje de oxígeno en sangre, mientras la app está en segundo plano."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Accede a los datos de temperatura de la muñeca del sensor corporal mientras la app está en uso."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permite que, mientras esté en uso, la app acceda a los datos de temperatura de la muñeca del sensor corporal."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Accede a los datos de temperatura de la muñeca del sensor corporal mientras la app está en segundo plano."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permite que, mientras esté en segundo plano, la app acceda a los datos de temperatura de la muñeca del sensor corporal."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Leer eventos y detalles del calendario"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Esta app puede leer todos los eventos del calendario de tu tablet y compartir o guardar los datos correspondientes."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Esta app puede leer todos los eventos del calendario guardados en el dispositivo Android TV, así como compartir o almacenar los datos correspondientes."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Iniciando Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Iniciando tablet…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Iniciando dispositivo…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimizando almacenamiento"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Finalizando actualización del sistema…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Se está actualizando <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimizando la aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicaciones"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Finalizando el inicio"</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visualización en pantalla completa"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Para salir, desliza el dedo hacia abajo desde la parte superior."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Entendido"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gira la pantalla para obtener una mejor vista"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Sal de la pantalla dividida para obtener una mejor vista"</string>
     <string name="done_label" msgid="7283767013231718521">"Listo"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Control deslizante circular de horas"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Control deslizante circular de minutos"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Clon de <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para quitar fijación"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Solicitar desbloqueo para quitar fijación"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicitar contraseña para quitar fijación"</string>
@@ -2316,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que una aplicación complementaria inicie servicios en primer plano desde el segundo plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"El micrófono está disponible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"El micrófono está bloqueado"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-watch/strings.xml b/core/res/res/values-es-watch/strings.xml
index 4b094e6..dea270b 100644
--- a/core/res/res/values-es-watch/strings.xml
+++ b/core/res/res/values-es-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensores"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index abec04b..40e3b54 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite que la aplicación acceda a datos del sensor corporal, como la frecuencia cardiaca, la temperatura y el porcentaje de oxígeno en sangre, mientras se usa."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Acceso en segundo plano a datos del sensor corporal, como la frecuencia cardiaca"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permite que la aplicación acceda a datos del sensor corporal, como la frecuencia cardiaca, la temperatura y el porcentaje de oxígeno en sangre, mientras está en segundo plano."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Acceder a los datos de temperatura de la muñeca del sensor corporal mientras la aplicación está en uso."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permite que la aplicación acceda a los datos de temperatura de la muñeca del sensor corporal mientras está en uso."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Acceder a los datos de temperatura de la muñeca del sensor corporal mientras la aplicación está en segundo plano."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permite que la aplicación acceda a los datos de temperatura de la muñeca del sensor corporal mientras está en segundo plano."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Leer eventos y detalles del calendario"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Esta aplicación puede leer los eventos de calendario almacenados en tu tablet y compartir o guardar los datos de tu calendario."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Esta aplicación puede ver los eventos de calendario almacenados en tu dispositivo Android TV y compartir o guardar los datos de tu calendario."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android se está iniciando…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"El tablet se está iniciando…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"El dispositivo se está iniciando…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimizando almacenamiento."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Finalizando actualización del sistema…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> se está actualizando…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>..."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicaciones"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Finalizando inicio..."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Modo de pantalla completa"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Para salir, desliza el dedo de arriba abajo."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Entendido"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gira la pantalla para verlo mejor"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Sal de la pantalla dividida para verlo mejor"</string>
     <string name="done_label" msgid="7283767013231718521">"Hecho"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Control deslizante circular de horas"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Control deslizante circular de minutos"</string>
@@ -1862,6 +1858,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para desactivar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir patrón de desbloqueo para dejar de fijar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicitar contraseña para desactivar"</string>
@@ -1953,7 +1951,7 @@
     <string name="work_mode_off_message" msgid="7319580997683623309">"Accede a tus aplicaciones y notificaciones de trabajo"</string>
     <string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string>
     <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Emergencia"</string>
-    <string name="work_mode_dialer_off_message" msgid="2193299184850387465">"Consigue acceso a tus aplicaciones y llamadas de trabajo"</string>
+    <string name="work_mode_dialer_off_message" msgid="2193299184850387465">"Solicita acceso a tus aplicaciones y llamadas de trabajo"</string>
     <string name="app_blocked_title" msgid="7353262160455028160">"La aplicación no está disponible"</string>
     <string name="app_blocked_message" msgid="542972921087873023">"En estos momentos, <xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible."</string>
     <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no disponible"</string>
@@ -2316,4 +2314,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que una aplicación complementaria inicie servicios en primer plano desde el segundo plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"El micrófono está disponible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"El micrófono está bloqueado"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et-watch/strings.xml b/core/res/res/values-et-watch/strings.xml
index bcbe94b..4888bc1 100644
--- a/core/res/res/values-et-watch/strings.xml
+++ b/core/res/res/values-et-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Rakendus <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Andurid"</string>
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index f246539..b15b0f5 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Lubab rakendusel pääseda juurde kehaanduri andmetele, nagu pulss, temperatuur ja vere hapnikusisaldus, kui rakendust kasutatakse."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Juurdepääs kehaanduri andmetele, nagu pulss, kui rakendus töötab taustal"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Lubab rakendusel pääseda juurde kehaanduri andmetele, nagu pulss, temperatuur ja vere hapnikusisaldus, kui rakendus töötab taustal."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Juurdepääs kehaanduri randmetemperatuuri andmetele, kui rakendust kasutatakse."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Lubab rakendusel pääseda juurde kehaanduri randmetemperatuuri andmetele, kui rakendust kasutatakse."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Juurdepääs kehaanduri randmetemperatuuri andmetele, kui rakendus töötab taustal."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Lubab rakendusel pääseda juurde kehaanduri randmetemperatuuri andmetele, kui rakendus töötab taustal."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Kalendrisündmuste ja üksikasjade lugemine"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"See rakendus saab kõiki teie tahvelarvutisse salvestatud kalendrisündmusi lugeda ja teie kalendriandmeid jagada või salvestada."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"See rakendus saab kõiki teie Android TV seadmesse salvestatud kalendrisündmusi lugeda ja teie kalendriandmeid jagada või salvestada."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android käivitub ..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tahvelarvuti käivitub …"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Seade käivitub …"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Salvestusruumi optimeerimine."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Süsteemivärskenduse lõpuleviimine …"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Rakenduse <xliff:g id="APPLICATION">%1$s</xliff:g> versiooni uuendatakse …"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. rakenduse <xliff:g id="NUMBER_1">%2$d</xliff:g>-st optimeerimine."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> ettevalmistamine."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Rakenduste käivitamine."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Käivitamise lõpuleviimine."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Kuvamine täisekraanil"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Väljumiseks pühkige ülevalt alla."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Selge"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Pöörake parema vaate jaoks"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Parema vaate jaoks väljuge jagatud ekraanikuvast"</string>
     <string name="done_label" msgid="7283767013231718521">"Valmis"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Ringikujuline tunniliugur"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Ringikujuline minutiliugur"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Enne vabastamist küsi PIN-koodi"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Enne vabastamist küsi avamismustrit"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Enne vabastamist küsi parooli"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Lubab kaasrakendusel taustal käivitada esiplaanil olevaid teenuseid."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon on saadaval"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon on blokeeritud"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-eu-watch/strings.xml b/core/res/res/values-eu-watch/strings.xml
index d7051bf..7bb5e9d 100644
--- a/core/res/res/values-eu-watch/strings.xml
+++ b/core/res/res/values-eu-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> aplikaz."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sentsoreak"</string>
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 86e804c..28bfaa6 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Aplikazioak erabiltzen diren bitartean, gorputz-sentsoreen datuak (besteak beste, bihotz-maiztasuna, tenperatura eta odolean dagoen oxigenoaren ehunekoa) atzitzeko baimena ematen die aplikazio horiei."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Atzitu gorputz-sentsoreen datuak (adib., bihotz-maiztasunarenak) atzeko planoan"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Aplikazioak atzeko planoan egon bitartean, gorputz-sentsoreen datuak (besteak beste, bihotz-maiztasuna, tenperatura eta odolean dagoen oxigenoaren ehunekoa) atzitzeko baimena ematen die aplikazio horiei."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Atzitu gorputz-sentsoreek eskumuturrean neurtutako tenperaturaren datuak aplikazioak erabili bitartean."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Aplikazioak erabili bitartean, gorputz-sentsoreek eskumuturrean neurtutako tenperaturaren datuak atzitzeko baimena ematen die aplikazioei."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Atzitu gorputz-sentsoreek eskumuturrean neurtutako tenperaturaren datuak aplikazioak atzeko planoan exekutatu bitartean."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Aplikazioak atzeko planoan exekutatu bitartean, gorputz-sentsoreek eskumuturrean neurtutako tenperaturaren datuak atzitzeko baimena ematen die aplikazioei."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"irakurri egutegiko gertaerak eta xehetasunak"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Aplikazioak tabletan gordetako egutegiko gertaerak irakur ditzake eta egutegiko datuak parteka eta gorde ditzake."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Aplikazioak Android TV gailuan gordeta dituzun egutegiko gertaerak irakur ditzake, baita egutegiko datuak partekatu eta gorde ere."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android abiarazten ari da…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tableta abiarazten ari da…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Gailua abiarazten ari da…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Memoria optimizatzen."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Sistema eguneratzen amaitzen…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> bertsio-berritzen ari da…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> aplikazio optimizatzen."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> prestatzen."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Aplikazioak abiarazten."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Bertsio-berritzea amaitzen."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Pantaila osoko ikuspegia"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Irteteko, pasatu hatza goitik behera."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Ados"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Biratu pantaila ikuspegi hobea lortzeko"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Irten pantaila zatitutik ikuspegi hobea lortzeko"</string>
     <string name="done_label" msgid="7283767013231718521">"Eginda"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Ordua aukeratzeko ikuspegi zirkularra"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Minutuak aukeratzeko ikuspegi zirkularra"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Laneko <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Laneko 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Laneko 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Eskatu PINa aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Eskatu desblokeatzeko eredua aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Eskatu pasahitza aingura kendu aurretik"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Aurreko planoko zerbitzuak atzeko planotik abiarazteko baimena ematen die aplikazio osagarriei."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Erabilgarri dago mikrofonoa"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Blokeatuta dago mikrofonoa"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa-watch/strings.xml b/core/res/res/values-fa-watch/strings.xml
index 979dfe4..4bd0216 100644
--- a/core/res/res/values-fa-watch/strings.xml
+++ b/core/res/res/values-fa-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"برنامه <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"حسگرها"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index e1a8322..a208d8c 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"دسترسی به داده‌های دمای مچ دست حسگر بدن درحین استفاده از برنامه."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"به برنامه اجازه می‌دهد تا زمانی که درحال استفاده است، به داده‌های دمای مچ دست حسگر بدن دسترسی داشته باشد."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"دسترسی به داده‌های دمای مچ دست حسگر بدن وقتی برنامه در پس‌زمینه است."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"به برنامه اجازه می‌دهد تا زمانی که در پس‌زمینه است، به داده‌های دمای مچ دست حسگر بدن دسترسی داشته باشد."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"‏Android در حال راه‌اندازی است..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"رایانه لوحی درحال راه‌اندازی است…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"دستگاه درحال راه‌اندازی است…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"بهینه‌سازی فضای ذخیره‌سازی."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"درحال اتمام به‌روزرسانی سیستم…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> درحال ارتقا است...."</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"در حال بهینه‌سازی برنامهٔ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"آماده‌سازی <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"درحال آغاز کردن برنامه‌ها."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"درحال اتمام راه‌اندازی."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"مشاهده در حالت تمام صفحه"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"برای خروج، انگشتتان را از بالای صفحه به پایین بکشید."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"متوجه شدم"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"برای دید بهتر، دستگاه را بچرخانید"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"برای دید بهتر، از صفحهٔ دونیمه خارج شوید"</string>
     <string name="done_label" msgid="7283767013231718521">"تمام"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"لغزنده دایره‌ای ساعت"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"لغزنده دایره‌ای دقیقه"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> محل کار"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"کار دوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"کار سوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"درخواست کد پین قبل از برداشتن پین"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"درخواست الگوی بازگشایی قفل قبل‌از برداشتن سنجاق"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"درخواست گذرواژه قبل از برداشتن سنجاق"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"به برنامه همراه اجازه می‌دهد سرویس‌های پیش‌نما را از پس‌زمینه راه‌اندازی کند."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"میکروفون دردسترس است"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"میکروفون مسدود شد"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi-watch/strings.xml b/core/res/res/values-fi-watch/strings.xml
index 536fdba..d565979c3 100644
--- a/core/res/res/values-fi-watch/strings.xml
+++ b/core/res/res/values-fi-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Sovellus <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Anturit"</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 297278e..b96aba9 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Myöntää sovellukselle pääsyn kehoanturidataan, esim. sykkeeseen, lämpötilaan ja veren happipitoisuuteen, kun sovellusta käytetään."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Pääsy kehoanturidataan, esim. sykkeeseen, kun käynnissä taustalla"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Myöntää sovellukselle pääsyn kehoanturidataan, esim. sykkeeseen, lämpötilaan ja veren happipitoisuuteen, kun sovellus on käynnissä taustalla."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Pääsy kehoanturin ranteen lämpötiladataan, kun sovellusta käytetään."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Myöntää sovellukselle pääsyn kehoanturin ranteen lämpötiladataan, kun sovellusta käytetään."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Pääsy kehoanturin ranteen lämpötiladataan, kun sovellus on käynnissä taustalla."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Myöntää sovellukselle pääsyn kehoanturin ranteen lämpötiladataan, kun sovellus on käynnissä taustalla."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Lue kalenterin tapahtumia ja tietoja"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Tämä sovellus voi lukea kaikkia tabletille tallennettuja kalenteritapahtumia sekä jakaa tai tallentaa kalenteritietoja."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Tämä sovellus voi lukea kaikkia Android TV ‑laitteeseen tallennettuja kalenteritapahtumia sekä jakaa tai tallentaa kalenteritietoja."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android käynnistyy…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tabletti käynnistyy…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Laite käynnistyy…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimoidaan tallennustilaa."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Viimeistellään järjestelmäpäivitystä…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> päivittyy…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimoidaan sovellusta <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Valmistellaan: <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Käynnistetään sovelluksia."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Viimeistellään päivitystä."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Koko ruudun tilassa"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Sulje palkki pyyhkäisemällä alas ruudun ylälaidasta."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Selvä"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Kierrä, niin saat paremman näkymän"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Poistu jaetulta näytöltä, niin saat paremman näkymän"</string>
     <string name="done_label" msgid="7283767013231718521">"Valmis"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Tuntien ympyränmuotoinen liukusäädin"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Minuuttien ympyränmuotoinen liukusäädin"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (työ)"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Toinen <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Kolmas <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pyydä PIN ennen irrotusta"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pyydä lukituksenpoistokuvio ennen irrotusta"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pyydä salasana ennen irrotusta"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Sallii kumppanisovelluksen aloittaa etualan palveluja taustalla."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofoni on käytettävissä"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofoni on estetty"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA-watch/strings.xml b/core/res/res/values-fr-rCA-watch/strings.xml
index a3316ab..dc71b35 100644
--- a/core/res/res/values-fr-rCA-watch/strings.xml
+++ b/core/res/res/values-fr-rCA-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Appli <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Capteurs"</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index adc0f98..e00b0f5 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permet à l\'application d\'accéder aux données des capteurs corporels telles que la fréquence cardiaque, la température et le pourcentage d\'oxygène dans le sang pendant l\'utilisation de l\'application."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Accéder aux données des capteurs corporels (comme la fréq. card.) en arrière-plan"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permet à l\'application d\'accéder aux données des capteurs corporels telles que la fréquence cardiaque, la température et le pourcentage d\'oxygène dans le sang pendant que l\'application s\'exécute en arrière-plan."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Accéder aux données relatives à la température au poignet des capteurs corporels pendant l\'utilisation de l\'application."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permet à l\'application d\'accéder aux données relatives à la température au poignet des capteurs corporels pendant l\'utilisation de l\'application."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Accéder aux données relatives à la température au poignet des capteurs corporels pendant que l\'application s\'exécute en arrière-plan."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permet à l\'application d\'accéder aux données relatives à la température au poignet des capteurs corporels pendant que l\'application s\'exécute en arrière-plan."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Lire les événements d\'agenda et leurs détails"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Cette application peut lire tous les événements d\'agenda stockés sur votre tablette et partager ou enregistrer les données de votre agenda."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Cette application peut lire tous les événements d\'agenda stockés sur votre appareil Android TV et partager ou enregistrer les données de votre agenda."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android en cours de démarrage..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Démarrage de la tablette en cours…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Démarrage de l\'appareil en cours…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimisation du stockage."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Finalisation de la m. à j. syst. en cours…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Mise à niveau de <xliff:g id="APPLICATION">%1$s</xliff:g> en cours…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimisation de l\'application <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>…"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Préparation de <xliff:g id="APPNAME">%1$s</xliff:g> en cours…"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Lancement des applications…"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Finalisation de la mise à jour."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Affichage plein écran"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Pour quitter, balayez vers le bas à partir du haut."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Faire pivoter pour obtenir un meilleur affichage"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Quitter l\'écran partagé pour obtenir un meilleur affichage"</string>
     <string name="done_label" msgid="7283767013231718521">"Terminé"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Curseur circulaire des heures"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Curseur circulaire des minutes"</string>
@@ -1862,6 +1858,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Demander le NIP avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
@@ -2316,4 +2314,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permet à une application compagnon en arrière-plan de lancer des services d\'avant-plan."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Le microphone est accessible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Le microphone est bloqué"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-watch/strings.xml b/core/res/res/values-fr-watch/strings.xml
index f0574b5..dc71b35 100644
--- a/core/res/res/values-fr-watch/strings.xml
+++ b/core/res/res/values-fr-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Appli <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Capteurs"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index ea481cd..4f54214 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permet à l\'appli d\'accéder aux données des capteurs corporels (fréquence cardiaque, température, taux d\'oxygène dans le sang, etc.) quand l\'appli est en cours d\'utilisation."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Accéder aux données de capteurs corporels (comme le pouls) en arrière-plan"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permet à l\'appli d\'accéder aux données des capteurs corporels (fréquence cardiaque, température, taux d\'oxygène dans le sang, etc.) quand l\'appli est en arrière-plan."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Accédez aux données des capteurs corporels relatives à la température du poignet quand l\'appli est en cours d\'utilisation."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permet à l\'appli d\'accéder aux données des capteurs corporels relatives à la température du poignet quand l\'appli est en cours d\'utilisation."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Accédez aux données des capteurs corporels relatives à la température du poignet quand l\'appli est en arrière-plan."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permet à l\'appli d\'accéder aux données des capteurs corporels relatives à la température du poignet quand l\'appli est en arrière-plan."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Lire les événements d\'agenda et les détails associés"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Cette application peut lire tous les événements d\'agenda enregistrés sur votre tablette et partager ou enregistrer vos données d\'agenda."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Cette application peut lire tous les événements de l\'agenda enregistrés sur votre appareil Android TV, et partager ou enregistrer les données de votre agenda."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Démarrage d\'Android en cours"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Démarrage de la tablette…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Démarrage de l\'appareil…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimisation du stockage en cours…"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Finalisation de la mise à jour du système…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Mise à jour de l\'application <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimisation de l\'application <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>…"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Préparation de <xliff:g id="APPNAME">%1$s</xliff:g> en cours…"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Lancement des applications…"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Finalisation de la mise à jour."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Affichage en plein écran"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Pour quitter, balayez l\'écran du haut vers le bas."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Faites pivoter pour mieux voir"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Quittez l\'écran partagé pour mieux voir"</string>
     <string name="done_label" msgid="7283767013231718521">"OK"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Curseur circulaire des heures"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Curseur circulaire des minutes"</string>
@@ -1862,6 +1858,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (pro)"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Demander le code avant de retirer l\'épingle"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Demander le schéma de déverrouillage avant de retirer l\'épingle"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demander le mot de passe avant de retirer l\'épingle"</string>
@@ -2316,4 +2314,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Autorise une application associée à lancer des services de premier plan à partir de l\'arrière-plan."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Le micro est disponible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Le micro est bloqué"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gl-watch/strings.xml b/core/res/res/values-gl-watch/strings.xml
index 4b094e6..dea270b 100644
--- a/core/res/res/values-gl-watch/strings.xml
+++ b/core/res/res/values-gl-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensores"</string>
 </resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 735a4d5d..486b14f 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -393,7 +393,7 @@
     <string name="permlab_useDataInBackground" msgid="783415807623038947">"usar datos en segundo plano"</string>
     <string name="permdesc_useDataInBackground" msgid="1230753883865891987">"Esta aplicación pode usar datos en segundo plano. Por este motivo, quizais aumente o uso de datos."</string>
     <string name="permlab_schedule_exact_alarm" msgid="6683283918033029730">"Planificar accións para que se leven a cabo nun momento determinado"</string>
-    <string name="permdesc_schedule_exact_alarm" msgid="8198009212013211497">"Esta aplicación pode planificar o traballo para que se leve a cabo nun momento determinado no futuro. Isto tamén supón que a aplicación poderá executarse cando non esteas usando o dispositivo de forma activa."</string>
+    <string name="permdesc_schedule_exact_alarm" msgid="8198009212013211497">"Esta aplicación pode planificar accións para que se leven a cabo nun momento determinado no futuro. Isto tamén supón que a aplicación poderá executarse cando non esteas usando o dispositivo de forma activa."</string>
     <string name="permlab_use_exact_alarm" msgid="348045139777131552">"Planificar alarmas ou recordatorios de eventos"</string>
     <string name="permdesc_use_exact_alarm" msgid="7033761461886938912">"Esta aplicación pode planificar accións (por exemplo, alarmas ou recordatorios) para enviarche notificacións nun momento determinado no futuro."</string>
     <string name="permlab_persistentActivity" msgid="464970041740567970">"facer que a aplicación se execute sempre"</string>
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite que a aplicación acceda aos datos dos sensores corporais (por exemplo, a frecuencia cardíaca, a temperatura ou a porcentaxe de osíxeno en sangue) mentres se estea utilizando."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Acceso en segundo plano aos datos dos sensores corporais, como a frecuencia cardíaca"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permite que a aplicación acceda aos datos dos sensores corporais (por exemplo, a frecuencia cardíaca, a temperatura ou a porcentaxe de osíxeno en sangue) mentres se estea executando en segundo plano."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Acceder aos datos de temperatura do sensor corporal do pulso mentres se está utilizando a aplicación."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permite que a aplicación acceda aos datos de temperatura do sensor corporal do pulso mentres se está utilizando a aplicación."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Acceder aos datos de temperatura do sensor corporal do pulso mentres a aplicación está en segundo plano."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permite que a aplicación acceda aos datos de temperatura do sensor corporal do pulso mentres a aplicación está en segundo plano."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Ler os detalles e os eventos do calendario"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Esta aplicación pode ler todos os eventos do calendario almacenados na túa tableta e compartir ou gardar os datos do calendario."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Esta aplicación pode ler todos os eventos do calendario almacenados no dispositivo Android TV e compartir ou gardar os datos do calendario."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Estase iniciando Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"A tableta estase iniciando…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"O dispositivo estase iniciando…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimizando almacenamento."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Finalizando actualización do sistema…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Actualizando <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicacións."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Está finalizando o arranque"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Vendo pantalla completa"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Para saír, pasa o dedo cara abaixo desde a parte superior."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Entendido"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Xira a pantalla para que se vexa mellor"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Sae da pantalla dividida para que se vexa mellor"</string>
     <string name="done_label" msgid="7283767013231718521">"Feito"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Control desprazable circular das horas"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Control desprazable circular dos minutos"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de soltar a fixación"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrón de desbloqueo antes de soltar a fixación"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir contrasinal antes de soltar a fixación"</string>
@@ -2312,7 +2310,19 @@
     <string name="permlab_deliverCompanionMessages" msgid="3931552294842980887">"Enviar mensaxes complementarias"</string>
     <string name="permdesc_deliverCompanionMessages" msgid="2170847384281412850">"Permite que unha aplicación complementaria envíe mensaxes complementarias a outros dispositivos."</string>
     <string name="permlab_startForegroundServicesFromBackground" msgid="6363004936218638382">"Desde un segundo plano iniciar servizos en primeiro plano"</string>
-    <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que nun segundo plano unha aplicación complementaria inicie servizos en primeiro plano."</string>
+    <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que unha aplicación complementaria, desde un segundo plano, inicie servizos en primeiro plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"O micrófono está dispoñible"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"O micrófono está bloqueado"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gu-watch/strings.xml b/core/res/res/values-gu-watch/strings.xml
index 3a03f359..8d38a68 100644
--- a/core/res/res/values-gu-watch/strings.xml
+++ b/core/res/res/values-gu-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g> માંથી <xliff:g id="NUMBER_0">%1$d</xliff:g> ઍપ્લિકેશન."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"સેન્સર્સ"</string>
 </resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 00bddbb..2889652 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ઍપનો ઉપયોગ થઈ રહ્યો હોય ત્યારે કાંડા મારફતે મપાયેલા શરીરના તાપમાન સંબંધિત બૉડી સેન્સરનો ડેટા ઍક્સેસ કરો."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"ઍપનો ઉપયોગ થઈ રહ્યો હોય ત્યારે કાંડા મારફતે મપાયેલા શરીરના તાપમાન સંબંધિત બૉડી સેન્સરનો ડેટા ઍક્સેસ કરવાની ઍપને મંજૂરી આપે છે."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"બૅકગ્રાઉન્ડમાં ઍપ ચાલી રહી હોય ત્યારે કાંડા મારફતે મપાયેલા શરીરના તાપમાન સંબંધિત બૉડી સેન્સરનો ડેટા ઍક્સેસ કરો."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"બૅકગ્રાઉન્ડમાં ઍપ ચાલી રહી હોય ત્યારે કાંડા મારફતે મપાયેલા શરીરના તાપમાન સંબંધિત બૉડી સેન્સરનો ડેટા ઍક્સેસ કરવાની ઍપને મંજૂરી આપે છે."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android પ્રારંભ થઈ રહ્યું છે…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ટૅબ્લેટ શરૂ થઈ રહ્યું છે…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ઉપકરણ શરૂ થઈ રહ્યું છે…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"સંગ્રહ ઓપ્ટિમાઇઝ કરી રહ્યું છે."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"સિસ્ટમ અપડેટ સમાપ્ત કરી રહ્યાં છીએ…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> અપગ્રેડ થઈ રહી છે…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> માંથી <xliff:g id="NUMBER_0">%1$d</xliff:g> ઍપ્લિકેશન ઓપ્ટિમાઇઝ કરી રહ્યું છે."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> તૈયાર કરી રહ્યું છે."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ઍપ્લિકેશનો શરૂ કરી રહ્યાં છે."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"બૂટ સમાપ્ત કરી રહ્યાં છે."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"પૂર્ણ સ્ક્રીન પર જુઓ"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"બહાર નીકળવા માટે, ટોચ પરથી નીચે સ્વાઇપ કરો."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"સમજાઈ ગયું"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"બહેતર વ્યૂ માટે ફેરવો"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"બહેતર વ્યૂ માટે, વિભાજિત સ્ક્રીનમાંથી બહાર નીકળો"</string>
     <string name="done_label" msgid="7283767013231718521">"થઈ ગયું"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"કલાકનું વર્તુળાકાર સ્લાઇડર"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"મિનિટનું વર્તુળાકાર સ્લાઇડર"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"ઑફિસ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"અનપિન કરતા પહેલાં પિન માટે પૂછો"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"અનપિન કરતા પહેલાં અનલૉક પૅટર્ન માટે પૂછો"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"અનપિન કરતાં પહેલાં પાસવર્ડ માટે પૂછો"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"સાથી ઍપને બૅકગ્રાઉન્ડમાંથી ફૉરગ્રાઉન્ડ સેવાઓ શરૂ કરવાની મંજૂરી આપે છે."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"માઇક્રોફોન ઉપલબ્ધ છે"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"માઇક્રોફોનને બ્લૉક કરવામાં આવ્યો છે"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi-watch/strings.xml b/core/res/res/values-hi-watch/strings.xml
index f4c82f1..e73ce77 100644
--- a/core/res/res/values-hi-watch/strings.xml
+++ b/core/res/res/values-hi-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g> में से <xliff:g id="NUMBER_0">%1$d</xliff:g> ऐप."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"संवेदक"</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 65b1242..20b2d33 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ऐप्लिकेशन को यह अनुमति दें कि जब उसे इस्तेमाल किया जा रहा हो, तब वह आपके शरीर के उस तापमान का डेटा ऐक्सेस कर पाए जो बॉडी सेंसर ने सोते समय रिकॉर्ड किया है."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"इससे ऐप्लिकेशन, आपके शरीर के उस तापमान का डेटा ऐक्सेस कर पाएगा जो बॉडी सेंसर ने सोते समय रिकॉर्ड किया है. इस डेटा का ऐक्सेस उस समय मिलेगा जब ऐप्लिकेशन का इस्तेमाल किया जा रहा हो."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"ऐप्लिकेशन को यह अनुमति दें कि बैकग्राउंड में चलते समय, वह आपके शरीर के उस तापमान का डेटा ऐक्सेस कर पाए जो बॉडी सेंसर ने सोते समय रिकॉर्ड किया है."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"इससे ऐप्लिकेशन, आपके शरीर के उस तापमान का डेटा ऐक्सेस कर पाएगा जो बॉडी सेंसर ने सोते समय रिकॉर्ड किया है. इस डेटा का ऐक्सेस उस समय मिलेगा जब ऐप्लिकेशन बैकग्राउंड में चल रहा होगा."</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">"यह ऐप्लिकेशन आपके टीवी पर सेव किए गए सभी कैलेंडर इवेंट को पढ़ सकता है. इसके अलावा यह आपके कैलेंडर का डेटा शेयर कर सकता है या सेव कर सकता है."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android प्रारंभ हो रहा है…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"टैबलेट चालू हो रहा है…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"डिवाइस चालू हो रहा है…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"मेमोरी ऑप्‍टिमाइज़ हो रही है."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"सिस्टम अपडेट पूरा होने वाला है…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> अपग्रेड हो रहा है…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> में से <xliff:g id="NUMBER_0">%1$d</xliff:g> ऐप्स  अनुकूलित हो रहा है."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> तैयार हो रहा है."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ऐप्स  प्रारंभ होने वाले हैं"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"बूट खत्म हो रहा है."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"आप पूरे स्क्रीन पर देख रहे हैं"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"बाहर निकलने के लिए, ऊपर से नीचे स्वा‍इप करें."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"ठीक है"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"बेहतर व्यू पाने के लिए, डिवाइस की स्क्रीन को घुमाएं"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"बेहतर व्यू पाने के लिए, स्प्लिट स्क्रीन मोड बंद करें"</string>
     <string name="done_label" msgid="7283767013231718521">"हो गया"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"घंटो का चक्राकार स्लाइडर"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"मिनटों का चक्राकार स्लाइडर"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"दफ़्तर का <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"दूसरा काम <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"तीसरा काम <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन करने से पहले पिन के लिए पूछें"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन करने से पहले लॉक खोलने के पैटर्न के लिए पूछें"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string>
@@ -2315,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"इससे साथी ऐप्लिकेशन को बैकग्राउंड में फ़ोरग्राउंड सेवाएं चलाने की अनुमति मिलती है."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"माइक्रोफ़ोन इस्तेमाल किया जा सकता है"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"माइक्रोफ़ोन को ब्लॉक किया गया है"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ड्यूअल स्क्रीन"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"ड्यूअल स्क्रीन की सुविधा चालू है"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>, कॉन्टेंट दिखाने के लिए दोनों डिसप्ले का इस्तेमाल कर रहा है"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"आपका फ़ोन बहुत गर्म हो गया है"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ड्यूअल स्क्रीन की सुविधा अभी उपलब्ध नहीं है, क्योंकि आपका फ़ोन बहुत गर्म हो रहा है"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"बंद करें"</string>
 </resources>
diff --git a/core/res/res/values-hr-watch/strings.xml b/core/res/res/values-hr-watch/strings.xml
index 699c148..da58726 100644
--- a/core/res/res/values-hr-watch/strings.xml
+++ b/core/res/res/values-hr-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplikacija <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Senzori"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 85a4c45..95e17b5 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Omogućuje aplikaciji pristup podacima s biometrijskih senzora, kao što su puls, temperatura i postotak kisika u krvi, dok se aplikacija upotrebljava."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Pristup podacima s biometrijskih senzora, kao što je puls, dok je u pozadini"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Omogućuje aplikaciji pristup podacima s biometrijskih senzora, kao što su puls, temperatura i postotak kisika u krvi, dok je aplikacija u pozadini."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Pristupite podacima o temperaturi na zapešću s biometrijskog senzora dok se aplikacija koristi."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Omogućuje aplikaciji da pristupi podacima o temperaturi na zapešću s biometrijskog senzora dok se aplikacija koristi."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Pristupite podacima o temperaturi na zapešću s biometrijskog senzora dok je aplikacija u pozadini."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Omogućuje aplikaciji da pristupi podacima o temperaturi na zapešću s biometrijskog senzora dok je aplikacija u pozadini."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Čitanje događaja i pojedinosti kalendara"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Aplikacija može čitati sve kalendarske događaje pohranjene na tabletu i dijeliti ili spremati podatke iz vašeg kalendara."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Aplikacija može čitati sve kalendarske događaje pohranjene na Android TV uređaju i dijeliti ili spremati podatke iz vašeg kalendara."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Pokretanje Androida..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet se pokreće…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Uređaj se pokreće…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimiziranje pohrane."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Dovršavanje ažuriranja sustava…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Nadogradnja aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimiziranje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Pripremanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Pokretanje aplikacija."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Završetak inicijalizacije."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Gledanje preko cijelog zaslona"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Za izlaz prijeđite prstom od vrha prema dolje."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Shvaćam"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Zakrenite kako biste bolje vidjeli"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Zatvorite podijeljeni zaslon kako biste bolje vidjeli"</string>
     <string name="done_label" msgid="7283767013231718521">"Gotovo"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Kružni klizač sati"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Kružni klizač minuta"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Kloniraj <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN radi otkvačivanja"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži uzorak za otključavanje radi otkvačivanja"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži zaporku radi otkvačivanja"</string>
@@ -2316,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Popratnoj aplikaciji omogućuje da iz pozadine pokrene usluge u prednjem planu."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je dostupan"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je blokiran"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dvostruki zaslon"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Uključen je dvostruki zaslon"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> upotrebljava oba zaslona za prikazivanje sadržaja"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Uređaj se pregrijao"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvostruki zaslon nije podržan jer se vaš telefon pregrijao"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Isključi"</string>
 </resources>
diff --git a/core/res/res/values-hu-watch/strings.xml b/core/res/res/values-hu-watch/strings.xml
index a038ffa..b8053c1 100644
--- a/core/res/res/values-hu-watch/strings.xml
+++ b/core/res/res/values-hu-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>. alkalmazás"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Érzékelők"</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 0c9a6cd..875be30 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Lehetővé teszi, hogy az alkalmazás hozzáférjen a testérzékelők adataihoz (pl. pulzusszám, testhőmérséklet és véroxigénszint), miközben az alkalmazás használatban van."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Hozzáférés a testérzékelők adataihoz (pl. pulzusszám) a háttérben"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Lehetővé teszi, hogy az alkalmazás hozzáférjen a testérzékelők adataihoz (pl. pulzusszám, testhőmérséklet és véroxigénszint), miközben az alkalmazás a háttérben van."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Hozzáférés a testérzékelő által a csuklón mért hőmérsékletadatokhoz, miközben az alkalmazás használatban van."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Lehetővé teszi, hogy az alkalmazás hozzáférjen a testérzékelő által a csuklón mért hőmérsékletadatokhoz, miközben az alkalmazás használatban van."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Hozzáférés a testérzékelő által a csuklón mért hőmérsékletadatokhoz, miközben az alkalmazás a háttérben van."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Lehetővé teszi, hogy az alkalmazás hozzáférjen a testérzékelő által a csuklón mért hőmérsékletadatokhoz, miközben az alkalmazás a háttérben van."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Naptáresemények és a naptári adatok olvasása"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Az alkalmazás olvashatja a táblagépen tárolt összes naptáreseményt, és megoszthatja vagy mentheti a naptáradatokat."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Az alkalmazás olvashatja az Android TV eszközön tárolt összes naptáreseményt, és megoszthatja vagy mentheti a naptáradatokat."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Az Android indítása…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"A táblagép indítása…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Az eszköz indítása…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Tárhely-optimalizálás."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"A rendszerfrissítés befejezése…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> frissítése folyamatban van"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Alkalmazás optimalizálása: <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> előkészítése."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Kezdő alkalmazások."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Rendszerindítás befejezése."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Megtekintése teljes képernyőn"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Kilépéshez csúsztassa ujját fentről lefelé."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Értem"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Forgassa el a jobb élmény érdekében"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Lépjen ki az osztott képernyős módból a jobb élmény érdekében"</string>
     <string name="done_label" msgid="7283767013231718521">"Kész"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Óra kör alakú csúszkája"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Perc kör alakú csúszkája"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> klónozása"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-kód kérése a kitűzés feloldásához"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Feloldási minta kérése a rögzítés feloldásához"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Jelszó kérése a rögzítés feloldásához"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Lehetővé teszi a társalkalmazások számára, hogy előtérben futó szolgáltatásokat indítsanak a háttérből."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"A mikrofon rendelkezésre áll"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"A mikrofon le van tiltva"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hy-watch/strings.xml b/core/res/res/values-hy-watch/strings.xml
index a8197d3..4966e04 100644
--- a/core/res/res/values-hy-watch/strings.xml
+++ b/core/res/res/values-hy-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Հավելված <xliff:g id="NUMBER_0">%1$d</xliff:g>՝ <xliff:g id="NUMBER_1">%2$d</xliff:g>-ից:"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Սենսորներ"</string>
 </resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 3c2b686..2e2da4e 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Մարմնի սենսորների՝ դաստակի ջերմաստիճանի մասին տվյալների հասանելիություն հավելվածի օգտագործման ընթացքում։"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Գործարկված հավելվածին հասանելի է դարձնում մարմնի սենսորների՝ դաստակի ջերմաստիճանի մասին տվյալները։"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Մարմնի սենսորների՝ դաստակի ջերմաստիճանի մասին տվյալների հասանելիություն ֆոնային ռեժիմում։"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Ֆոնային ռեժիմում գործարկված հավելվածին հասանելի է դարձնում մարմնի սենսորների՝ դաստակի ջերմաստիճանի մասին տվյալները։"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android-ը մեկնարկում է…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Պլանշետը միանում է…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Սարքը միանում է…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Պահեստի օպտիմալացում:"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Համակարգի թարմացումը շուտով կվերջանա…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը նորացվում է…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Օպտիմալացվում է հավելված <xliff:g id="NUMBER_0">%1$d</xliff:g>-ը <xliff:g id="NUMBER_1">%2$d</xliff:g>-ից:"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը պատրաստվում է:"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Հավելվածները մեկնարկում են:"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Բեռնումն ավարտվում է:"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Լիաէկրան դիտում"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Դուրս գալու համար վերևից սահահարվածեք դեպի ներքև:"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Պարզ է"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Պտտեք՝ դիտակերպը լավացնելու համար"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Դուրս եկեք կիսված էկրանի ռեժիմից՝ դիտակերպը լավացնելու համար"</string>
     <string name="done_label" msgid="7283767013231718521">"Պատրաստ է"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Ժամերի ընտրություն թվատախտակից"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Րոպեների ընտրություն թվատախտակից"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Աշխատանքային <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Հարցնել PIN կոդը"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Հարցնել ապակողպող նախշը"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Հարցնել գաղտնաբառը"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Թույլատրում է ուղեկցող հավելվածին ակտիվ ծառայություններ գործարկել ֆոնային ռեժիմից։"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Խոսափողը հասանելի է"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Խոսափողն արգելափակված է"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in-watch/strings.xml b/core/res/res/values-in-watch/strings.xml
index e7dc878..4d64473 100644
--- a/core/res/res/values-in-watch/strings.xml
+++ b/core/res/res/values-in-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplikasi <xliff:g id="NUMBER_0">%1$d</xliff:g> dari <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensor"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index ce78f79..6ba9169 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Mengizinkan aplikasi mengakses data sensor tubuh, seperti detak jantung, suhu, dan persentase oksigen dalam darah, saat aplikasi sedang digunakan."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Mengakses data sensor tubuh, seperti detak jantung, saat ada di latar belakang"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Mengizinkan aplikasi mengakses data sensor tubuh, seperti detak jantung, suhu, dan persentase oksigen dalam darah, saat aplikasi berada di latar belakang."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Mengakses data suhu pergelangan tangan sensor tubuh saat aplikasi sedang digunakan."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Mengizinkan aplikasi mengakses data suhu pergelangan tangan sensor tubuh, saat aplikasi sedang digunakan."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Mengakses data suhu pergelangan tangan sensor tubuh saat aplikasi sedang berada di latar belakang."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Mengizinkan aplikasi mengakses data suhu pergelangan tangan sensor tubuh, saat aplikasi sedang berada di latar belakang."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Baca acara kalender dan detailnya"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Aplikasi ini dapat membaca semua acara kalender yang tersimpan di tablet dan membagikan atau menyimpan data kalender."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Aplikasi ini dapat membaca semua acara kalender yang tersimpan di perangkat Android TV dan membagikan atau menyimpan data kalender."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Memulai Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Menyalakan tablet…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Menyalakan perangkat…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Mengoptimalkan penyimpanan."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Menyelesaikan update sistem…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> sedang ditingkatkan versinya…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Mengoptimalkan aplikasi <xliff:g id="NUMBER_0">%1$d</xliff:g> dari <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Menyiapkan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Memulai aplikasi."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Menyelesaikan boot."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Melihat layar penuh"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Untuk keluar, geser layar ke bawah dari atas."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Mengerti"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Putar posisi layar untuk mendapatkan tampilan yang lebih baik"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Keluar dari layar terpisah untuk mendapatkan tampilan yang lebih baik"</string>
     <string name="done_label" msgid="7283767013231718521">"Selesai"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Penggeser putar jam"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Penggeser putar menit"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Kantor <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Upaya ke-2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Upaya ke-3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Meminta PIN sebelum melepas sematan"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Meminta pola pembukaan kunci sebelum melepas sematan"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Meminta sandi sebelum melepas sematan"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Mengizinkan aplikasi pendamping memulai layanan latar depan dari latar belakang."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon tersedia"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon diblokir"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-is-watch/strings.xml b/core/res/res/values-is-watch/strings.xml
index 7286ac0..041a534 100644
--- a/core/res/res/values-is-watch/strings.xml
+++ b/core/res/res/values-is-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Forrit <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Skynjarar"</string>
 </resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index cba0380..5b5a9b1 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Veitir forritinu aðgang að gögnum frá líkamsskynjurum, svo sem um hjartslátt, hitastig og súrefnismettun í blóði á meðan forritið er í notkun."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Aðgangur að gögnum líkamsskynjara, t.d. um hjartslátt, meðan það er í bakgrunni"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Veitir forritinu aðgang að gögnum frá líkamsskynjurum, svo sem um hjartslátt, hitastig og súrefnismettun í blóði á meðan forritið keyrir í bakgrunni."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Aðgangur að gögnum um úlnliðshita frá líkamsskynjurum á meðan forritið er í notkun."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Veitir forritinu aðgang að gögnum um úlnliðshita frá líkamsskynjurum á meðan forritið er í notkun."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Aðgangur að gögnum um úlnliðshita frá líkamsskynjurum á meðan forritið er í bakgrunni."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Veitir forritinu aðgang að gögnum um úlnliðshita frá líkamsskynjurum á meðan forritið er í bakgrunni."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Lesa dagatalsviðburði og upplýsingar"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Þetta forrit getur lesið alla dagatalsviðburði sem eru vistaðir í spjaldtölvunni og deilt eða vistað dagatalsgögnin þín."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Þetta forrit getur lesið alla dagatalsviðburði sem eru vistaðir í Android TV og deilt eða vistað dagatalsgögnin þín."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android er að ræsast…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Spjaldtölvan kveikir á sér…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Tækið kveikir á sér…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Fínstillir geymslu."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Lýkur við kerfisuppfærslu…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> uppfærir…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Fínstillir forrit <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Undirbýr <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Ræsir forrit."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Lýkur ræsingu."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Notar allan skjáinn"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Strjúktu niður frá efri brún til að hætta."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Ég skil"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Snúðu til að sjá betur"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Lokaðu skjáskiptingu til að sjá betur"</string>
     <string name="done_label" msgid="7283767013231718521">"Lokið"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Valskífa fyrir klukkustundir"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Valskífa fyrir mínútur"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (2)"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (3)"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Biðja um PIN-númer til að losa"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Biðja um opnunarmynstur til að losa"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Biðja um aðgangsorð til að losa"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Leyfir fylgiforriti að ræsa forgrunnsþjónustur úr bakgrunni."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Hljóðnemi er í boði"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Lokað er fyrir hljóðnemann"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it-watch/strings.xml b/core/res/res/values-it-watch/strings.xml
index e74d3d7..e22f614 100644
--- a/core/res/res/values-it-watch/strings.xml
+++ b/core/res/res/values-it-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> di <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensori"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bfa9666..caa1856 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Autorizza l\'app ad accedere ai dati dei sensori del corpo, ad esempio battito cardiaco, temperatura e percentuale di ossigeno nel sangue, mentre l\'app è in uso."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Accesso ai dati dei sensori del corpo, come il battito cardiaco, in background"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Autorizza l\'app ad accedere ai dati dei sensori del corpo, ad esempio battito cardiaco, temperatura e percentuale di ossigeno nel sangue, mentre l\'app è in background."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Accesso ai dati della temperatura del polso misurata dal sensore del corpo mentre l\'app è in uso."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Consente all\'app, mentre è in uso, di accedere ai dati della temperatura del polso misurata dal sensore del corpo."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Accesso ai dati della temperatura del polso misurata dal sensore del corpo mentre l\'app è in background."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Consente all\'app, mentre è in background, di accedere ai dati della temperatura del polso misurata dal sensore del corpo."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"lettura di eventi di calendario e dettagli"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Questa app può leggere tutti gli eventi di calendario memorizzati sul tablet e condividere o salvare i dati di calendario."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Questa app può leggere tutti gli eventi di calendario memorizzati sul dispositivo Android TV e condividere o salvare i dati di calendario."</string>
@@ -1034,7 +1030,7 @@
     <string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"Selettore utente"</string>
     <string name="keyguard_accessibility_status" msgid="6792745049712397237">"Stato"</string>
     <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"Fotocamera"</string>
-    <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Controlli media"</string>
+    <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Controlli multimediali"</string>
     <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"Riordino dei widget iniziato."</string>
     <string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"Riordino dei widget terminato."</string>
     <string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> eliminato."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Avvio di Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Avvio del tablet…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Avvio del dispositivo…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Ottimizzazione archiviazione."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Completamento aggiornamento di sistema…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Upgrade dell\'app <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Ottimizzazione applicazione <xliff:g id="NUMBER_0">%1$d</xliff:g> di <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> in preparazione."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Avvio app."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Conclusione dell\'avvio."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visualizzazione a schermo intero"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Per uscire, scorri dall\'alto verso il basso."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Ruota per migliorare l\'anteprima"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Esci dallo schermo diviso per migliorare l\'anteprima"</string>
     <string name="done_label" msgid="7283767013231718521">"Fine"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Dispositivo di scorrimento circolare per le ore"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Dispositivo di scorrimento circolare per i minuti"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> lavoro"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (2°)"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (3°)"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> (clone)"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Richiedi il PIN per lo sblocco"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Richiedi sequenza di sblocco prima di sbloccare"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Richiedi password prima di sbloccare"</string>
@@ -2316,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Consente a un\'app complementare di avviare servizi in primo piano dal background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microfono disponibile"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microfono bloccato"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Doppio schermo"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Doppio schermo attivo"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> sta usando entrambi i display per mostrare contenuti"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Il dispositivo è troppo caldo"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Il doppio schermo non è disponibile perché il telefono si sta surriscaldando"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Disattiva"</string>
 </resources>
diff --git a/core/res/res/values-iw-watch/strings.xml b/core/res/res/values-iw-watch/strings.xml
index 3f0912f..d03a499 100644
--- a/core/res/res/values-iw-watch/strings.xml
+++ b/core/res/res/values-iw-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"אפליקציה <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"חיישנים"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 7315331..c92a032 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -459,14 +459,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"הרשאת גישה לנתונים של החיישן הלביש, כמו טמפרטורת פרק כף היד, כשנעשה שימוש באפליקציה."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"ההרשאה מאפשרת לאפליקציה לגשת לנתונים של החיישן הלביש, כמו טמפרטורת פרק כף היד, כשנעשה שימוש באפליקציה."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"הרשאת גישה לנתונים של החיישן הלביש, כמו טמפרטורת פרק כף היד, כשהאפליקציה פועלת ברקע."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"ההרשאה מאפשרת לאפליקציה לגשת לנתונים של החיישן הלביש, כמו טמפרטורת פרק כף היד, כשהאפליקציה פועלת ברקע."</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>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"‏הפעלת Android מתחילה…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"הטאבלט בתהליך הפעלה…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"הפעלת המכשיר מתחילה…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"מתבצעת אופטימיזציה של האחסון."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"עדכון המערכת לקראת סיום…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> בתהליך שדרוג…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"מתבצעת אופטימיזציה של אפליקציה <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"המערכת מכינה את <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"מתבצעת הפעלה של אפליקציות."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"תהליך האתחול בשלבי סיום."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"צפייה במסך מלא"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"כדי לצאת, פשוט מחליקים אצבע מלמעלה למטה."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"הבנתי"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"מסובבים כדי לראות טוב יותר"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"צריך לצאת מהמסך המפוצל כדי לראות טוב יותר"</string>
     <string name="done_label" msgid="7283767013231718521">"סיום"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"מחוון שעות מעגלי"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"מחוון דקות מעגלי"</string>
@@ -1862,6 +1858,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"עבודה <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> שני בעבודה"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> שלישי בעבודה"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"יש לבקש קוד אימות לפני ביטול הצמדה"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"צריך לבקש קו ביטול נעילה לפני ביטול הצמדה"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"יש לבקש סיסמה לפני ביטול הצמדה"</string>
@@ -2316,4 +2314,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ההרשאה הזו מאפשרת לאפליקציה נלווית להפעיל מהרקע שירותים שפועלים בחזית."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"המיקרופון זמין"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"המיקרופון חסום"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja-watch/strings.xml b/core/res/res/values-ja-watch/strings.xml
index 62b7007..05ee203 100644
--- a/core/res/res/values-ja-watch/strings.xml
+++ b/core/res/res/values-ja-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"アプリ<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"センサー"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 52d018c..1f272a3 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"アプリの使用中にボディセンサーの手首の体温データにアクセスします。"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"アプリの使用中に、ボディセンサーの手首の体温データへのアクセスをアプリに許可します。"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"アプリのバックグラウンド実行中に、ボディセンサーの手首の体温データにアクセスします。"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"アプリのバックグラウンド実行中に、ボディセンサーの手首の体温データへのアクセスをアプリに許可します。"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Androidの起動中…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"タブレットの起動中…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"デバイスの起動中…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"ストレージを最適化しています。"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"システム アップデートの完了中…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」をアップグレードしています…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g>個中<xliff:g id="NUMBER_0">%1$d</xliff:g>個のアプリを最適化しています。"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>をペア設定しています。"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"アプリを起動しています。"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"ブートを終了しています。"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"全画面表示"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"終了するには、上から下にスワイプします。"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"画面を回転させて見やすくしましょう"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"分割画面を終了して見やすくしましょう"</string>
     <string name="done_label" msgid="7283767013231718521">"完了"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"円形スライダー(時)"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"円形スライダー(分)"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"仕事の<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> のクローン"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"オフライン再生を解除する前にPINの入力を求める"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"オフライン再生を解除する前にパスワードの入力を求める"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"バックグラウンドからのフォアグラウンド サービスの起動をコンパニオン アプリに許可します。"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"マイクを利用できます"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"マイクがブロックされています"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"デュアル スクリーン"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"デュアル スクリーン: ON"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>は 2 画面でコンテンツを表示しています"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"デバイスが熱くなりすぎています"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"スマートフォンが熱くなりすぎているため、デュアル スクリーンを使用できません"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"オフにする"</string>
 </resources>
diff --git a/core/res/res/values-ka-watch/strings.xml b/core/res/res/values-ka-watch/strings.xml
index 1b7ebca..e91e2d3 100644
--- a/core/res/res/values-ka-watch/strings.xml
+++ b/core/res/res/values-ka-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"აპი <xliff:g id="NUMBER_0">%1$d</xliff:g>, სულ <xliff:g id="NUMBER_1">%2$d</xliff:g>-დან."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"სენსორები"</string>
 </resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index c0fa6a0..96b7cdb 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -311,7 +311,7 @@
     <string name="permgrouplab_microphone" msgid="2480597427667420076">"მიკროფონი"</string>
     <string name="permgroupdesc_microphone" msgid="1047786732792487722">"აუდიოს ჩაწერა"</string>
     <string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"ფიზიკური აქტივობა"</string>
-    <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ფიზიკური აქტივობაზე წვდომა"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ფიზიკურ აქტივობაზე წვდომა"</string>
     <string name="permgrouplab_camera" msgid="9090413408963547706">"კამერა"</string>
     <string name="permgroupdesc_camera" msgid="7585150538459320326">"ფოტოებისა და ვიდეოების გადაღება"</string>
     <string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"ახლომახლო მოწყობილობები"</string>
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"სხეულის სენსორის მაჯის ტემპერატურის მონაცემებზე წვდომა აპის მუშაობისას."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"საშუალებას აძლევს აპს, მუშაობისას წვდომა ჰქონდეს სხეულის სენსორის მაჯის ტემპერატურის მონაცემებზე."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"სხეულის სენსორის მაჯის ტემპერატურის მონაცემებზე წვდომა აპის ფონურ რეჟმში მუშაობისას."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"საშუალებას აძლევს აპს, ფონურ რეჟიმში მუშაობისას წვდომა ჰქონდეს სხეულის სენსორის მაჯის ტე,პერატურის მონაცემებზე."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android იწყება…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"მიმდინარეობს ტაბლეტის ჩართვა…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"მიმდინარეობს მოწყობილობის ჩართვა…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"მეხსიერების ოპტიმიზირება."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"სისტემის განახლება სრულდება…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> ახალ ვერსიაზე გადადის…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"მიმდინარეობს აპლიკაციების ოპტიმიზაცია. დასრულებულია <xliff:g id="NUMBER_0">%1$d</xliff:g>, სულ <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"ემზადება <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"აპების ჩართვა"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"ჩატვირთვის დასასრული."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"სრულ ეკრანზე ნახვა"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"გამოსვლისათვის, გაასრიალეთ ზემოდან ქვემოთ."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"გასაგებია"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"შეატრიალეთ უკეთესი ხედისთვის"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"უკეთესი ხედვისთვის გამოდით გაყოფილი ეკრანიდან"</string>
     <string name="done_label" msgid="7283767013231718521">"დასრულდა"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"საათების წრიული სლაიდერი"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"წუთების წრიული სლაიდერი"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"მე-2 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"მე-3 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> კლონის შექმნა"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ფიქსაციის მოხსნამდე PIN-ის მოთხოვნა"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ფიქსაციის მოხსნამდე განბლოკვის ნიმუშის მოთხოვნა"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"საშუალებას აძლევს კომპანიონ აპს, რომ გაუშვას უპირატესი სერვისები ფონური რეჟიმიდან."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"მიკროფონი ხელმისაწვდომია"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"მიკროფონი დაბლოკილია"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kk-watch/strings.xml b/core/res/res/values-kk-watch/strings.xml
index b992f96..6eb05ba 100644
--- a/core/res/res/values-kk-watch/strings.xml
+++ b/core/res/res/values-kk-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> бағдарлама."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Сенсорлар"</string>
 </resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 68ebba9..8ffaa3f 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Қолданба пайдаланылып жатқанда оған қолдағы дене датчигінен алынған деректі пайдалануға рұқсат беру."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Қолданба пайдаланылып жатқанда оған қолдағы дене датчигінен алынған деректі пайдалануға рұқсат береді."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Фондық режимдегі қолданбаға қолдағы дене датчигінен алынған деректі пайдалануға рұқсат беру."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Фондық режимдегі қолданбаға қолдағы дене датчигінен алынған деректі пайдалануға рұқсат береді."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android іске қосылуда…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Планшет іске қосылуда…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Құрылғы іске қосылуда…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Қойманы оңтайландыру."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Жүйелік жаңарту аяқталуда…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> жаңартылуда…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ішінен <xliff:g id="NUMBER_0">%1$d</xliff:g> қолданба оңтайландырылуда."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> дайындалуда."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Қолданбалар іске қосылуда."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Қосуды аяқтауда."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Толық экранда көру"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Шығу үшін жоғарыдан төмен қарай сырғытыңыз."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Түсінікті"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Жақсырақ көру үшін бұрыңыз."</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Жақсырақ көру үшін экранды бөлу режимінен шығыңыз."</string>
     <string name="done_label" msgid="7283767013231718521">"Дайын"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Сағаттар айналымының қозғалтқышы"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Минут айналымын қозғалтқыш"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Жұмыс <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Босату алдында PIN кодын сұрау"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Босату алдында бекітпесін ашу өрнегін сұрау"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Босату алдында құпия сөзді сұрау"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Қосымша қолданбаға экрандық режимдегі қызметтерді фоннан іске қосуға рұқсат беріледі."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофон қолжетімді."</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофон бөгелген."</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-km-watch/strings.xml b/core/res/res/values-km-watch/strings.xml
index 0ac6ced..dd72ee4 100644
--- a/core/res/res/values-km-watch/strings.xml
+++ b/core/res/res/values-km-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"កម្មវិធី <xliff:g id="NUMBER_0">%1$d</xliff:g> នៃ <xliff:g id="NUMBER_1">%2$d</xliff:g>។"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"ឧបករណ៍ចាប់សញ្ញា"</string>
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index ee39924..8c722971 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ចូលប្រើ​ទិន្នន័យសីតុណ្ហភាពកដៃ​ពីសេនស័ររាងកាយ នៅពេល​កំពុងប្រើកម្មវិធី។"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"អនុញ្ញាតឱ្យកម្មវិធីចូលប្រើ​ទិន្នន័យសីតុណ្ហភាពកដៃ​ពីសេនស័ររាងកាយ នៅពេល​កំពុងប្រើកម្មវិធី។"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"ចូលប្រើ​ទិន្នន័យសីតុណ្ហភាព​កដៃពីសេនស័ររាងកាយ នៅពេល​កម្មវិធីស្ថិត​នៅផ្ទៃខាងក្រោយ។"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"អនុញ្ញាតឱ្យ​កម្មវិធីចូលប្រើ​ទិន្នន័យសីតុណ្ហភាព​កដៃពីសេនស័ររាងកាយ នៅពេល​កម្មវិធីស្ថិត​នៅផ្ទៃខាងក្រោយ។"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android កំពុង​ចាប់ផ្ដើម…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ថេប្លេត​កំពុង​ចាប់ផ្ដើម…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ឧបករណ៍​កំពុង​ចាប់ផ្ដើម…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"កំពុងធ្វើឲ្យឧបករណ៍ផ្ទុកមានប្រសិទ្ធភាព។"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"កំពុងបញ្ចប់​បច្ចុប្បន្នភាព​ប្រព័ន្ធ…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> អាប់គ្រេត…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"ធ្វើ​ឲ្យ​កម្មវិធី​ប្រសើរ​ឡើង <xliff:g id="NUMBER_0">%1$d</xliff:g> នៃ <xliff:g id="NUMBER_1">%2$d</xliff:g> ។"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"កំពុងរៀបចំ <xliff:g id="APPNAME">%1$s</xliff:g>។"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ចាប់ផ្ដើម​កម្មវិធី។"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"បញ្ចប់​ការ​ចាប់ផ្ដើម។"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"កំពុងមើលពេញអេក្រង់"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"ដើម្បីចាកចេញ សូមអូសពីលើចុះក្រោម។"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"យល់ហើយ"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"បង្វិលដើម្បីមើលបានកាន់តែច្បាស់"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ចេញពីមុខងារ​បំបែកអេក្រង់ដើម្បីមើលបានកាន់តែច្បាស់"</string>
     <string name="done_label" msgid="7283767013231718521">"រួចរាល់"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"គ្រាប់​រំកិល​រង្វង់​ម៉ោង"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"គ្រាប់​រំកិល​រង្វង់​នាទី"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g>​ការងារ"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 2"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 3"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"សួរ​រក​កូដ PIN មុន​ពេលដកខ្ទាស់"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"សួរ​រក​លំនាំ​ដោះ​សោ​មុន​ពេលដោះខ្ទាស់"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"សួរ​រក​ពាក្យ​សម្ងាត់​មុន​ពេល​ផ្ដាច់"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"អនុញ្ញាតឱ្យកម្មវិធីដៃគូចាប់ផ្តើមសេវាកម្មផ្ទៃខាងមុខពីផ្ទៃខាងក្រោយ។"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"អាចប្រើ​មីក្រូហ្វូនបាន"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"មីក្រូហ្វូនត្រូវ​បានទប់ស្កាត់"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kn-watch/strings.xml b/core/res/res/values-kn-watch/strings.xml
index 30a00d3..b5cf763 100644
--- a/core/res/res/values-kn-watch/strings.xml
+++ b/core/res/res/values-kn-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="NUMBER_0">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"ಸೆನ್ಸರ್‌ಗಳು"</string>
 </resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index d23a53e..27e2554 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ಆ್ಯಪ್ ಬಳಕೆಯಲ್ಲಿರುವಾಗ ದೇಹದ ಸೆನ್ಸರ್‌ನಿಂದ ಮಣಿಕಟ್ಟಿನ ತಾಪಮಾನದ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಿ."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"ಆ್ಯಪ್ ಬಳಕೆಯಲ್ಲಿರುವಾಗ ದೇಹದ ಸೆನ್ಸರ್‌ನಿಂದ ಮಣಿಕಟ್ಟಿನ ತಾಪಮಾನದ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"ಆ್ಯಪ್ ಹಿನ್ನೆಲೆಯಲ್ಲಿರುವಾಗ ದೇಹದ ಸೆನ್ಸರ್‌ನಿಂದ ಮಣಿಕಟ್ಟಿನ ತಾಪಮಾನದ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಿ."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"ಆ್ಯಪ್ ಹಿನ್ನೆಲೆಯಲ್ಲಿರುವಾಗ ದೇಹದ ಸೆನ್ಸರ್‌ನಿಂದ ಮಣಿಕಟ್ಟಿನ ತಾಪಮಾನದ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ಟ್ಯಾಬ್ಲೆಟ್ ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ಸಾಧನವನ್ನು ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"ಸಂಗ್ರಹಣೆಯನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"ಸಿಸ್ಟಮ್ ಅಪ್‌ಡೇಟ್ ಮುಕ್ತಾಯಗೊಳ್ಳುತ್ತಿದೆ…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> ಅಪ್‌ಗ್ರೇಡ್ ಆಗುತ್ತಿದೆ..."</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="NUMBER_0">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"ಬೂಟ್ ಪೂರ್ಣಗೊಳಿಸಲಾಗುತ್ತಿದೆ."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"ಪೂರ್ಣ ಪರದೆಯನ್ನು ವೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"ನಿರ್ಗಮಿಸಲು, ಮೇಲಿನಿಂದ ಕೆಳಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"ತಿಳಿಯಿತು"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ಅತ್ಯುತ್ತಮ ವೀಕ್ಷಣೆಗಾಗಿ ತಿರುಗಿಸಿ"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ಅತ್ಯುತ್ತಮ ವೀಕ್ಷಣೆಗಾಗಿ ಸ್ಪ್ಲಿಟ್‌ ಸ್ಕ್ರೀನ್‌ನಿಂದ ನಿರ್ಗಮಿಸಿ"</string>
     <string name="done_label" msgid="7283767013231718521">"ಮುಗಿದಿದೆ"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"ಗಂಟೆಗಳ ವೃತ್ತಾಕಾರ ಸ್ಲೈಡರ್"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"ನಿಮಿಷಗಳ ವೃತ್ತಾಕಾರ ಸ್ಲೈಡರ್"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"ಕೆಲಸ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> ಕ್ಲೋನ್"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಿನ್‌ ಕೇಳು"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅನ್‌ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್ ಕೇಳು"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ಮುನ್ನೆಲೆ ಸೇವೆಗಳನ್ನು ಹಿನ್ನೆಲೆಯಿಂದ ಪ್ರಾರಂಭಿಸಲು ಕಂಪ್ಯಾನಿಯನ್ ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ಮೈಕ್ರೊಫೋನ್ ಲಭ್ಯವಿದೆ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko-watch/strings.xml b/core/res/res/values-ko-watch/strings.xml
index 1a14bcd..a9cbb63 100644
--- a/core/res/res/values-ko-watch/strings.xml
+++ b/core/res/res/values-ko-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"앱 <xliff:g id="NUMBER_1">%2$d</xliff:g>개 중 <xliff:g id="NUMBER_0">%1$d</xliff:g>개"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"센서"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index a52259a..03a8fe1 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"앱 사용 중에 생체 신호 센서 손목 온도 데이터에 액세스합니다"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"앱이 사용 중에 생체 신호 센서 손목 온도 데이터에 액세스하도록 허용합니다."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"앱이 백그라운드에 있을 때 생체 신호 센서 손목 온도 데이터에 액세스합니다"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"앱이 백그라운드에서 생체 신호 센서 손목 온도 데이터에 액세스하도록 허용합니다."</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>
@@ -636,7 +632,7 @@
     <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"너무 밝음"</string>
     <string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"전원 누름이 감지되었습니다."</string>
     <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"조정 시도"</string>
-    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"지문을 등록할 때마다 손가락을 조금씩 이동하세요"</string>
+    <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"지문이 인식될 때마다 손가락을 조금씩 이동하세요"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
     <string name="fingerprint_error_not_match" msgid="4599441812893438961">"지문이 인식되지 않았습니다."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android가 시작되는 중…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"태블릿을 시작하는 중…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"기기를 시작하는 중…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"저장소 최적화 중"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"시스템 업데이트를 완료하는 중…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> 업그레이드 중…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"앱 <xliff:g id="NUMBER_1">%2$d</xliff:g>개 중 <xliff:g id="NUMBER_0">%1$d</xliff:g>개 최적화 중"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> 준비 중..."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"앱을 시작하는 중입니다."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"부팅 완료"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"전체 화면 모드"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"종료하려면 위에서 아래로 스와이프합니다."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"확인"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"카메라 미리보기 화면이 잘 보이도록 회전하세요."</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"카메라 미리보기 화면이 잘 보이도록 화면 분할을 종료하세요."</string>
     <string name="done_label" msgid="7283767013231718521">"완료"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"시간 원형 슬라이더"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"분 원형 슬라이더"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"두 번째 업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"세 번째 업무용<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"고정 해제 이전에 PIN 요청"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"고정 해제 시 잠금 해제 패턴 요청"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"고정 해제 이전에 비밀번호 요청"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"호환 앱이 백그라운드에서 포그라운드 서비스를 시작할 수 있게 허용합니다."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"마이크 사용 가능"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"마이크가 차단됨"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ky-watch/strings.xml b/core/res/res/values-ky-watch/strings.xml
index fa1c47c..4095282 100644
--- a/core/res/res/values-ky-watch/strings.xml
+++ b/core/res/res/values-ky-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колднм."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Сенсорлор"</string>
 </resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 67a890d..03c59e7 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Колдонмо иштеп жатканда, дене сенсорлорунун температура тууралуу маалыматын көрүү."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Колдонмо иштеп жатканда, дене сенсорлорунун температура тууралуу маалыматын көрө алат."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Колдонмо фондо иштеп жатканда, дене сенсорлорунун температура тууралуу маалыматын көрүү."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Колдонмо фондо дене сенсорлорунун температура тууралуу маалыматын көрө алат."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android жүргүзүлүүдө…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Планшет күйгүзүлүүдө…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Түзмөк күйүгүзүлүүдө…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Сактагыч ыңгайлаштырылууда."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Система жаңырып бүтөйүн деп калды…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> жаңыртылууда..."</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колдонмо оптималдаштырылууда."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> даярдалууда."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Колдонмолорду иштетип баштоо"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Жүктөлүүдө"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Толук экран режими"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Чыгуу үчүн экранды ылдый сүрүп коюңуз."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Түшүндүм"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Жакшыраак көрүү үчүн буруңуз"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Жакшыраак көрүү үчүн экранды бөлүү режиминен чыгыңыз"</string>
     <string name="done_label" msgid="7283767013231718521">"Даяр"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Саат жебеси"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Мүнөт жебеси"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> клону"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Бошотуудан мурун PIN суралсын"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Бошотуудан мурун графикалык ачкыч суралсын"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Бошотуудан мурун сырсөз суралсын"</string>
@@ -2000,7 +1997,7 @@
     <string name="app_category_social" msgid="2278269325488344054">"Социалдык жана коммуникация"</string>
     <string name="app_category_news" msgid="1172762719574964544">"Жаңылыктар жана журналдар"</string>
     <string name="app_category_maps" msgid="6395725487922533156">"Карталар жана чабыттоо"</string>
-    <string name="app_category_productivity" msgid="1844422703029557883">"Өндүрүш категориясы"</string>
+    <string name="app_category_productivity" msgid="1844422703029557883">"Майнаптуулук"</string>
     <string name="app_category_accessibility" msgid="6643521607848547683">"Атайын мүмкүнчүлүктөр"</string>
     <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"Түзмөктүн сактагычы"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB аркылуу мүчүлүштүктөрдү аныктоо"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Көмөкчү колдонмого активдүү кызматтарды фондо иштетүүгө уруксат берет."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофон жеткиликтүү"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофон бөгөттөлгөн"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lo-watch/strings.xml b/core/res/res/values-lo-watch/strings.xml
index 1a42725..e83751a 100644
--- a/core/res/res/values-lo-watch/strings.xml
+++ b/core/res/res/values-lo-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"ແອັບ <xliff:g id="NUMBER_0">%1$d</xliff:g> ໃນ <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"ເຊັນເຊີ"</string>
 </resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index e890cc6..ac67378 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ເຂົ້າເຖິງຂໍ້ມູນອຸນຫະພູມຢູ່ຂໍ້ມືຈາກເຊັນເຊີຮ່າງກາຍໃນຂະນະທີ່ນຳໃຊ້ແອັບ."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"ອະນຸຍາດໃຫ້ແອັບເຂົ້າເຖິງຂໍ້ມູນອຸນຫະພູມຢູ່ຂໍ້ມືຈາກເຊັນເຊີຮ່າງກາຍໃນຂະນະທີ່ນຳໃຊ້ແອັບ."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"ເຂົ້າເຖິງຂໍ້ມູນອຸນຫະພູມຢູ່ຂໍ້ມືຈາກເຊັນເຊີຮ່າງກາຍໃນຂະນະທີ່ແອັບເຮັດວຽກໃນພື້ນຫຼັງ."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"ອະນຸຍາດໃຫ້ແອັບເຂົ້າເຖິງຂໍ້ມູນອຸນຫະພູມຢູ່ຂໍ້ມືຈາກເຊັນເຊີຮ່າງກາຍໃນຂະນະທີ່ແອັບເຮັດວຽກໃນພື້ນຫຼັງ."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Read calendar events and details"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"This app can read all calendar events stored on your tablet and share or save your calendar data."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"ແອັບນີ້ສາມາດອ່ານນັດໝາຍປະຕິທິນທັງໝົດທີ່ບັນທຶກໄວ້ຢູ່ອຸປະກອນ Android TV ຂອງທ່ານ ແລະ ແບ່ງປັນ ຫຼື ບັນທຶກຂໍ້ມູນປະຕິທິນຂອງທ່ານ."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"ກຳ​ລັງ​ເລີ່ມລະ​ບົບ​ Android …"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ກຳລັງເລີ່ມແທັບເລັດ…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ກຳລັງເລີ່ມອຸປະກອນ…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"ການ​ປັບ​ບ່ອນ​ເກັບ​ຂໍ້​ມູນ​ໃຫ້​ເໝາະ​ສົມ."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"ກຳລັງສຳເລັດການອັບເດດລະບົບ…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"ກຳລັງອັບເກຣດ<xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"ກຳລັງ​ປັບປຸງ​ປະສິດທິພາບ​ແອັບຯ​ທີ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຈາກ​ທັງ​ໝົດ <xliff:g id="NUMBER_1">%2$d</xliff:g> ແອັບຯ."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"ກຳ​ລັງ​ກຽມ <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ກຳລັງເປີດແອັບຯ."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"ກຳລັງສຳເລັດການເປີດລະບົບ."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"ການ​ເບິ່ງ​ເຕັມ​ໜ້າ​ຈໍ"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"ຫາກຕ້ອງການອອກ, ໃຫ້ຮູດຈາກທາງເທິງລົງມາທາງລຸ່ມ."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"ໄດ້​ແລ້ວ"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ໝຸນເພື່ອມຸມມອງທີ່ດີຂຶ້ນ"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ອອກຈາກແບ່ງໜ້າຈໍເພື່ອມຸມມອງທີ່ດີຂຶ້ນ"</string>
     <string name="done_label" msgid="7283767013231718521">"ແລ້ວໆ"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"ໂຕໝຸນປັບຊົ່ວໂມງ"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"ໂຕໝຸນປັບນາທີ"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"​ບ່ອນ​ເຮັດ​ວຽກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"ບ່ອນເຮັດວຽກທີ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"ບ່ອນເຮັດວຽກທີ 3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"ໂຄລນ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"​ຖາມ​ຫາ PIN ກ່ອນ​ຍົກ​ເລີກ​ການປັກ​ໝຸດ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"​ຖາມ​ຫາ​ຮູບ​ແບບ​ປົດ​ລັອກ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"​ຖາມ​ຫາ​ລະ​ຫັດ​ຜ່ານ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ອະນຸຍາດຈາກເບື້ອງຫຼັງໃຫ້ແອັບຊ່ວຍເຫຼືອເລີ່ມໃຊ້ບໍລິການທີ່ເຮັດວຽກຢູ່ເບື້ອງໜ້າ."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ໄມໂຄຣໂຟນພ້ອມໃຫ້ນຳໃຊ້"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ໄມໂຄຣໂຟນຖືກບລັອກໄວ້"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt-watch/strings.xml b/core/res/res/values-lt-watch/strings.xml
index e8ec6bb..bf6e92a 100644
--- a/core/res/res/values-lt-watch/strings.xml
+++ b/core/res/res/values-lt-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g> programa iš <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Jutikliai"</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 0c43543..e2a3910 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -460,14 +460,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Leidžiama programai pasiekti kūno jutiklių duomenis, pvz., pulso dažnį, temperatūrą ir deguonies procentinę dalį kraujyje, kai programa naudojama."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Prieiga prie kūno jutiklių duomenų, pvz., pulso dažnio, kai veikia fone"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Leidžiama programai pasiekti kūno jutiklių duomenis, pvz., pulso dažnį, temperatūrą ir deguonies procentinę dalį kraujyje, kai programa veikia fone."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Pasiekti kūno jutiklio riešo temperatūros duomenis, kol programa naudojama."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Leidžiama programai pasiekti kūno jutiklio riešo temperatūros duomenis, kol programa naudojama."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Pasiekti kūno jutiklio riešo temperatūros duomenis, kol programa veikia fone."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Leidžiama programai pasiekti kūno jutiklio riešo temperatūros duomenis, kol programa veikia fone."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Skaityti kalendoriaus įvykius arba išsamią informaciją"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Ši programa gali nuskaityti visus planšetiniame kompiuteryje saugomus kalendoriaus įvykius ir bendrinti arba išsaugoti kalendoriaus duomenis."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ši programa gali nuskaityti visus „Android TV“ įrenginyje saugomus kalendoriaus įvykius ir bendrinti arba išsaugoti kalendoriaus duomenis."</string>
@@ -1251,10 +1247,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Paleidžiama „Android“…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Planšetinis kompiuteris paleidžiamas…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Įrenginys paleidžiamas…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimizuojama saugykla."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Baigiama atnaujinti sistemą…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"„<xliff:g id="APPLICATION">%1$s</xliff:g>“ naujovinama..."</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimizuojama <xliff:g id="NUMBER_0">%1$d</xliff:g> progr. iš <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Ruošiama „<xliff:g id="APPNAME">%1$s</xliff:g>“."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Paleidžiamos programos."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Užbaigiamas paleidimas."</string>
@@ -1852,6 +1846,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Peržiūrima viso ekrano režimu"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Jei norite išeiti, perbraukite žemyn iš viršaus."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Supratau"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Pasukite, kad geriau matytumėte vaizdą"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Išeikite iš išskaidyto ekrano režimo, kad geriau matytumėte vaizdą"</string>
     <string name="done_label" msgid="7283767013231718521">"Atlikta"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Apskritas valandų šliaužiklis"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Apskritas minučių šliaužiklis"</string>
@@ -1863,6 +1859,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-asis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-iasis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Prašyti PIN kodo prieš atsegant"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Prašyti atrakinimo piešinio prieš atsegant"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Prašyti slaptažodžio prieš atsegant"</string>
@@ -2317,4 +2315,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Leidžiama papildomai programai paleisti priekinio plano paslaugas fone."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofonas pasiekiamas"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofonas užblokuotas"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dvigubas ekranas"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Įjungtas dvigubas ekranas"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja abu ekranus turiniui rodyti"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Įrenginys per daug kaista"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvigubas ekranas nepasiekiamas, nes telefonas per daug kaista"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Išjungti"</string>
 </resources>
diff --git a/core/res/res/values-lv-watch/strings.xml b/core/res/res/values-lv-watch/strings.xml
index 61e9bfc..e22f614 100644
--- a/core/res/res/values-lv-watch/strings.xml
+++ b/core/res/res/values-lv-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. lietotne no <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensori"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 47233ff..c266988 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -240,7 +240,7 @@
     <string name="global_actions" product="tv" msgid="3871763739487450369">"Android TV opcijas"</string>
     <string name="global_actions" product="default" msgid="6410072189971495460">"Tālruņa opcijas"</string>
     <string name="global_action_lock" msgid="6949357274257655383">"Ekrāna bloķētājs"</string>
-    <string name="global_action_power_off" msgid="4404936470711393203">"Izslēgt strāvas padevi"</string>
+    <string name="global_action_power_off" msgid="4404936470711393203">"Izslēgt"</string>
     <string name="global_action_power_options" msgid="1185286119330160073">"Barošana"</string>
     <string name="global_action_restart" msgid="4678451019561687074">"Restartēt"</string>
     <string name="global_action_emergency" msgid="1387617624177105088">"Ārkārtas situācija"</string>
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Ļauj lietotnei piekļūt ķermeņa sensoru datiem, piemēram, sirdsdarbības ātrumam, temperatūrai un procentuālajam skābekļa daudzumam asinīs, kamēr lietotne tiek izmantota."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Piekļuve ķermeņa sensoru datiem, piemēram, sirdsdarbības ātrumam, fonā"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Ļauj lietotnei piekļūt ķermeņa sensoru datiem, piemēram, sirdsdarbības ātrumam, temperatūrai un procentuālajam skābekļa daudzumam asinīs, kamēr lietotne darbojas fonā."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Piekļuve ķermeņa sensora noteiktajiem plaukstas locītavas temperatūras datiem, kamēr lietotne tiek izmantota."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Ļauj lietotnei piekļūt ķermeņa sensora noteiktajiem plaukstas locītavas temperatūras datiem, kamēr lietotne tiek izmantota."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Piekļuve ķermeņa sensora noteiktajiem plaukstas locītavas temperatūras datiem, kamēr lietotne darbojas fonā."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Ļauj lietotnei piekļūt ķermeņa sensora noteiktajiem plaukstas locītavas temperatūras datiem, kamēr lietotne darbojas fonā."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Lasīt kalendāra pasākumus un informāciju"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Šī lietotne var lasīt visus kalendāra pasākumus, kas saglabāti planšetdatorā, un kopīgot vai saglabāt jūsu kalendāra datus."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Šī lietotne var lasīt visus kalendāra pasākumus, kas saglabāti Android TV ierīcē, un kopīgot vai saglabāt jūsu kalendāra datus."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Notiek Android palaišana…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Notiek planšetdatora palaišana…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Notiek ierīces palaišana…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Notiek krātuves optimizēšana."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Notiek sistēmas atjauninājuma pabeigšana"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Notiek lietotnes <xliff:g id="APPLICATION">%1$s</xliff:g> jaunināšana…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Tiek optimizēta <xliff:g id="NUMBER_0">%1$d</xliff:g>. lietotne no <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Notiek lietotnes <xliff:g id="APPNAME">%1$s</xliff:g> sagatavošana."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Notiek lietotņu palaišana."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Tiek pabeigta sāknēšana."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Skatīšanās pilnekrāna režīmā"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Lai izietu, no augšdaļas velciet lejup."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Labi"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Lai uzlabotu skatu, pagrieziet ekrānu."</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Lai uzlabotu skatu, izejiet no ekrāna sadalīšanas režīma."</string>
     <string name="done_label" msgid="7283767013231718521">"Gatavs"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Stundu apļveida slīdnis"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Minūšu apļveida slīdnis"</string>
@@ -1862,6 +1858,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Darbā: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Prasīt PIN kodu pirms atspraušanas"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pirms atspraušanas pieprasīt atbloķēšanas kombināciju"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pirms atspraušanas pieprasīt paroli"</string>
@@ -2316,4 +2314,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Ļauj palīglietotnei sākt priekšplāna pakalpojumus no fona."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofons ir pieejams."</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofons ir bloķēts."</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mk-watch/strings.xml b/core/res/res/values-mk-watch/strings.xml
index ac3cf09..7977f66 100644
--- a/core/res/res/values-mk-watch/strings.xml
+++ b/core/res/res/values-mk-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Апликац. <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Сензори"</string>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 6c4bcb1..e7b2b67 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Пристап до податоците за температура на зглобот од телесниот сензор додека се користи апликацијата."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Дозволува апликацијата да пристапува до податоците за температура на зглобот од телесниот сензор додека се користи апликацијата."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Пристап до податоците за температура на зглобот од телесниот сензор додека апликацијата работи во заднина."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Дозволува апликацијата да пристапува до податоците за температура на зглобот од телесниот сензор додека апликацијата работи во заднина."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android стартува…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Таблетот стартува…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Уредот стартува…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Оптимизирање на складирањето."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Завршува системската надградба…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> се надградува…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Се оптимизира апликација <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Се подготвува <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Се стартуваат апликациите."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Подигањето завршува."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Се прикажува на цел екран"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"За да излезете, повлечете одозгора надолу."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Сфатив"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Ротирајте за подобар приказ"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"За подобар приказ, излезете од поделениот екран"</string>
     <string name="done_label" msgid="7283767013231718521">"Готово"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Приказ на часови во кружно движење"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Приказ на минути во кружно движење"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Работа <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Втора деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Трета деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Клонирајте го <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Побарај PIN пред откачување"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Побарај шема за откл. пред откачување"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Побарај лозинка пред откачување"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Дозволува придружна апликација да започне услуги во преден план од заднината."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофонот е достапен"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофонот е блокиран"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Двоен екран"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Вклучен е двоен екран"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ги користи двата екрани за да прикажува содржини"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Уредот е претопол"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Двојниот екран е недостапен бидејќи вашиот телефон станува претопол"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Исклучи"</string>
 </resources>
diff --git a/core/res/res/values-ml-watch/strings.xml b/core/res/res/values-ml-watch/strings.xml
index f3e3a31..807f1a9 100644
--- a/core/res/res/values-ml-watch/strings.xml
+++ b/core/res/res/values-ml-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> അപ്ലിക്കേഷൻ."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"സെൻസറുകൾ"</string>
 </resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 9652af5..86665d7 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"കണങ്കയ്യിലൂടെ അറിയാനാകുന്ന ശരീരോഷ്‌മാവ് സംബന്ധിച്ച ബോഡി സെൻസർ ഡാറ്റ, ആപ്പ് പ്രവർത്തിച്ചുകൊണ്ടിരിക്കുമ്പോൾ ആക്‌സസ് ചെയ്യുക."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"കണങ്കയ്യിലൂടെ അറിയാനാകുന്ന ശരീരോഷ്‌മാവ് സംബന്ധിച്ച ബോഡി സെൻസർ ഡാറ്റ, ആപ്പ് പ്രവർത്തിച്ചുകൊണ്ടിരിക്കുമ്പോൾ ആക്‌സസ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"കണങ്കയ്യിലൂടെ അറിയാനാകുന്ന ശരീരോഷ്‌മാവ് സംബന്ധിച്ച ബോഡി സെൻസർ ഡാറ്റ, ആപ്പ് പശ്ചാത്തലത്തിൽ പ്രവർത്തിക്കുമ്പോൾ ആക്‌സസ് ചെയ്യുക."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"കണങ്കയ്യിലൂടെ അറിയാനാകുന്ന ശരീരോഷ്‌മാവ് സംബന്ധിച്ച ബോഡി സെൻസർ ഡാറ്റ, ആപ്പ് പശ്ചാത്തലത്തിൽ പ്രവർത്തിക്കുമ്പോൾ ആക്‌സസ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android ആരംഭിക്കുന്നു…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ടാബ്‌ലെറ്റ് ആരംഭിക്കുന്നു…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ഉപകരണം ആരംഭിക്കുന്നു…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"സ്റ്റോറേജ്  ഒപ്‌റ്റിമൈസ് ചെയ്യുന്നു."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"സിസ്‌റ്റം അപ്‌ഡേറ്റ് പൂർത്തിയാക്കുന്നു…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> അപ്ഗ്രേഡ് ചെയ്യുന്നു…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> അപ്ലിക്കേഷൻ ഓപ്റ്റിമൈസ് ചെയ്യുന്നു."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> തയ്യാറാക്കുന്നു."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"അപ്ലിക്കേഷനുകൾ ആരംഭിക്കുന്നു."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"ബൂട്ട് ചെയ്യൽ പൂർത്തിയാകുന്നു."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"പൂർണ്ണ സ്‌ക്രീനിൽ കാണുന്നു"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"അവസാനിപ്പിക്കാൻ, മുകളിൽ നിന്ന് താഴോട്ട് സ്വൈപ്പ് ചെയ്യുക."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"മനസ്സിലായി"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"മികച്ച കാഴ്‌ചയ്‌ക്കായി റൊട്ടേറ്റ് ചെയ്യുക"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"മികച്ച കാഴ്‌ചയ്‌ക്കായി സ്‌ക്രീൻ വിഭജന മോഡിൽ നിന്ന് പുറത്തുകടക്കുക"</string>
     <string name="done_label" msgid="7283767013231718521">"പൂർത്തിയാക്കി"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"ചാക്രികമായി മണിക്കൂറുകൾ ദൃശ്യമാകുന്ന സ്ലൈഡർ"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"ചാക്രികമായി മിനിറ്റുകൾ ദൃശ്യമാകുന്ന സ്ലൈഡർ"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"ഔദ്യോഗികം <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"രണ്ടാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"മൂന്നാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"ക്ലോൺ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ചെയ്യുംമുമ്പ് പിൻ ചോദിക്കൂ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"അൺപിന്നിനുമുമ്പ് അൺലോക്ക് പാറ്റേൺ ആവശ്യപ്പെടൂ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"അൺപിന്നിനുമുമ്പ് പാസ്‌വേഡ് ആവശ്യപ്പെടൂ"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"പശ്ചാത്തലത്തിൽ നിന്ന് ഫോർഗ്രൗണ്ട് സേവനങ്ങൾ ആരംഭിക്കാൻ സഹകാരി ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"മൈക്രോഫോൺ ലഭ്യമാണ്"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"മൈക്രോഫോൺ ബ്ലോക്ക് ചെയ്‌തു"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ഡ്യുവൽ സ്ക്രീൻ"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"ഡ്യുവൽ സ്ക്രീൻ ഓണാണ്"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"ഉള്ളടക്കം കാണിക്കാൻ <xliff:g id="APP_NAME">%1$s</xliff:g> രണ്ട് ഡിസ്പ്ലേകളും ഉപയോഗിക്കുന്നു"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ഉപകരണത്തിന് ചൂട് കൂടുതലാണ്"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"നിങ്ങളുടെ ഫോൺ വളരെയധികം ചൂടാകുന്നതിനാൽ ഡ്യുവൽ സ്‌ക്രീൻ ലഭ്യമല്ല"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ഓഫാക്കുക"</string>
 </resources>
diff --git a/core/res/res/values-mn-watch/strings.xml b/core/res/res/values-mn-watch/strings.xml
index d46592e..b00580f 100644
--- a/core/res/res/values-mn-watch/strings.xml
+++ b/core/res/res/values-mn-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g>-ны <xliff:g id="NUMBER_1">%2$d</xliff:g> апп."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Мэдрэгч"</string>
 </resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 5f9c268..0aeddf9 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -299,7 +299,7 @@
     <string name="permgrouplab_location" msgid="1858277002233964394">"Байршил"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"энэ төхөөрөмжийн байршилд хандалт хийх"</string>
     <string name="permgrouplab_calendar" msgid="6426860926123033230">"Календарь"</string>
-    <string name="permgroupdesc_calendar" msgid="6762751063361489379">"Календарь руу хандах"</string>
+    <string name="permgroupdesc_calendar" msgid="6762751063361489379">"Календарьд хандах"</string>
     <string name="permgrouplab_sms" msgid="795737735126084874">"Мессеж"</string>
     <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS мессежийг илгээх, харах"</string>
     <string name="permgrouplab_storage" msgid="17339216290379241">"Файлууд"</string>
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Аппыг ашиглаж байх үед биеийн мэдрэгчийн бугуйн температурын өгөгдөлд хандана."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Аппыг ашиглаж байх үед биеийн мэдрэгчийн бугуйн температурын өгөгдөлд хандахыг аппад зөвшөөрнө."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Аппыг ард байх үед биеийн мэдрэгчийн бугуйн температурын өгөгдөлд хандана."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Аппыг ард байх үед биеийн мэдрэгчийн бугуйн температурын өгөгдөлд хандахыг аппад зөвшөөрнө."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Андройд эхэлж байна..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Таблетыг эхлүүлж байна…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Төхөөрөмжийг эхлүүлж байна…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Хадгалалтыг сайжруулж байна."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Системийн шинэчлэлтийг дуусгаж байна…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г сайжруулж байна…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g>-н <xliff:g id="NUMBER_0">%1$d</xliff:g> апп-г тохируулж байна."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Бэлдэж байна <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Апп-г эхлүүлж байна."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Эхлэлийг дуусгаж байна."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Бүтэн дэлгэцээр үзэж байна"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Гарахаар бол дээрээс нь доош нь чирнэ үү."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Ойлголоо"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Харагдах байдлыг сайжруулах бол эргүүлнэ үү"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Харагдах байдлыг сайжруулах бол дэлгэцийг хуваах горимоос гарна уу"</string>
     <string name="done_label" msgid="7283767013231718521">"Дууссан"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Цаг гүйлгэгч"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Минут гүйлгэгч"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Клон <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Бэхэлснийг болиулахаасаа өмнө ПИН асуух"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Бэхэлснийг болиулахаас өмнө түгжээ тайлах хээ асуух"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Дэмжигч аппад нүүрэн талын үйлчилгээнүүдийг ардаас эхлүүлэхийг зөвшөөрнө."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофоныг ашиглах боломжгүй байна"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофоныг блоклосон байна"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Хоёр дэлгэц"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Хоёр дэлгэц асаалттай байна"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> контент харуулахын тулд хоёр дэлгэцийг хоёуланг нь ашиглаж байна"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Төхөөрөмж хэт халуун байна"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Таны утас хэт халж байгаа тул Хоёр дэлгэц боломжгүй байна"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Унтраах"</string>
 </resources>
diff --git a/core/res/res/values-mr-watch/strings.xml b/core/res/res/values-mr-watch/strings.xml
index 311a720..0bc7ad6 100644
--- a/core/res/res/values-mr-watch/strings.xml
+++ b/core/res/res/values-mr-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g> पैकी <xliff:g id="NUMBER_0">%1$d</xliff:g> अ‍ॅप"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"सेन्सर"</string>
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index e6dd0bb..8cc1b73 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ॲप वापरात असताना, शरीर सेन्सर मनगट तापमान डेटा अ‍ॅक्सेस करा."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"ॲप वापरात असताना, शरीर सेन्सर मनगट तापमान डेटा अ‍ॅक्सेस करण्याची ॲपला अनुमती देते."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"ॲप बॅकग्राउंडमध्ये असताना, शरीर सेन्सर मनगट तापमान डेटा अ‍ॅक्सेस करा."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"ॲप बॅकग्राउंडमध्ये असताना, शरीर सेन्सर मनगट तापमान डेटा अ‍ॅक्सेस करण्याची ॲपला अनुमती देते."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android सुरू करत आहे…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"टॅबलेट सुरू होत आहे…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"डिव्‍हाइस सुरू होत आहे…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"संचयन ऑप्टिमाइझ करत आहे."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"सिस्‍टम अपडेट संपत आहे…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> श्रेणीसुधारित करत आहे…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> पैकी <xliff:g id="NUMBER_0">%1$d</xliff:g> अ‍ॅप ऑप्टिमाइझ करत आहे."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> तयार करत आहे."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"अ‍ॅप्स सुरू करत आहे."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"बूट समाप्त होत आहे."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"पूर्ण स्क्रीनवर पाहत आहात"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"बाहेर पडण्यासाठी, वरून खाली स्वाइप करा."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"समजले"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"अधिक चांगल्या दृश्यासाठी फिरवा"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"अधिक चांगल्या दृश्यासाठी स्प्लिट स्क्रीनमधून बाहेर पडा"</string>
     <string name="done_label" msgid="7283767013231718521">"पूर्ण झाले"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"तास परिपत्रक स्लायडर"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"मिनिटे परिपत्रक स्लायडर"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> क्लोन केलेले"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन करण्‍यापूर्वी पिन विचारा"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन करण्‍यापूर्वी अनलॉक नमुन्यासाठी विचारा"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"अनपिन करण्‍यापूर्वी संकेतशब्दासाठी विचारा"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"सहयोगी अ‍ॅपला बॅकग्राउंडमधून फोरग्राउंड सेवा सुरू करण्याची अनुमती देते."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"मायक्रोफोन उपलब्ध आहे"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"मायक्रोफोन ब्लॉक केलेला आहे"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms-watch/strings.xml b/core/res/res/values-ms-watch/strings.xml
index 10379c9..cadbbbd 100644
--- a/core/res/res/values-ms-watch/strings.xml
+++ b/core/res/res/values-ms-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Apl <xliff:g id="NUMBER_0">%1$d</xliff:g> daripada <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Penderia"</string>
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 364c325..a58a21f 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Membenarkan apl mengakses data penderia tubuh, seperti kadar denyut jantung, suhu dan peratusan oksigen darah, semasa apl digunakan."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Akses data penderia tubuh, seperti kadar denyut jantung, semasa di latar"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Membenarkan apl mengakses data penderia tubuh, seperti kadar denyut jantung, suhu dan peratusan oksigen darah, semasa apl berjalan di latar belakang."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Akses data suhu pergelangan tangan penderia tubuh semasa apl digunakan."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Membenarkan apl mengakses data suhu pergelangan tangan penderia tubuh semasa apl digunakan."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Akses data suhu pergelangan tangan penderia tubuh semasa apl berjalan di latar belakang."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Membenarkan apl mengakses data suhu pergelangan tangan penderia tubuh semasa apl berjalan di latar belakang."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Baca acara dan butiran kalendar"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Apl ini boleh membaca semua acara kalendar yang disimpan pada tablet anda dan berkongsi atau menyimpan data kalendar anda."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Apl ini boleh membaca semua acara kalendar yang disimpan pada peranti Android TV anda dan berkongsi atau menyimpan data kalendar anda."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android sedang dimulakan…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet sedang dimulakan…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Peranti sedang dimulakan…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Mengoptimumkan storan."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Menyelesaikan kemas kini sistem…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> sedang ditingkatkan…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Mengoptimumkan apl <xliff:g id="NUMBER_0">%1$d</xliff:g> daripada <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Menyediakan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Memulakan apl."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"But akhir."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Melihat skrin penuh"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Untuk keluar, leret dari atas ke bawah."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Faham"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Putar untuk mendapatkan paparan yang lebih baik"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Keluar daripada skrin pisah untuk mendapatkan paparan yang lebih baik"</string>
     <string name="done_label" msgid="7283767013231718521">"Selesai"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Penggelangsar bulatan jam"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Penggelangsar bulatan minit"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Kerja <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-2"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-3"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> Klon"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Minta PIN sebelum menyahsemat"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Minta corak buka kunci sebelum menyahsemat"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Minta kata laluan sebelum menyahsemat"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Benarkan apl rakan memulakan perkhidmatan latar depan dari latar."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon tersedia"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon disekat"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dwiskrin"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dwiskrin dihidupkan"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> menggunakan kedua-dua paparan untuk menunjukkan kandungan"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Peranti terlalu panas"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dwiskrin tidak tersedia kerana telefon anda terlalu panas"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Matikan"</string>
 </resources>
diff --git a/core/res/res/values-my-watch/strings.xml b/core/res/res/values-my-watch/strings.xml
index 9270741..c471b3831 100644
--- a/core/res/res/values-my-watch/strings.xml
+++ b/core/res/res/values-my-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g>၏  <xliff:g id="NUMBER_0">%1$d</xliff:g> ‌အသေးစားဆော့ဝဲ"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"အာရုံခံကိရိယာများ"</string>
 </resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 0a8990c..12651a7 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"အက်ပ်သုံးနေစဉ် ခန္ဓာကိုယ် အာရုံခံကိရိယာမှ လက်ကောက်ဝတ်အပူချိန်ဒေတာကို သုံးပါ။"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"အက်ပ်သုံးနေစဉ် ခန္ဓာကိုယ် အာရုံခံကိရိယာမှ လက်ကောက်ဝတ်အပူချိန်ဒေတာသုံးရန် အက်ပ်ကို ခွင့်ပြုသည်။"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"နောက်ခံတွင် အက်ပ်ဖွင့်ထားစဉ် ခန္ဓာကိုယ် အာရုံခံကိရိယာမှ လက်ကောက်ဝတ်အပူချိန်ဒေတာကို သုံးပါ။"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"နောက်ခံတွင် အက်ပ်ဖွင့်ထားစဉ် ခန္ဓာကိုယ် အာရုံခံကိရိယာမှ လက်ကောက်ဝတ်အပူချိန်ဒေတာသုံးရန် အက်ပ်ကို ခွင့်ပြုသည်။"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android စတင်နေ…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"တက်ဘလက် စတင်နေသည်…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"စက်ပစ္စည်း စတင်နေသည်…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"သိုလှောင်မှုအား ပြုပြင်ခြင်း။"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"စနစ်အပ်ဒိတ်ကို အပြီးသတ်နေသည်…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> ကို အဆင့်မြှင့်တင်နေပါသည်…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_0">%1$d</xliff:g> ထဲက အက်ပ်<xliff:g id="NUMBER_1">%2$d</xliff:g>ကို ဆီလျော်အောင် လုပ်နေ"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> အားပြင်ဆင်နေသည်။"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"အက်ပ်များကို စတင်နေ"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"လုပ်ငန်းစနစ်ထည့်သွင်း၍ ပြန်လည်စတင်ရန် ပြီးပါပြီ"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"မျက်နှာပြင်အပြည့် ကြည့်နေသည်"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"ထွက်ရန် အပေါ်မှ အောက်သို့ ဆွဲချပါ။"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"ရပါပြီ"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ပိုကောင်းသောမြင်ကွင်းအတွက် လှည့်ပါ"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ပိုကောင်းသောမြင်ကွင်းအတွက် မျက်နှာပြင် ခွဲ၍ပြသခြင်းမှ ထွက်ပါ"</string>
     <string name="done_label" msgid="7283767013231718521">"ပြီးပါပြီ"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"နာရီရွေးချက်စရာ"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"မိနစ်လှည့်သော ရွေ့လျားတန်"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"အလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"ဒုတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"တတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ပင်မဖြုတ်မီမှာ PIN ကို မေးကြည့်ရန်"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ပင်မဖြုတ်မီမှာ သော့ဖွင့် ရေးဆွဲမှုပုံစံကို မေးကြည့်ရန်"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"နောက်ခံမှနေ၍ မျက်နှာစာဝန်ဆောင်မှုများ စတင်ရန် တွဲဖက် အက်ပ်ကို ခွင့်ပြုသည်။"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"မိုက်ခရိုဖုန်း သုံးနိုင်သည်"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"မိုက်ခရိုဖုန်း ပိတ်ထားသည်"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb-watch/strings.xml b/core/res/res/values-nb-watch/strings.xml
index d126fe0..fa296b6 100644
--- a/core/res/res/values-nb-watch/strings.xml
+++ b/core/res/res/values-nb-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensorer"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index d646c76..88f4dc9 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Gir appen tilgang til data fra kroppssensorer, for eksempel puls, temperatur og oksygenmetning i blodet, når den er i bruk."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Tilgang til data fra kroppssensorer, for eksempel puls, når den er i bakgrunnen"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Gir appen tilgang til data fra kroppssensorer, for eksempel puls, temperatur og oksygenmetning i blodet, når den er i bakgrunnen."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Tilgang til data fra kroppssensorer for håndleddstemperatur mens appen er i bruk."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Gir appen tilgang til data fra kroppssensorer for håndleddstemperatur mens appen er i bruk."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Tilgang til data fra kroppssensorer for håndleddstemperatur mens appen er i bakgrunnen."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Gir appen tilgang til data fra kroppssensorer for håndleddstemperatur mens appen er i bakgrunnen."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Les kalenderaktivitet og detaljer"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Denne appen kan lese all kalenderaktivitet som er lagret på nettbrettet ditt, og dele eller lagre kalenderdataene."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Denne appen kan lese all kalenderaktivitet som er lagret på Android TV-enheten din, og dele eller lagre kalenderdataene."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android starter …"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Nettbrettet starter …"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Enheten starter …"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimaliser lagring."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Fullfører systemoppdateringen …"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> oppgraderes …"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimaliserer app <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starter apper."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Ferdigstiller oppstart."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visning i fullskjerm"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Sveip ned fra toppen for å avslutte."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Skjønner"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Roter for å få en bedre visning"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Avslutt delt skjerm for å få en bedre visning"</string>
     <string name="done_label" msgid="7283767013231718521">"Ferdig"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Sirkulær glidebryter for timer"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Sirkulær glidebryter for minutter"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Jobb-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Andre <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Krev PIN-kode for å løsne app"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Krev opplåsingsmønster for å løsne apper"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Krev passord for å løsne apper"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Lar en følgeapp starte forgrunnstjenester fra bakgrunnen."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofonen er tilgjengelig"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofonen er blokkert"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ne-watch/strings.xml b/core/res/res/values-ne-watch/strings.xml
index 54002fc9ea..8c0df82 100644
--- a/core/res/res/values-ne-watch/strings.xml
+++ b/core/res/res/values-ne-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g> को <xliff:g id="NUMBER_0">%1$d</xliff:g> अनुप्रयोग।"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"सेन्सरहरू"</string>
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index d300beb..dd1b0ab 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"यो एप प्रयोग भइरहेका बेला बडी सेन्सरले रेकर्ड गरेको नाडीको तापक्रमसम्बन्धी डेटा प्रयोग गर्ने अनुमति।"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"यसले यो एप प्रयोग भइरहेका बेला यो एपलाई बडी सेन्सरले रेकर्ड गरेको नाडीको तापक्रमसम्बन्धी डेटा प्रयोग गर्ने अनुमति दिन्छ।"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"यो एप ब्याकग्राउन्डमा चलिरहेका बेला बडी सेन्सरले रेकर्ड गरेको नाडीको तापक्रमसम्बन्धी डेटा प्रयोग गर्ने अनुमति।"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"यसले यो एप ब्याकग्राउन्डमा चलिरहेका बेला यो एपलाई बडी सेन्सरले रेकर्ड गरेको नाडीको तापक्रमसम्बन्धी डेटा प्रयोग गर्ने अनुमति दिन्छ।"</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 टिभी डिभाइसमा भण्डारण गरिएका पात्रोसम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android शुरू हुँदैछ..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ट्याब्लेट सुरु हुँदै छ…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"यन्त्र सुरु हुँदै छ…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"भण्डारण आफू अनुकूल गर्दै।"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"सिस्टम अपडेट सम्पन्न गरिँदै छ…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> को स्तरवृद्धि हुँदैछ…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"एप अनुकुल हुँदै <xliff:g id="NUMBER_0">%1$d</xliff:g> को <xliff:g id="NUMBER_1">%2$d</xliff:g>।"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> तयारी गर्दै।"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"सुरुवात एपहरू।"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"बुट पुरा हुँदै।"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"पूरा पर्दा हेर्दै"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"बाहिर निस्कन, माथिबाट तल स्वाइप गर्नुहोस्।"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"बुझेँ"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"अझ राम्रो दृश्य हेर्न चाहनुहुन्छ भने रोटेट गर्नुहोस्"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"अझ राम्रो दृश्य हेर्न चाहनुहुन्छ भने \"स्प्लिट स्क्रिन\" बाट बाहिरिनुहोस्"</string>
     <string name="done_label" msgid="7283767013231718521">"भयो"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"घन्टा गोलाकार स्लाइडर"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"मिनेट गोलाकार स्लाइडर"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"कार्यालयको दोस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"कार्यालयको तेस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> क्लोन गर्नुहोस्"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन गर्नुअघि PIN मागियोस्"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन गर्नअघि अनलक प्याटर्न माग्नुहोस्"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"यसले सहयोगी एपलाई ब्याकग्राउन्डमा फोरग्राउन्ड सेवाहरू चलाउने अनुमति दिन्छ।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"माइक्रोफोन अनम्युट गरिएको छ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"माइक्रोफोन म्युट गरिएको छ"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl-watch/strings.xml b/core/res/res/values-nl-watch/strings.xml
index 0222164..3f693a9 100644
--- a/core/res/res/values-nl-watch/strings.xml
+++ b/core/res/res/values-nl-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensoren"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 9b6b896..2a9f028 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"De app heeft toegang tot gegevens van lichaamssensoren, zoals hartslag, temperatuur en zuurstofpercentage in het bloed, terwijl de app wordt gebruikt."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Toegang tot gegevens van lichaamssensoren, zoals hartslag, op de achtergrond"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"De app heeft toegang tot gegevens van lichaamssensoren, zoals hartslag, temperatuur en zuurstofpercentage in het bloed, terwijl de app op de achtergrond wordt uitgevoerd."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Toegang tot gegevens van de lichaamssensor voor polstemperatuur terwijl de app in gebruik is."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Geeft de app toegang tot gegevens van de lichaamssensor voor polstemperatuur terwijl de app in gebruik is."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Toegang tot gegevens van de lichaamssensor voor polstemperatuur terwijl de app op de achtergrond wordt uitgevoerd."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Geeft de app toegang tot gegevens van de lichaamssensor voor polstemperatuur terwijl de app op de achtergrond wordt uitgevoerd."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Agenda-afspraken en -gegevens lezen"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Deze app kan alle agenda-afspraken lezen die zijn opgeslagen op je tablet en je agendagegevens delen of opslaan."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Deze app kan alle agenda-afspraken lezen die zijn opgeslagen op je Android TV-apparaat en je agendagegevens delen of opslaan."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android wordt gestart…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet wordt gestart…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Apparaat wordt gestart…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Opslagruimte wordt geoptimaliseerd."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Systeemupdate voltooien…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> upgraden…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g> optimaliseren."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> voorbereiden."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Apps starten."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Opstarten afronden."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Volledig scherm wordt getoond"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Swipe omlaag vanaf de bovenkant van het scherm om af te sluiten."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Ik snap het"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Draai voor een betere weergave"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Sluit het gesplitste scherm voor een betere weergave"</string>
     <string name="done_label" msgid="7283767013231718521">"Klaar"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Ronde schuifregelaar voor uren"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Ronde schuifregelaar voor minuten"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Werk <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Vraag pin voor losmaken"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Vraag om ontgrendelingspatroon voor losmaken"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Vraag wachtwoord voor losmaken"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Hiermee kan een bijbehorende app services op de voorgrond vanuit de achtergrond starten."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microfoon is beschikbaar"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microfoon is geblokkeerd"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-or-watch/strings.xml b/core/res/res/values-or-watch/strings.xml
index 75de26d..8b11631 100644
--- a/core/res/res/values-or-watch/strings.xml
+++ b/core/res/res/values-or-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଆପ୍‍ରୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଟି।"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"ସେନ୍ସର୍‍"</string>
 </resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index c2560da..9188c4f 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ଆପଟି ବ୍ୟବହାରରେ ଥିବା ସମୟରେ ବଡି ସେନ୍ସର ରିଷ୍ଟ ତାପମାତ୍ରା ଡାଟାକୁ ଆକ୍ସେସ କରନ୍ତୁ।"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"ଆପଟି ବ୍ୟବହାରରେ ଥିବା ସମୟରେ, ବଡି ସେନ୍ସର ରିଷ୍ଟ ତାପମାତ୍ରା ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"ଆପଟି ପୃଷ୍ଠପଟରେ ଥିବା ସମୟରେ ବଡି ସେନ୍ସର ରିଷ୍ଟ ତାପମାତ୍ରା ଡାଟାକୁ ଆକ୍ସେସ କରନ୍ତୁ।"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"ଆପଟି ପୃଷ୍ଠପଟରେ ଥିବା ସମୟରେ, ବଡି ସେନ୍ସର ରିଷ୍ଟ ତାପମାତ୍ରା ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ।"</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>
@@ -1081,13 +1077,13 @@
     <string name="menu_space_shortcut_label" msgid="5949311515646872071">"ସ୍ପେସ୍‍"</string>
     <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"ଏଣ୍ଟର୍"</string>
     <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"ଡିଲିଟ୍‌ କରନ୍ତୁ"</string>
-    <string name="search_go" msgid="2141477624421347086">"ସନ୍ଧାନ କରନ୍ତୁ"</string>
-    <string name="search_hint" msgid="455364685740251925">"ସନ୍ଧାନ…"</string>
-    <string name="searchview_description_search" msgid="1045552007537359343">"ସନ୍ଧାନ କରନ୍ତୁ"</string>
+    <string name="search_go" msgid="2141477624421347086">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
+    <string name="search_hint" msgid="455364685740251925">"ସର୍ଚ୍ଚ କରନ୍ତୁ…"</string>
+    <string name="searchview_description_search" msgid="1045552007537359343">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
     <string name="searchview_description_query" msgid="7430242366971716338">"କ୍ୱେରୀ ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
     <string name="searchview_description_clear" msgid="1989371719192982900">"କ୍ୱେରୀ ଖାଲି କରନ୍ତୁ"</string>
     <string name="searchview_description_submit" msgid="6771060386117334686">"କ୍ୱେରୀ ଦାଖଲ କରନ୍ତୁ"</string>
-    <string name="searchview_description_voice" msgid="42360159504884679">"ଭଏସ୍‍ ସର୍ଚ୍ଚ"</string>
+    <string name="searchview_description_voice" msgid="42360159504884679">"ଭଏସ ସର୍ଚ୍ଚ"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍‍ କରନ୍ତୁ’ ସକ୍ଷମ କରିବେ?"</string>
     <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍ କରନ୍ତୁ’ ସକ୍ଷମ କରିବାକୁ ଚାହେଁ। ’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍ କରନ୍ତୁ’ ଅନ୍‌ ଥିବାବେଳେ, ଆପଣଙ୍କ ଆଙ୍ଗୁଠି ତଳେ କ’ଣ ଅଛି, ତାହାର ବ୍ୟାଖ୍ୟା ଦେଖିପାରିବେ କିମ୍ବା ଟାବ୍‍ଲେଟ୍‍ ସହ କଥାବାର୍ତ୍ତା କରିବାକୁ ଜେଶ୍ଚର୍‌ କରିପାରିବେ।"</string>
     <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍ କରନ୍ତୁ’ ସକ୍ଷମ କରିବାକୁ ଚାହେଁ। ’ସ୍ପର୍ଶ କରି ଏକ୍ସପ୍ଲୋର୍ କରନ୍ତୁ’ ଅନ୍‌ ଥିବାବେଳେ, ଆପଣଙ୍କ ଆଙ୍ଗୁଠି ତଳେ କ’ଣ ଅଛି, ତାହାର ବ୍ୟାଖ୍ୟା ଦେଖିପାରିବେ କିମ୍ବା ଫୋନ୍‍ ସହ କଥାବାର୍ତ୍ତା କରିବାକୁ ଜେଶ୍ଚର୍‌ କରିପାରିବେ।"</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"ଆଣ୍ଡ୍ରଏଡ୍ ଆରମ୍ଭ ହେଉଛି…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ଟାବଲେଟ୍ ଆରମ୍ଭ ହେଉଛି…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ଡିଭାଇସ୍ ଆରମ୍ଭ ହେଉଛି…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"ଷ୍ଟୋରେଜ୍‍ ବଢ଼ାଯାଉଛି"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"ସିଷ୍ଟମ୍ ଅପଡେଟ୍ ସମାପ୍ତ ହେଉଛି…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅପଗ୍ରେଡ୍‍ କରାଯାଉଛି…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g>ରୁ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଆପ୍‍ ଅନୁକୂଳନ କରୁଛି।"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> ପ୍ରସ୍ତୁତ କରାଯାଉଛି।"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ଆପ୍‍ ଆରମ୍ଭ କରାଯାଉଛି।"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"ବୁଟ୍‍ ସମାପ୍ତ କରୁଛି।"</string>
@@ -1468,7 +1462,7 @@
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"ଜୁମ୍ ନିୟନ୍ତ୍ରଣ ପାଇଁ ଦୁଇଥର ଟାପ୍‌ କରନ୍ତୁ"</string>
     <string name="gadget_host_error_inflating" msgid="2449961590495198720">"ୱିଜେଟ୍‍ ଯୋଡ଼ିପାରିବ ନାହିଁ।"</string>
     <string name="ime_action_go" msgid="5536744546326495436">"ଯାଆନ୍ତୁ"</string>
-    <string name="ime_action_search" msgid="4501435960587287668">"ସନ୍ଧାନ କରନ୍ତୁ"</string>
+    <string name="ime_action_search" msgid="4501435960587287668">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
     <string name="ime_action_send" msgid="8456843745664334138">"ପଠାନ୍ତୁ"</string>
     <string name="ime_action_next" msgid="4169702997635728543">"ପରବର୍ତ୍ତୀ"</string>
     <string name="ime_action_done" msgid="6299921014822891569">"ହୋଇଗଲା"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ଦେଖାଯାଉଛି"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"ବାହାରିବା ପାଇଁ, ଉପରୁ ତଳକୁ ସ୍ୱାଇପ୍‍ କରନ୍ତୁ।"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"ବୁଝିଗଲି"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ଏକ ଭଲ ଭ୍ୟୁ ପାଇଁ ରୋଟେଟ କରନ୍ତୁ"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ଏକ ଭଲ ଭ୍ୟୁ ପାଇଁ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନରୁ ବାହାରି ଯାଆନ୍ତୁ"</string>
     <string name="done_label" msgid="7283767013231718521">"ହୋଇଗଲା"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"ଘଣ୍ଟା ସର୍କୁଲାର୍‍ ସ୍ଲାଇଡର୍‍"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"ମିନିଟ୍ସ ସର୍କୁଲାର୍‍ ସ୍ଲାଇଡର୍‍"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"ୱାର୍କ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2ୟ କାର୍ଯ୍ୟ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3ୟ କାର୍ଯ୍ୟ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> କ୍ଲୋନ"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ଅନପିନ୍‌ କରିବା ପୂର୍ବରୁ PIN ପଚାରନ୍ତୁ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ଅନପିନ୍‌ କରିବା ପୂର୍ବରୁ ଲକ୍‌ ଖୋଲିବା ପାଟର୍ନ ପଚାରନ୍ତୁ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ଅନପିନ୍‌ କରିବା ପୂର୍ବରୁ ପାସ୍‌ୱର୍ଡ ପଚାରନ୍ତୁ"</string>
@@ -1943,7 +1940,7 @@
     <string name="region_picker_section_suggested_bilingual" msgid="704607569328224133">"ପ୍ରସ୍ତାବିତ ଅଞ୍ଚଳଗୁଡ଼ିକ"</string>
     <string name="language_picker_section_all" msgid="1985809075777564284">"ସମସ୍ତ ଭାଷା"</string>
     <string name="region_picker_section_all" msgid="756441309928774155">"ସମସ୍ତ ଅଞ୍ଚଳ"</string>
-    <string name="locale_search_menu" msgid="6258090710176422934">"ସନ୍ଧାନ କରନ୍ତୁ"</string>
+    <string name="locale_search_menu" msgid="6258090710176422934">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
     <string name="app_suspended_title" msgid="888873445010322650">"ଆପ୍‌ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="app_suspended_default_message" msgid="6451215678552004172">"ବର୍ତ୍ତମାନ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ଉପଲବ୍ଧ ନାହିଁ। ଏହା <xliff:g id="APP_NAME_1">%2$s</xliff:g> ଦ୍ଵାରା ପରିଚାଳିତ ହେଉଛି।"</string>
     <string name="app_suspended_more_details" msgid="211260942831587014">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ପୃଷ୍ଠପଟରୁ ଫୋରଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକ ଆରମ୍ଭ କରିବାକୁ ଏକ ସହଯୋଗୀ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ମାଇକ୍ରୋଫୋନ ଉପଲବ୍ଧ ଅଛି"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ମାଇକ୍ରୋଫୋନକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pa-watch/strings.xml b/core/res/res/values-pa-watch/strings.xml
index c98b307..b1eb3a7 100644
--- a/core/res/res/values-pa-watch/strings.xml
+++ b/core/res/res/values-pa-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"ਐਪ <xliff:g id="NUMBER_1">%2$d</xliff:g> ਦਾ <xliff:g id="NUMBER_0">%1$d</xliff:g>"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"ਸੰੰਵੇਦਕ"</string>
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 4086ab7..aba9d12 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ਐਪ ਦੇ ਵਰਤੋਂ ਵਿੱਚ ਹੋਣ \'ਤੇ, ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਵੱਲੋਂ ਤੁਹਾਡੇ ਸੌਣ ਵੇਲੇ ਰਿਕਾਰਡ ਕੀਤੇ ਜਾਣ ਵਾਲੇ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰੋ।"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"ਐਪ ਦੇ ਵਰਤੋਂ ਵਿੱਚ ਹੋਣ \'ਤੇ, ਐਪ ਨੂੰ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਵੱਲੋਂ ਤੁਹਾਡੇ ਸੌਣ ਵੇਲੇ ਰਿਕਾਰਡ ਕੀਤੇ ਜਾਣ ਵਾਲੇ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"ਐਪ ਦੇ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਦੇ ਹੋਣ \'ਤੇ, ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਵੱਲੋਂ ਤੁਹਾਡੇ ਸੌਣ ਵੇਲੇ ਰਿਕਾਰਡ ਕੀਤੇ ਜਾਣ ਵਾਲੇ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰੋ।"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"ਐਪ ਦੇ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਦੇ ਹੋਣ \'ਤੇ, ਐਪ ਨੂੰ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਵੱਲੋਂ ਤੁਹਾਡੇ ਸੌਣ ਵੇਲੇ ਰਿਕਾਰਡ ਕੀਤੇ ਜਾਣ ਵਾਲੇ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦਿੰਦਾ ਹੈ।"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ਟੈਬਲੈੱਟ ਚਾਲੂ ਹੋ ਰਿਹਾ ਹੈ…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ਡੀਵਾਈਸ ਚਾਲੂ ਹੋ ਰਿਹਾ ਹੈ…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"ਸਟੋਰੇਜ ਅਨੁਕੂਲ ਹੋ ਰਹੀ ਹੈ।"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"ਸਿਸਟਮ ਅੱਪਡੇਟ ਪੂਰਾ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> ਅੱਪਗ੍ਰੇਡ ਹੋ ਰਹੀ ਹੈ…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_0">%1$d</xliff:g> <xliff:g id="NUMBER_1">%2$d</xliff:g> ਦਾ ਐਪ ਅਨੁਕੂਲ ਕਰ ਰਿਹਾ ਹੈ।"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> ਤਿਆਰ ਕਰ ਰਿਹਾ ਹੈ।"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ਐਪਸ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ।"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"ਬੂਟ ਪੂਰਾ ਕਰ ਰਿਹਾ ਹੈ।"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"ਪੂਰੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦੇਖੋ"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"ਬਾਹਰ ਜਾਣ ਲਈ, ਉਪਰੋਂ ਹੇਠਾਂ ਸਵਾਈਪ ਕਰੋ।"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"ਸਮਝ ਲਿਆ"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ਬਿਹਤਰ ਦ੍ਰਿਸ਼ ਅਨੁਭਵ ਲਈ ਘੁਮਾਓ"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ਬਿਹਤਰ ਦ੍ਰਿਸ਼ ਅਨੁਭਵ ਲਈ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਤੋਂ ਬਾਹਰ ਆਓ"</string>
     <string name="done_label" msgid="7283767013231718521">"ਹੋ ਗਿਆ"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"ਘੰਟੇ ਸਰਕੁਲਰ ਸਲਾਈਡਰ"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"ਮਿੰਟ ਸਰਕੁਲਰ ਸਲਾਈਡਰ"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"ਕੰਮ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"ਦੂਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"ਤੀਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਿੰਨ ਮੰਗੋ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਣਲਾਕ ਪੈਟਰਨ ਵਾਸਤੇ ਪੁੱਛੋ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ਅਣਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ਸੰਬੰਧੀ ਐਪ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਤੋਂ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾਵਾਂ ਸ਼ੁਰੂ ਕਰਨ ਦੀ ਆਗਿਆ ਮਿਲਦੀ ਹੈ।"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਉਪਲਬਧ ਹੈ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl-watch/strings.xml b/core/res/res/values-pl-watch/strings.xml
index 582b18e..2d81625 100644
--- a/core/res/res/values-pl-watch/strings.xml
+++ b/core/res/res/values-pl-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplikacja <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Czujniki"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index f57ec7e..f2b662f 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -460,14 +460,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Zezwala aplikacji na dostęp do danych z czujników na ciele, takich jak tętno, temperatura i poziom saturacji, gdy aplikacja ta jest używana."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Zezwól na dostęp do danych z czujników na ciele, np. tętna, podczas używania aplikacji w tle"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Zezwala aplikacji na dostęp do danych z czujników na ciele, takich jak tętno, temperatura i poziom saturacji, gdy aplikacja ta jest używana w tle."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Dostęp do pochodzących z czujnika na ciele danych temperatury na nadgarstku, kiedy aplikacja jest w użyciu."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Zezwala na dostęp aplikacji do pochodzących z czujnika na ciele danych temperatury na nadgarstku, kiedy aplikacja jest w użyciu."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Dostęp do pochodzących z czujnika na ciele danych temperatury na nadgarstku, kiedy aplikacja działa w tle."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Zezwala na dostęp aplikacji do pochodzących z czujnika na ciele danych temperatury na nadgarstku, kiedy aplikacja działa w tle."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Odczytywanie wydarzeń i informacji z kalendarza"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Ta aplikacja może odczytywać wszystkie zapisane na tablecie wydarzenia z kalendarza i udostępniać oraz zapisywać dane kalendarza."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ta aplikacja może odczytywać wszystkie wydarzenia z kalendarza zapisane na urządzeniu z Androidem TV oraz udostępniać i zapisywać dane z kalendarza."</string>
@@ -1251,10 +1247,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android się uruchamia…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet się uruchamia…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Urządzenie się uruchamia…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optymalizacja pamięci."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Kończę aktualizację systemu…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Uaktualniam aplikację <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optymalizowanie aplikacji <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Przygotowuję aplikację <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Uruchamianie aplikacji."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Kończenie uruchamiania."</string>
@@ -1852,6 +1846,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Włączony pełny ekran"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Aby wyjść, przesuń palcem z góry na dół."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Obróć, aby lepiej widzieć"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Zamknij podzielony ekran, aby lepiej widzieć"</string>
     <string name="done_label" msgid="7283767013231718521">"Gotowe"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Kołowy suwak godzin"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Kołowy suwak minut"</string>
@@ -1863,6 +1859,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (służbowy)"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 2"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 3"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Podaj PIN, aby odpiąć"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Aby odpiąć, poproś o wzór odblokowania"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Aby odpiąć, poproś o hasło"</string>
@@ -2317,4 +2315,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Zezwala aplikacji towarzyszącej na uruchamianie usług działających na pierwszym planie, podczas gdy sama działa w tle."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon jest dostępny"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon jest zablokowany"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rBR-watch/strings.xml b/core/res/res/values-pt-rBR-watch/strings.xml
index 04178e0..dea270b 100644
--- a/core/res/res/values-pt-rBR-watch/strings.xml
+++ b/core/res/res/values-pt-rBR-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensores"</string>
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 6fc8ce5..6f1051c 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite que o app acesse dados do sensor corporal, como a frequência cardíaca, a temperatura e a porcentagem de oxigênio no sangue, enquanto o app está em uso."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Acessar dados do sensor corporal, como a frequência cardíaca, segundo plano"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permite que o app acesse dados do sensor corporal, como a frequência cardíaca, a temperatura e a porcentagem de oxigênio no sangue, enquanto o app está em segundo plano."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Acessar dados de temperatura do sensor corporal no pulso enquanto o app está em uso."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permite que o app acesse dados de temperatura do sensor corporal no pulso enquanto está em uso."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Acessar dados de temperatura do sensor corporal no pulso enquanto o app está em segundo plano."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permite que o app acesse dados de temperatura do sensor corporal no pulso enquanto está em segundo plano."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Ler detalhes e eventos da agenda"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Este app pode ler todos os eventos da agenda armazenados no seu tablet e compartilhar ou salvar os dados da sua agenda."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Este app pode ler todos os eventos da agenda armazenados no seu dispositivo Android TV e compartilhar ou salvar os dados da sua agenda."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"O Android está iniciando..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"O tablet está iniciando…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"O dispositivo está iniciando…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Otimizando o armazenamento."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Concluindo atualização do sistema…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> está fazendo upgrade…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Otimizando app <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando apps."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Concluindo a inicialização."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visualização em tela cheia"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Para sair, deslize de cima para baixo."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Entendi"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gire a tela para ter uma visualização melhor"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Saia da tela dividida para ter uma visualização melhor"</string>
     <string name="done_label" msgid="7283767013231718521">"Concluído"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Controle deslizante circular das horas"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Controle deslizante circular dos minutos"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> (clone)"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de liberar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de liberar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir senha antes de liberar"</string>
@@ -2316,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que um app complementar em segundo plano inicie serviços em primeiro plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"O microfone está disponível"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"O microfone está bloqueado"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT-watch/strings.xml b/core/res/res/values-pt-rPT-watch/strings.xml
index a1cdd89..dea270b 100644
--- a/core/res/res/values-pt-rPT-watch/strings.xml
+++ b/core/res/res/values-pt-rPT-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplicação <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensores"</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index f7b9e69..c9ca4b8 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite à app aceder a dados de sensores de corpo, como ritmo cardíaco, temperatura e percentagem de oxigénio no sangue, enquanto está a ser usada."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Aceder a dados de sensores de corpo, como ritmo cardíaco, quando em seg. plano"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permite à app aceder a dados de sensores de corpo, como ritmo cardíaco, temperatura e percentagem de oxigénio no sangue, enquanto está em segundo plano."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Aceda a dados de temperatura do pulso de sensores de corpo enquanto a app está a ser usada."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permite à app aceder a dados de temperatura do pulso de sensores de corpo enquanto a app está a ser usada."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Aceda a dados de temperatura do pulso de sensores de corpo enquanto a app está em segundo plano."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permite à app aceder a dados de temperatura do pulso de sensores de corpo enquanto a app está em segundo plano."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Ler detalhes e eventos do calendário"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Esta app pode ler todos os eventos do calendário armazenados no seu tablet e partilhar ou guardar os dados do calendário."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Esta app pode ler todos os eventos do calendário armazenados no seu dispositivo Android TV e partilhar ou guardar os dados do calendário."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"O Android está a iniciar…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"O tablet está a iniciar…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"O dispositivo está a iniciar…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"A otimizar o armazenamento."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"A concluir a atualização do sistema…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"O <xliff:g id="APPLICATION">%1$s</xliff:g> está a ser atualizado…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"A otimizar a app <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"A preparar o <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"A iniciar aplicações"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"A concluir o arranque."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visualização de ecrã inteiro"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Para sair, deslize rapidamente para baixo a partir da parte superior."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rode para uma melhor visualização"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Saia do ecrã dividido para uma melhor visualização"</string>
     <string name="done_label" msgid="7283767013231718521">"Concluído"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Controlo de deslize circular das horas"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Controlo de deslize circular dos minutos"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Clonar <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de soltar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de soltar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir palavra-passe antes de soltar"</string>
@@ -2316,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que uma app associada em segundo plano inicie serviços em primeiro plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"O microfone está disponível"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"O microfone está bloqueado"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dois ecrãs"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"A funcionalidade Dois ecrãs está ativada"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a usar ambos os ecrãs para mostrar conteúdo"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"O dispositivo está a ficar demasiado quente"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"A funcionalidade Dois ecrãs está indisponível porque o seu telemóvel está a ficar demasiado quente"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desativar"</string>
 </resources>
diff --git a/core/res/res/values-pt-watch/strings.xml b/core/res/res/values-pt-watch/strings.xml
index 04178e0..dea270b 100644
--- a/core/res/res/values-pt-watch/strings.xml
+++ b/core/res/res/values-pt-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensores"</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 6fc8ce5..6f1051c 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite que o app acesse dados do sensor corporal, como a frequência cardíaca, a temperatura e a porcentagem de oxigênio no sangue, enquanto o app está em uso."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Acessar dados do sensor corporal, como a frequência cardíaca, segundo plano"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permite que o app acesse dados do sensor corporal, como a frequência cardíaca, a temperatura e a porcentagem de oxigênio no sangue, enquanto o app está em segundo plano."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Acessar dados de temperatura do sensor corporal no pulso enquanto o app está em uso."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permite que o app acesse dados de temperatura do sensor corporal no pulso enquanto está em uso."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Acessar dados de temperatura do sensor corporal no pulso enquanto o app está em segundo plano."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permite que o app acesse dados de temperatura do sensor corporal no pulso enquanto está em segundo plano."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Ler detalhes e eventos da agenda"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Este app pode ler todos os eventos da agenda armazenados no seu tablet e compartilhar ou salvar os dados da sua agenda."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Este app pode ler todos os eventos da agenda armazenados no seu dispositivo Android TV e compartilhar ou salvar os dados da sua agenda."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"O Android está iniciando..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"O tablet está iniciando…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"O dispositivo está iniciando…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Otimizando o armazenamento."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Concluindo atualização do sistema…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> está fazendo upgrade…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Otimizando app <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando apps."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Concluindo a inicialização."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visualização em tela cheia"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Para sair, deslize de cima para baixo."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Entendi"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gire a tela para ter uma visualização melhor"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Saia da tela dividida para ter uma visualização melhor"</string>
     <string name="done_label" msgid="7283767013231718521">"Concluído"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Controle deslizante circular das horas"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Controle deslizante circular dos minutos"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"<xliff:g id="LABEL">%1$s</xliff:g> (clone)"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pedir PIN antes de liberar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pedir padrão de desbloqueio antes de liberar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pedir senha antes de liberar"</string>
@@ -2316,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite que um app complementar em segundo plano inicie serviços em primeiro plano."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"O microfone está disponível"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"O microfone está bloqueado"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro-watch/strings.xml b/core/res/res/values-ro-watch/strings.xml
index 7dfedbb..da58726 100644
--- a/core/res/res/values-ro-watch/strings.xml
+++ b/core/res/res/values-ro-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplic. <xliff:g id="NUMBER_0">%1$d</xliff:g> din <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Senzori"</string>
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index b9c90b1..f1f8015 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -459,14 +459,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite aplicației să acceseze date de la senzorii corporali, cum ar fi pulsul, temperatura și procentul de oxigen din sânge, în timpul folosirii aplicației."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Să acceseze date de la senzorii corporali, precum pulsul, când rulează în fundal"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permite aplicației să acceseze date de la senzorii corporali, cum ar fi pulsul, temperatura și procentul de oxigen din sânge, în timp ce aplicația rulează în fundal."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Accesează date despre temperatura încheieturii de la senzorii corporali în timpul folosirii aplicației."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Permite aplicației să acceseze date despre temperatura încheieturii de la senzorii corporali în timpul folosirii aplicației."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Accesează date despre temperatura încheieturii de la senzorii corporali în timp ce aplicația rulează în fundal."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Permite aplicației să acceseze date despre temperatura încheieturii de la senzorii corporali în timp ce aplicația rulează în fundal."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"să citească evenimentele din calendar și detaliile"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Această aplicație poate să citească toate evenimentele din calendar stocate pe tabletă și să trimită sau să salveze datele din calendar."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Această aplicație poate să citească toate evenimentele din calendar stocate pe dispozitivul Android TV și să trimită sau să salveze datele din calendar."</string>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android pornește..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Pornește tableta…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Pornește dispozitivul…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Se optimizează stocarea."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Se finalizează actualizarea sistemului…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Se face upgrade pentru <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Se optimizează aplicația <xliff:g id="NUMBER_0">%1$d</xliff:g> din <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Se pregătește <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Se pornesc aplicațiile."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Se finalizează pornirea."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Vizualizare pe ecran complet"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Pentru a ieși, glisează de sus în jos."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Am înțeles"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotește pentru o previzualizare mai bună"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Ieși din ecranul împărțit pentru o previzualizare mai bună"</string>
     <string name="done_label" msgid="7283767013231718521">"Terminat"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Selector circular pentru ore"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Selector circular pentru minute"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> de serviciu"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (2)"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (3)"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Clonă pentru <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicită codul PIN înainte de a anula fixarea"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Solicită mai întâi modelul pentru deblocare"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicită parola înainte de a anula fixarea"</string>
@@ -2316,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Permite unei aplicații partenere să inițieze servicii în prim-plan din fundal."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Microfonul este disponibil"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Microfonul este blocat"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru-watch/strings.xml b/core/res/res/values-ru-watch/strings.xml
index 02f068b..b8416c3 100644
--- a/core/res/res/values-ru-watch/strings.xml
+++ b/core/res/res/values-ru-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Приложение <xliff:g id="NUMBER_0">%1$d</xliff:g> из <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Датчики"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index b7a3f60..b6381379 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -460,14 +460,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Доступ к данным с нательных датчиков о температуре запястья (при использовании приложения)"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Когда приложение используется, это разрешение предоставляет ему доступ к данным о температуре запястья, которые собираются нательными датчиками."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Доступ к данным с нательных датчиков о температуре запястья (при работе приложения в фоновом режиме)"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Когда приложение работает в фоновом режиме, это разрешение предоставляет ему доступ к данным о температуре запястья, которые собираются нательными датчиками."</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>
@@ -1251,10 +1247,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Запуск Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Запуск планшета…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Запуск устройства…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Оптимизация хранилища…"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Завершение обновления системы…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Обновление приложения \"<xliff:g id="APPLICATION">%1$s</xliff:g>\"…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Оптимизация приложения <xliff:g id="NUMBER_0">%1$d</xliff:g> из <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Подготовка приложения \"<xliff:g id="APPNAME">%1$s</xliff:g>\"..."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск приложений."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Окончание загрузки..."</string>
@@ -1852,6 +1846,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Полноэкранный режим"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Чтобы выйти, проведите по экрану сверху вниз."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"ОК"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Поверните, чтобы лучше видеть."</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Выйдите из режима разделения экрана, чтобы лучше видеть."</string>
     <string name="done_label" msgid="7283767013231718521">"Готово"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Выбор часов на циферблате"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Выбор минут на циферблате"</string>
@@ -1863,6 +1859,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Рабочий <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Задача 2: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Задача 3: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Клонировать <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Запрашивать PIN-код"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запрашивать графический ключ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запрашивать пароль"</string>
@@ -2317,4 +2314,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Сопутствующее приложение сможет запускать активные службы из фонового режима."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофон доступен."</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофон заблокирован."</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-si-watch/strings.xml b/core/res/res/values-si-watch/strings.xml
index 6d08c1b..bab95aa 100644
--- a/core/res/res/values-si-watch/strings.xml
+++ b/core/res/res/values-si-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g> හි <xliff:g id="NUMBER_1">%2$d</xliff:g> යෙදුම."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"සංවේදක"</string>
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index edb7dc2..ffbffc9 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"යෙදුම භාවිතයේ පවතින අතරේ ශරීර සංවේදක මැණික් කටුවේ උෂ්ණත්ව දත්ත වෙත ප්‍රවේශ වන්න."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"යෙදුම භාවිතයේ ඇති අතරේ, ශරීර සංවේදක මැණික් කටුවේ උෂ්ණත්ව දත්ත වෙත ප්‍රවේශ වීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"යෙදුම පසුබිමේ ඇති අතරේ ශරීර සංවේදක මැණික් කටුවේ උෂ්ණත්ව දත්ත වෙත ප්‍රවේශ වන්න."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"යෙදුම පසුබිමේ ඇති අතරේ, ශරීර සංවේදක මැණික් කටුවේ උෂ්ණත්ව දත්ත වෙත ප්‍රවේශ වීමට යෙදුමට ඉඩ දෙයි."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android ආරම්භ කරමින්…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ටැබ්ලට් පරිගණකය ආරම්භ කරමින්…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"උපාංගය ආරම්භ කරමින්…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"ආචයනය ප්‍රශස්තිකරණය කිරීම."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"පද්ධති යාවත්කාලීනය අවසන් කරමින්…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> උත්ශ්‍රේණි කරමින්…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> කින් <xliff:g id="NUMBER_0">%1$d</xliff:g> වැනි යෙදුම ප්‍රශස්ත කරමින්."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> සූදානම් කරමින්."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"යෙදුම් ආරම්භ කරමින්."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"ඇරඹුම අවසාන කරමින්."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"මුළු තිරය බලමින්"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"ඉවත් වීමට, ඉහළ සිට පහළට ස්වයිප් කරන්න"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"වැටහුණි"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"වඩා හොඳ දසුනක් සඳහා කරකවන්න"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"වඩා හොඳ දර්ශනයක් සඳහා බෙදුම් තිරයෙන් පිටවන්න"</string>
     <string name="done_label" msgid="7283767013231718521">"අවසන්"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"පැය කවාකාර සර්පනය"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"මිනිත්තු කවාකාර සර්පනය"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ගැලවීමට පෙර PIN විමසන්න"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ගැලවීමට පෙර අගුළු අරින රටාව සඳහා අසන්න"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ගැලවීමට පෙර මුරපදය විමසන්න"</string>
@@ -2315,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"පසුබිමේ සිට පෙරබිම් සේවා ආරම්භ කිරීමට සහායක යෙදුමකට ඉඩ දෙයි."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"මයික්‍රෆෝනය තිබේ"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"මයික්‍රෆෝනය අවහිර කර ඇත"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ද්විත්ව තිරය"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"ද්විත්ව තිරය සක්‍රීයයි"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"අන්තර්ගතය පෙන්වීමට <xliff:g id="APP_NAME">%1$s</xliff:g> සංදර්ශන දෙකම භාවිත කරයි"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"උපාංගය ඉතා උණුසුම් වේ"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ඔබේ දුරකථනය ඉතා උණුසුම් නිසා ද්විත්ව තිරය ලබා ගත නොහැක"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"අක්‍රිය කරන්න"</string>
 </resources>
diff --git a/core/res/res/values-sk-watch/strings.xml b/core/res/res/values-sk-watch/strings.xml
index 39cce8b..6c9d718 100644
--- a/core/res/res/values-sk-watch/strings.xml
+++ b/core/res/res/values-sk-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplikácia <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Senzory"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index af6cc59..a6c19a8 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -460,14 +460,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Poskytne aplikácii prístup k dátam telových senzorov, ako sú pulz, teplota a saturácia krvi kyslíkom počas používania aplikácie."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Prístup k dátam telových senzorov (napríklad pulzu) počas spustenia na pozadí"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Poskytne aplikácii prístup k dátam telových senzorov, ako sú pulz, teplota a saturácia krvi kyslíkom počas spustenia aplikácie na pozadí."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Prístup k údajom o teplote zápästia z telového senzora počas používania aplikácie."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Umožňuje aplikácii prístup k údajom o teplote zápästia z telového senzora počas používania aplikácie."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Prístup k údajom o teplote zápästia z telového senzora, keď je aplikácia na pozadí."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Umožňuje aplikácii prístup k údajom o teplote zápästia z telového senzora, keď je aplikácia na pozadí."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Čítanie udalostí kalendára a podrobností"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Táto aplikácia môže čítať všetky udalosti kalendára uložené vo vašom tablete a zdieľať alebo ukladať dáta kalendára."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Táto aplikácia môže čítať všetky udalosti kalendára uložené vo vašom zariadení Android TV a zdieľať alebo ukladať údaje kalendára."</string>
@@ -1251,10 +1247,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Systém Android sa spúšťa…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet sa spúšťa…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Zariadenie sa spúšťa…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimalizuje sa úložisko"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Dokončuje sa aktualizácia systému…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Aplikácia <xliff:g id="APPLICATION">%1$s</xliff:g> sa inovuje…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Prebieha optimalizácia aplikácie <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Pripravuje sa aplikácia <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Prebieha spúšťanie aplikácií."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Prebieha dokončovanie spúšťania."</string>
@@ -1852,6 +1846,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Zobrazenie na celú obrazovku"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Ukončíte potiahnutím zhora nadol."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Dobre"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Otočte zariadenie pre lepšie zobrazenie"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Ukončite rozdelenú obrazovku pre lepšie zobrazenie"</string>
     <string name="done_label" msgid="7283767013231718521">"Hotovo"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Kruhový posúvač hodín"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Kruhový posúvač minút"</string>
@@ -1863,6 +1859,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Práca – <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pred odopnutím požiadať o číslo PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pred uvoľnením požiadať o bezpečnostný vzor"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pred odopnutím požiadať o heslo"</string>
@@ -2317,4 +2315,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Umožňuje sprievodnej aplikácii spúšťať služby na popredí z pozadia."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofón je k dispozícii"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofón je blokovaný"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dvojitá obrazovka"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dvojitá obrazovka je zapnutá"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> zobrazuje obsah na oboch obrazovkách"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Zariadenie je príliš horúce"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvojitá obrazovka nie je k dispozícii, pretože telefón sa prehrieva"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Vypnúť"</string>
 </resources>
diff --git a/core/res/res/values-sl-watch/strings.xml b/core/res/res/values-sl-watch/strings.xml
index 8e15da5..0afcaa3 100644
--- a/core/res/res/values-sl-watch/strings.xml
+++ b/core/res/res/values-sl-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. aplikac. od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Tipala"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e33b67d..3c81e74 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -460,14 +460,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Aplikaciji dovoljuje dostop do podatkov tipal telesnih funkcij, kot so srčni utrip, temperatura, odstotek kisika v krvi, ko je aplikacija v uporabi."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Dostop do podatkov tipal telesnih funkcij, kot je srčni utrip, ko je v ozadju"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Aplikaciji dovoljuje dostop do podatkov tipal telesnih funkcij, kot so srčni utrip, temperatura, odstotek kisika v krvi, ko je aplikacija v ozadju."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Dostop do podatkov tipal telesnih funkcij o temperaturi na zapestju, ko je aplikacija v uporabi."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Aplikaciji dovoljuje dostop do podatkov tipal telesnih funkcij o temperaturi na zapestju, ko je aplikacija v uporabi."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Dostop do podatkov tipal telesnih funkcij o temperaturi na zapestju, ko je aplikacija v ozadju."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Aplikaciji dovoljuje dostop do podatkov tipal telesnih funkcij o temperaturi na zapestju, ko je aplikacija v ozadju."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Branje dogodkov v koledarjih in podrobnosti koledarjev"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v tabličnem računalniku, ter shrani podatke koledarja ali jih deli z drugimi."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ta aplikacija lahko prebere vse dogodke v koledarju, ki so shranjeni v napravi Android TV, ter shrani podatke koledarja ali jih deli z drugimi."</string>
@@ -1251,10 +1247,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android se zaganja …"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablični računalnik se zaganja …"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Naprava se zaganja …"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Optimiziranje shrambe."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Zaključevanje posodobitve sistema …"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> se nadgrajuje …"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimiranje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Pripravljanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Zagon aplikacij."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Dokončevanje zagona."</string>
@@ -1852,6 +1846,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Vklopljen je celozaslonski način"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Zaprete ga tako, da z vrha s prstom povlečete navzdol."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Razumem"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Zasukajte za boljši pregled."</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Zaprite razdeljeni zaslon za boljši pregled."</string>
     <string name="done_label" msgid="7283767013231718521">"Dokončano"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Okrogli drsnik za ure"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Okrogli drsnik za minute"</string>
@@ -1863,6 +1859,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> za delo"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Klon aplikacije <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Zahtevaj PIN pred odpenjanjem"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pred odpenjanjem vprašaj za vzorec za odklepanje"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pred odpenjanjem vprašaj za geslo"</string>
@@ -2317,4 +2314,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Spremljevalni aplikaciji dovoljuje, da storitve v ospredju zažene iz ozadja."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon je na voljo"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon je blokiran"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dvojni zaslon"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dvojni zaslon je vklopljen"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> uporablja oba zaslona za prikaz vsebine."</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Naprava se pregreva"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvojni zaslon ni na voljo, ker se telefon pregreva."</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Izklopi"</string>
 </resources>
diff --git a/core/res/res/values-sq-watch/strings.xml b/core/res/res/values-sq-watch/strings.xml
index 4285532..093d3b1 100644
--- a/core/res/res/values-sq-watch/strings.xml
+++ b/core/res/res/values-sq-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Aplikacioni <xliff:g id="NUMBER_0">%1$d</xliff:g> nga <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensorët"</string>
 </resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index b3e3108..e19711d 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Lejon aplikacionin që të ketë qasje te të dhënat e sensorit të trupit, si p.sh. rrahjet e zemrës, temperatura dhe përqindja e oksigjenit në gjak ndërkohë që aplikacioni është në përdorim."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Qasje te të dhënat e sensorit të trupit, si rrahjet e zemrës kur është në sfond"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Lejon aplikacionin që të ketë qasje te të dhënat e sensorit të trupit, si p.sh. rrahjet e zemrës, temperatura dhe përqindja e oksigjenit në gjak ndërkohë që aplikacioni është në sfond."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Qasu te të dhënat e temperaturës së kyçit të dorës nga sensori i trupit ndërsa aplikacioni është në përdorim."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Lejon aplikacionin të ketë qasje te të dhënat e temperaturës së kyçit të dorës nga sensori i trupit, ndërsa aplikacioni është në përdorim."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Qasu te të dhënat e temperaturës së kyçit të dorës nga sensori i trupit ndërsa aplikacioni është në sfond."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Lejon aplikacionin të ketë qasje te të dhënat e temperaturës së kyçit të dorës nga sensori i trupit, ndërsa aplikacioni është në sfond."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Lexo ngjarjet e kalendarit dhe detajet"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Ky aplikacion mund të lexojë të gjitha ngjarjet e kalendarit të ruajtura në tabletin tënd dhe të ndajë ose të ruajë të dhënat e kalendarit."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ky aplikacion mund të lexojë të gjitha ngjarjet e kalendarit të ruajtura në pajisjen tënde Android TV dhe të ndajë ose të ruajë të dhënat e kalendarit."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"\"Androidi\" po fillon…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tableti po niset…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Pajisja po niset…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Po përshtat ruajtjen."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Po përfundon përditësimi i sistemit…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> po përmirësohet…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Po përshtat aplikacionin <xliff:g id="NUMBER_0">%1$d</xliff:g> nga gjithsej <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Po përgatit <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Aplikacionet e fillimit."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Po përfundon nisjen."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Po shikon ekranin e plotë"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Për të dalë, rrëshqit nga lart poshtë."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"E kuptova"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rrotullo për një pamje më të mirë"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Dil nga ekrani i ndarë për një pamje më të mirë"</string>
     <string name="done_label" msgid="7283767013231718521">"U krye"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Rrëshqitësi rrethor i orëve"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Rrëshqitësi rrethor i minutave"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Puna <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> i dytë i punës"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> i tretë i punës"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Klonim i <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Zhgozhdimi kërkon PIN-in"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Kërko motivin e shkyçjes para heqjes së gozhdimit"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Kërko fjalëkalim para heqjes nga gozhdimi."</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Lejon një aplikacion shoqërues të fillojë shërbimet në plan të parë nga sfondi."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofoni ofrohet"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofoni është i bllokuar"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr-watch/strings.xml b/core/res/res/values-sr-watch/strings.xml
index 054fdf8..7977f66 100644
--- a/core/res/res/values-sr-watch/strings.xml
+++ b/core/res/res/values-sr-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Апликација <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Сензори"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index fd55aa2e..740ca61 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -459,14 +459,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Приступајте подацима о температури са сензора за тело на ручном зглобу док се апликација користи."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Дозвољава апликацији да приступа подацима о температури са сензора за тело на ручном зглобу док се апликација користи."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Приступајте подацима о температури са сензора за тело на ручном зглобу док је апликација у позадини."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Дозвољава апликацији да приступа подацима о температури са сензора за тело на ручном зглобу док је апликација у позадини."</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>
@@ -1250,10 +1246,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android се покреће…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Таблет се покреће…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Уређај се покреће…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Меморија се оптимизује."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Ажурирање система се довршава…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> се надограђује…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Оптимизовање апликације <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Припрема се <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Покретање апликација."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Завршавање покретања."</string>
@@ -1851,6 +1845,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Приказује се цео екран"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Да бисте изашли, превуците надоле одозго."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Важи"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Ротирајте ради бољег приказа"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Изађите из подељеног екрана ради бољег приказа"</string>
     <string name="done_label" msgid="7283767013231718521">"Готово"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Кружни клизач за сате"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Кружни клизач за минуте"</string>
@@ -1862,6 +1858,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> на послу"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2. пословни <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3. пословни имејл <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Клонирај <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Тражи PIN пре откачињања"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Тражи шаблон за откључавање пре откачињања"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тражи лозинку пре откачињања"</string>
@@ -2316,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Дозвољава пратећој апликацији да покрене услуге у првом плану из позадине."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофон је доступан"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофон је блокиран"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Двојни екран"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Двојни екран је укључен"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи оба екрана за приказивање садржаја"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Уређај је превише загрејан"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Двојни екран је недоступан јер је телефон превише загрејан"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Искључи"</string>
 </resources>
diff --git a/core/res/res/values-sv-watch/strings.xml b/core/res/res/values-sv-watch/strings.xml
index d126fe0..fa296b6 100644
--- a/core/res/res/values-sv-watch/strings.xml
+++ b/core/res/res/values-sv-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensorer"</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index eec2656..5c7fb48 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Tillåter att appen får åtkomst till data från kroppssensorer, t.ex. puls, kroppstemperatur och blodets syrehalt, medan appen används."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Åtkomst till data från kroppssensorer, t.ex. puls, i bakgrunden"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Tillåter att appen får åtkomst till data från kroppssensorer, t.ex. puls, kroppstemperatur och blodets syrehalt, medan appen är i bakgrunden."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Åtkomst till data om handledstemperatur från kroppssensorer medan appen används."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Tillåter att appen får åtkomst till data om handledstemperatur från kroppssensorer medan appen används."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Åtkomst till data om handledstemperatur från kroppssensorer medan appen är i bakgrunden."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Tillåter att appen får åtkomst till data om handledstemperatur från kroppssensorer medan appen är i bakgrunden."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Läsa kalenderhändelser och kalenderuppgifter"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Appen kan läsa alla kalenderhändelser som sparats på surfplattan och dela eller spara uppgifter i din kalender."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Appen kan läsa alla kalenderhändelser som sparats på Android TV-enheten och dela eller spara uppgifter i din kalender."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android startar …"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Surfplattan startar …"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Enheten startar …"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Lagringsutrymmet optimeras."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Systemuppdatering avslutas …"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> uppgraderas …"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Optimerar app <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> förbereds."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Appar startas."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Uppgraderingen är klar."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visar på fullskärm"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Svep nedåt från skärmens överkant för att avsluta."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotera för att få en bättre vy"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Stäng delad skärm för att få en bättre vy"</string>
     <string name="done_label" msgid="7283767013231718521">"Klart"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Cirkelreglage för timmar"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Cirkelreglage för minuter"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> för arbetet"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Andra <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"Klona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Be om pinkod innan skärmen slutar fästas"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Be om upplåsningsmönster innan skärmen slutar fästas"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Be om lösenord innan skärmen slutar fästas"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Tillåter att en tillhörande app startar förgrundstjänster i bakgrunden."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofonen är tillgänglig"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofonen är blockerad"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw-watch/strings.xml b/core/res/res/values-sw-watch/strings.xml
index 0257a56..bf6b2c5 100644
--- a/core/res/res/values-sw-watch/strings.xml
+++ b/core/res/res/values-sw-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Programu ya <xliff:g id="NUMBER_0">%1$d</xliff:g> kati ya <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Vihisi"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index f0bb94b..689f839 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Hurushusu programu ifikie data ya vitambuzi shughuli za mwili, kama vile mapigo ya moyo, halijoto na asilimia ya oksijeni kwenye damu wakati programu inatumika."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Fikia data ya vitambuzi shughuli za mwili, kama vile mapigo ya moyo, wakati programu inatumika chinichini"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Hurushusu programu ifikie data ya vitambuzi shughuli za mwili, kama vile mapigo ya moyo, halijoto na asilimia ya oksijeni kwenye damu wakati programu inatumika chinichini."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Fikia data ya kitambuzi cha halijoto ya kifundo cha mkono, wakati programu inatumika."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Huruhusu programu kufikia data ya kitambuzi cha halijoto ya kifundo cha mkono, wakati programu inatumika."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Fikia data ya kitambuzi cha halijoto ya kifundo cha mkono, wakati programu inatumika chinichini."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Huruhusu programu kufikia data ya kitambuzi cha halijoto ya kifundo cha mkono, wakati programu inatumika chinichini."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Soma matukio na maelezo ya kalenda"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Programu hii inaweza kusoma matukio yote ya kalenda yaliyohifadhiwa kwenye kompyuta yako kibao na kushiriki au kuhifadhi data yako ya kalenda."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Programu hii inaweza kusoma matukio yote ya kalenda yaliyohifadhiwa kwenye kifaa chako cha Android TV na kushiriki au kuhifadhi data ya kalenda yako."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Inawasha Android..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Kompyuta kibao inawaka…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Kifaa kiwaka…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Inaboresha hifadhi."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Inakamilisha sasisho la mfumo…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> inapata toleo jipya…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Inaboresha programu <xliff:g id="NUMBER_0">%1$d</xliff:g> kutoka <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Inaandaa <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Programu zinaanza"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Inamaliza kuwasha."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Unatazama skrini nzima"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Ili kuondoka, telezesha kidole kutoka juu hadi chini."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Nimeelewa"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Zungusha ili upate mwonekano bora"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Funga skrini iliyogawanywa ili upate mwonekano bora"</string>
     <string name="done_label" msgid="7283767013231718521">"Imekamilika"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Kitelezi cha mviringo wa saa"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Kitelezi cha mviringo wa dakika"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Ya kazini <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> ya 2 ya Kazini"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> ya 3 ya Kazini"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Itisha PIN kabla hujabandua"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Omba mchoro wa kufungua kabla hujabandua"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Omba nenosiri kabla hujabandua"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Huruhusu programu oanifu kuanzisha huduma zinazoonekana kwenye skrini kutoka katika huduma zinazoendelea chinichini."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Maikrofoni inapatikana"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Maikrofoni imezuiwa"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ta-watch/strings.xml b/core/res/res/values-ta-watch/strings.xml
index 97539aa..baaa696 100644
--- a/core/res/res/values-ta-watch/strings.xml
+++ b/core/res/res/values-ta-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"ஆப்ஸ்: <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"உணர்விகள்"</string>
 </resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 80a9ee9..21b4d3d 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ஆப்ஸ் பயன்பாட்டில் இருக்கும்போது உடல் சென்சார் மணிக்கட்டு வெப்பநிலைத் தரவை அணுகுதல்."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"ஆப்ஸ் பயன்பாட்டில் இருக்கும்போது உடல் சென்சார் மணிக்கட்டு வெப்பநிலைத் தரவை அணுகுவதற்கு ஆப்ஸை அனுமதிக்கும்."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"ஆப்ஸ் பின்னணியில் இயங்கும்போது உடல் சென்சார் மணிக்கட்டு வெப்பநிலைத் தரவை அணுகுதல்."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"ஆப்ஸ் பின்னணியில் இயங்கும்போது உடல் சென்சார் மணிக்கட்டு வெப்பநிலைத் தரவை அணுகுவதற்கு ஆப்ஸை அனுமதிக்கும்."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android துவங்குகிறது..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"டேப்லெட் தொடங்குகிறது…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"சாதனம் தொடங்குகிறது…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"சேமிப்பகத்தை உகந்ததாக்குகிறது."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"சிஸ்டம் புதுப்பிப்பை நிறைவுசெய்கிறது…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g>ஐ மேம்படுத்துகிறது…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> ஆப்ஸை ஒருங்கிணைக்கிறது."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>ஐத் தயார்செய்கிறது."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ஆப்ஸ் தொடங்கப்படுகின்றன."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"துவக்குதலை முடிக்கிறது."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"முழுத் திரையில் காட்டுகிறது"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"வெளியேற, மேலிருந்து கீழே ஸ்வைப் செய்யவும்"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"புரிந்தது"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"சிறந்த காட்சிக்கு சுழற்றுங்கள்"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"சிறந்த காட்சிக்கு திரைப் பிரிப்புப் பயன்முறையில் இருந்து வெளியேறுங்கள்"</string>
     <string name="done_label" msgid="7283767013231718521">"முடிந்தது"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"மணிநேர வட்ட வடிவ ஸ்லைடர்"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"நிமிடங்களுக்கான வட்டவடிவ ஸ்லைடர்"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"பணியிடம் <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"அகற்றும் முன் PINஐக் கேள்"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"அகற்றும் முன் அன்லாக் பேட்டர்னைக் கேள்"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"அகற்றும் முன் கடவுச்சொல்லைக் கேள்"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"பின்னணியிலிருந்து முன்புலச் சேவைகளைத் தொடங்க துணைத் தயாரிப்பு ஆப்ஸை அனுமதிக்கும்."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"மைக்ரோஃபோன் இயக்கப்பட்டது"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"மைக்ரோஃபோன் முடக்கப்பட்டுள்ளது"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-te-watch/strings.xml b/core/res/res/values-te-watch/strings.xml
index e97ee7c..3a487bd 100644
--- a/core/res/res/values-te-watch/strings.xml
+++ b/core/res/res/values-te-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో<xliff:g id="NUMBER_0">%1$d</xliff:g>వ యాప్."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"సెన్సార్‌లు"</string>
 </resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index e0e232f..f881b8f 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"యాప్ వినియోగంలో ఉన్నప్పుడు, శరీర సెన్సార్ మణికట్టు ఉష్ణోగ్రత డేటాను యాక్సెస్ చేయండి."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"యాప్ వినియోగంలో ఉన్నప్పుడు, శరీర సెన్సార్ మణికట్టు ఉష్ణోగ్రత డేటాను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"యాప్ బ్యాక్‌గ్రౌండ్‌లో ఉన్నప్పుడు, శరీర సెన్సార్ మణికట్టు ఉష్ణోగ్రత డేటాను యాక్సెస్ చేయండి."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"యాప్ బ్యాక్‌గ్రౌండ్‌లో ఉన్నప్పుడు, శరీర సెన్సార్ మణికట్టు ఉష్ణోగ్రత డేటాను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది."</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android ప్రారంభమవుతోంది…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"టాబ్లెట్ ప్రారంభమవుతోంది…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"పరికరం ప్రారంభమవుతోంది…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"నిల్వను అనుకూలపరుస్తోంది."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"సిస్టమ్ అప్‌డేట్‌ని పూర్తి చేస్తోంది…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g>ని అప్‌గ్రేడ్ చేస్తోంది…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో <xliff:g id="NUMBER_0">%1$d</xliff:g> యాప్‌ను అనుకూలీకరిస్తోంది."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>ని సిద్ధం చేస్తోంది."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"యాప్‌లను ప్రారంభిస్తోంది."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"బూట్‌ను ముగిస్తోంది."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"ఫుల్-స్క్రీన్‌లో వీక్షిస్తున్నారు"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"నిష్క్రమించడానికి, పై నుండి క్రిందికి స్వైప్ చేయండి."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"అర్థమైంది"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"మెరుగైన వీక్షణ కోసం తిప్పండి"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"మెరుగైన వీక్షణ కోసం స్ప్లిట్ స్క్రీన్ నుండి నిష్క్రమించండి"</string>
     <string name="done_label" msgid="7283767013231718521">"పూర్తయింది"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"గంటల వృత్తాకార స్లయిడర్"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"నిమిషాల వృత్తాకార స్లయిడర్"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"ఆఫీస్ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"క్లోన్ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"అన్‌పిన్ చేయడానికి ముందు పిన్‌ కోసం అడుగు"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"అన్‌పిన్ చేయడానికి ముందు అన్‌లాక్ ఆకృతి కోసం అడుగు"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"అన్‌పిన్ చేయడానికి ముందు పాస్‌వర్డ్ కోసం అడుగు"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"బ్యాక్‌గ్రౌండ్ నుండి ఫోర్‌గ్రౌండ్ సర్వీస్‌లను ప్రారంభించడానికి సహాయక యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"మైక్రోఫోన్ అందుబాటులో ఉంది"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"మైక్రోఫోన్ బ్లాక్ చేయబడింది"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-th-watch/strings.xml b/core/res/res/values-th-watch/strings.xml
index 3ffe914..bc4be24 100644
--- a/core/res/res/values-th-watch/strings.xml
+++ b/core/res/res/values-th-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"แอป <xliff:g id="NUMBER_0">%1$d</xliff:g> จาก <xliff:g id="NUMBER_1">%2$d</xliff:g> แอป"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"เซ็นเซอร์"</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 6c6b406..938bac9 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"เข้าถึงข้อมูลอุณหภูมิบนข้อมือจากเซ็นเซอร์ร่างกายขณะใช้งานแอป"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"อนุญาตให้แอปเข้าถึงข้อมูลอุณหภูมิบนข้อมือจากเซ็นเซอร์ร่างกายขณะใช้งานแอป"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"เข้าถึงข้อมูลอุณหภูมิบนข้อมือจากเซ็นเซอร์ร่างกายขณะที่แอปทำงานในเบื้องหลัง"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"อนุญาตให้แอปเข้าถึงข้อมูลอุณหภูมิบนข้อมือจากเซ็นเซอร์ร่างกายขณะที่แอปทำงานในเบื้องหลัง"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android กำลังเริ่มต้น…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"แท็บเล็ตกำลังเริ่มต้น…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"อุปกรณ์กำลังเริ่มต้น…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"กำลังเพิ่มประสิทธิภาพพื้นที่จัดเก็บข้อมูล"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"กำลังอัปเดตระบบ…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"กำลังอัปเกรด <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"กำลังเพิ่มประสิทธิภาพแอปพลิเคชัน <xliff:g id="NUMBER_0">%1$d</xliff:g> จาก <xliff:g id="NUMBER_1">%2$d</xliff:g> รายการ"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"กำลังเตรียม <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"กำลังเริ่มต้นแอปพลิเคชัน"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"เสร็จสิ้นการบูต"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"กำลังดูแบบเต็มหน้าจอ"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"หากต้องการออก ให้เลื่อนลงจากด้านบน"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"รับทราบ"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"หมุนเพื่อรับมุมมองที่ดียิ่งขึ้น"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ออกจากโหมดแยกหน้าจอเพื่อรับมุมมองที่ดียิ่งขึ้น"</string>
     <string name="done_label" msgid="7283767013231718521">"เสร็จสิ้น"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"ตัวเลื่อนหมุนระบุชั่วโมง"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"ตัวเลื่อนหมุนระบุนาที"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g>ที่ทำงาน"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 2"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 3"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"โคลน <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ขอ PIN ก่อนเลิกปักหมุด"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ขอรูปแบบการปลดล็อกก่อนเลิกปักหมุด"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ขอรหัสผ่านก่อนเลิกปักหมุด"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"อนุญาตจากเบื้องหลังให้แอปที่ใช้ร่วมกันเริ่มการทำงานของบริการที่ทำงานอยู่เบื้องหน้า"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"ไมโครโฟนพร้อมใช้งาน"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"ไมโครโฟนถูกบล็อก"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"หน้าจอคู่"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"หน้าจอคู่เปิดอยู่"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้จอแสดงผลทั้งสองจอเพื่อแสดงเนื้อหา"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"อุปกรณ์ร้อนเกินไป"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"หน้าจอคู่ไม่พร้อมให้ใช้งานเนื่องจากโทรศัพท์ของคุณร้อนเกินไป"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ปิด"</string>
 </resources>
diff --git a/core/res/res/values-tl-watch/strings.xml b/core/res/res/values-tl-watch/strings.xml
index 619d9f9..961cccf 100644
--- a/core/res/res/values-tl-watch/strings.xml
+++ b/core/res/res/values-tl-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> ng <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Mga Sensor"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 21f8e39..63047bf 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Nagpapahintulot sa app na i-access ang data ng sensor ng katawan, gaya ng bilis ng tibok ng puso, temperatura, at porsyento ng oxygen sa dugo, habang ginagamit ang app."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"I-access ang data ng sensor ng katawan gaya ng heart rate habang nasa background"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Nagpapahintulot sa app na i-access ang data ng sensor ng katawan, gaya ng bilis ng tibok ng puso, temperatura, at porsyento ng oxygen sa dugo, habang nasa background ang app."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"I-access ang data ng temperatura ng wrist mula sa sensor ng katawan habang ginagamit ang app."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Nagpapahintulot sa app na i-access ang data ng temperatura ng wrist mula sa sensor ng katawan, habang ginagamit ang app."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"I-access ang data ng temperatura ng wrist mula sa sensor ng katawan habang nasa background ang app."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Nagpapahintulot sa app na i-access ang data ng temperatura ng wrist mula sa sensor ng katawan, habang nasa background ang app."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Magbasa ng mga event sa kalendaryo at detalye"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Mababasa ng app na ito ang lahat ng event sa kalendaryo na naka-store sa iyong tablet at maibabahagi o mase-save nito ang data ng iyong kalendaryo."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Mababasa ng app na ito ang lahat ng event sa kalendaryo na naka-store sa iyong Android TV device at maibabahagi o mase-save nito ang data ng kalendaryo mo."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Nagsisimula ang Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Nagsisimula ang tablet…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Nagsisimula ang device…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Ino-optimize ang storage."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Tinatapos ang pag-update ng system…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Nag-a-upgrade ang <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Ino-optimize ang app <xliff:g id="NUMBER_0">%1$d</xliff:g> ng <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Ihinahanda ang <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Sinisimulan ang apps."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Pagtatapos ng pag-boot."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Panonood sa full screen"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Upang lumabas, mag-swipe mula sa itaas pababa."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Nakuha ko"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"I-rotate para sa mas magandang view"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Lumabas sa split screen para sa mas magandang view"</string>
     <string name="done_label" msgid="7283767013231718521">"Tapos na"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Pabilog na slider ng mga oras"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Pabilog na slider ng mga minuto"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Pangalawang <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Pangatlong <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"I-clone ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Humingi ng PIN bago mag-unpin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Humingi ng pattern sa pag-unlock bago mag-unpin"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Humingi ng password bago mag-unpin"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Nagbibigay-daan sa kasamang app na magsimula ng mga serbisyo sa foreground mula sa background."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Available ang mikropono"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Naka-block ang mikropono"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr-watch/strings.xml b/core/res/res/values-tr-watch/strings.xml
index e407867..19add08 100644
--- a/core/res/res/values-tr-watch/strings.xml
+++ b/core/res/res/values-tr-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Uygulama <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensörler"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index f62560e..94e9937 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Kullanımdaki uygulamanın nabız, vücut ısısı, kandaki oksijen yüzdesi gibi vücut sensörü verilerine erişmesine izin verir."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Arka plandayken nabız gibi vücut sensörü verilerine erişme"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Arka plandaki uygulamanın nabız, vücut ısısı, kandaki oksijen yüzdesi gibi vücut sensörü verilerine erişmesine izin verir."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Uygulama kullanımdayken bilek ısısı gibi vücut sensörü verilerine erişme."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Kullanımdaki uygulamanın bilek ısısı gibi vücut sensörü verilerine erişmesine izin verir."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Uygulama arka plandayken bilek ısısı gibi vücut sensörü verilerine erişme."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Arka plandaki uygulamanın bilek ısısı gibi vücut sensörü verilerine erişmesine izin verir."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Takvim etkinlikleri ve ayrıntılarını okuma"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Bu uygulama, tabletinizde kayıtlı tüm takvim etkinliklerini okuyabilir ve takvim verilerinizi paylaşabilir ya da kaydedebilir."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Bu uygulama, Android TV cihazınızda kayıtlı tüm takvim etkinliklerini okuyabilir ve takvim verilerinizi paylaşabilir ya da kaydedebilir."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android başlatılıyor…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet başlatılıyor…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Cihaz başlatılıyor…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Depolama optimize ediliyor."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Sistem güncellemesi tamamlanıyor…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> yeni sürüme geçiriliyor…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> uygulama optimize ediliyor."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> hazırlanıyor."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Uygulamalar başlatılıyor"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Açılış tamamlanıyor."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Tam ekran olarak görüntüleme"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Çıkmak için yukarıdan aşağıya doğru hızlıca kaydırın."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Anladım"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Daha iyi bir görünüm elde etmek için ekranı döndürün"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Daha iyi bir görünüm elde etmek için bölünmüş ekrandan çıkın"</string>
     <string name="done_label" msgid="7283767013231718521">"Bitti"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Saat kaydırma çemberi"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Dakika kaydırma çemberi"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> (İş)"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"İş için 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"İş için 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Sabitlemeyi kaldırmadan önce PIN\'i sor"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Sabitlemeyi kaldırmadan önce kilit açma desenini sor"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Tamamlayıcı uygulamanın arka plandan ön plan hizmetlerini başlatmasına izin verir."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon kullanılabilir"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon engellenmiş"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk-watch/strings.xml b/core/res/res/values-uk-watch/strings.xml
index 1d1fb60..b8416c3 100644
--- a/core/res/res/values-uk-watch/strings.xml
+++ b/core/res/res/values-uk-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Додаток <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Датчики"</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 322929f..eb11658 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -460,14 +460,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Отримувати доступ до даних датчика на тілі про температуру в зоні зап’ястя, коли додаток використовується."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Під час використання додатка він матиме доступ до даних датчика на тілі про температуру в зоні зап’ястя."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Отримувати доступ до даних датчика на тілі про температуру в зоні зап’ястя, коли додаток працює у фоновому режимі."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Коли додаток працюватиме у фоновому режимі, він матиме доступ до даних датчика на тілі про температуру в зоні зап’ястя."</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>
@@ -1251,10 +1247,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Запуск ОС Android…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Планшет запускається…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Пристрій запускається…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Оптимізація пам’яті."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Завершується оновлення системи…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Додаток <xliff:g id="APPLICATION">%1$s</xliff:g> оновлюється…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Оптимізація програми <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Підготовка додатка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск програм."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Завершення завантаження."</string>
@@ -1852,6 +1846,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Перегляд на весь екран"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Щоб вийти, проведіть пальцем зверху вниз."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Оберніть для кращого огляду"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Для кращого огляду вийдіть із режиму розділення екрана"</string>
     <string name="done_label" msgid="7283767013231718521">"Готово"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Вибір годин на циферблаті"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Вибір хвилин на циферблаті"</string>
@@ -1863,6 +1859,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Робоча <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-а робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-я робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-код для відкріплення"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Запитувати ключ розблокування перед відкріпленням"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Запитувати пароль перед відкріпленням"</string>
@@ -2317,4 +2315,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Дозволяє супутньому додатку запускати активні сервіси у фоновому режимі."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Мікрофон доступний"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Мікрофон заблоковано"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ur-watch/strings.xml b/core/res/res/values-ur-watch/strings.xml
index 073022d..ec1089c 100644
--- a/core/res/res/values-ur-watch/strings.xml
+++ b/core/res/res/values-ur-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"ایپ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>۔"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"سینسرز"</string>
 </resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 50e79a1..c984f46 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"ایپ کے استعمال میں ہونے کے دوران، باڈی سینسر کلائی کے درجہ حرارت کے ڈیٹا تک رسائی حاصل کریں۔"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"ایپ کے استعمال میں ہونے کے دوران، ایپ کو باڈی سینسر کلائی کے درجہ حرارت کے ڈیٹا تک رسائی کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"ایپ کے پس منظر میں ہونے کے دوران، باڈی سینسر کلائی کے درجہ حرارت کے ڈیٹا تک رسائی حاصل کریں۔"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"ایپ کے پس منظر میں ہونے کے دوران، ایپ کو باڈی سینسر کلائی کے درجہ حرارت کے ڈیٹا تک رسائی کی اجازت دیتا ہے۔"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"‏Android شروع ہو رہا ہے…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"ٹیبلیٹ شروع ہو رہا ہے…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"آلہ شروع ہو رہا ہے…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"اسٹوریج کو بہترین بنایا جا رہا ہے۔"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"سسٹم اپ ڈیٹ مکمل ہو رہا ہے…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> اپ گریڈ ہو رہی ہے…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"ایپ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g> کو بہتر بنایا جا رہا ہے۔"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> تیار ہو رہی ہے۔"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ایپس شروع ہو رہی ہیں۔"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"بوٹ مکمل ہو رہا ہے۔"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"پوری اسکرین میں دیکھ رہے ہیں"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"خارج ہونے کیلئے اوپر سے نیچے سوائپ کریں۔"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"سمجھ آ گئی"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"بہتر منظر کے لیے گھمائیں"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"بہتر منظر کے لیے اسپلٹ اسکرین سے باہر نکلیں"</string>
     <string name="done_label" msgid="7283767013231718521">"ہو گیا"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"گھنٹوں کا سرکلر سلائیڈر"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"منٹس سرکلر سلائیڈر"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"دفتر <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"دوسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"تیسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"‏پن ہٹانے سے پہلے PIN طلب کریں"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"پن ہٹانے سے پہلے غیر مقفل کرنے کا پیٹرن طلب کریں"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string>
@@ -2315,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"ساتھی ایپ کو پس منظر سے پیش منظر کی سروسز شروع کرنے کی اجازت دیتی ہے۔"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"مائیکروفون دستیاب ہے"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"مائیکروفون مسدود ہے"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"دوہری اسکرین"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"دوہری اسکرین آن ہے"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> مواد دکھانے کیلئے دونوں ڈسپلیز استعمال کر رہی ہے"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"آلہ بہت زیادہ گرم ہے"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"دوہری اسکرین دستیاب نہیں ہے کیونکہ آپ کا فون بہت زیادہ گرم ہو رہا ہے"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"آف کریں"</string>
 </resources>
diff --git a/core/res/res/values-uz-watch/strings.xml b/core/res/res/values-uz-watch/strings.xml
index fd5b2e9..cf1b7a5 100644
--- a/core/res/res/values-uz-watch/strings.xml
+++ b/core/res/res/values-uz-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"<xliff:g id="NUMBER_1">%2$d</xliff:g>dan <xliff:g id="NUMBER_0">%1$d</xliff:g> ilova."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensorlar"</string>
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index ddcb6e1..f7b60d5 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Ilovaga yurak urishi, harorat, qondagi kislorod foizi kabi tanadagi sensor maʼlumotlaridan foydalanishga ruxsat beradi."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Fonda ishlaganda yurak urishi kabi tanadagi sensor maʼlumotlariga ruxsat"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Ilovaga yurak urishi, harorat, qondagi kislorod foizi kabi tanadagi sensor maʼlumotlaridan ilova fonda ishlaganda foydalanishga ruxsat beradi."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Ilova ishlayotgan vaqtda tana sensori bilak harorati maʼlumotlariga kirish."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Ilovaga tana sensori bilak harorati maʼlumotlaridan ilova ishlayotganda foydalanishga ruxsat beradi."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Ilova fonda ishlayotgan vaqtda tana sensori bilak harorati maʼlumotlariga kirish."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Ilovaga tana sensori bilan harorati maʼlumotlaridan ilova fonda ishlayotganda foydalanishga ruxsat beradi."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Taqvim tadbirlari va tafsilotlarini o‘qish"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Bu ilova planshetdagi barcha taqvim tadbirlarini o‘qiy olishi hamda taqvim ma’lumotlarini ulashishi yoki saqlashi mumkin."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Bu ilova Android TV qurilmangizda barcha taqvim tadbirlarini oʻqiy olishi hamda taqvim maʼlumotlarini ulashishi yoki saqlashi mumkin."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android ishga tushmoqda…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Planshet ishga tushirilmoqda…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Qurilma ishga tushirilmoqda…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Xotira optimallashtirilmoqda."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Tizimni yangilash tugay deb qoldi…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasi yangilanmoqda…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Ilovalar optimallashtirilmoqda (<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>)."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> tayyorlanmoqda."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Ilovalar ishga tushirilmoqda."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Tizimni yuklashni tugatish."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Butun ekranli rejim"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Chiqish uchun tepadan pastga torting."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Yaxshiroq koʻrish uchun kamerani buring"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Yaxshiroq koʻrish uchun ajratilgan ekran rejimidan chiqing"</string>
     <string name="done_label" msgid="7283767013231718521">"Tayyor"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Doiradan soatni tanlang"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Doiradan daqiqani tanlang"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Ish <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Yechishda PIN kod talab qilinsin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Yechishdan oldin grafik kalit so‘ralsin"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Bo‘shatishdan oldin parol so‘ralsin"</string>
@@ -2315,4 +2313,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Hamroh ilovaga faol xizmatlarni fonda ishga tushirishga ruxsat beradi."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Mikrofon yoqildi"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Mikrofon bloklandi"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Ikki ekranli rejim"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Ikki ekranli rejim yoniq"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> kontentni ikkala ekranda chiqarmoqda"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Qurilma qizib ketdi"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Telefon qizib ketgani uchun hozir ikki ekranli rejim ishlamaydi"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Faolsizlantirish"</string>
 </resources>
diff --git a/core/res/res/values-vi-watch/strings.xml b/core/res/res/values-vi-watch/strings.xml
index e81211e..162a223 100644
--- a/core/res/res/values-vi-watch/strings.xml
+++ b/core/res/res/values-vi-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Ứng dụng <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Cảm biến"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 9ae3290..4104909 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Cho phép ứng dụng truy cập vào dữ liệu cảm biến cơ thể khi đang dùng, chẳng hạn như nhịp tim, thân nhiệt và tỷ lệ phần trăm oxy trong máu."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Truy cập vào dữ liệu cảm biến cơ thể khi ở chế độ nền, chẳng hạn như nhịp tim"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Cho phép ứng dụng truy cập vào dữ liệu cảm biến cơ thể khi ở chế độ nền, chẳng hạn như nhịp tim, thân nhiệt và tỷ lệ phần trăm oxy trong máu."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Quyền truy cập vào dữ liệu nhiệt độ cổ tay đo bằng cảm biến cơ thể khi ứng dụng đang được sử dụng."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Cho phép ứng dụng truy cập vào dữ liệu nhiệt độ cổ tay đo bằng cảm biến cơ thể khi ứng dụng đang được sử dụng."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Quyền truy cập vào dữ liệu nhiệt độ cổ tay đo bằng cảm biến cơ thể khi ứng dụng ở chế độ nền."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Cho phép ứng dụng truy cập vào dữ liệu nhiệt độ cổ tay đo bằng cảm biến cơ thể khi ứng dụng ở chế độ nền."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Đọc chi tiết và sự kiện lịch"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Ứng dụng này có thể đọc tất cả các sự kiện lịch được lưu trữ trên máy tính bảng của bạn và chia sẻ hoặc lưu dữ liệu lịch của bạn."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Ứng dụng này có thể đọc tất cả sự kiện trên lịch mà bạn lưu vào thiết bị Android TV cũng như chia sẻ hoặc lưu dữ liệu lịch của bạn."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android đang khởi động..."</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Máy tính bảng đang khởi động…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Thiết bị đang khởi động…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Tối ưu hóa lưu trữ."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Đang hoàn tất cập nhật hệ thống…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> đang nâng cấp…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Đang tối ưu hóa ứng dụng <xliff:g id="NUMBER_0">%1$d</xliff:g> trong tổng số <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Đang chuẩn bị <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Khởi động ứng dụng."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Hoàn tất khởi động."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Xem toàn màn hình"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Để thoát, hãy vuốt từ trên cùng xuống dưới."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Xoay để xem dễ hơn"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Thoát chế độ chia đôi màn hình để xem dễ hơn"</string>
     <string name="done_label" msgid="7283767013231718521">"Xong"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Thanh trượt giờ hình tròn"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Thanh trượt phút hình tròn"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> làm việc"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Hỏi mã PIN trước khi bỏ ghim"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Hỏi hình mở khóa trước khi bỏ ghim"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Hỏi mật khẩu trước khi bỏ ghim"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Cho phép một ứng dụng đồng hành bắt đầu các dịch vụ trên nền trước từ nền."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Micrô đang hoạt động"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Micrô đang bị chặn"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-watch/strings.xml b/core/res/res/values-watch/strings.xml
index 4d4ce1e..e44eda3 100644
--- a/core/res/res/values-watch/strings.xml
+++ b/core/res/res/values-watch/strings.xml
@@ -18,12 +18,6 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- [CHAR LIMIT=16] Message shown in upgrading dialog for each .apk that is optimized. -->
-    <!-- Each word has an 8 character limit due to screen width limitation. -->
-    <string name="android_upgrading_apk">App
-        <xliff:g id="number" example="123">%1$d</xliff:g> of
-        <xliff:g id="number" example="123">%2$d</xliff:g>.</string>
-
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. Override from base which says "Body Sensors". [CHAR_LIMIT=25] -->
     <string name="permgrouplab_sensors">Sensors</string>
 
diff --git a/core/res/res/values-zh-rCN-watch/strings.xml b/core/res/res/values-zh-rCN-watch/strings.xml
index 0cbe677..d047d8e 100644
--- a/core/res/res/values-zh-rCN-watch/strings.xml
+++ b/core/res/res/values-zh-rCN-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"应用:<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>。"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"传感器"</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 118c520..85ae74e 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"在应用使用期间访问身体传感器的手腕温度数据。"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"允许应用在使用期间访问身体传感器的手腕温度数据。"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"在应用于后台运行时访问身体传感器的手腕温度数据。"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"允许应用在后台运行时访问身体传感器的手腕温度数据。"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android 正在启动…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"平板电脑正在启动…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"设备正在启动…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"正在优化存储空间。"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"正在完成系统更新…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"正在升级<xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"正在优化第<xliff:g id="NUMBER_0">%1$d</xliff:g>个应用(共<xliff:g id="NUMBER_1">%2$d</xliff:g>个)。"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"正在准备升级<xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在启动应用。"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"即将完成启动。"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"目前处于全屏模式"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"要退出,请从顶部向下滑动。"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"知道了"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"旋转可改善预览效果"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"退出分屏可改善预览效果"</string>
     <string name="done_label" msgid="7283767013231718521">"完成"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"小时转盘"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"分钟转盘"</string>
@@ -1861,6 +1857,8 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"第二个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"第三个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for clone_profile_label_badge (1871997694718793964) -->
+    <skip />
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消时要求输入PIN码"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消时要求绘制解锁图案"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消时要求输入密码"</string>
@@ -2315,4 +2313,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"允许配套应用从后台启动前台服务。"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"麦克风可用"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"麦克风已被屏蔽"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK-watch/strings.xml b/core/res/res/values-zh-rHK-watch/strings.xml
index 101b4e5..668061e 100644
--- a/core/res/res/values-zh-rHK-watch/strings.xml
+++ b/core/res/res/values-zh-rHK-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"應用程式 (<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>)"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"感應器"</string>
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 2e44412..271a01a 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"應用程式在使用期間存取人體感應器手腕溫度資料。"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"允許應用程式在使用期間存取人體感應器手腕溫度資料。"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"應用程式在背景執行時存取人體感應器手腕溫度資料。"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"允許應用程式在背景執行時存取人體感應器手腕溫度資料。"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android 正在啟動…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"平板電腦正在啟動…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"裝置正在啟動…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"正在優化儲存空間。"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"正在完成系統更新…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」正在升級…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"正在優化第 <xliff:g id="NUMBER_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="NUMBER_1">%2$d</xliff:g> 個)。"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"正在準備 <xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在啟動應用程式。"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"啟動完成。"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"開啟全螢幕"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"由頂部向下滑動即可退出。"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"知道了"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"旋轉以改善預覽效果"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"退出分割螢幕,以改善預覽效果"</string>
     <string name="done_label" msgid="7283767013231718521">"完成"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"小時環形滑桿"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"分鐘環形滑桿"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"第二個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"第三個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"複製<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消固定時必須輸入 PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定時必須提供解鎖圖案"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消固定時必須輸入密碼"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"允許隨附應用程式從背景啟動前景服務。"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"可以使用麥克風"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"已封鎖麥克風"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"雙螢幕"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"雙螢幕功能已啟用"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用雙螢幕顯示內容"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"裝置過熱"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"手機過熱,因此無法使用雙螢幕功能"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"停用"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW-watch/strings.xml b/core/res/res/values-zh-rTW-watch/strings.xml
index 122ac0a..668061e 100644
--- a/core/res/res/values-zh-rTW-watch/strings.xml
+++ b/core/res/res/values-zh-rTW-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"應用程式 <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>。"</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"感應器"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 2155790..9a51f75 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -458,14 +458,10 @@
     <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>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"在應用程式使用期間存取手錶人體感應器上的溫度資料。"</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"允許應用程式在使用期間存取手錶人體感應器上的溫度資料。"</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"在背景執行應用程式時存取手錶人體感應器上的溫度資料。"</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"允許應用程式在背景執行時存取手錶人體感應器上的溫度資料。"</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>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android 正在啟動…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"平板電腦正在啟動…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"裝置正在啟動…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"正在對儲存空間進行最佳化處理。"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"正在完成系統更新…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"正在升級「<xliff:g id="APPLICATION">%1$s</xliff:g>」…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"正在最佳化第 <xliff:g id="NUMBER_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="NUMBER_1">%2$d</xliff:g> 個)。"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"正在準備升級「<xliff:g id="APPNAME">%1$s</xliff:g>」。"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在啟動應用程式。"</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"啟動完成。"</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"以全螢幕檢視"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"如要退出,請從畫面頂端向下滑動。"</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"知道了"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"旋轉螢幕以瀏覽完整的檢視畫面"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"結束分割畫面以全螢幕瀏覽"</string>
     <string name="done_label" msgid="7283767013231718521">"完成"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"小時數環狀滑桿"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"分鐘數環狀滑桿"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"第 2 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"第 3 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"複製<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"取消固定時必須輸入 PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"取消固定時必須畫出解鎖圖案"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"取消固定時必須輸入密碼"</string>
@@ -2315,4 +2312,10 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"允許隨附應用程式從背景啟動前景服務。"</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"麥克風已可使用"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"麥克風已封鎖"</string>
+    <string name="concurrent_display_notification_name" msgid="1526911253558311131">"雙螢幕"</string>
+    <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"雙螢幕功能已啟用"</string>
+    <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用雙螢幕顯示內容"</string>
+    <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"裝置過熱"</string>
+    <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"手機過熱,因此無法使用雙螢幕功能"</string>
+    <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"停用"</string>
 </resources>
diff --git a/core/res/res/values-zu-watch/strings.xml b/core/res/res/values-zu-watch/strings.xml
index 36acb14..a19d77f 100644
--- a/core/res/res/values-zu-watch/strings.xml
+++ b/core/res/res/values-zu-watch/strings.xml
@@ -20,6 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="android_upgrading_apk" msgid="5356436701512342265">"Uhlelo lokusebenza olungu-<xliff:g id="NUMBER_0">%1$d</xliff:g> kokungu-<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Izinzwa"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c81ab5e..26fa34b 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -458,14 +458,10 @@
     <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Ivumela i-app ukuthi ifinyelele idatha yenzwa yomzimba, efana nokushaya kwenhliziyo, izinga lokushisa, namaphesenti komoyampilo wegazi, kuyilapho i-app isetshenziswa."</string>
     <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Finyelela kudatha yenzwa yomzimba, njengokushaya kwenhliziyo, ngenkathi ungemuva"</string>
     <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Ivumela i-app ukuthi ifinyelele idatha yenzwa yomzimba, efana nokushaya kwenhliziyo, izinga lokushisa, namaphesenti komoyampilo wegazi, kuyilapho i-app ingemuva."</string>
-    <!-- no translation found for permlab_bodySensorsWristTemperature (5007987988922337657) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensorsWristTemperature (4978345709781045181) -->
-    <skip />
-    <!-- no translation found for permlab_bodySensors_wristTemperature_background (7692772783509074356) -->
-    <skip />
-    <!-- no translation found for permdesc_bodySensors_wristTemperature_background (3170369705518699219) -->
-    <skip />
+    <string name="permlab_bodySensorsWristTemperature" msgid="5007987988922337657">"Finyelela kudatha yezinga lokushisa lenzwa yomzimba ngenkathi i-app isetshenziswa."</string>
+    <string name="permdesc_bodySensorsWristTemperature" product="default" msgid="4978345709781045181">"Ivumela i-app ukuthi ifinyelele idatha yezinga lokushisa kwengalo yenzwa yomzimba, kuyilapho i-app isetshenziswa."</string>
+    <string name="permlab_bodySensors_wristTemperature_background" msgid="7692772783509074356">"Finyelela kudatha yezinga lokushisa lenzwa yomzimba ngenkathi i-app ingemuva."</string>
+    <string name="permdesc_bodySensors_wristTemperature_background" product="default" msgid="3170369705518699219">"Ivumela i-app ifinyelele idatha yezinga lokushisa lengalo yenzwa yomzimba, kuyilapho i-app ingemuva."</string>
     <string name="permlab_readCalendar" msgid="6408654259475396200">"Funda imicimbi yekhalenda nemininingwane"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Lolu hlelo lokusebenza lungafunda yonke imicimbi yekhalenda elondolozwe kuthebhulethi yakho nokwabelana noma ukulondoloza idatha yakho yekhalenda."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Lolu hlelo lokusebenza lungafunda yonke imicimbi yekhalenda elondolozwe kudivayisi yakho ye-Android TV nokwabelana noma ukulondoloza idatha yakho yekhalenda."</string>
@@ -1249,10 +1245,8 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"I-Android iyaqala…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Ithebulethi iyaqala…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Idivayisi iyaqala…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"Ikhulisa isitoreji."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Iqedela ukubuyekezwa kwesistimu…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> iyathuthukisa…"</string>
-    <string name="android_upgrading_apk" msgid="1339564803894466737">"Ukubeka ezingeni eliphezulu <xliff:g id="NUMBER_0">%1$d</xliff:g> uhlelo lokusebenza <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"Ukulungisela i-<xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Qalisa izinhlelo zokusebenza."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"Qedela ukuqala kabusha."</string>
@@ -1850,6 +1844,8 @@
     <string name="immersive_cling_title" msgid="2307034298721541791">"Ukubuka isikrini esigcwele"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Ukuze uphume, swayiphela phansi kusuka phezulu."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Ngiyitholile"</string>
+    <string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Zungezisa ukuze uthole ukubuka okungcono"</string>
+    <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Phuma ekuhlukaniseni isikrini ukuze ubuke kangcono"</string>
     <string name="done_label" msgid="7283767013231718521">"Kwenziwe"</string>
     <string name="hour_picker_description" msgid="5153757582093524635">"Amahora weslayidi esiyindingilizi"</string>
     <string name="minute_picker_description" msgid="9029797023621927294">"Amaminithi weslayidi esiyindingilizi"</string>
@@ -1861,6 +1857,7 @@
     <string name="managed_profile_label_badge" msgid="6762559569999499495">"Umsebenzi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"Umsebenzi wesibili <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"Umsebenzi wesithathu <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="clone_profile_label_badge" msgid="1871997694718793964">"I-Clone <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Cela iphinikhodi ngaphambi kokuphina"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Cela iphethini yokuvula ngaphambi kokususa ukuphina"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Cela iphasiwedi ngaphambi kokususa ukuphina"</string>
@@ -2315,4 +2312,16 @@
     <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Ivumela i-app ehambisanayo ukuthi iqale amasevisi angaphambili kusukela ngemuva."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Imakrofoni iyatholakala"</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Imakrofoni ivinjiwe"</string>
+    <!-- no translation found for concurrent_display_notification_name (1526911253558311131) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_title (4892473462327943673) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_active_content (5889355473710601270) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_title (5921609404644739229) -->
+    <skip />
+    <!-- no translation found for concurrent_display_notification_thermal_content (2075484836527609319) -->
+    <skip />
+    <!-- no translation found for device_state_notification_turn_off_button (6327161707661689232) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 9e735d0..4468ebe 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -207,4 +207,24 @@
          be set by OEMs for devices which use eUICCs. -->
     <integer-array name="non_removable_euicc_slots"></integer-array>
 
+    <!-- Device state identifiers and strings for system notifications. The string arrays must have
+         the same length and order as the identifier array. -->
+    <integer-array name="device_state_notification_state_identifiers">
+        <item>@integer/config_deviceStateConcurrentRearDisplay</item>
+    </integer-array>
+    <string-array name="device_state_notification_names">
+        <item>@string/concurrent_display_notification_name</item>
+    </string-array>
+    <string-array name="device_state_notification_active_titles">
+        <item>@string/concurrent_display_notification_active_title</item>
+    </string-array>
+    <string-array name="device_state_notification_active_contents">
+        <item>@string/concurrent_display_notification_active_content</item>
+    </string-array>
+    <string-array name="device_state_notification_thermal_titles">
+        <item>@string/concurrent_display_notification_thermal_title</item>
+    </string-array>
+    <string-array name="device_state_notification_thermal_contents">
+        <item>@string/concurrent_display_notification_thermal_content</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index e242e20..0befa8b 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -523,15 +523,15 @@
     <color name="system_error_container_dark">#930001</color>
     <color name="system_on_error_container_dark">#FFDAD5</color>
     <color name="system_primary_fixed_dark">#D8E2FF</color>
-    <color name="system_primary_fixeder_dark">#ADC6FF</color>
+    <color name="system_primary_fixed_darker_dark">#ADC6FF</color>
     <color name="system_on_primary_fixed_dark">#001A41</color>
     <color name="system_on_primary_fixed_variant_dark">#2B4678</color>
     <color name="system_secondary_fixed_dark">#DBE2F9</color>
-    <color name="system_secondary_fixeder_dark">#BFC6DC</color>
+    <color name="system_secondary_fixed_darker_dark">#BFC6DC</color>
     <color name="system_on_secondary_fixed_dark">#141B2C</color>
     <color name="system_on_secondary_fixed_variant_dark">#3F4759</color>
     <color name="system_tertiary_fixed_dark">#FBD7FC</color>
-    <color name="system_tertiary_fixeder_dark">#DEBCDF</color>
+    <color name="system_tertiary_fixed_darker_dark">#DEBCDF</color>
     <color name="system_on_tertiary_fixed_dark">#29132D</color>
     <color name="system_on_tertiary_fixed_variant_dark">#583E5B</color>
     <color name="system_control_activated_dark">#2B4678</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a07d85e..a1de6bb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -465,12 +465,6 @@
     <string-array translatable="false" name="config_cdma_dun_supported_types">
     </string-array>
 
-    <!-- Package name of the system app that implements the shared connectivity service -->
-    <string translatable="false" name="sharedconnectivity_service_package"></string>
-
-     <!-- Class name in the system app that implements the shared connectivity service -->
-    <string translatable="false" name="sharedconnectivity_service_class"></string>
-
     <!-- Flag indicating whether we should enable the automatic brightness.
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
@@ -974,12 +968,22 @@
     <!-- Boolean indicating whether light mode is allowed when DWB is turned on. -->
     <bool name="config_displayWhiteBalanceLightModeAllowed">true</bool>
 
+    <!-- Duration, in milliseconds, of the display white balance animated transitions. -->
+    <integer name="config_displayWhiteBalanceTransitionTime">3000</integer>
+
     <!-- Device states where the sensor based rotation values should be reversed around the Z axis
          for the default display.
          TODO(b/265312193): Remove this workaround when this bug is fixed.-->
     <integer-array name="config_deviceStatesToReverseDefaultDisplayRotationAroundZAxis">
     </integer-array>
 
+    <!-- Boolean indicating whether secondary built-in displays should have their orientation
+         match the active default display. This config assumes that the secondary display only
+         requires swapping ROTATION_90 and ROTATION_270.
+         TODO(b/265991392): This should eventually be configured and parsed in
+          display_settings.xml -->
+    <bool name="config_matchSecondaryInternalDisplaysOrientationToReverseDefaultDisplay">true</bool>
+
     <!-- Indicate available ColorDisplayManager.COLOR_MODE_xxx. -->
     <integer-array name="config_availableColorModes">
         <!-- Example:
@@ -1306,7 +1310,7 @@
     <!-- Default value for led color when battery is medium charged -->
     <integer name="config_notificationsBatteryMediumARGB">0xFFFFFF00</integer>
 
-    <!-- Default value for led color when battery is fully charged -->
+    <!-- Default value for led color when battery is fully or nearly fully charged -->
     <integer name="config_notificationsBatteryFullARGB">0xFF00FF00</integer>
 
     <!-- Default value for LED on time when the battery is low on charge in miliseconds -->
@@ -1321,6 +1325,9 @@
     <!-- Default value for LED off time when the battery is low on charge in miliseconds -->
     <integer name="config_notificationsBatteryLedOff">2875</integer>
 
+    <!-- Battery level percent that is treated as nearly full. -->
+    <integer name="config_notificationsBatteryNearlyFullLevel">90</integer>
+
     <!-- If true, only colorized CallStyle notifications will apply custom colors -->
     <bool name="config_callNotificationActionColorsRequireColorized">true</bool>
 
@@ -2183,6 +2190,9 @@
     <!-- The name of the package that will hold the system financed device controller role. -->
     <string name="config_systemFinancedDeviceController" translatable="false">com.android.devicelockcontroller</string>
 
+    <!-- The component name of the wear service class that will be started by the system server. -->
+    <string name="config_wearServiceComponent" translatable="false"></string>
+
     <!-- The name of the package that will handle updating the device management role. -->
     <string name="config_devicePolicyManagementUpdater" translatable="false"></string>
 
@@ -2671,6 +2681,14 @@
     <!-- Maximum velocity to initiate a fling, as measured in dips per second. -->
     <dimen name="config_viewMaxFlingVelocity">8000dp</dimen>
 
+    <!-- Minimum velocity (absolute value) to initiate a fling from a rotary encoder device, as
+         measured in dips per second. Setting this to -1dp disables rotary encoder fling.  -->
+    <dimen name="config_viewMinRotaryEncoderFlingVelocity">-1dp</dimen>
+
+    <!-- Maximum velocity (absolute value) to initiate a fling from a rotary encoder device, as
+         measured in dips per second. Setting this to -1dp disables rotary encoder fling.  -->
+    <dimen name="config_viewMaxRotaryEncoderFlingVelocity">-1dp</dimen>
+
     <!-- Amount of time in ms the user needs to press the relevant key to bring up the
          global actions dialog -->
     <integer name="config_globalActionsKeyTimeout">500</integer>
@@ -2732,6 +2750,11 @@
          Should be false for most devices, except automotive vehicle with passenger displays. -->
     <bool name="config_multiuserVisibleBackgroundUsers">false</bool>
 
+    <!-- Whether the device allows users to start in background visible on the default display.
+         Should be false for most devices, except passenger-only automotive build (i.e., when
+         Android runs in a separate system in the back seat to manage the passenger displays) -->
+    <bool name="config_multiuserVisibleBackgroundUsersOnDefaultDisplay">false</bool>
+
     <!-- Whether to automatically switch to the designated Dock User (the user chosen for
          displaying dreams, etc.) after a timeout when the device is docked.  -->
     <bool name="config_enableTimeoutToDockUserWhenDocked">false</bool>
@@ -3217,6 +3240,12 @@
     <string name="config_somnambulatorComponent" translatable="false"
             >com.android.systemui/com.android.systemui.Somnambulator</string>
 
+    <!-- The component name of the screenshot App Clips service that communicates with SystemUI to
+         evaluate certain aspects of App Clips flow such as whether a calling activity can launch
+         capture content for note activity. -->
+    <string name="config_screenshotAppClipsServiceComponent" translatable="false"
+            >com.android.systemui/com.android.systemui.screenshot.appclips.AppClipsService</string>
+
     <!-- The component name of a special dock app that merely launches a dream.
          We don't want to launch this app when docked because it causes an unnecessary
          activity transition.  We just want to start the dream.. -->
@@ -4088,16 +4117,6 @@
     -->
     <string-array translatable="false" name="config_convert_to_emergency_number_map" />
 
-    <!-- An array of packages for which notifications cannot be blocked.
-         Should only be used for core device functionality that must not be
-         rendered inoperative for safety reasons, like the phone dialer and
-         SMS handler. -->
-    <string-array translatable="false" name="config_nonBlockableNotificationPackages">
-        <item>com.android.dialer</item>
-        <item>com.android.messaging</item>
-        <item>com.android.cellbroadcastreceiver.module</item>
-    </string-array>
-
     <!-- An array of packages that can make sound on the ringer stream in priority-only DND
      mode -->
     <string-array translatable="false" name="config_priorityOnlyDndExemptPackages">
@@ -4154,12 +4173,19 @@
     <bool name="config_quickSettingsSupported">true</bool>
 
     <!-- The component name, flattened to a string, for the default autofill service
-         to  enabled for an user. This service must be trusted, as it can be activated
+         to  enabled for a user. This service must be trusted, as it can be activated
          without explicit consent of the user. If no autofill service with the
           specified name exists on the device, autofill will be disabled by default.
     -->
     <string name="config_defaultAutofillService" translatable="false"></string>
 
+    <!-- The component name, flattened to a string, for the default field classification service
+         to  enabled for a user. This service must be trusted, as it can be activated
+         without explicit consent of the user. If no field classification service with the
+         specified name exists on the device, field classification will be disabled by default.
+    -->
+    <string name="config_defaultFieldClassificationService" translatable="false"></string>
+
     <!-- The package name for the OEM custom system textclassifier service.
          This service must be trusted, as it can be activated without explicit consent of the user.
          Example: "com.android.textclassifier"
@@ -4998,6 +5024,26 @@
       -->
     </integer-array>
 
+    <!-- The properties for handling UDFPS touch detection
+    <string-array name="config_udfps_touch_detection_options">
+        <item>[detector_type],[sensor_shape],[target_size],[min_ellipse_overlap_percentage]</item>
+    </string-array>
+
+        [detector_type]: 0 for bounding box detector, 1 for ellipse detector
+        [sensor_shape]: 0 for square, 1 for circle
+        [target_size]: percentage (defined as a float of 0-1) of sensor that is considered the target, expands outward from center
+        [min_ellipse_overlap_percentage]: minimum percentage (float from 0-1) needed to be considered a valid overlap
+        [step_size]: size of each step when iterating over sensor pixel grid
+    -->
+    <string-array name="config_udfps_touch_detection_options">
+        <item>0,0,1.0,0,1</item>
+        <item>1,1,1.0,0,1</item>
+        <item>1,1,1.0,.4,1</item>
+    </string-array>
+
+    <!-- The integer index of the selected option in config_udfps_touch_detection_options -->
+    <integer name="config_selected_udfps_touch_detection">2</integer>
+
     <!-- An array of arrays of side fingerprint sensor properties relative to each display.
          Note: this value is temporary and is expected to be queried directly
          from the HAL in the future. -->
@@ -6161,6 +6207,18 @@
          different from the home screen wallpaper. -->
     <bool name="config_independentLockscreenLiveWallpaper">false</bool>
 
+    <!-- Device state that corresponds to concurrent display mode where the default display
+         is the internal display. Public API for the feature is provided through Jetpack
+         WindowManager.
+         TODO(b/236022708) Move concurrent display state to device state config file
+    -->
+    <integer name="config_deviceStateConcurrentRearDisplay">-1</integer>
+
+    <!-- Physical display address that corresponds to the rear display in rear display mode
+         and concurrent display mode. Used to get information about the display before
+         entering the corresponding modes -->
+    <string name="config_rearDisplayPhysicalAddress" translatable="false"></string>
+
     <!-- List of certificate to be used for font fs-verity integrity verification -->
     <string-array translatable="false" name="config_fontManagerServiceCerts">
     </string-array>
@@ -6207,4 +6265,33 @@
         trusted certificate using the SHA-256 digest algorithm. -->
     <string-array name="config_healthConnectMigrationKnownSigners">
     </string-array>
+
+    <!-- Package name of Health Connect data migrator application.  -->
+    <string name="config_healthConnectMigratorPackageName"></string>
+
+    <!-- The Universal Stylus Initiative (USI) protocol version supported by each display.
+         (@see https://universalstylus.org/).
+
+         The i-th value in this array corresponds to the supported USI version of the i-th display
+         listed in config_displayUniqueIdArray. On a single-display device, the
+         config_displayUniqueIdArray may be empty, in which case the only value in this array should
+         be the USI version for the main built-in display.
+
+         If the display does not support USI, the version value should be an empty string. If the
+         display supports USI, the version must be in the following format:
+           "<major-version>.<minor-version>"
+
+         For example, "", "1.0", and "2.0" are valid values. -->
+    <string-array name="config_displayUsiVersionArray" translatable="false">
+        <item>""</item>
+    </string-array>
+
+    <!-- Whether system apps should be scanned in the stopped state during initial boot.
+        Packages can be added by OEMs in an allowlist, to prevent them from being scanned as
+        "stopped" during initial boot of a device, or after an OTA update. Stopped state of
+        an app is not changed during subsequent reboots.  -->
+    <bool name="config_stopSystemPackagesByDefault">false</bool>
+
+    <!-- Whether to show weather on the lock screen by default. -->
+    <bool name="config_lockscreenWeatherEnabledByDefault">false</bool>
 </resources>
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index 0ec3ef7..7d41f76 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -242,15 +242,15 @@
     <public name="system_error_container_dark"/>
     <public name="system_on_error_container_dark"/>
     <public name="system_primary_fixed_dark"/>
-    <public name="system_primary_fixeder_dark"/>
+    <public name="system_primary_fixed_darker_dark"/>
     <public name="system_on_primary_fixed_dark"/>
     <public name="system_on_primary_fixed_variant_dark"/>
     <public name="system_secondary_fixed_dark"/>
-    <public name="system_secondary_fixeder_dark"/>
+    <public name="system_secondary_fixed_darker_dark"/>
     <public name="system_on_secondary_fixed_dark"/>
     <public name="system_on_secondary_fixed_variant_dark"/>
     <public name="system_tertiary_fixed_dark"/>
-    <public name="system_tertiary_fixeder_dark"/>
+    <public name="system_tertiary_fixed_darker_dark"/>
     <public name="system_on_tertiary_fixed_dark"/>
     <public name="system_on_tertiary_fixed_variant_dark"/>
     <public name="system_control_activated_dark"/>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e330ee3..dacf4fa 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3396,7 +3396,6 @@
     <string name="android_start_title" product="device">Device is starting\u2026</string>
 
     <!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog when doing an fstrim. -->
-    <string name="android_upgrading_fstrim">Optimizing storage.</string>
 
     <!-- [CHAR LIMIT=40] Title of notification that is shown when finishing a system update. -->
     <string name="android_upgrading_notification_title" product="default">Finishing system update\u2026</string>
@@ -3404,11 +3403,6 @@
     <!-- [CHAR LIMIT=40] Toast that is shown when an app is still upgrading. -->
     <string name="app_upgrading_toast"><xliff:g id="application">%1$s</xliff:g> is upgrading\u2026</string>
 
-    <!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog for each .apk that is optimized. -->
-    <string name="android_upgrading_apk">Optimizing app
-        <xliff:g id="number" example="123">%1$d</xliff:g> of
-        <xliff:g id="number" example="123">%2$d</xliff:g>.</string>
-
     <!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog for each .apk pre boot broadcast -->
     <string name="android_preparing_apk">Preparing <xliff:g id="appname">%1$s</xliff:g>.</string>
 
@@ -3699,6 +3693,8 @@
     <string name="usb_tether_notification_title">USB tethering turned on</string>
     <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MIDI mode.  This is the title -->
     <string name="usb_midi_notification_title">MIDI via USB turned on</string>
+    <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in UVC mode.  This is the title -->
+    <string name="usb_uvc_notification_title">Device connected as Webcam</string>
     <!-- USB_PREFERENCES: Notification for when a USB accessory is attached.  This is the title -->
     <string name="usb_accessory_notification_title">USB accessory connected</string>
     <!-- See USB_PREFERENCES. This is the message. -->
@@ -4713,7 +4709,7 @@
 
     <!-- Title of Color Inversion feature shown in the warning dialog about the accessibility
     shortcut. -->
-    <string name="color_inversion_feature_name">Color Inversion</string>
+    <string name="color_inversion_feature_name">Color inversion</string>
 
     <!-- Title of Color Correction feature, which is mostly used to help users who are colorblind,
      shown in the warning dialog about the accessibility shortcut. -->
@@ -5067,6 +5063,13 @@
     <string name="managed_profile_label_badge_2">2nd Work <xliff:g id="label" example="Email">%1$s</xliff:g></string>
     <string name="managed_profile_label_badge_3">3rd Work <xliff:g id="label" example="Email">%1$s</xliff:g></string>
 
+    <!--
+        Used to wrap a label for content description for a Clone profile, e.g. "Clone Messenger"
+        instead of Messenger when the Messenger app is cloned.
+        [CHAR LIMIT=20]
+    -->
+    <string name="clone_profile_label_badge">Clone <xliff:g id="label" example="Messenger">%1$s</xliff:g></string>
+
     <!-- DO NOT TRANSLATE -->
     <string name="time_placeholder">--</string>
 
@@ -6234,4 +6237,17 @@
     <string name="mic_access_on_toast">Microphone is available</string>
     <!-- Toast message that is shown when the user mutes the microphone from the keyboard. [CHAR LIMIT=TOAST] -->
     <string name="mic_access_off_toast">Microphone is blocked</string>
+
+    <!-- Name of concurrent display notifications. [CHAR LIMIT=NONE] -->
+    <string name="concurrent_display_notification_name">Dual screen</string>
+    <!-- Title of concurrent display active notification. [CHAR LIMIT=NONE] -->
+    <string name="concurrent_display_notification_active_title">Dual screen is on</string>
+    <!-- Content of concurrent display active notification. [CHAR LIMIT=NONE] -->
+    <string name="concurrent_display_notification_active_content"><xliff:g id="app_name" example="Camera app">%1$s</xliff:g> is using both displays to show content</string>
+    <!-- Title of concurrent display thermal notification. [CHAR LIMIT=NONE] -->
+    <string name="concurrent_display_notification_thermal_title">Device is too warm</string>
+    <!-- Content of concurrent display thermal notification. [CHAR LIMIT=NONE] -->
+    <string name="concurrent_display_notification_thermal_content">Dual Screen is unavailable because your phone is getting too warm</string>
+    <!-- Text of device state notification turn off button. [CHAR LIMIT=NONE] -->
+    <string name="device_state_notification_turn_off_button">Turn off</string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f1b8cca..f237ece 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -370,6 +370,7 @@
   <java-symbol type="string" name="config_controlsPackage" />
   <java-symbol type="string" name="config_screenRecorderComponent" />
   <java-symbol type="string" name="config_somnambulatorComponent" />
+  <java-symbol type="string" name="config_screenshotAppClipsServiceComponent" />
   <java-symbol type="string" name="config_screenshotServiceComponent" />
   <java-symbol type="string" name="config_screenshotErrorReceiverComponent" />
   <java-symbol type="string" name="config_slicePermissionComponent" />
@@ -473,6 +474,7 @@
   <java-symbol type="integer" name="config_multiuserMaxRunningUsers" />
   <java-symbol type="bool" name="config_multiuserDelayUserDataLocking" />
   <java-symbol type="bool" name="config_multiuserVisibleBackgroundUsers" />
+  <java-symbol type="bool" name="config_multiuserVisibleBackgroundUsersOnDefaultDisplay" />
   <java-symbol type="bool" name="config_enableTimeoutToDockUserWhenDocked" />
   <java-symbol type="integer" name="config_userTypePackageWhitelistMode"/>
   <java-symbol type="xml" name="config_user_types" />
@@ -514,6 +516,8 @@
   <java-symbol type="dimen" name="config_ambiguousGestureMultiplier" />
   <java-symbol type="dimen" name="config_viewMinFlingVelocity" />
   <java-symbol type="dimen" name="config_viewMaxFlingVelocity" />
+  <java-symbol type="dimen" name="config_viewMinRotaryEncoderFlingVelocity" />
+  <java-symbol type="dimen" name="config_viewMaxRotaryEncoderFlingVelocity" />
   <java-symbol type="dimen" name="config_scrollbarSize" />
   <java-symbol type="dimen" name="config_horizontalScrollFactor" />
   <java-symbol type="dimen" name="config_verticalScrollFactor" />
@@ -1063,6 +1067,7 @@
   <java-symbol type="string" name="managed_profile_label_badge" />
   <java-symbol type="string" name="managed_profile_label_badge_2" />
   <java-symbol type="string" name="managed_profile_label_badge_3" />
+  <java-symbol type="string" name="clone_profile_label_badge" />
   <java-symbol type="string" name="mediasize_unknown_portrait" />
   <java-symbol type="string" name="mediasize_unknown_landscape" />
   <java-symbol type="string" name="mediasize_iso_a0" />
@@ -1386,6 +1391,8 @@
   <java-symbol type="drawable" name="ic_qs_auto_rotate" />
   <java-symbol type="drawable" name="ic_qs_dnd" />
   <java-symbol type="drawable" name="ic_qs_one_handed_mode" />
+  <java-symbol type="drawable" name="ic_clone_icon_badge" />
+  <java-symbol type="drawable" name="ic_clone_badge" />
 
   <java-symbol type="drawable" name="sim_light_blue" />
   <java-symbol type="drawable" name="sim_light_green" />
@@ -1434,6 +1441,8 @@
   <java-symbol type="drawable" name="ic_feedback_downrank" />
 
   <java-symbol type="drawable" name="ic_account_circle" />
+  <java-symbol type="drawable" name="ic_dual_screen" />
+  <java-symbol type="drawable" name="ic_thermostat" />
   <java-symbol type="color" name="user_icon_1" />
   <java-symbol type="color" name="user_icon_2" />
   <java-symbol type="color" name="user_icon_3" />
@@ -1992,6 +2001,7 @@
   <java-symbol type="integer" name="config_notificationsBatteryLedOn" />
   <java-symbol type="integer" name="config_notificationsBatteryLowARGB" />
   <java-symbol type="integer" name="config_notificationsBatteryMediumARGB" />
+  <java-symbol type="integer" name="config_notificationsBatteryNearlyFullLevel" />
   <java-symbol type="integer" name="config_notificationServiceArchiveSize" />
   <java-symbol type="integer" name="config_previousVibrationsDumpLimit" />
   <java-symbol type="integer" name="config_defaultVibrationAmplitude" />
@@ -2045,8 +2055,6 @@
   <java-symbol type="string" name="aerr_process" />
   <java-symbol type="string" name="aerr_application_repeated" />
   <java-symbol type="string" name="aerr_process_repeated" />
-  <java-symbol type="string" name="android_upgrading_fstrim" />
-  <java-symbol type="string" name="android_upgrading_apk" />
   <java-symbol type="string" name="android_upgrading_complete" />
   <java-symbol type="string" name="android_upgrading_starting_apps" />
   <java-symbol type="string" name="anr_activity_application" />
@@ -2134,6 +2142,7 @@
   <java-symbol type="string" name="usb_power_notification_message" />
   <java-symbol type="string" name="usb_ptp_notification_title" />
   <java-symbol type="string" name="usb_midi_notification_title" />
+  <java-symbol type="string" name="usb_uvc_notification_title" />
   <java-symbol type="string" name="usb_tether_notification_title" />
   <java-symbol type="string" name="usb_supplying_notification_title" />
   <java-symbol type="string" name="usb_unsupported_audio_accessory_title" />
@@ -2494,6 +2503,8 @@
   <java-symbol type="string" name="zen_mode_default_weekends_name" />
   <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="array" name="config_system_condition_providers" />
   <java-symbol type="string" name="muted_by" />
   <java-symbol type="string" name="zen_mode_alarm" />
@@ -2646,6 +2657,8 @@
   <java-symbol type="array" name="config_biometric_sensors" />
   <java-symbol type="bool" name="allow_test_udfps" />
   <java-symbol type="array" name="config_udfps_sensor_props" />
+  <java-symbol type="array" name="config_udfps_touch_detection_options" />
+  <java-symbol type="integer" name="config_selected_udfps_touch_detection" />
   <java-symbol type="array" name="config_sfps_sensor_props" />
   <java-symbol type="bool" name="config_is_powerbutton_fps" />
   <java-symbol type="array" name="config_udfps_enroll_stage_thresholds" />
@@ -3384,12 +3397,20 @@
   <java-symbol type="array" name="config_displayWhiteBalanceDisplayPrimaries" />
   <java-symbol type="array" name="config_displayWhiteBalanceDisplayNominalWhite" />
   <java-symbol type="bool" name="config_displayWhiteBalanceLightModeAllowed" />
+  <java-symbol type="integer" name="config_displayWhiteBalanceTransitionTime" />
 
   <!-- Device states where the sensor based rotation values should be reversed around the Z axis
        for the default display.
        TODO(b/265312193): Remove this workaround when this bug is fixed.-->
   <java-symbol type="array" name="config_deviceStatesToReverseDefaultDisplayRotationAroundZAxis" />
 
+  <!-- Boolean indicating whether secondary built-in displays should have their orientation
+       match the active default display. This config assumes that the secondary display only
+       requires swapping ROTATION_90 and ROTATION_270.
+       TODO(b/265991392): This should eventually be configured and parsed in
+        display_settings.xml -->
+  <java-symbol type="bool" name="config_matchSecondaryInternalDisplaysOrientationToReverseDefaultDisplay" />
+
   <!-- Default user restrictions for the SYSTEM user -->
   <java-symbol type="array" name="config_defaultFirstUserRestrictions" />
 
@@ -3405,7 +3426,6 @@
 
   <java-symbol type="array" name="config_convert_to_emergency_number_map" />
 
-  <java-symbol type="array" name="config_nonBlockableNotificationPackages" />
   <java-symbol type="array" name="config_priorityOnlyDndExemptPackages" />
 
   <!-- Screen-size-dependent modes for picker dialogs. -->
@@ -3699,6 +3719,7 @@
   <java-symbol type="string" name="notification_channel_accessibility_magnification" />
   <java-symbol type="string" name="notification_channel_accessibility_security_policy" />
   <java-symbol type="string" name="config_defaultAutofillService" />
+  <java-symbol type="string" name="config_defaultFieldClassificationService" />
   <java-symbol type="string" name="config_defaultOnDeviceSpeechRecognitionService" />
   <java-symbol type="string" name="config_defaultTextClassifierPackage" />
   <java-symbol type="string" name="config_defaultWellbeingPackage" />
@@ -4873,7 +4894,21 @@
   <java-symbol type="array" name="config_deviceStatesAvailableForAppRequests" />
   <java-symbol type="array" name="config_serviceStateLocationAllowedPackages" />
   <java-symbol type="integer" name="config_deviceStateRearDisplay"/>
+  <java-symbol type="array" name="device_state_notification_state_identifiers"/>
+  <java-symbol type="array" name="device_state_notification_names"/>
+  <java-symbol type="array" name="device_state_notification_active_titles"/>
+  <java-symbol type="array" name="device_state_notification_active_contents"/>
+  <java-symbol type="array" name="device_state_notification_thermal_titles"/>
+  <java-symbol type="array" name="device_state_notification_thermal_contents"/>
+  <java-symbol type="string" name="concurrent_display_notification_name"/>
+  <java-symbol type="string" name="concurrent_display_notification_active_title"/>
+  <java-symbol type="string" name="concurrent_display_notification_active_content"/>
+  <java-symbol type="string" name="concurrent_display_notification_thermal_title"/>
+  <java-symbol type="string" name="concurrent_display_notification_thermal_content"/>
+  <java-symbol type="string" name="device_state_notification_turn_off_button"/>
   <java-symbol type="bool" name="config_independentLockscreenLiveWallpaper"/>
+  <java-symbol type="integer" name="config_deviceStateConcurrentRearDisplay" />
+  <java-symbol type="string" name="config_rearDisplayPhysicalAddress" />
 
   <!-- For app language picker -->
   <java-symbol type="string" name="system_locale_title" />
@@ -4891,4 +4926,10 @@
   <java-symbol type="string" name="config_mainDisplayShape"/>
   <java-symbol type="string" name="config_secondaryDisplayShape"/>
   <java-symbol type="array" name="config_displayShapeArray" />
+
+  <java-symbol type="bool" name="config_stopSystemPackagesByDefault"/>
+  <java-symbol type="string" name="config_wearServiceComponent" />
+
+  <!-- Whether to show weather on the lockscreen by default. -->
+  <java-symbol type="bool" name="config_lockscreenWeatherEnabledByDefault" />
 </resources>
diff --git a/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java b/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java
index b1991c2..b3c7f88 100644
--- a/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java
+++ b/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java
@@ -60,8 +60,8 @@
 
     public void timeReadWriteInsetsState(int reps) {
         final InsetsState insetsState = new InsetsState();
-        for (int i = 0; i < InsetsState.SIZE; i++) {
-            insetsState.addSource(new InsetsSource(i, InsetsState.toPublicType(i)));
+        for (int i = 0; i < 10; i++) {
+            insetsState.addSource(new InsetsSource(i, 1 << i));
         }
         for (int i = 0; i < reps; i++) {
             insetsState.writeToParcel(mParcel, 0);
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 4548730..34d669b 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -31,6 +31,7 @@
 import static android.app.Notification.EXTRA_MEDIA_REMOTE_INTENT;
 import static android.app.Notification.EXTRA_MEDIA_SESSION;
 import static android.app.Notification.EXTRA_MESSAGING_PERSON;
+import static android.app.Notification.EXTRA_PEOPLE_LIST;
 import static android.app.Notification.EXTRA_PICTURE;
 import static android.app.Notification.EXTRA_PICTURE_ICON;
 import static android.app.Notification.MessagingStyle.Message.KEY_DATA_URI;
@@ -817,6 +818,23 @@
     }
 
     @Test
+    public void testRecoverBuilder_nullExtraPeopleList_noCrash() {
+        Bundle extras = new Bundle();
+        extras.putParcelable(EXTRA_PEOPLE_LIST, null);
+
+        Notification n = new Notification.Builder(mContext, "test")
+                .setSmallIcon(0)
+                .addExtras(extras)
+                .build();
+        Bundle fakeTypes = new Bundle();
+        fakeTypes.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, new Bundle());
+
+        Notification.Builder.recoverBuilder(mContext, n);
+
+        // no crash, good
+    }
+
+    @Test
     public void testVisitUris_invalidExtra_noCrash() {
         Notification n = new Notification.Builder(mContext, "test")
                 .setSmallIcon(0)
diff --git a/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java b/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java
new file mode 100644
index 0000000..d8298fd
--- /dev/null
+++ b/core/tests/coretests/src/android/app/admin/PackagePolicyTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+import static android.app.admin.PackagePolicy.PACKAGE_POLICY_ALLOWLIST;
+import static android.app.admin.PackagePolicy.PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM;
+import static android.app.admin.PackagePolicy.PACKAGE_POLICY_BLOCKLIST;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class PackagePolicyTest {
+
+    private static final String TEST_PACKAGE_NAME = "com.example";
+
+    private static final String TEST_PACKAGE_NAME_2 = "com.example.2";
+
+    private static final String TEST_SYSTEM_PACKAGE_NAME = "com.system";
+
+
+    @Test
+    public void testParceling() {
+        final int policyType = PACKAGE_POLICY_BLOCKLIST;
+        final Set<String> packageNames = new ArraySet<>();
+        packageNames.add(TEST_PACKAGE_NAME);
+
+        final Parcel parcel = Parcel.obtain();
+        PackagePolicy packagePolicy = new PackagePolicy(policyType, packageNames);
+        try {
+            packagePolicy.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            packagePolicy = PackagePolicy.CREATOR.createFromParcel(parcel);
+        } finally {
+            parcel.recycle();
+        }
+
+        assertEquals(policyType, packagePolicy.getPolicyType());
+        assertNotNull(packagePolicy.getPackageNames());
+        assertEquals(1, packagePolicy.getPackageNames().size());
+        assertTrue(packagePolicy.getPackageNames().contains(TEST_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testEmptyBlocklistCreation() {
+        PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_BLOCKLIST);
+        assertEquals(PACKAGE_POLICY_BLOCKLIST, policy.getPolicyType());
+        assertNotNull(policy.getPackageNames());
+        assertTrue(policy.getPackageNames().isEmpty());
+    }
+
+    @Test
+    public void testEmptyAllowlistCreation() {
+        PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST);
+        assertEquals(PACKAGE_POLICY_ALLOWLIST, policy.getPolicyType());
+        assertNotNull(policy.getPackageNames());
+        assertTrue(policy.getPackageNames().isEmpty());
+    }
+
+    @Test
+    public void testEmptyAllowlistAndSystemCreation() {
+        PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM);
+        assertEquals(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM, policy.getPolicyType());
+        assertNotNull(policy.getPackageNames());
+        assertTrue(policy.getPackageNames().isEmpty());
+    }
+
+    @Test
+    public void testSuppliedBlocklistCreation() {
+        final Set<String> packageNames = new ArraySet<>();
+        packageNames.add(TEST_PACKAGE_NAME);
+        PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_BLOCKLIST, packageNames);
+        assertEquals(PACKAGE_POLICY_BLOCKLIST, policy.getPolicyType());
+        assertNotNull(policy.getPackageNames());
+        assertEquals(1, policy.getPackageNames().size());
+        assertTrue(policy.getPackageNames().contains(TEST_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testSuppliedAllowlistCreation() {
+        final Set<String> packageNames = new ArraySet<>();
+        packageNames.add(TEST_PACKAGE_NAME);
+        PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST, packageNames);
+        assertEquals(PACKAGE_POLICY_ALLOWLIST, policy.getPolicyType());
+        assertNotNull(policy.getPackageNames());
+        assertEquals(1, policy.getPackageNames().size());
+        assertTrue(policy.getPackageNames().contains(TEST_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testSuppliedAllowlistAndSystemCreation() {
+        final Set<String> packageNames = new ArraySet<>();
+        packageNames.add(TEST_PACKAGE_NAME);
+        PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM, packageNames);
+        assertEquals(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM, policy.getPolicyType());
+        assertNotNull(policy.getPackageNames());
+        assertEquals(1, policy.getPackageNames().size());
+        assertTrue(policy.getPackageNames().contains(TEST_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testBlocklist_isPackageAllowed() {
+        final Set<String> packageNames = new ArraySet<>();
+        packageNames.add(TEST_PACKAGE_NAME);
+        final Set<String> systemPackages = new ArraySet<>();
+        systemPackages.add(TEST_SYSTEM_PACKAGE_NAME);
+
+        PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_BLOCKLIST, packageNames);
+
+        assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME, Collections.emptySet()));
+        assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME, systemPackages));
+        assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, Collections.emptySet()));
+        assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, systemPackages));
+        assertTrue(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, Collections.emptySet()));
+        assertTrue(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, systemPackages));
+    }
+
+    @Test
+    public void testAllowlist_isPackageAllowed() {
+        final Set<String> packageNames = new ArraySet<>();
+        packageNames.add(TEST_PACKAGE_NAME);
+        final Set<String> systemPackages = new ArraySet<>();
+        systemPackages.add(TEST_SYSTEM_PACKAGE_NAME);
+        PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST, packageNames);
+
+        assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME, Collections.emptySet()));
+        assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME, systemPackages));
+        assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, Collections.emptySet()));
+        assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, systemPackages));
+        assertFalse(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, Collections.emptySet()));
+        assertFalse(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, systemPackages));
+    }
+
+    @Test
+    public void testAllowlistAndSystem_isPackageAllowed() {
+        final Set<String> packageNames = new ArraySet<>();
+        packageNames.add(TEST_PACKAGE_NAME);
+        final Set<String> systemPackages = new ArraySet<>();
+        systemPackages.add(TEST_SYSTEM_PACKAGE_NAME);
+        PackagePolicy policy = new PackagePolicy(PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM, packageNames);
+
+        assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME, Collections.emptySet()));
+        assertTrue(policy.isPackageAllowed(TEST_PACKAGE_NAME, systemPackages));
+        assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, Collections.emptySet()));
+        assertFalse(policy.isPackageAllowed(TEST_PACKAGE_NAME_2, systemPackages));
+        assertFalse(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, Collections.emptySet()));
+        assertTrue(policy.isPackageAllowed(TEST_SYSTEM_PACKAGE_NAME, systemPackages));
+    }
+
+}
diff --git a/core/tests/coretests/src/android/app/time/TimeZoneCapabilitiesTest.java b/core/tests/coretests/src/android/app/time/TimeZoneCapabilitiesTest.java
index 8bed31f..6636cbd 100644
--- a/core/tests/coretests/src/android/app/time/TimeZoneCapabilitiesTest.java
+++ b/core/tests/coretests/src/android/app/time/TimeZoneCapabilitiesTest.java
@@ -44,10 +44,12 @@
     public void testEquals() {
         TimeZoneCapabilities.Builder builder1 = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
                 .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+                .setUseLocationEnabled(true)
                 .setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
                 .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED);
         TimeZoneCapabilities.Builder builder2 = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
                 .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+                .setUseLocationEnabled(true)
                 .setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
                 .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED);
         {
@@ -70,6 +72,20 @@
             assertEquals(one, two);
         }
 
+        builder2.setUseLocationEnabled(false);
+        {
+            TimeZoneCapabilities one = builder1.build();
+            TimeZoneCapabilities two = builder2.build();
+            assertNotEquals(one, two);
+        }
+
+        builder1.setUseLocationEnabled(false);
+        {
+            TimeZoneCapabilities one = builder1.build();
+            TimeZoneCapabilities two = builder2.build();
+            assertEquals(one, two);
+        }
+
         builder2.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
         {
             TimeZoneCapabilities one = builder1.build();
@@ -103,6 +119,7 @@
     public void testParcelable() {
         TimeZoneCapabilities.Builder builder = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
                 .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+                .setUseLocationEnabled(true)
                 .setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
                 .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED);
         assertRoundTripParcelable(builder.build());
@@ -110,6 +127,9 @@
         builder.setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
         assertRoundTripParcelable(builder.build());
 
+        builder.setUseLocationEnabled(false);
+        assertRoundTripParcelable(builder.build());
+
         builder.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
         assertRoundTripParcelable(builder.build());
 
@@ -126,6 +146,7 @@
                         .build();
         TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
                 .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+                .setUseLocationEnabled(true)
                 .setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
                 .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED)
                 .build();
@@ -149,6 +170,7 @@
                         .build();
         TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
                 .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+                .setUseLocationEnabled(true)
                 .setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
                 .setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
                 .build();
@@ -164,6 +186,7 @@
     public void copyBuilder_copiesAllFields() {
         TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
                 .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+                .setUseLocationEnabled(true)
                 .setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
                 .setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
                 .build();
@@ -176,6 +199,24 @@
             TimeZoneCapabilities expectedCapabilities =
                     new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
                             .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+                            .setUseLocationEnabled(true)
+                            .setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+                            .setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
+                            .build();
+
+            assertThat(updatedCapabilities).isEqualTo(expectedCapabilities);
+        }
+
+        {
+            TimeZoneCapabilities updatedCapabilities =
+                    new TimeZoneCapabilities.Builder(capabilities)
+                            .setUseLocationEnabled(false)
+                            .build();
+
+            TimeZoneCapabilities expectedCapabilities =
+                    new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
+                            .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+                            .setUseLocationEnabled(false)
                             .setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
                             .setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
                             .build();
@@ -192,6 +233,7 @@
             TimeZoneCapabilities expectedCapabilities =
                     new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
                             .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+                            .setUseLocationEnabled(true)
                             .setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
                             .setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
                             .build();
@@ -208,6 +250,7 @@
             TimeZoneCapabilities expectedCapabilities =
                     new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
                             .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+                            .setUseLocationEnabled(true)
                             .setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
                             .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED)
                             .build();
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index 958fdc6..a3eda8d 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -17,7 +17,7 @@
 package android.view;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 
@@ -92,7 +92,7 @@
 
     @Test
     public void testImeVisibility() {
-        final InsetsSourceControl ime = new InsetsSourceControl(ITYPE_IME, WindowInsets.Type.ime(),
+        final InsetsSourceControl ime = new InsetsSourceControl(ID_IME, WindowInsets.Type.ime(),
                 mLeash, false, new Point(), Insets.NONE);
         mController.onControlsChanged(new InsetsSourceControl[] { ime });
 
@@ -121,7 +121,7 @@
             mController.show(WindowInsets.Type.ime(), true /* fromIme */, null /* statsToken */);
 
             // set control and verify visibility is applied.
-            InsetsSourceControl control = new InsetsSourceControl(ITYPE_IME,
+            InsetsSourceControl control = new InsetsSourceControl(ID_IME,
                     WindowInsets.Type.ime(), mLeash, false, new Point(), Insets.NONE);
             mController.onControlsChanged(new InsetsSourceControl[] { control });
             // IME show animation should be triggered when control becomes available.
@@ -161,7 +161,7 @@
             }
 
             // set control and verify visibility is applied.
-            InsetsSourceControl control = Mockito.spy(new InsetsSourceControl(ITYPE_IME,
+            InsetsSourceControl control = Mockito.spy(new InsetsSourceControl(ID_IME,
                     WindowInsets.Type.ime(), mLeash, false, new Point(), Insets.NONE));
             // Simulate IME source control set this flag when the target has starting window.
             control.setSkipAnimationOnce(true);
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index cc5f7f8..1682135 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -16,8 +16,8 @@
 
 package android.view;
 
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowInsets.Type.systemBars;
 
 import static org.junit.Assert.assertEquals;
@@ -66,6 +66,11 @@
 @RunWith(AndroidJUnit4.class)
 public class InsetsAnimationControlImplTest {
 
+    private static final int ID_STATUS_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, statusBars());
+    private static final int ID_NAVIGATION_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, navigationBars());
+
     private InsetsAnimationControlImpl mController;
 
     private SurfaceSession mSession = new SurfaceSession();
@@ -87,29 +92,31 @@
                 .setName("testSurface")
                 .build();
         mInsetsState = new InsetsState();
-        mInsetsState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 500, 100));
-        mInsetsState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(400, 0, 500, 500));
-        InsetsSourceConsumer topConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR,
+        mInsetsState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 500, 100));
+        mInsetsState.getOrCreateSource(ID_NAVIGATION_BAR, navigationBars())
+                .setFrame(new Rect(400, 0, 500, 500));
+        InsetsSourceConsumer topConsumer = new InsetsSourceConsumer(ID_STATUS_BAR,
                 WindowInsets.Type.statusBars(), mInsetsState,
                 () -> mMockTransaction, mMockController);
         topConsumer.setControl(
-                new InsetsSourceControl(ITYPE_STATUS_BAR, WindowInsets.Type.statusBars(),
+                new InsetsSourceControl(ID_STATUS_BAR, WindowInsets.Type.statusBars(),
                         mStatusLeash, true, new Point(0, 0), Insets.of(0, 100, 0, 0)),
                 new int[1], new int[1]);
 
-        InsetsSourceConsumer navConsumer = new InsetsSourceConsumer(ITYPE_NAVIGATION_BAR,
+        InsetsSourceConsumer navConsumer = new InsetsSourceConsumer(ID_NAVIGATION_BAR,
                 WindowInsets.Type.navigationBars(), mInsetsState,
                 () -> mMockTransaction, mMockController);
         navConsumer.setControl(
-                new InsetsSourceControl(ITYPE_NAVIGATION_BAR, WindowInsets.Type.navigationBars(),
+                new InsetsSourceControl(ID_NAVIGATION_BAR, WindowInsets.Type.navigationBars(),
                         mNavLeash, true, new Point(400, 0), Insets.of(0, 0, 100, 0)),
                 new int[1], new int[1]);
         mMockController.setRequestedVisibleTypes(0, WindowInsets.Type.navigationBars());
         navConsumer.applyLocalVisibilityOverride();
 
         SparseArray<InsetsSourceControl> controls = new SparseArray<>();
-        controls.put(ITYPE_STATUS_BAR, topConsumer.getControl());
-        controls.put(ITYPE_NAVIGATION_BAR, navConsumer.getControl());
+        controls.put(ID_STATUS_BAR, topConsumer.getControl());
+        controls.put(ID_NAVIGATION_BAR, navConsumer.getControl());
         mController = new InsetsAnimationControlImpl(controls,
                 new Rect(0, 0, 500, 500), mInsetsState, mMockListener, systemBars(),
                 mMockController, 10 /* durationMs */, new LinearInterpolator(),
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 5ec93e5..ca1367a 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -22,16 +22,13 @@
 import static android.view.InsetsController.ANIMATION_TYPE_RESIZE;
 import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
 import static android.view.InsetsController.AnimationType;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
 import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
-import static android.view.InsetsState.FIRST_TYPE;
-import static android.view.InsetsState.ITYPE_CAPTION_BAR;
-import static android.view.InsetsState.ITYPE_IME;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.LAST_TYPE;
 import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
+import static android.view.WindowInsets.Type.SIZE;
 import static android.view.WindowInsets.Type.all;
+import static android.view.WindowInsets.Type.captionBar;
 import static android.view.WindowInsets.Type.defaultVisible;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
@@ -64,7 +61,6 @@
 import android.graphics.Rect;
 import android.os.CancellationSignal;
 import android.platform.test.annotations.Presubmit;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.SurfaceControl.Transaction;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsController.OnControllableInsetsChangedListener;
@@ -101,6 +97,12 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class InsetsControllerTest {
+
+    private static final int ID_STATUS_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, statusBars());
+    private static final int ID_NAVIGATION_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, navigationBars());
+
     private InsetsSource mStatusSource;
     private InsetsSource mNavSource;
     private InsetsSource mImeSource;
@@ -153,11 +155,11 @@
                 }
             }, mTestHandler);
             final Rect rect = new Rect(5, 5, 5, 5);
-            mStatusSource = new InsetsSource(ITYPE_STATUS_BAR, statusBars());
+            mStatusSource = new InsetsSource(ID_STATUS_BAR, statusBars());
             mStatusSource.setFrame(new Rect(0, 0, 100, 10));
-            mNavSource = new InsetsSource(ITYPE_NAVIGATION_BAR, navigationBars());
+            mNavSource = new InsetsSource(ID_NAVIGATION_BAR, navigationBars());
             mNavSource.setFrame(new Rect(0, 90, 100, 100));
-            mImeSource = new InsetsSource(ITYPE_IME, ime());
+            mImeSource = new InsetsSource(ID_IME, ime());
             mImeSource.setFrame(new Rect(0, 0, 100, 10));
             InsetsState state = new InsetsState();
             state.addSource(mStatusSource);
@@ -179,7 +181,7 @@
 
     @Test
     public void testControlsChanged() {
-        mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR, statusBars()));
+        mController.onControlsChanged(createSingletonControl(ID_STATUS_BAR, statusBars()));
         assertNotNull(mController.getSourceConsumer(mStatusSource).getControl().getLeash());
         mController.addOnControllableInsetsChangedListener(
                 ((controller, typeMask) -> assertEquals(statusBars(), typeMask)));
@@ -190,7 +192,7 @@
         OnControllableInsetsChangedListener listener
                 = mock(OnControllableInsetsChangedListener.class);
         mController.addOnControllableInsetsChangedListener(listener);
-        mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR, statusBars()));
+        mController.onControlsChanged(createSingletonControl(ID_STATUS_BAR, statusBars()));
         mController.onControlsChanged(new InsetsSourceControl[0]);
         assertNull(mController.getSourceConsumer(mStatusSource).getControl());
         InOrder inOrder = Mockito.inOrder(listener);
@@ -202,7 +204,7 @@
     @Test
     public void testControlsRevoked_duringAnim() {
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR, statusBars()));
+            mController.onControlsChanged(createSingletonControl(ID_STATUS_BAR, statusBars()));
 
             ArgumentCaptor<WindowInsetsAnimationController> animationController =
                     ArgumentCaptor.forClass(WindowInsetsAnimationController.class);
@@ -231,7 +233,7 @@
 
             InsetsSourceControl control =
                     new InsetsSourceControl(
-                            ITYPE_STATUS_BAR, statusBars(), mLeash, true, new Point(),
+                            ID_STATUS_BAR, statusBars(), mLeash, true, new Point(),
                             Insets.of(0, 10, 0, 0));
             mController.onControlsChanged(new InsetsSourceControl[]{control});
             mController.controlWindowInsetsAnimation(0, 0 /* durationMs */,
@@ -284,7 +286,7 @@
 
     @Test
     public void testApplyImeVisibility() {
-        InsetsSourceControl ime = createControl(ITYPE_IME, ime());
+        InsetsSourceControl ime = createControl(ID_IME, ime());
         mController.onControlsChanged(new InsetsSourceControl[] { ime });
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             mController.getSourceConsumer(mImeSource).onWindowFocusGained(true);
@@ -423,28 +425,28 @@
 
     @Test
     public void testRestoreStartsAnimation() {
-        mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR, statusBars()));
+        mController.onControlsChanged(createSingletonControl(ID_STATUS_BAR, statusBars()));
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             mController.hide(statusBars());
             mController.cancelExistingAnimations();
             assertFalse(isRequestedVisible(mController, statusBars()));
-            assertFalse(mController.getState().getSource(ITYPE_STATUS_BAR).isVisible());
+            assertFalse(mController.getState().peekSource(ID_STATUS_BAR).isVisible());
 
             // Loosing control
             InsetsState state = new InsetsState(mController.getState());
-            state.setSourceVisible(ITYPE_STATUS_BAR, true);
+            state.setSourceVisible(ID_STATUS_BAR, true);
             mController.onStateChanged(state);
             mController.onControlsChanged(new InsetsSourceControl[0]);
             assertFalse(isRequestedVisible(mController, statusBars()));
-            assertTrue(mController.getState().getSource(ITYPE_STATUS_BAR).isVisible());
+            assertTrue(mController.getState().peekSource(ID_STATUS_BAR).isVisible());
 
             // Gaining control
-            mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR, statusBars()));
+            mController.onControlsChanged(createSingletonControl(ID_STATUS_BAR, statusBars()));
             assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(statusBars()));
             mController.cancelExistingAnimations();
             assertFalse(isRequestedVisible(mController, statusBars()));
-            assertFalse(mController.getState().getSource(ITYPE_STATUS_BAR).isVisible());
+            assertFalse(mController.getState().peekSource(ID_STATUS_BAR).isVisible());
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
@@ -455,18 +457,18 @@
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
 
             mController.show(ime());
-            assertFalse(mController.getState().getSource(ITYPE_IME).isVisible());
+            assertFalse(mController.getState().peekSource(ID_IME).isVisible());
 
             // Pretend IME is calling
             mController.show(ime(), true /* fromIme */, null /* statsToken */);
 
             // Gaining control shortly after
-            mController.onControlsChanged(createSingletonControl(ITYPE_IME, ime()));
+            mController.onControlsChanged(createSingletonControl(ID_IME, ime()));
 
             assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ime()));
             mController.cancelExistingAnimations();
             assertTrue(isRequestedVisible(mController, ime()));
-            assertTrue(mController.getState().getSource(ITYPE_IME).isVisible());
+            assertTrue(mController.getState().peekSource(ID_IME).isVisible());
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
@@ -476,10 +478,10 @@
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
 
             mController.show(ime());
-            assertFalse(mController.getState().getSource(ITYPE_IME).isVisible());
+            assertFalse(mController.getState().peekSource(ID_IME).isVisible());
 
             // Gaining control shortly after
-            mController.onControlsChanged(createSingletonControl(ITYPE_IME, ime()));
+            mController.onControlsChanged(createSingletonControl(ID_IME, ime()));
 
             // Pretend IME is calling
             mController.show(ime(), true /* fromIme */, null /* statsToken */);
@@ -487,14 +489,14 @@
             assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ime()));
             mController.cancelExistingAnimations();
             assertTrue(isRequestedVisible(mController, ime()));
-            assertTrue(mController.getState().getSource(ITYPE_IME).isVisible());
+            assertTrue(mController.getState().peekSource(ID_IME).isVisible());
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
 
     @Test
     public void testAnimationEndState_controller() throws Exception {
-        mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR, statusBars()));
+        mController.onControlsChanged(createSingletonControl(ID_STATUS_BAR, statusBars()));
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             WindowInsetsAnimationControlListener mockListener =
@@ -520,7 +522,7 @@
 
     @Test
     public void testCancellation_afterGainingControl() throws Exception {
-        mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR, statusBars()));
+        mController.onControlsChanged(createSingletonControl(ID_STATUS_BAR, statusBars()));
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             WindowInsetsAnimationControlListener mockListener =
@@ -641,61 +643,60 @@
     public void testFrameUpdateDuringAnimation() {
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
 
-            mController.onControlsChanged(createSingletonControl(ITYPE_IME, ime()));
+            mController.onControlsChanged(createSingletonControl(ID_IME, ime()));
 
             // Pretend IME is calling
             mController.show(ime(), true /* fromIme */, null /* statsToken */);
 
             InsetsState copy = new InsetsState(mController.getState(), true /* copySources */);
-            copy.getSource(ITYPE_IME).setFrame(0, 1, 2, 3);
-            copy.getSource(ITYPE_IME).setVisibleFrame(new Rect(4, 5, 6, 7));
+            copy.peekSource(ID_IME).setFrame(0, 1, 2, 3);
+            copy.peekSource(ID_IME).setVisibleFrame(new Rect(4, 5, 6, 7));
             mController.onStateChanged(copy);
             assertNotEquals(new Rect(0, 1, 2, 3),
-                    mController.getState().getSource(ITYPE_IME).getFrame());
+                    mController.getState().peekSource(ID_IME).getFrame());
             assertNotEquals(new Rect(4, 5, 6, 7),
-                    mController.getState().getSource(ITYPE_IME).getVisibleFrame());
+                    mController.getState().peekSource(ID_IME).getVisibleFrame());
             mController.cancelExistingAnimations();
             assertEquals(new Rect(0, 1, 2, 3),
-                    mController.getState().getSource(ITYPE_IME).getFrame());
+                    mController.getState().peekSource(ID_IME).getFrame());
             assertEquals(new Rect(4, 5, 6, 7),
-                    mController.getState().getSource(ITYPE_IME).getVisibleFrame());
+                    mController.getState().peekSource(ID_IME).getVisibleFrame());
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
 
     @Test
     public void testResizeAnimation_insetsTypes() {
-        for (@InternalInsetsType int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
-            final @AnimationType int expectedAnimationType =
-                    (InsetsState.toPublicType(type) & systemBars()) != 0
+        for (int i = 0; i < SIZE; i++) {
+            final @InsetsType int type = 1 << i;
+            final @AnimationType int expectedAnimationType = (type & systemBars()) != 0
                             ? ANIMATION_TYPE_RESIZE
                             : ANIMATION_TYPE_NONE;
             doTestResizeAnimation_insetsTypes(type, expectedAnimationType);
         }
     }
 
-    private void doTestResizeAnimation_insetsTypes(@InternalInsetsType int type,
+    private void doTestResizeAnimation_insetsTypes(@InsetsType int type,
             @AnimationType int expectedAnimationType) {
-        final @InsetsType int publicType = InsetsState.toPublicType(type);
+        final int id = type;
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             final InsetsState state1 = new InsetsState();
-            state1.getSource(type).setVisible(true);
-            state1.getSource(type).setFrame(0, 0, 500, 50);
+            state1.getOrCreateSource(id, type).setVisible(true).setFrame(0, 0, 500, 50);
             final InsetsState state2 = new InsetsState(state1, true /* copySources */);
-            state2.getSource(type).setFrame(0, 0, 500, 60);
-            final String message = "Animation type of " + InsetsState.typeToString(type) + ":";
+            state2.peekSource(id).setFrame(0, 0, 500, 60);
+            final String message = "Animation type of " + WindowInsets.Type.toString(type) + ":";
 
             // New insets source won't cause the resize animation.
             mController.onStateChanged(state1);
-            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
+            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
 
             // Changing frame might cause the resize animation. This depends on the insets type.
             mController.onStateChanged(state2);
-            assertEquals(message, expectedAnimationType, mController.getAnimationType(publicType));
+            assertEquals(message, expectedAnimationType, mController.getAnimationType(type));
 
             // Cancel the existing animations for the next iteration.
             mController.cancelExistingAnimations();
-            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
+            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
@@ -703,23 +704,23 @@
     @Test
     public void testResizeAnimation_displayFrame() {
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            final @InternalInsetsType int type = ITYPE_STATUS_BAR;
-            final @InsetsType int publicType = statusBars();
+            final int id = ID_STATUS_BAR;
+            final @InsetsType int type = statusBars();
             final InsetsState state1 = new InsetsState();
             state1.setDisplayFrame(new Rect(0, 0, 500, 1000));
-            state1.getSource(type).setFrame(0, 0, 500, 50);
+            state1.getOrCreateSource(id, type).setFrame(0, 0, 500, 50);
             final InsetsState state2 = new InsetsState(state1, true /* copySources */);
             state2.setDisplayFrame(new Rect(0, 0, 500, 1010));
-            state2.getSource(type).setFrame(0, 0, 500, 60);
+            state2.peekSource(id).setFrame(0, 0, 500, 60);
             final String message = "There must not be resize animation.";
 
             // New insets source won't cause the resize animation.
             mController.onStateChanged(state1);
-            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
+            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
 
             // Changing frame won't cause the resize animation if the display frame is also changed.
             mController.onStateChanged(state2);
-            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
+            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
@@ -727,32 +728,29 @@
     @Test
     public void testResizeAnimation_visibility() {
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            final @InternalInsetsType int type = ITYPE_STATUS_BAR;
-            final @InsetsType int publicType = statusBars();
+            final int id = ID_STATUS_BAR;
+            final @InsetsType int type = statusBars();
             final InsetsState state1 = new InsetsState();
-            state1.getSource(type).setVisible(true);
-            state1.getSource(type).setFrame(0, 0, 500, 50);
+            state1.getOrCreateSource(id, type).setVisible(true).setFrame(0, 0, 500, 50);
             final InsetsState state2 = new InsetsState(state1, true /* copySources */);
-            state2.getSource(type).setVisible(false);
-            state2.getSource(type).setFrame(0, 0, 500, 60);
+            state2.peekSource(id).setVisible(false).setFrame(0, 0, 500, 60);
             final InsetsState state3 = new InsetsState(state2, true /* copySources */);
-            state3.getSource(type).setVisible(true);
-            state3.getSource(type).setFrame(0, 0, 500, 70);
+            state3.peekSource(id).setVisible(true).setFrame(0, 0, 500, 70);
             final String message = "There must not be resize animation.";
 
             // New insets source won't cause the resize animation.
             mController.onStateChanged(state1);
-            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
+            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
 
             // Changing source visibility (visible --> invisible) won't cause the resize animation.
             // The previous source and the current one must be both visible.
             mController.onStateChanged(state2);
-            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
+            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
 
             // Changing source visibility (invisible --> visible) won't cause the resize animation.
             // The previous source and the current one must be both visible.
             mController.onStateChanged(state3);
-            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
+            assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
@@ -765,22 +763,20 @@
             return;
         }
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            mController.onFrameChanged(new Rect(0, 0, 100, 300));
-            final InsetsState state = new InsetsState(mController.getState(), true);
-            final Rect captionFrame = new Rect(0, 0, 100, 100);
-            mController.setCaptionInsetsHeight(100);
-            mController.onStateChanged(state);
-            final InsetsState currentState = new InsetsState(mController.getState());
-            // The caption bar source should be synced with the info in mAttachInfo.
-            assertEquals(captionFrame, currentState.peekSource(ITYPE_CAPTION_BAR).getFrame());
-            assertTrue(currentState.equals(state, true /* excludingCaptionInsets*/,
-                    true /* excludeInvisibleIme */));
+            final Rect frame = new Rect(0, 0, 100, 300);
+            final int captionBarHeight = 100;
+            final InsetsState state = mController.getState();
+            mController.onFrameChanged(frame);
+            mController.setCaptionInsetsHeight(captionBarHeight);
+            // The caption bar insets height should be the same as the caption bar height.
+            assertEquals(captionBarHeight, state.calculateInsets(frame, captionBar(), false).top);
             // Test update to remove the caption bar
             mController.setCaptionInsetsHeight(0);
-            mController.onStateChanged(state);
             // The caption bar source should not be there at all, because we don't add empty
             // caption to the state from the server.
-            assertNull(mController.getState().peekSource(ITYPE_CAPTION_BAR));
+            for (int i = state.sourceSize() - 1; i >= 0; i--) {
+                assertNotEquals(captionBar(), state.sourceAt(i).getType());
+            }
         });
     }
 
@@ -792,7 +788,6 @@
             return;
         }
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            final InsetsState state = new InsetsState(mController.getState(), true);
             reset(mTestHost);
             mController.setCaptionInsetsHeight(100);
             verify(mTestHost).notifyInsetsChanged();
@@ -881,28 +876,28 @@
             // Changing status bar frame should cause notifyInsetsChanged.
             clearInvocations(mTestHost);
             InsetsState newState = new InsetsState(localState, true /* copySources */);
-            newState.getSource(ITYPE_STATUS_BAR).getFrame().bottom++;
+            newState.peekSource(ID_STATUS_BAR).getFrame().bottom++;
             mController.onStateChanged(newState);
             verify(mTestHost, times(1)).notifyInsetsChanged();
 
             // Changing status bar visibility should cause notifyInsetsChanged.
             clearInvocations(mTestHost);
             newState = new InsetsState(localState, true /* copySources */);
-            newState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+            newState.peekSource(ID_STATUS_BAR).setVisible(false);
             mController.onStateChanged(newState);
             verify(mTestHost, times(1)).notifyInsetsChanged();
 
             // Changing invisible IME frame should not cause notifyInsetsChanged.
             clearInvocations(mTestHost);
             newState = new InsetsState(localState, true /* copySources */);
-            newState.getSource(ITYPE_IME).getFrame().top--;
+            newState.peekSource(ID_IME).getFrame().top--;
             mController.onStateChanged(newState);
             verify(mTestHost, never()).notifyInsetsChanged();
 
             // Changing IME visibility should cause notifyInsetsChanged.
             clearInvocations(mTestHost);
             newState = new InsetsState(localState, true /* copySources */);
-            newState.getSource(ITYPE_IME).setVisible(true);
+            newState.peekSource(ID_IME).setVisible(true);
             mController.onStateChanged(newState);
             verify(mTestHost, times(1)).notifyInsetsChanged();
         });
@@ -947,9 +942,9 @@
     }
 
     private InsetsSourceControl[] prepareControls() {
-        final InsetsSourceControl navBar = createControl(ITYPE_NAVIGATION_BAR, navigationBars());
-        final InsetsSourceControl statusBar = createControl(ITYPE_STATUS_BAR, statusBars());
-        final InsetsSourceControl ime = createControl(ITYPE_IME, ime());
+        final InsetsSourceControl navBar = createControl(ID_NAVIGATION_BAR, navigationBars());
+        final InsetsSourceControl statusBar = createControl(ID_STATUS_BAR, statusBars());
+        final InsetsSourceControl ime = createControl(ID_IME, ime());
 
         InsetsSourceControl[] controls = new InsetsSourceControl[3];
         controls[0] = navBar;
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index 0486e3c..988e690 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -18,9 +18,8 @@
 
 import static android.view.InsetsController.ANIMATION_TYPE_NONE;
 import static android.view.InsetsController.ANIMATION_TYPE_USER;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
-import static android.view.InsetsState.ITYPE_IME;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.statusBars;
 
@@ -69,6 +68,9 @@
 @RunWith(AndroidJUnit4.class)
 public class InsetsSourceConsumerTest {
 
+    private static final int ID_STATUS_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, statusBars());
+
     private InsetsSourceConsumer mConsumer;
 
     private SurfaceSession mSession = new SurfaceSession();
@@ -97,11 +99,11 @@
                 // activity isn't running, lets ignore BadTokenException.
             }
             mState = new InsetsState();
-            mSpyInsetsSource = Mockito.spy(new InsetsSource(ITYPE_STATUS_BAR, statusBars()));
+            mSpyInsetsSource = Mockito.spy(new InsetsSource(ID_STATUS_BAR, statusBars()));
             mState.addSource(mSpyInsetsSource);
 
             mController = new InsetsController(new ViewRootInsetsControllerHost(mViewRoot));
-            mConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, statusBars(), mState,
+            mConsumer = new InsetsSourceConsumer(ID_STATUS_BAR, statusBars(), mState,
                     () -> mMockTransaction, mController) {
                 @Override
                 public void removeSurface() {
@@ -113,7 +115,7 @@
         instrumentation.waitForIdleSync();
 
         mConsumer.setControl(
-                new InsetsSourceControl(ITYPE_STATUS_BAR, statusBars(), mLeash,
+                new InsetsSourceControl(ID_STATUS_BAR, statusBars(), mLeash,
                         true /* initialVisible */, new Point(), Insets.NONE),
                 new int[1], new int[1]);
     }
@@ -147,25 +149,25 @@
         InsetsController controller = new InsetsController(new ViewRootInsetsControllerHost(
                 mViewRoot));
         InsetsSourceConsumer consumer = new InsetsSourceConsumer(
-                ITYPE_IME, ime(), state, null, controller);
+                ID_IME, ime(), state, null, controller);
 
-        InsetsSource source = new InsetsSource(ITYPE_IME, ime());
+        InsetsSource source = new InsetsSource(ID_IME, ime());
         source.setFrame(0, 1, 2, 3);
         consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_NONE);
 
         // While we're animating, updates are delayed
         source.setFrame(4, 5, 6, 7);
         consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
-        assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ITYPE_IME).getFrame());
+        assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ID_IME).getFrame());
 
         // Finish the animation, now the pending frame should be applied
         assertTrue(consumer.onAnimationStateChanged(false /* running */));
-        assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
+        assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ID_IME).getFrame());
 
         // Animating again, updates are delayed
         source.setFrame(8, 9, 10, 11);
         consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
-        assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
+        assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ID_IME).getFrame());
 
         // Updating with the current frame triggers a different code path, verify this clears
         // the pending 8, 9, 10, 11 frame:
@@ -173,7 +175,7 @@
         consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER);
 
         assertFalse(consumer.onAnimationStateChanged(false /* running */));
-        assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
+        assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ID_IME).getFrame());
     }
 
     @Test
@@ -185,7 +187,7 @@
             verifyZeroInteractions(mMockTransaction);
             int[] hideTypes = new int[1];
             mConsumer.setControl(
-                    new InsetsSourceControl(ITYPE_STATUS_BAR, statusBars(), mLeash,
+                    new InsetsSourceControl(ID_STATUS_BAR, statusBars(), mLeash,
                             true /* initialVisible */, new Point(), Insets.NONE),
                     new int[1], hideTypes);
             assertEquals(statusBars(), hideTypes[0]);
@@ -203,7 +205,7 @@
             mRemoveSurfaceCalled = false;
             int[] hideTypes = new int[1];
             mConsumer.setControl(
-                    new InsetsSourceControl(ITYPE_STATUS_BAR, statusBars(), mLeash,
+                    new InsetsSourceControl(ID_STATUS_BAR, statusBars(), mLeash,
                             false /* initialVisible */, new Point(), Insets.NONE),
                     new int[1], hideTypes);
             assertTrue(mRemoveSurfaceCalled);
@@ -219,7 +221,7 @@
             ViewRootInsetsControllerHost host = new ViewRootInsetsControllerHost(mViewRoot);
             InsetsController insetsController = new InsetsController(host, (controller, source) -> {
                 if (source.getType() == ime()) {
-                    return new InsetsSourceConsumer(ITYPE_IME, ime(), state,
+                    return new InsetsSourceConsumer(ID_IME, ime(), state,
                             () -> mMockTransaction, controller) {
                         @Override
                         public int requestShow(boolean fromController,
@@ -231,11 +233,11 @@
                 return new InsetsSourceConsumer(source.getId(), source.getType(),
                         controller.getState(), Transaction::new, controller);
             }, host.getHandler());
-            InsetsSource imeSource = new InsetsSource(ITYPE_IME, ime());
+            InsetsSource imeSource = new InsetsSource(ID_IME, ime());
             InsetsSourceConsumer imeConsumer = insetsController.getSourceConsumer(imeSource);
 
             // Initial IME insets source control with its leash.
-            imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, ime(), mLeash,
+            imeConsumer.setControl(new InsetsSourceControl(ID_IME, ime(), mLeash,
                     false /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]);
             reset(mMockTransaction);
 
@@ -244,7 +246,7 @@
             insetsController.controlWindowInsetsAnimation(ime(), 0L,
                     null /* interpolator */, null /* cancellationSignal */, null /* listener */);
             assertEquals(ANIMATION_TYPE_USER, insetsController.getAnimationType(ime()));
-            imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, ime(), mLeash,
+            imeConsumer.setControl(new InsetsSourceControl(ID_IME, ime(), mLeash,
                     true /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]);
             verify(mMockTransaction, never()).show(mLeash);
         });
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index e01440c..1db6587 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -16,15 +16,19 @@
 
 package android.view;
 
-import static android.view.WindowInsets.Type.captionBar;
+import static android.view.WindowInsets.Type.FIRST;
+import static android.view.WindowInsets.Type.LAST;
+import static android.view.WindowInsets.Type.SIZE;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
+import android.util.SparseArray;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -47,13 +51,11 @@
 
     private final InsetsSource mSource = new InsetsSource(0 /* id */, navigationBars());
     private final InsetsSource mImeSource = new InsetsSource(1 /* id */, ime());
-    private final InsetsSource mCaptionSource = new InsetsSource(2 /* id */, captionBar());
 
     @Before
     public void setUp() {
         mSource.setVisible(true);
         mImeSource.setVisible(true);
-        mCaptionSource.setVisible(true);
     }
 
     @Test
@@ -105,17 +107,6 @@
     }
 
     @Test
-    public void testCalculateInsets_caption_resizing() {
-        mCaptionSource.setFrame(new Rect(0, 0, 100, 100));
-        Insets insets = mCaptionSource.calculateInsets(new Rect(0, 0, 200, 200), false);
-        assertEquals(Insets.of(0, 100, 0, 0), insets);
-        insets = mCaptionSource.calculateInsets(new Rect(0, 0, 50, 200), false);
-        assertEquals(Insets.of(0, 100, 0, 0), insets);
-        insets = mCaptionSource.calculateInsets(new Rect(100, 100, 200, 500), false);
-        assertEquals(Insets.of(0, 100, 0, 0), insets);
-    }
-
-    @Test
     public void testCalculateInsets_invisible() {
         mSource.setFrame(new Rect(0, 0, 500, 100));
         mSource.setVisible(false);
@@ -206,6 +197,21 @@
         assertEquals(Insets.of(0, 0, 0, 0), insets);
     }
 
+    @Test
+    public void testCreateId() {
+        final int numSourcePerType = 2048;
+        final int numTotalSources = SIZE * numSourcePerType;
+        final SparseArray<InsetsSource> sources = new SparseArray<>(numTotalSources);
+        final Object owner = new Object();
+        for (int index = 0; index < numSourcePerType; index++) {
+            for (int type = FIRST; type <= LAST; type = type << 1) {
+                final int id = InsetsSource.createId(owner, index, type);
+                assertNull("Must not create the same ID.", sources.get(id));
+                sources.append(id, new InsetsSource(id, type));
+            }
+        }
+        assertEquals(numTotalSources, sources.size());
+    }
 
     // Parcel and equals already tested via InsetsStateTest
 }
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 6a96f28..b035c23 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -18,24 +18,20 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.InsetsState.ISIDE_BOTTOM;
 import static android.view.InsetsState.ISIDE_TOP;
-import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
-import static android.view.InsetsState.ITYPE_CAPTION_BAR;
-import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_IME;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT;
 import static android.view.RoundedCorner.POSITION_BOTTOM_RIGHT;
 import static android.view.RoundedCorner.POSITION_TOP_LEFT;
 import static android.view.RoundedCorner.POSITION_TOP_RIGHT;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+import static android.view.WindowInsets.Type.captionBar;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
 import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowInsets.Type.systemBars;
+import static android.view.WindowInsets.Type.systemGestures;
 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
@@ -47,8 +43,10 @@
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Insets;
@@ -76,33 +74,50 @@
 @RunWith(AndroidJUnit4.class)
 public class InsetsStateTest {
 
-    private InsetsState mState = new InsetsState();
-    private InsetsState mState2 = new InsetsState();
+    private static final int ID_STATUS_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, statusBars());
+    private static final int ID_NAVIGATION_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, navigationBars());
+    private static final int ID_CAPTION_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, captionBar());
+    private static final int ID_CLIMATE_BAR = InsetsSource.createId(
+            null /* owner */, 1 /* index */, statusBars());
+    private static final int ID_EXTRA_NAVIGATION_BAR = InsetsSource.createId(
+            null /* owner */, 1 /* index */, navigationBars());
+    private static final int ID_BOTTOM_GESTURES = InsetsSource.createId(
+            null /* owner */, 0 /* index */, systemGestures());
+
+    private final InsetsState mState = new InsetsState();
+    private final InsetsState mState2 = new InsetsState();
 
     @Test
     public void testCalculateInsets() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
-        mState.getSource(ITYPE_IME).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 200, 100, 300))
+                .setVisible(true);
         SparseIntArray typeSideMap = new SparseIntArray();
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
                 typeSideMap);
         assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
         assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
-        assertEquals(ISIDE_TOP, typeSideMap.get(ITYPE_STATUS_BAR));
-        assertEquals(ISIDE_BOTTOM, typeSideMap.get(ITYPE_IME));
+        assertEquals(ISIDE_TOP, typeSideMap.get(ID_STATUS_BAR));
+        assertEquals(ISIDE_BOTTOM, typeSideMap.get(ID_IME));
         assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars()));
         assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(ime()));
     }
 
     @Test
     public void testCalculateInsets_imeAndNav() {
-        mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
-        mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 100, 100, 300));
-        mState.getSource(ITYPE_IME).setVisible(true);
+        mState.getOrCreateSource(ID_NAVIGATION_BAR, navigationBars())
+                .setFrame(new Rect(0, 200, 100, 300))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 100, 100, 300))
+                .setVisible(true);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
                 null);
@@ -116,10 +131,12 @@
 
     @Test
     public void testCalculateInsets_navRightStatusTop() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
-        mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_NAVIGATION_BAR, navigationBars())
+                .setFrame(new Rect(80, 0, 100, 300))
+                .setVisible(true);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
         assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
@@ -129,14 +146,14 @@
 
     @Test
     public void testCalculateInsets_extraNavRightClimateTop() throws Exception {
-        mState.getSource(ITYPE_CLIMATE_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_CLIMATE_BAR).setVisible(true);
-        mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
-        mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setVisible(true);
+        mState.getOrCreateSource(ID_CLIMATE_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_EXTRA_NAVIGATION_BAR, navigationBars())
+                .setFrame(new Rect(80, 0, 100, 300))
+                .setVisible(true);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
-        // ITYPE_CLIMATE_BAR is a type of status bar and ITYPE_EXTRA_NAVIGATION_BAR is a type
-        // of navigation bar.
         assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
         assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
         assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
@@ -144,10 +161,12 @@
 
     @Test
     public void testCalculateInsets_imeIgnoredWithoutAdjustResize() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
-        mState.getSource(ITYPE_IME).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 200, 100, 300))
+                .setVisible(true);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, SOFT_INPUT_ADJUST_NOTHING, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
                 null);
@@ -158,10 +177,12 @@
 
     @Test
     public void testCalculateInsets_systemUiFlagLayoutStable() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
-        mState.getSource(ITYPE_IME).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(false);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 200, 100, 300))
+                .setVisible(true);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, SOFT_INPUT_ADJUST_NOTHING, 0, SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION,
                 WINDOWING_MODE_UNDEFINED, null);
@@ -174,8 +195,9 @@
 
     @Test
     public void testCalculateInsets_systemUiFlagLayoutStable_windowFlagFullscreen() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(false);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN, SYSTEM_UI_FLAG_LAYOUT_STABLE,
                 TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
@@ -188,8 +210,9 @@
 
     @Test
     public void testCalculateInsets_flagLayoutNoLimits() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS,
                 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
@@ -211,10 +234,12 @@
 
     @Test
     public void testCalculateInsets_captionStatusBarOverlap() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
-        mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_CAPTION_BAR, captionBar())
+                .setFrame(new Rect(0, 0, 100, 300))
+                .setVisible(true);
 
         Insets visibleInsets = mState.calculateVisibleInsets(
                 new Rect(0, 0, 100, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
@@ -223,22 +248,13 @@
     }
 
     @Test
-    public void testCalculateInsets_captionBarOffset() {
-        mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
-        mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
-
-        Insets visibleInsets = mState.calculateVisibleInsets(
-                new Rect(0, 0, 150, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
-                SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
-        assertEquals(Insets.of(0, 300, 0, 0), visibleInsets);
-    }
-
-    @Test
     public void testCalculateInsets_extraNavRightStatusTop() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
-        mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_EXTRA_NAVIGATION_BAR, navigationBars())
+                .setFrame(new Rect(80, 0, 100, 300))
+                .setVisible(true);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
         assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
@@ -248,10 +264,12 @@
 
     @Test
     public void testCalculateInsets_navigationRightClimateTop() {
-        mState.getSource(ITYPE_CLIMATE_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_CLIMATE_BAR).setVisible(true);
-        mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
-        mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
+        mState.getOrCreateSource(ID_CLIMATE_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_NAVIGATION_BAR, navigationBars())
+                .setFrame(new Rect(80, 0, 100, 300))
+                .setVisible(true);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
                 false, 0, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
         assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
@@ -261,11 +279,13 @@
 
     @Test
     public void testStripForDispatch() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
-        mState.getSource(ITYPE_IME).setVisible(true);
-        mState.removeSource(ITYPE_IME);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 200, 100, 300))
+                .setVisible(true);
+        mState.removeSource(ID_IME);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false,
                 SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null);
         assertEquals(0, insets.getSystemWindowInsetBottom());
@@ -273,32 +293,42 @@
 
     @Test
     public void testEquals_differentRect() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState2.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 10, 10));
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100));
+        mState2.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 10, 10));
         assertNotEqualsAndHashCode();
     }
 
     @Test
     public void testEquals_differentSource() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState2.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100));
+        mState2.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 0, 100, 100));
         assertNotEqualsAndHashCode();
     }
 
     @Test
     public void testEquals_sameButDifferentInsertOrder() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100));
-        mState2.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100));
-        mState2.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100));
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 0, 100, 100));
+        mState2.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 0, 100, 100));
+        mState2.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100));
         assertEqualsAndHashCode();
     }
 
     @Test
     public void testEquals_visibility() {
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_IME).setVisible(true);
-        mState2.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState2.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 0, 100, 100));
         assertNotEqualsAndHashCode();
     }
 
@@ -363,19 +393,23 @@
 
     @Test
     public void testEquals_excludeInvisibleIme() {
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_IME).setVisible(false);
-        mState2.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 200));
-        mState2.getSource(ITYPE_IME).setVisible(false);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(false);
+        mState2.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 0, 100, 200))
+                .setVisible(false);
         assertTrue(mState2.equals(mState, true, true /* excludeInvisibleIme */));
     }
 
     @Test
     public void testParcelUnparcel() {
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_IME).setVisibleFrame(new Rect(0, 0, 50, 10));
-        mState.getSource(ITYPE_IME).setVisible(true);
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisibleFrame(new Rect(0, 0, 50, 10))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100));
         Parcel p = Parcel.obtain();
         mState.writeToParcel(p, 0 /* flags */);
         p.setDataPosition(0);
@@ -386,35 +420,31 @@
 
     @Test
     public void testCopy() {
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_IME).setVisibleFrame(new Rect(0, 0, 50, 10));
-        mState.getSource(ITYPE_IME).setVisible(true);
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState2.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(0, 0, 100, 100));
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisibleFrame(new Rect(0, 0, 50, 10))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100));
+        mState2.getOrCreateSource(ID_NAVIGATION_BAR, navigationBars())
+                .setFrame(new Rect(0, 0, 100, 100));
         mState2.set(mState, true);
         assertEquals(mState, mState2);
     }
 
     @Test
-    public void testGetDefaultVisibility() {
-        assertTrue(InsetsState.getDefaultVisibility(ITYPE_STATUS_BAR));
-        assertTrue(InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR));
-        assertTrue(InsetsState.getDefaultVisibility(ITYPE_CLIMATE_BAR));
-        assertTrue(InsetsState.getDefaultVisibility(ITYPE_EXTRA_NAVIGATION_BAR));
-        assertTrue(InsetsState.getDefaultVisibility(ITYPE_CAPTION_BAR));
-        assertFalse(InsetsState.getDefaultVisibility(ITYPE_IME));
-    }
-
-    @Test
     public void testCalculateVisibleInsets() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
-        mState.getSource(ITYPE_IME).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 200, 100, 300))
+                .setVisible(true);
 
         // Make sure bottom gestures are ignored
-        mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300));
-        mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true);
+        mState.getOrCreateSource(ID_BOTTOM_GESTURES, systemGestures())
+                .setFrame(new Rect(0, 100, 100, 300))
+                .setVisible(true);
         Insets visibleInsets = mState.calculateVisibleInsets(
                 new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
                 SOFT_INPUT_ADJUST_PAN, 0 /* windowFlags */);
@@ -423,14 +453,17 @@
 
     @Test
     public void testCalculateVisibleInsets_adjustNothing() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
-        mState.getSource(ITYPE_IME).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 200, 100, 300))
+                .setVisible(true);
 
         // Make sure bottom gestures are ignored
-        mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300));
-        mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true);
+        mState.getOrCreateSource(ID_BOTTOM_GESTURES, systemGestures())
+                .setFrame(new Rect(0, 100, 100, 300))
+                .setVisible(true);
         Insets visibleInsets = mState.calculateVisibleInsets(
                 new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
                 SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
@@ -439,14 +472,17 @@
 
     @Test
     public void testCalculateVisibleInsets_layoutNoLimits() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300));
-        mState.getSource(ITYPE_IME).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 100, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 200, 100, 300))
+                .setVisible(true);
 
         // Make sure bottom gestures are ignored
-        mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300));
-        mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true);
+        mState.getOrCreateSource(ID_BOTTOM_GESTURES, systemGestures())
+                .setFrame(new Rect(0, 100, 100, 300))
+                .setVisible(true);
         Insets visibleInsets = mState.calculateVisibleInsets(
                 new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
                 SOFT_INPUT_ADJUST_PAN, FLAG_LAYOUT_NO_LIMITS);
@@ -455,12 +491,15 @@
 
     @Test
     public void testCalculateUncontrollableInsets() {
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 200, 100));
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 200, 300));
-        mState.getSource(ITYPE_IME).setVisible(true);
-        mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(100, 0, 200, 300));
-        mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
+                .setFrame(new Rect(0, 0, 200, 100))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setFrame(new Rect(0, 200, 200, 300))
+                .setVisible(true);
+        mState.getOrCreateSource(ID_NAVIGATION_BAR, navigationBars())
+                .setFrame(new Rect(100, 0, 200, 300))
+                .setVisible(true);
 
         mState.setDisplayFrame(new Rect(0, 0, 200, 300));
         assertEquals(0,
@@ -539,4 +578,77 @@
         assertNotEquals(mState, mState2);
         assertNotEquals(mState.hashCode(), mState2.hashCode());
     }
+
+    @Test
+    public void testTraverse() {
+        // The type doesn't matter in this test.
+        final int type = statusBars();
+
+        final InsetsState insetsState1 = new InsetsState();
+        insetsState1.getOrCreateSource(2000, type);
+        insetsState1.getOrCreateSource(1000, type);
+        insetsState1.getOrCreateSource(3000, type);
+
+        final InsetsState insetsState2 = new InsetsState();
+        insetsState2.getOrCreateSource(3000, type);
+        insetsState2.getOrCreateSource(4000, type);
+        insetsState2.getOrCreateSource(2000, type);
+        insetsState2.getOrCreateSource(5000, type);
+
+        final int[] onStartCalled = {0};
+        final int[] onIdMatchCalled = {0};
+        final int[] onIdNotFoundInState1Called = {0};
+        final int[] onIdNotFoundInState2Called = {0};
+        final int[] onFinishCalled = {0};
+
+        InsetsState.traverse(insetsState1, insetsState2, new InsetsState.OnTraverseCallbacks() {
+            @Override
+            public void onStart(InsetsState state1, InsetsState state2) {
+                assertSame("state1 must be the same as insetsState1", state1, insetsState1);
+                assertSame("state2 must be the same as insetsState2", state2, insetsState2);
+                onStartCalled[0]++;
+            }
+
+            @Override
+            public void onIdMatch(InsetsSource source1, InsetsSource source2) {
+                assertNotNull("source1 must not be null.", source1);
+                assertNotNull("source2 must not be null.", source2);
+                assertEquals("Source IDs must match.", source1.getId(), source2.getId());
+                onIdMatchCalled[0]++;
+            }
+
+            @Override
+            public void onIdNotFoundInState1(int index2, InsetsSource source2) {
+                assertNotNull("source2 must not be null.", source2);
+                assertSame(source2 + " must be placed at " + index2 + " of insetsState2",
+                        source2, insetsState2.sourceAt(index2));
+                assertNull("state1 must not have " + source2,
+                        insetsState1.peekSource(source2.getId()));
+                onIdNotFoundInState1Called[0]++;
+            }
+
+            @Override
+            public void onIdNotFoundInState2(int index1, InsetsSource source1) {
+                assertNotNull("source1 must not be null.", source1);
+                assertSame(source1 + " must be placed at " + index1 + " of insetsState1",
+                        source1, insetsState1.sourceAt(index1));
+                assertNull("state2 must not have " + source1,
+                        insetsState2.peekSource(source1.getId()));
+                onIdNotFoundInState2Called[0]++;
+            }
+
+            @Override
+            public void onFinish(InsetsState state1, InsetsState state2) {
+                assertSame("state1 must be the same as insetsState1", state1, insetsState1);
+                assertSame("state2 must be the same as insetsState2", state2, insetsState2);
+                onFinishCalled[0]++;
+            }
+        });
+
+        assertEquals(1, onStartCalled[0]);
+        assertEquals(2, onIdMatchCalled[0]); // 2000 and 3000.
+        assertEquals(2, onIdNotFoundInState1Called[0]); // 4000 and 5000.
+        assertEquals(1, onIdNotFoundInState2Called[0]); // 1000.
+        assertEquals(1, onFinishCalled[0]);
+    }
 }
diff --git a/core/tests/coretests/src/android/view/SurfaceControlViewHostInsetsTest.java b/core/tests/coretests/src/android/view/SurfaceControlViewHostInsetsTest.java
index 4731e81..a65830f 100644
--- a/core/tests/coretests/src/android/view/SurfaceControlViewHostInsetsTest.java
+++ b/core/tests/coretests/src/android/view/SurfaceControlViewHostInsetsTest.java
@@ -16,35 +16,26 @@
 
 package android.view;
 
+import static android.view.WindowInsets.Type.statusBars;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-
 import android.app.Instrumentation;
 import android.content.Context;
 import android.graphics.Insets;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Binder;
 import android.platform.test.annotations.Presubmit;
-import android.view.InsetsState.InternalInsetsType;
-import android.view.SurfaceControlViewHost;
-import android.view.View;
-import android.view.WindowInsets;
-import android.view.WindowInsets.Type;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class SurfaceControlViewHostInsetsTest {
@@ -79,8 +70,10 @@
     private InsetsState statusBarState(boolean visible) {
         final InsetsState insetsState = new InsetsState();
         insetsState.setDisplayFrame(new Rect(0, 0, 1000, 1000));
-        insetsState.getSource(ITYPE_STATUS_BAR).setVisible(visible);
-        insetsState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 10));
+        insetsState.getOrCreateSource(
+                InsetsSource.createId(null /* owner */, 0 /* index */, statusBars()), statusBars())
+                        .setVisible(visible)
+                        .setFrame(new Rect(0, 0, 100, 10));
         return insetsState;
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java b/core/tests/coretests/src/android/view/WindowLayoutTests.java
similarity index 83%
rename from services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
rename to core/tests/coretests/src/android/view/WindowLayoutTests.java
index 56c59cc..5cac98d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowLayoutTests.java
+++ b/core/tests/coretests/src/android/view/WindowLayoutTests.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.server.wm;
+package android.view;
 
-import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
-import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT;
+import static android.view.InsetsSource.ID_IME;
+import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowLayout.UNSPECIFIED_LENGTH;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
@@ -38,12 +37,6 @@
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.view.DisplayCutout;
-import android.view.Gravity;
-import android.view.InsetsState;
-import android.view.WindowInsets;
-import android.view.WindowLayout;
-import android.view.WindowManager;
 import android.window.ClientWindowFrames;
 
 import androidx.test.filters.SmallTest;
@@ -70,6 +63,11 @@
             new Rect(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT);
     private static final Insets WATERFALL_INSETS = Insets.of(6, 0, 12, 0);
 
+    private static final int ID_STATUS_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, statusBars());
+    private static final int ID_NAVIGATION_BAR = InsetsSource.createId(
+            null /* owner */, 0 /* index */, navigationBars());
+
     private final WindowLayout mWindowLayout = new WindowLayout();
     private final ClientWindowFrames mFrames = new ClientWindowFrames();
 
@@ -88,9 +86,9 @@
         mAttrs = new WindowManager.LayoutParams();
         mState = new InsetsState();
         mState.setDisplayFrame(new Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
-        mState.getSource(ITYPE_STATUS_BAR).setFrame(
+        mState.getOrCreateSource(ID_STATUS_BAR, statusBars()).setFrame(
                 0, 0, DISPLAY_WIDTH, STATUS_BAR_HEIGHT);
-        mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(
+        mState.getOrCreateSource(ID_NAVIGATION_BAR, navigationBars()).setFrame(
                 0, DISPLAY_HEIGHT - NAVIGATION_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT);
         mState.getDisplayCutoutSafe(mDisplayCutoutSafe);
         mWindowBounds = new Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
@@ -117,14 +115,14 @@
                 new Rect(),
                 WATERFALL_INSETS));
         mState.getDisplayCutoutSafe(mDisplayCutoutSafe);
-        mState.getSource(ITYPE_LEFT_DISPLAY_CUTOUT).setFrame(
-                0, 0, mDisplayCutoutSafe.left, DISPLAY_HEIGHT);
-        mState.getSource(ITYPE_TOP_DISPLAY_CUTOUT).setFrame(
-                0, 0, DISPLAY_WIDTH, mDisplayCutoutSafe.top);
-        mState.getSource(ITYPE_RIGHT_DISPLAY_CUTOUT).setFrame(
-                mDisplayCutoutSafe.right, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
-        mState.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(
-                0, mDisplayCutoutSafe.bottom, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+        mState.getOrCreateSource(InsetsSource.createId(null, 0, displayCutout()), displayCutout())
+                .setFrame(0, 0, mDisplayCutoutSafe.left, DISPLAY_HEIGHT);
+        mState.getOrCreateSource(InsetsSource.createId(null, 1, displayCutout()), displayCutout())
+                .setFrame(0, 0, DISPLAY_WIDTH, mDisplayCutoutSafe.top);
+        mState.getOrCreateSource(InsetsSource.createId(null, 2, displayCutout()), displayCutout())
+                .setFrame(mDisplayCutoutSafe.right, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+        mState.getOrCreateSource(InsetsSource.createId(null, 3, displayCutout()), displayCutout())
+                .setFrame(0, mDisplayCutoutSafe.bottom, DISPLAY_WIDTH, DISPLAY_HEIGHT);
     }
 
     private static void assertInsetByTopBottom(int top, int bottom, Rect actual) {
@@ -266,8 +264,8 @@
 
     @Test
     public void fitInvisibleInsets() {
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
+        mState.setSourceVisible(ID_STATUS_BAR, false);
+        mState.setSourceVisible(ID_NAVIGATION_BAR, false);
         computeFrames();
 
         assertInsetByTopBottom(0, 0, mFrames.displayFrame);
@@ -277,8 +275,8 @@
 
     @Test
     public void fitInvisibleInsetsIgnoringVisibility() {
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
+        mState.setSourceVisible(ID_STATUS_BAR, false);
+        mState.setSourceVisible(ID_NAVIGATION_BAR, false);
         mAttrs.setFitInsetsIgnoringVisibility(true);
         computeFrames();
 
@@ -289,9 +287,9 @@
 
     @Test
     public void insetParentFrameByIme() {
-        mState.getSource(InsetsState.ITYPE_IME).setVisible(true);
-        mState.getSource(InsetsState.ITYPE_IME).setFrame(
-                0, DISPLAY_HEIGHT - IME_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+        mState.getOrCreateSource(ID_IME, ime())
+                .setVisible(true)
+                .setFrame(0, DISPLAY_HEIGHT - IME_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT);
         mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
         computeFrames();
 
@@ -322,11 +320,11 @@
         mAttrs.setFitInsetsTypes(0);
         computeFrames();
 
-        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
+        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                 mFrames.displayFrame);
-        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
+        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                 mFrames.parentFrame);
-        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
+        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                 mFrames.frame);
     }
 
@@ -363,17 +361,17 @@
     @Test
     public void layoutInDisplayCutoutModeDefaultWithInvisibleSystemBars() {
         addDisplayCutout();
-        mState.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
+        mState.setSourceVisible(ID_STATUS_BAR, false);
+        mState.setSourceVisible(ID_NAVIGATION_BAR, false);
         mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
         mAttrs.setFitInsetsTypes(0);
         computeFrames();
 
-        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
+        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                 mFrames.displayFrame);
-        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
+        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                 mFrames.parentFrame);
-        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
+        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                 mFrames.frame);
     }
 
@@ -396,11 +394,11 @@
         mAttrs.setFitInsetsTypes(0);
         computeFrames();
 
-        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
+        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                 mFrames.displayFrame);
-        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
+        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                 mFrames.parentFrame);
-        assertInsetBy(WATERFALL_INSETS.left, STATUS_BAR_HEIGHT, WATERFALL_INSETS.right, 0,
+        assertInsetBy(WATERFALL_INSETS.left, DISPLAY_CUTOUT_HEIGHT, WATERFALL_INSETS.right, 0,
                 mFrames.frame);
     }
 
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java
index 5469843..7d2d6e0 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java
@@ -53,7 +53,7 @@
 
     @SuppressWarnings("Since15")
     public Function<PackageManager, PackageManager> createPackageManager;
-    public Function<TargetInfo, Boolean> onSafelyStartCallback;
+    public Function<TargetInfo, Boolean> onSafelyStartInternalCallback;
     public Function<ChooserListAdapter, Void> onQueryDirectShareTargets;
     public BiFunction<
             IChooserWrapper, ChooserListAdapter, Pair<Integer, ChooserActivity.ServiceResultInfo[]>>
@@ -82,7 +82,7 @@
     public PackageManager packageManager;
 
     public void reset() {
-        onSafelyStartCallback = null;
+        onSafelyStartInternalCallback = null;
         onQueryDirectShareTargets = null;
         directShareTargets = null;
         isVoiceInteraction = null;
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index c06df94..9f398ec 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -446,7 +446,7 @@
         onView(withIdFromRuntimeResource("profile_button")).check(doesNotExist());
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -501,7 +501,7 @@
         assertThat(activity.getAdapter().getCount(), is(6));
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -541,7 +541,7 @@
         verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1))
                 .topK(any(List.class), anyInt());
         assertThat(activity.getIsSelected(), is(false));
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             return true;
         };
         ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
@@ -592,7 +592,7 @@
     @Test
     public void autoLaunchSingleResult() throws InterruptedException {
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -638,7 +638,7 @@
         assertThat(activity.getAdapter().getCount(), is(1));
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -681,7 +681,7 @@
         assertThat(activity.getAdapter().getCount(), is(2));
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -719,7 +719,7 @@
         assertThat(activity.getAdapter().getCount(), is(2));
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -1949,7 +1949,7 @@
         Intent sendIntent = createSendTextIntent();
         sendIntent.setType(TEST_MIME_TYPE);
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -2127,7 +2127,7 @@
         onView(withIdFromRuntimeResource("profile_button")).check(doesNotExist());
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -2513,7 +2513,7 @@
         Intent sendIntent = createSendTextIntent();
         sendIntent.setType(TEST_MIME_TYPE);
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -2543,7 +2543,7 @@
         Intent sendIntent = createSendTextIntent();
         sendIntent.setType(TEST_MIME_TYPE);
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -2569,7 +2569,7 @@
         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
         Intent sendIntent = createSendTextIntent();
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
@@ -2597,7 +2597,7 @@
         Intent chooserIntent = createChooserIntent(createSendTextIntent(),
                 new Intent[] {new Intent("action.fake")});
         ResolveInfo[] chosen = new ResolveInfo[1];
-        ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> {
+        ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> {
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt b/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt
index 8218b98..2eeaf53 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt
@@ -22,6 +22,7 @@
 import android.content.pm.PackageManager
 import android.content.pm.ResolveInfo
 import android.os.Bundle
+import android.os.UserHandle
 import android.service.chooser.ChooserTarget
 import android.view.View
 import android.widget.FrameLayout
@@ -73,7 +74,8 @@
             selectableTargetInfoCommunicator,
             packageManager,
             chooserActivityLogger,
-            taskProvider
+            null,
+            taskProvider,
         )
 
     @Test
@@ -160,6 +162,7 @@
     selectableTargetInfoCommunicator: SelectableTargetInfoCommunicator?,
     packageManager: PackageManager?,
     chooserActivityLogger: ChooserActivityLogger?,
+    initialIntentsUserHandle: UserHandle?,
     private val taskProvider: (SelectableTargetInfo?) -> LoadDirectShareIconTask
 ) : ChooserListAdapter(
     context,
@@ -171,7 +174,8 @@
     chooserListCommunicator,
     selectableTargetInfoCommunicator,
     packageManager,
-    chooserActivityLogger
+    chooserActivityLogger,
+    initialIntentsUserHandle,
 ) {
     override fun createLoadDirectShareIconTask(
         info: SelectableTargetInfo?
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index d7a8b3a..dcea912 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -64,14 +64,14 @@
     @Override
     public ChooserListAdapter createChooserListAdapter(Context context, List<Intent> payloadIntents,
             Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed,
-            ResolverListController resolverListController) {
+            UserHandle userHandle) {
         PackageManager packageManager =
                 sOverrides.packageManager == null ? context.getPackageManager()
                         : sOverrides.packageManager;
         return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
-                filterLastUsed, resolverListController,
+                filterLastUsed, createListController(userHandle),
                 this, this, packageManager,
-                getChooserActivityLogger());
+                getChooserActivityLogger(), userHandle);
     }
 
     @Override
@@ -143,15 +143,14 @@
         return super.createQuietModeManager();
     }
 
-    // TODO: Remove this and override safelyStartActivityInternal() instead.
     @Override
-    public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user,
+    public void safelyStartActivityInternal(TargetInfo cti, UserHandle user,
             @Nullable Bundle options) {
-        if (sOverrides.onSafelyStartCallback != null &&
-                sOverrides.onSafelyStartCallback.apply(cti)) {
+        if (sOverrides.onSafelyStartInternalCallback != null
+                && sOverrides.onSafelyStartInternalCallback.apply(cti)) {
             return;
         }
-        super.safelyStartActivityAsUser(cti, user, options);
+        super.safelyStartActivityInternal(cti, user, options);
     }
 
     @Override
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index b82bc16..b6813ff 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -64,6 +64,8 @@
 import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
 import com.android.internal.widget.ResolverDrawerLayout;
 
+import com.google.android.collect.Lists;
+
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
@@ -110,8 +112,8 @@
         assertThat(activity.getAdapter().getCount(), is(2));
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
 
@@ -226,8 +228,8 @@
         assertThat(activity.getAdapter().getPlaceholderCount(), is(1));
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
 
@@ -258,8 +260,8 @@
         assertThat(activity.getAdapter().getCount(), is(1));
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
         // Make a stable copy of the components as the original list may be modified
@@ -298,8 +300,8 @@
         assertThat(activity.getAdapter().getCount(), is(2));
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
 
@@ -345,8 +347,8 @@
         assertThat(activity.getAdapter().getCount(), is(2));
 
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
 
@@ -531,8 +533,8 @@
         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
         Intent sendIntent = createSendImageIntent();
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
 
@@ -634,8 +636,8 @@
         setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
         Intent sendIntent = createSendImageIntent();
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
 
@@ -848,8 +850,8 @@
         Intent sendIntent = createSendImageIntent();
         sendIntent.setType("TestType");
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
         waitForIdle();
@@ -873,8 +875,8 @@
         Intent sendIntent = createSendImageIntent();
         sendIntent.setType("TestType");
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
         waitForIdle();
@@ -902,8 +904,8 @@
         Intent sendIntent = createSendImageIntent();
         sendIntent.setType("TestType");
         ResolveInfo[] chosen = new ResolveInfo[1];
-        sOverrides.onSafelyStartCallback = targetInfo -> {
-            chosen[0] = targetInfo.getResolveInfo();
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            chosen[0] = result.first.getResolveInfo();
             return true;
         };
 
@@ -1072,8 +1074,8 @@
         Intent sendIntent = createSendImageIntent();
         sendIntent.setType("TestType");
         final UserHandle[] selectedActivityUserHandle = new UserHandle[1];
-        sOverrides.onSafelyStartInternalCallback = userHandle -> {
-            selectedActivityUserHandle[0] = userHandle;
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            selectedActivityUserHandle[0] = result.second;
             return true;
         };
 
@@ -1109,8 +1111,8 @@
         Intent sendIntent = createSendImageIntent();
         sendIntent.setType("TestType");
         final UserHandle[] selectedActivityUserHandle = new UserHandle[1];
-        sOverrides.onSafelyStartInternalCallback = userHandle -> {
-            selectedActivityUserHandle[0] = userHandle;
+        sOverrides.onSafelyStartInternalCallback = result -> {
+            selectedActivityUserHandle[0] = result.second;
             return true;
         };
 
@@ -1129,6 +1131,31 @@
         assertThat(selectedActivityUserHandle[0], is(activity.getAdapter().getUserHandle()));
     }
 
+    @Test
+    public void testClonedProfilePresent_personalProfileResolverComparatorHasCorrectUsers()
+            throws Exception {
+        // enable cloneProfile
+        markCloneProfileUserAvailable();
+        List<ResolvedComponentInfo> resolvedComponentInfos =
+                createResolvedComponentsWithCloneProfileForTest(
+                        3,
+                        PERSONAL_USER_HANDLE,
+                        sOverrides.cloneProfileUserHandle);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+        Intent sendIntent = createSendImageIntent();
+
+        final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+        List<UserHandle> result = activity
+                .getResolverRankerServiceUserHandleList(PERSONAL_USER_HANDLE);
+
+        assertTrue(result.containsAll(Lists.newArrayList(PERSONAL_USER_HANDLE,
+                sOverrides.cloneProfileUserHandle)));
+    }
+
     private Intent createSendImageIntent() {
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
index 8f6f29d..e193de0 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
@@ -29,6 +29,7 @@
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.util.Pair;
 
 import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
 import com.android.internal.app.AbstractMultiProfilePagerAdapter.QuietModeManager;
@@ -53,7 +54,7 @@
             List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
             boolean filterLastUsed, UserHandle userHandle) {
         return new ResolverWrapperAdapter(context, payloadIntents, initialIntents, rList,
-                filterLastUsed, createListController(userHandle), this);
+                filterLastUsed, createListController(userHandle), this, userHandle);
     }
 
     @Override
@@ -95,22 +96,11 @@
         return super.isVoiceInteraction();
     }
 
-    // TODO: Remove this and override safelyStartActivityInternal() instead.
-    @Override
-    public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user,
-            @Nullable Bundle options) {
-        if (sOverrides.onSafelyStartCallback != null &&
-                sOverrides.onSafelyStartCallback.apply(cti)) {
-            return;
-        }
-        super.safelyStartActivityAsUser(cti, user, options);
-    }
-
     @Override
     public void safelyStartActivityInternal(TargetInfo cti, UserHandle user,
             @Nullable Bundle options) {
         if (sOverrides.onSafelyStartInternalCallback != null
-                && sOverrides.onSafelyStartInternalCallback.apply(user)) {
+                && sOverrides.onSafelyStartInternalCallback.apply(new Pair<>(cti, user))) {
             return;
         }
         super.safelyStartActivityInternal(cti, user, options);
@@ -166,6 +156,12 @@
         super.startActivityAsUser(intent, options, user);
     }
 
+    @Override
+    protected List<UserHandle> getResolverRankerServiceUserHandleListInternal(UserHandle
+            userHandle) {
+        return super.getResolverRankerServiceUserHandleListInternal(userHandle);
+    }
+
     /**
      * We cannot directly mock the activity created since instrumentation creates it.
      * <p>
@@ -174,8 +170,7 @@
     static class OverrideData {
         @SuppressWarnings("Since15")
         public Function<PackageManager, PackageManager> createPackageManager;
-        public Function<TargetInfo, Boolean> onSafelyStartCallback;
-        public Function<UserHandle, Boolean> onSafelyStartInternalCallback;
+        public Function<Pair<TargetInfo, UserHandle>, Boolean> onSafelyStartInternalCallback;
         public ResolverListController resolverListController;
         public ResolverListController workResolverListController;
         public Boolean isVoiceInteraction;
@@ -189,7 +184,6 @@
         public CrossProfileIntentsChecker mCrossProfileIntentsChecker;
 
         public void reset() {
-            onSafelyStartCallback = null;
             onSafelyStartInternalCallback = null;
             isVoiceInteraction = null;
             createPackageManager = null;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java
index 2861428..32bef75 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
 
 import androidx.test.espresso.idling.CountingIdlingResource;
 
@@ -36,9 +37,10 @@
             Intent[] initialIntents,
             List<ResolveInfo> rList, boolean filterLastUsed,
             ResolverListController resolverListController,
-            ResolverListCommunicator resolverListCommunicator) {
+            ResolverListCommunicator resolverListCommunicator,
+            UserHandle initialIntentsUserHandle) {
         super(context, payloadIntents, initialIntents, rList, filterLastUsed,
-                resolverListController, resolverListCommunicator, false);
+                resolverListController, resolverListCommunicator, false, initialIntentsUserHandle);
     }
 
     public CountingIdlingResource getLabelIdlingResource() {
diff --git a/core/tests/coretests/src/com/android/internal/config/sysui/OWNERS b/core/tests/coretests/src/com/android/internal/config/sysui/OWNERS
new file mode 100644
index 0000000..2e96c97
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/config/sysui/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/config/sysui/SystemUiSystemPropertiesFlagsTest.java b/core/tests/coretests/src/com/android/internal/config/sysui/SystemUiSystemPropertiesFlagsTest.java
new file mode 100644
index 0000000..6b9d39c
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/config/sysui/SystemUiSystemPropertiesFlagsTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.internal.config.sysui;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.Flag;
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.FlagResolver;
+
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SmallTest
+public class SystemUiSystemPropertiesFlagsTest extends TestCase {
+
+    public class TestableDebugResolver extends SystemUiSystemPropertiesFlags.DebugResolver {
+        final Map<String, Boolean> mTestData = new HashMap<>();
+
+        @Override
+        public boolean getBoolean(String key, boolean defaultValue) {
+            Boolean testValue = mTestData.get(key);
+            return testValue == null ? defaultValue : testValue;
+        }
+
+        public void set(Flag flag, Boolean value) {
+            mTestData.put(flag.mSysPropKey, value);
+        }
+    }
+
+    private FlagResolver mProdResolver;
+    private TestableDebugResolver mDebugResolver;
+
+    private Flag mReleasedFlag;
+    private Flag mTeamfoodFlag;
+    private Flag mDevFlag;
+
+    public void setUp() {
+        mProdResolver = new SystemUiSystemPropertiesFlags.ProdResolver();
+        mDebugResolver = new TestableDebugResolver();
+        mReleasedFlag = SystemUiSystemPropertiesFlags.releasedFlag("mReleasedFlag");
+        mTeamfoodFlag = SystemUiSystemPropertiesFlags.teamfoodFlag("mTeamfoodFlag");
+        mDevFlag = SystemUiSystemPropertiesFlags.devFlag("mDevFlag");
+    }
+
+    public void tearDown() {
+        SystemUiSystemPropertiesFlags.TEST_RESOLVER = null;
+    }
+
+    public void testProdResolverReturnsDefault() {
+        assertThat(mProdResolver.isEnabled(mReleasedFlag)).isTrue();
+        assertThat(mProdResolver.isEnabled(mTeamfoodFlag)).isFalse();
+        assertThat(mProdResolver.isEnabled(mDevFlag)).isFalse();
+    }
+
+    public void testDebugResolverAndReleasedFlag() {
+        assertThat(mDebugResolver.isEnabled(mReleasedFlag)).isTrue();
+
+        mDebugResolver.set(mReleasedFlag, false);
+        assertThat(mDebugResolver.isEnabled(mReleasedFlag)).isFalse();
+
+        mDebugResolver.set(mReleasedFlag, true);
+        assertThat(mDebugResolver.isEnabled(mReleasedFlag)).isTrue();
+    }
+
+    private void assertTeamfoodFlag(Boolean flagValue, Boolean teamfood, boolean expected) {
+        mDebugResolver.set(mTeamfoodFlag, flagValue);
+        mDebugResolver.set(SystemUiSystemPropertiesFlags.TEAMFOOD, teamfood);
+        assertThat(mDebugResolver.isEnabled(mTeamfoodFlag)).isEqualTo(expected);
+    }
+
+    public void testDebugResolverAndTeamfoodFlag() {
+        assertTeamfoodFlag(null, null, false);
+        assertTeamfoodFlag(true, null, true);
+        assertTeamfoodFlag(false, null, false);
+        assertTeamfoodFlag(null, true, true);
+        assertTeamfoodFlag(true, true, true);
+        assertTeamfoodFlag(false, true, false);
+        assertTeamfoodFlag(null, false, false);
+        assertTeamfoodFlag(true, false, true);
+        assertTeamfoodFlag(false, false, false);
+    }
+
+    public void testDebugResolverAndDevFlag() {
+        assertThat(mDebugResolver.isEnabled(mDevFlag)).isFalse();
+
+        mDebugResolver.set(mDevFlag, true);
+        assertThat(mDebugResolver.isEnabled(mDevFlag)).isTrue();
+
+        mDebugResolver.set(mDevFlag, false);
+        assertThat(mDebugResolver.isEnabled(mDevFlag)).isFalse();
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
index 048c48b..f79ba28 100644
--- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
+++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
@@ -67,7 +67,7 @@
                 BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE,
                 WindowInsets.Type.defaultVisible(),
                 "test" /* packageName */,
-                new int[0] /* transientBarTypes */,
+                0 /* transientBarTypes */,
                 new LetterboxDetails[] {letterboxDetails});
 
         final RegisterStatusBarResult copy = clone(original);
diff --git a/core/tests/expresslog/Android.bp b/core/tests/expresslog/Android.bp
new file mode 100644
index 0000000..cab49a7
--- /dev/null
+++ b/core/tests/expresslog/Android.bp
@@ -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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "ExpressLogTests",
+
+    srcs: [
+        "src/**/*.java",
+    ],
+
+    static_libs: [
+        "androidx.test.rules",
+        "modules-utils-build",
+    ],
+
+    libs: [
+        "android.test.base",
+        "android.test.runner",
+    ],
+
+    platform_apis: true,
+    test_suites: [
+        "general-tests",
+    ],
+
+    certificate: "platform",
+}
diff --git a/core/tests/expresslog/AndroidManifest.xml b/core/tests/expresslog/AndroidManifest.xml
new file mode 100644
index 0000000..94a39e0
--- /dev/null
+++ b/core/tests/expresslog/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          android:installLocation="internalOnly"
+          package="com.android.internal.expresslog" >
+
+    <application >
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.internal.expresslog"
+            android:label="Telemetry Express Logging Helper Tests" />
+
+</manifest>
diff --git a/core/tests/expresslog/OWNERS b/core/tests/expresslog/OWNERS
new file mode 100644
index 0000000..3dc958b
--- /dev/null
+++ b/core/tests/expresslog/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 719316
+# Stats/expresslog
+file:/services/core/java/com/android/server/stats/OWNERS
diff --git a/core/tests/expresslog/TEST_MAPPING b/core/tests/expresslog/TEST_MAPPING
new file mode 100644
index 0000000..c9b0cf8
--- /dev/null
+++ b/core/tests/expresslog/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "ExpressLogTests",
+      "options": [
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java b/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java
new file mode 100644
index 0000000..9fa6d06
--- /dev/null
+++ b/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.internal.expresslog;
+
+import androidx.test.filters.SmallTest;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class UniformOptionsTest {
+    private static final String TAG = UniformOptionsTest.class.getSimpleName();
+
+    @Test
+    @SmallTest
+    public void testGetBinsCount() {
+        Histogram.UniformOptions options1 = new Histogram.UniformOptions(1, 100, 1000);
+        assertEquals(3, options1.getBinsCount());
+
+        Histogram.UniformOptions options10 = new Histogram.UniformOptions(10, 100, 1000);
+        assertEquals(12, options10.getBinsCount());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    @SmallTest
+    public void testConstructZeroBinsCount() {
+        new Histogram.UniformOptions(0, 100, 1000);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    @SmallTest
+    public void testConstructNegativeBinsCount() {
+        new Histogram.UniformOptions(-1, 100, 1000);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    @SmallTest
+    public void testConstructMaxValueLessThanMinValue() {
+        new Histogram.UniformOptions(10, 1000, 100);
+    }
+
+    @Test
+    @SmallTest
+    public void testBinIndexForRangeEqual1() {
+        Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 11);
+        for (int i = 0, bins = options.getBinsCount(); i < bins; i++) {
+            assertEquals(i, options.getBinForSample(i));
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testBinIndexForRangeEqual2() {
+        Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 21);
+        for (int i = 0, bins = options.getBinsCount(); i < bins; i++) {
+            assertEquals(i, options.getBinForSample(i * 2));
+            assertEquals(i, options.getBinForSample(i * 2 - 1));
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testBinIndexForRangeEqual5() {
+        Histogram.UniformOptions options = new Histogram.UniformOptions(2, 0, 10);
+        assertEquals(4, options.getBinsCount());
+        for (int i = 0; i < 2; i++) {
+            for (int sample = 0; sample < 5; sample++) {
+                assertEquals(i + 1, options.getBinForSample(i * 5 + sample));
+            }
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testBinIndexForRangeEqual10() {
+        Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 101);
+        assertEquals(0, options.getBinForSample(0));
+        assertEquals(options.getBinsCount() - 2, options.getBinForSample(100));
+        assertEquals(options.getBinsCount() - 1, options.getBinForSample(101));
+
+        final float binSize = (101 - 1) / 10f;
+        for (int i = 1, bins = options.getBinsCount() - 1; i < bins; i++) {
+            assertEquals(i, options.getBinForSample(i * binSize));
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testBinIndexForRangeEqual90() {
+        final int binCount = 10;
+        final int minValue = 100;
+        final int maxValue = 100000;
+
+        Histogram.UniformOptions options = new Histogram.UniformOptions(binCount, minValue,
+                maxValue);
+
+        // logging underflow sample
+        assertEquals(0, options.getBinForSample(minValue - 1));
+
+        // logging overflow sample
+        assertEquals(binCount + 1, options.getBinForSample(maxValue));
+        assertEquals(binCount + 1, options.getBinForSample(maxValue + 1));
+
+        // logging min edge sample
+        assertEquals(1, options.getBinForSample(minValue));
+
+        // logging max edge sample
+        assertEquals(binCount, options.getBinForSample(maxValue - 1));
+
+        // logging single valid sample per bin
+        final int binSize = (maxValue - minValue) / binCount;
+
+        for (int i = 0; i < binCount; i++) {
+            assertEquals(i + 1, options.getBinForSample(minValue + binSize * i));
+        }
+    }
+}
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java
index e82b699..2bce747 100755
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java
@@ -45,54 +45,63 @@
                                 .setCecSupported(isCec)
                                 .setMhlSupported(isMhl)
                                 .setArcSupported(isArcSupported)
-                                .setEarcSupported(isEarcSupported),
+                                .setEarcSupported(isEarcSupported)
+                                .build(),
                         new HdmiPortInfo.Builder(portId, portType, address)
                                 .setCecSupported(isCec)
                                 .setMhlSupported(isMhl)
                                 .setArcSupported(isArcSupported)
-                                .setEarcSupported(isEarcSupported))
+                                .setEarcSupported(isEarcSupported)
+                                .build())
                 .addEqualityGroup(
                         new HdmiPortInfo.Builder(portId + 1, portType, address)
                                 .setCecSupported(isCec)
                                 .setMhlSupported(isMhl)
                                 .setArcSupported(isArcSupported)
-                                .setEarcSupported(isEarcSupported))
+                                .setEarcSupported(isEarcSupported)
+                                .build())
                 .addEqualityGroup(
                         new HdmiPortInfo.Builder(portId, portType + 1, address)
                                 .setCecSupported(isCec)
                                 .setMhlSupported(isMhl)
                                 .setArcSupported(isArcSupported)
-                                .setEarcSupported(isEarcSupported))
+                                .setEarcSupported(isEarcSupported)
+                                .build())
                 .addEqualityGroup(
                         new HdmiPortInfo.Builder(portId, portType, address + 1)
                                 .setCecSupported(isCec)
                                 .setMhlSupported(isMhl)
                                 .setArcSupported(isArcSupported)
-                                .setEarcSupported(isEarcSupported))
+                                .setEarcSupported(isEarcSupported)
+                                .build())
                 .addEqualityGroup(
                         new HdmiPortInfo.Builder(portId, portType, address)
                                 .setCecSupported(!isCec)
                                 .setMhlSupported(isMhl)
                                 .setArcSupported(isArcSupported)
-                                .setEarcSupported(isEarcSupported))
+                                .setEarcSupported(isEarcSupported)
+                                .build())
                 .addEqualityGroup(
                         new HdmiPortInfo.Builder(portId, portType, address)
                                 .setCecSupported(isCec)
                                 .setMhlSupported(!isMhl)
                                 .setArcSupported(isArcSupported)
-                                .setEarcSupported(isEarcSupported))
+                                .setEarcSupported(isEarcSupported)
+                                .build())
                 .addEqualityGroup(
                         new HdmiPortInfo.Builder(portId, portType, address)
                                 .setCecSupported(isCec)
                                 .setMhlSupported(isMhl)
                                 .setArcSupported(!isArcSupported)
-                                .setEarcSupported(isEarcSupported))
+                                .setEarcSupported(isEarcSupported)
+                                .build())
                 .addEqualityGroup(
                         new HdmiPortInfo.Builder(portId, portType, address)
                                 .setCecSupported(isCec)
                                 .setMhlSupported(isMhl)
                                 .setArcSupported(isArcSupported)
-                                .setEarcSupported(!isEarcSupported))
+                                .setEarcSupported(!isEarcSupported)
+                                .build())
                 .testEquals();
     }
 }
diff --git a/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotRequestTest.java b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotRequestTest.java
index 30540a5..89acbc7 100644
--- a/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotRequestTest.java
+++ b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotRequestTest.java
@@ -131,6 +131,12 @@
         assertEquals(Insets.NONE, out.getInsets());
     }
 
+    @Test
+    public void testInvalidType() {
+        assertThrows(IllegalArgumentException.class,
+                () -> new ScreenshotRequest.Builder(5, 2).build());
+    }
+
     private Bitmap makeHardwareBitmap(int width, int height) {
         HardwareBuffer buffer = HardwareBuffer.create(
                 width, height, HardwareBuffer.RGBA_8888, 1, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index d0c3e5f..f233c6e 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -36,6 +36,12 @@
 }
 
 prebuilt_etc {
+    name: "initial-package-stopped-states.xml",
+    sub_dir: "sysconfig",
+    src: "initial-package-stopped-states.xml",
+}
+
+prebuilt_etc {
     name: "preinstalled-packages-platform-overlays.xml",
     product_specific: true,
     sub_dir: "sysconfig",
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index 0aad0a8..116aa489 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -50,6 +50,7 @@
         <permission name="android.permission.READ_FRAME_BUFFER"/>
         <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+        <permission name="android.permission.READ_PRECISE_PHONE_STATE"/>
         <permission name="android.permission.REAL_GET_TASKS"/>
         <permission name="android.permission.REQUEST_NETWORK_SCORES"/>
         <permission name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"/>
diff --git a/data/etc/initial-package-stopped-states.xml b/data/etc/initial-package-stopped-states.xml
new file mode 100644
index 0000000..6bda2c0
--- /dev/null
+++ b/data/etc/initial-package-stopped-states.xml
@@ -0,0 +1,38 @@
+<?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.
+ -->
+
+<!--
+This XML defines an allowlist for packages that should not be scanned in a "stopped" state.
+When this feature is turned on (indicated by the config config_stopSystemPackagesByDefault in
+core/res/res/values/config.xml) packages on the system partition that are encountered by
+the PackageManagerService for the first time are scanned in the "stopped" state. This allowlist
+is also considered while creating new users on the device. Stopped state is not set during
+subsequent reboots.
+
+Example usage
+    1. <initial-package-state package="com.example.app" stopped="false"/>
+        Indicates that a system package - com.example.app's initial stopped state should not be set
+        by the Package Manager. By default, system apps are marked as stopped.
+    2. <initial-package-state package="com.example.app" stopped="true"/>
+        Indicates that a system package - com.example.app's initial state should be set by the
+        Package Manager to "stopped=true". It will have the same effect on the
+        package's stopped state even if this package was not included in the allow list.
+    3. <initial-package-state package="com.example.app"/>
+        Invalid usage.
+-->
+
+<config></config>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index bccf283..53f4747 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -61,6 +61,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/WindowToken.java"
     },
+    "-2088209279": {
+      "message": "Notified TransitionController that the display is ready.",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/WindowManagerService.java"
+    },
     "-2072089308": {
       "message": "Attempted to add window with token that is a sub-window: %s.  Aborting.",
       "level": "WARN",
@@ -1771,6 +1777,12 @@
       "group": "WM_DEBUG_KEEP_SCREEN_ON",
       "at": "com\/android\/server\/wm\/RootWindowContainer.java"
     },
+    "-464564167": {
+      "message": "Current transition prevents automatic focus change",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_FOCUS",
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
     "-463348344": {
       "message": "Removing and adding activity %s to root task at top callers=%s",
       "level": "INFO",
@@ -2065,12 +2077,6 @@
       "group": "WM_DEBUG_ANIM",
       "at": "com\/android\/server\/wm\/SurfaceAnimator.java"
     },
-    "-206549078": {
-      "message": "Not moving display (displayId=%d) to top. Top focused displayId=%d. Reason: config_perDisplayFocusEnabled",
-      "level": "INFO",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "-203358733": {
       "message": "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW %s",
       "level": "INFO",
@@ -2767,6 +2773,12 @@
       "group": "WM_DEBUG_STATES",
       "at": "com\/android\/server\/wm\/TaskFragment.java"
     },
+    "378890013": {
+      "message": "Apply and finish immediately because player is disabled for transition #%d .",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/Transition.java"
+    },
     "385237117": {
       "message": "moveFocusableActivityToTop: already on top and focused, activity=%s",
       "level": "DEBUG",
@@ -3649,6 +3661,12 @@
       "group": "WM_DEBUG_STATES",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "1282992082": {
+      "message": "Disabling player for transition #%d because display isn't enabled yet",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/TransitionController.java"
+    },
     "1284122013": {
       "message": "TaskFragment appeared name=%s",
       "level": "VERBOSE",
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java
index c1a2048..abef78e 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java
@@ -68,6 +68,8 @@
                     .named("myUserId"),
             instanceMethod().onExactClass("android.content.pm.ShortcutManager")
                     .named("injectMyUserId"),
+            instanceMethod().onExactClass("android.os.UserManager")
+                    .named("getContextUserIfAppropriate"),
             instanceMethod().onDescendantOf("android.content.Context")
                     .named("getUserId")));
 
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
index fa173072..d39d4b4 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
@@ -412,11 +412,11 @@
 
     private static ParsedRequiresPermission parseRequiresPermissionRecursively(
             MethodInvocationTree tree, VisitorState state) {
-        if (ENFORCE_VIA_CONTEXT.matches(tree, state)) {
+        if (ENFORCE_VIA_CONTEXT.matches(tree, state) && tree.getArguments().size() > 0) {
             final ParsedRequiresPermission res = new ParsedRequiresPermission();
             res.allOf.add(String.valueOf(ASTHelpers.constValue(tree.getArguments().get(0))));
             return res;
-        } else if (ENFORCE_VIA_CHECKER.matches(tree, state)) {
+        } else if (ENFORCE_VIA_CHECKER.matches(tree, state) && tree.getArguments().size() > 1) {
             final ParsedRequiresPermission res = new ParsedRequiresPermission();
             res.allOf.add(String.valueOf(ASTHelpers.constValue(tree.getArguments().get(1))));
             return res;
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ContextUserIdCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ContextUserIdCheckerTest.java
index 1679bb6..854016f 100644
--- a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ContextUserIdCheckerTest.java
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ContextUserIdCheckerTest.java
@@ -148,4 +148,31 @@
                         "}")
                 .doTest();
     }
+
+    @Test
+    public void testUserManager() {
+        compilationHelper
+                .addSourceFile("/android/annotation/SystemService.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/content/Intent.java")
+                .addSourceFile("/android/foo/IFooService.java")
+                .addSourceFile("/android/os/IInterface.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/RemoteException.java")
+                .addSourceLines("UserManager.java",
+                        "package android.os;",
+                        "import android.annotation.SystemService;",
+                        "import android.content.Context;",
+                        "import android.foo.IFooService;",
+                        "import android.os.UserHandle;",
+                        "import android.os.RemoteException;",
+                        "@SystemService(\"user\") public class UserManager {",
+                        "  IFooService mService;",
+                        "  int getContextUserIfAppropriate() { return 0; }",
+                        "  void bar() throws RemoteException {",
+                        "    mService.baz(null, getContextUserIfAppropriate());",
+                        "  }",
+                        "}")
+                .doTest();
+    }
 }
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java
index 388988e..38831b1 100644
--- a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/RequiresPermissionCheckerTest.java
@@ -415,4 +415,27 @@
                         "}")
                 .doTest();
     }
+
+    @Test
+    public void testInvalidFunctions() {
+        compilationHelper
+                .addSourceFile("/android/annotation/RequiresPermission.java")
+                .addSourceFile("/android/annotation/SuppressLint.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceLines("Example.java",
+                        "import android.annotation.RequiresPermission;",
+                        "import android.annotation.SuppressLint;",
+                        "import android.content.Context;",
+                        "class Foo extends Context {",
+                        "  private static final String RED = \"red\";",
+                        "  public void checkPermission() {",
+                        "  }",
+                        "  @RequiresPermission(RED)",
+                        "  // BUG: Diagnostic contains:",
+                        "  public void exampleScoped(Context context) {",
+                        "    checkPermission();",
+                        "  }",
+                        "}")
+                .doTest();
+    }
 }
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 00ffd09..a7acaf9 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -670,11 +670,16 @@
     /**
      * Draws a mesh object to the screen.
      *
+     * <p>Note: antialiasing is not supported, therefore {@link Paint#ANTI_ALIAS_FLAG} is
+     * ignored.</p>
+     *
      * @param mesh {@link Mesh} object that will be drawn to the screen
-     * @param blendMode {@link BlendMode} used to blend mesh primitives with the Paint color/shader
+     * @param blendMode {@link BlendMode} used to blend mesh primitives as the destination color
+     *            with the Paint color/shader as the source color. This defaults to
+     *            {@link BlendMode#MODULATE} if null.
      * @param paint {@link Paint} used to provide a color/shader/blend mode.
      */
-    public void drawMesh(@NonNull Mesh mesh, BlendMode blendMode, @NonNull Paint paint) {
+    public void drawMesh(@NonNull Mesh mesh, @Nullable BlendMode blendMode, @NonNull Paint paint) {
         if (!isHardwareAccelerated() && onHwFeatureInSwMode()) {
             throw new RuntimeException("software rendering doesn't support meshes");
         }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 42c892a..e7814cb 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -241,7 +241,7 @@
 
     /**
      * Return true if the device that the current layer draws into is opaque
-     * (i.e. does not support per-pixel alpha).
+     * (that is, it does not support per-pixel alpha).
      *
      * @return true if the device that the current layer draws into is opaque
      */
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 2427dec..4c669b8 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -212,9 +212,9 @@
             new Rgb.TransferParameters(1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4);
     private static final Rgb.TransferParameters BT2020_HLG_TRANSFER_PARAMETERS =
             new Rgb.TransferParameters(2.0f, 2.0f, 1 / 0.17883277f,
-                0.28466892f, 0.5599107f, 0.0f, -3.0f, true);
+                0.28466892f, 0.5599107f, -11 / 12.0f, -3.0f, true);
     private static final Rgb.TransferParameters BT2020_PQ_TRANSFER_PARAMETERS =
-            new Rgb.TransferParameters(107 / 128.0f, 1.0f, 32 / 2523.0f,
+            new Rgb.TransferParameters(-107 / 128.0f, 1.0f, 32 / 2523.0f,
                 2413 / 128.0f, -2392 / 128.0f, 8192 / 1305.0f, -2.0f, true);
 
     // See static initialization block next to #get(Named)
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index f815a5e..0488b9d 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -158,6 +158,7 @@
     private boolean mOpaque = true;
     private boolean mForceDark = false;
     private @ActivityInfo.ColorMode int mColorMode = ActivityInfo.COLOR_MODE_DEFAULT;
+    private float mDesiredSdrHdrRatio = 1f;
 
     /**
      * Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
@@ -319,7 +320,8 @@
      * @param surfaceControl The surface control to pass to render thread in hwui.
      *        If null, any previous references held in render thread will be discarded.
     */
-    public void setSurfaceControl(@Nullable SurfaceControl surfaceControl) {
+    public void setSurfaceControl(@Nullable SurfaceControl surfaceControl,
+            @Nullable BLASTBufferQueue blastBufferQueue) {
         nSetSurfaceControl(mNativeProxy, surfaceControl != null ? surfaceControl.mNativeObject : 0);
     }
 
@@ -643,11 +645,12 @@
      * @param colorMode The @{@link ActivityInfo.ColorMode} to request
      * @hide
      */
-    public void setColorMode(@ActivityInfo.ColorMode int colorMode) {
+    public float setColorMode(@ActivityInfo.ColorMode int colorMode) {
         if (mColorMode != colorMode) {
             mColorMode = colorMode;
-            nSetColorMode(mNativeProxy, colorMode);
+            mDesiredSdrHdrRatio = nSetColorMode(mNativeProxy, colorMode);
         }
+        return mDesiredSdrHdrRatio;
     }
 
     /**
@@ -663,6 +666,12 @@
         nSetColorMode(mNativeProxy, colorMode);
     }
 
+    /** @hide */
+    public void setTargetSdrHdrRatio(float ratio) {
+        if (ratio < 1.f || !Float.isFinite(ratio)) ratio = 1.f;
+        nSetTargetSdrHdrRatio(mNativeProxy, ratio);
+    }
+
     /**
      * Blocks until all previously queued work has completed.
      *
@@ -1451,7 +1460,9 @@
 
     private static native void nSetOpaque(long nativeProxy, boolean opaque);
 
-    private static native void nSetColorMode(long nativeProxy, int colorMode);
+    private static native float nSetColorMode(long nativeProxy, int colorMode);
+
+    private static native void nSetTargetSdrHdrRatio(long nativeProxy, float ratio);
 
     private static native void nSetSdrWhitePoint(long nativeProxy, float whitePoint);
 
diff --git a/graphics/java/android/graphics/Mesh.java b/graphics/java/android/graphics/Mesh.java
index a599b2c..6a1313e 100644
--- a/graphics/java/android/graphics/Mesh.java
+++ b/graphics/java/android/graphics/Mesh.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.ColorInt;
+import android.annotation.ColorLong;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 
@@ -27,10 +29,8 @@
 /**
  * Class representing a mesh object.
  *
- * This class generates Mesh objects via the
- * {@link #make(MeshSpecification, int, Buffer, int, Rect)} and
- * {@link #makeIndexed(MeshSpecification, int, Buffer, int, ShortBuffer, Rect)} methods,
- * where a {@link MeshSpecification} is required along with various attributes for
+ * This class represents a Mesh object that can optionally be indexed.
+ * A {@link MeshSpecification} is required along with various attributes for
  * detailing the mesh object, including a mode, vertex buffer, optional index buffer, and bounds
  * for the mesh. Once generated, a mesh object can be drawn through
  * {@link Canvas#drawMesh(Mesh, BlendMode, Paint)}
@@ -62,7 +62,7 @@
     }
 
     /**
-     * Generates a {@link Mesh} object.
+     * Constructor for a non-indexed Mesh.
      *
      * @param meshSpec     {@link MeshSpecification} used when generating the mesh.
      * @param mode         Determines what mode to draw the mesh in. Must be one of
@@ -74,11 +74,9 @@
      *                     backed buffer generated.
      * @param vertexCount  the number of vertices represented in the vertexBuffer and mesh.
      * @param bounds       bounds of the mesh object.
-     * @return a new Mesh object.
      */
-    @NonNull
-    public static Mesh make(@NonNull MeshSpecification meshSpec, @Mode int mode,
-            @NonNull Buffer vertexBuffer, int vertexCount, @NonNull Rect bounds) {
+    public Mesh(@NonNull MeshSpecification meshSpec, @Mode int mode,
+            @NonNull Buffer vertexBuffer, int vertexCount, @NonNull RectF bounds) {
         if (mode != TRIANGLES && mode != TRIANGLE_STRIP) {
             throw new IllegalArgumentException("Invalid value passed in for mode parameter");
         }
@@ -88,11 +86,12 @@
         if (nativeMesh == 0) {
             throw new IllegalArgumentException("Mesh construction failed.");
         }
-        return new Mesh(nativeMesh, false);
+
+        meshSetup(nativeMesh, false);
     }
 
     /**
-     * Generates a {@link Mesh} object.
+     * Constructor for an indexed Mesh.
      *
      * @param meshSpec     {@link MeshSpecification} used when generating the mesh.
      * @param mode         Determines what mode to draw the mesh in. Must be one of
@@ -108,12 +107,10 @@
      *                     currently implementation will have a CPU
      *                     backed buffer generated.
      * @param bounds       bounds of the mesh object.
-     * @return a new Mesh object.
      */
-    @NonNull
-    public static Mesh makeIndexed(@NonNull MeshSpecification meshSpec, @Mode int mode,
+    public Mesh(@NonNull MeshSpecification meshSpec, @Mode int mode,
             @NonNull Buffer vertexBuffer, int vertexCount, @NonNull ShortBuffer indexBuffer,
-            @NonNull Rect bounds) {
+            @NonNull RectF bounds) {
         if (mode != TRIANGLES && mode != TRIANGLE_STRIP) {
             throw new IllegalArgumentException("Invalid value passed in for mode parameter");
         }
@@ -124,7 +121,8 @@
         if (nativeMesh == 0) {
             throw new IllegalArgumentException("Mesh construction failed.");
         }
-        return new Mesh(nativeMesh, true);
+
+        meshSetup(nativeMesh, true);
     }
 
     /**
@@ -137,7 +135,7 @@
      * @param color       the provided sRGB color will be converted into the shader program's output
      *                    colorspace and be available as a vec4 uniform in the program.
      */
-    public void setColorUniform(@NonNull String uniformName, int color) {
+    public void setColorUniform(@NonNull String uniformName, @ColorInt int color) {
         setUniform(uniformName, Color.valueOf(color).getComponents(), true);
     }
 
@@ -151,7 +149,7 @@
      * @param color       the provided sRGB color will be converted into the shader program's output
      *                    colorspace and be available as a vec4 uniform in the program.
      */
-    public void setColorUniform(@NonNull String uniformName, long color) {
+    public void setColorUniform(@NonNull String uniformName, @ColorLong long color) {
         Color exSRGB = Color.valueOf(color).convert(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB));
         setUniform(uniformName, exSRGB.getComponents(), true);
     }
@@ -357,7 +355,7 @@
                 mNativeMeshWrapper, uniformName, value1, value2, value3, value4, count);
     }
 
-    private Mesh(long nativeMeshWrapper, boolean isIndexed) {
+    private void meshSetup(long nativeMeshWrapper, boolean isIndexed) {
         mNativeMeshWrapper = nativeMeshWrapper;
         this.mIsIndexed = isIndexed;
         MeshHolder.MESH_SPECIFICATION_REGISTRY.registerNativeAllocation(this, mNativeMeshWrapper);
@@ -366,13 +364,13 @@
     private static native long nativeGetFinalizer();
 
     private static native long nativeMake(long meshSpec, int mode, Buffer vertexBuffer,
-            boolean isDirect, int vertexCount, int vertexOffset, int left, int top, int right,
-            int bottom);
+            boolean isDirect, int vertexCount, int vertexOffset, float left, float top, float right,
+            float bottom);
 
     private static native long nativeMakeIndexed(long meshSpec, int mode, Buffer vertexBuffer,
             boolean isVertexDirect, int vertexCount, int vertexOffset, ShortBuffer indexBuffer,
-            boolean isIndexDirect, int indexCount, int indexOffset, int left, int top, int right,
-            int bottom);
+            boolean isIndexDirect, int indexCount, int indexOffset, float left, float top,
+            float right, float bottom);
 
     private static native void nativeUpdateUniforms(long builder, String uniformName, float value1,
             float value2, float value3, float value4, int count);
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 2830d7eff..c1f6c29 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -801,25 +801,34 @@
             ));
 
             if (mSpec.isDevicePropertiesAttestationIncluded()) {
+                final String platformReportedBrand =
+                        isPropertyEmptyOrUnknown(Build.BRAND_FOR_ATTESTATION)
+                        ? Build.BRAND : Build.BRAND_FOR_ATTESTATION;
                 params.add(KeyStore2ParameterUtils.makeBytes(
                         KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND,
-                        Build.BRAND.getBytes(StandardCharsets.UTF_8)
+                        platformReportedBrand.getBytes(StandardCharsets.UTF_8)
                 ));
                 params.add(KeyStore2ParameterUtils.makeBytes(
                         KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,
                         Build.DEVICE.getBytes(StandardCharsets.UTF_8)
                 ));
+                final String platformReportedProduct =
+                        isPropertyEmptyOrUnknown(Build.PRODUCT_FOR_ATTESTATION)
+                        ? Build.PRODUCT : Build.PRODUCT_FOR_ATTESTATION;
                 params.add(KeyStore2ParameterUtils.makeBytes(
                         KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT,
-                        Build.PRODUCT.getBytes(StandardCharsets.UTF_8)
+                        platformReportedProduct.getBytes(StandardCharsets.UTF_8)
                 ));
                 params.add(KeyStore2ParameterUtils.makeBytes(
                         KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER,
                         Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8)
                 ));
+                final String platformReportedModel =
+                        isPropertyEmptyOrUnknown(Build.MODEL_FOR_ATTESTATION)
+                        ? Build.MODEL : Build.MODEL_FOR_ATTESTATION;
                 params.add(KeyStore2ParameterUtils.makeBytes(
                         KeymasterDefs.KM_TAG_ATTESTATION_ID_MODEL,
-                        Build.MODEL.getBytes(StandardCharsets.UTF_8)
+                        platformReportedModel.getBytes(StandardCharsets.UTF_8)
                 ));
             }
 
@@ -1220,4 +1229,8 @@
         result.retainAll(authorizedKeymasterKeyDigests);
         return result;
     }
+
+    private boolean isPropertyEmptyOrUnknown(String property) {
+        return TextUtils.isEmpty(property) || property.equals(Build.UNKNOWN);
+    }
 }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
index 666b472..76e0e1e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
@@ -48,7 +48,7 @@
     // TODO(b/241126279) Introduce constants to better version functionality
     @Override
     public int getVendorApiLevel() {
-        return 2;
+        return 3;
     }
 
     @NonNull
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentation.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentation.java
new file mode 100644
index 0000000..1ff1694
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentation.java
@@ -0,0 +1,68 @@
+/*
+ * 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 androidx.window.extensions.area;
+
+import android.app.Presentation;
+import android.content.Context;
+import android.view.Display;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.window.extensions.core.util.function.Consumer;
+
+/**
+ * {@link Presentation} object that is used to present extra content
+ * on the rear facing display when in a rear display presentation feature.
+ */
+class RearDisplayPresentation extends Presentation implements ExtensionWindowAreaPresentation {
+
+    @NonNull
+    private final Consumer<@WindowAreaComponent.WindowAreaSessionState Integer> mStateConsumer;
+
+    RearDisplayPresentation(@NonNull Context outerContext, @NonNull Display display,
+            @NonNull Consumer<@WindowAreaComponent.WindowAreaSessionState Integer> stateConsumer) {
+        super(outerContext, display);
+        mStateConsumer = stateConsumer;
+    }
+
+    /**
+     * {@code mStateConsumer} is notified that their content is now visible when the
+     * {@link Presentation} object is started. There is no comparable callback for
+     * {@link WindowAreaComponent#SESSION_STATE_INVISIBLE} in {@link #onStop()} due to the
+     * timing of when a {@link android.hardware.devicestate.DeviceStateRequest} is cancelled
+     * ending rear display presentation mode happening before the {@link Presentation} is stopped.
+     */
+    @Override
+    protected void onStart() {
+        super.onStart();
+        mStateConsumer.accept(WindowAreaComponent.SESSION_STATE_VISIBLE);
+    }
+
+    @NonNull
+    @Override
+    public Context getPresentationContext() {
+        return getContext();
+    }
+
+    @Override
+    public void setPresentationView(View view) {
+        setContentView(view);
+        if (!isShowing()) {
+            show();
+        }
+    }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationController.java
new file mode 100644
index 0000000..141a6ad
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationController.java
@@ -0,0 +1,100 @@
+/*
+ * 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 androidx.window.extensions.area;
+
+import static androidx.window.extensions.area.WindowAreaComponent.SESSION_STATE_ACTIVE;
+import static androidx.window.extensions.area.WindowAreaComponent.SESSION_STATE_INACTIVE;
+
+import android.content.Context;
+import android.hardware.devicestate.DeviceStateRequest;
+import android.hardware.display.DisplayManager;
+import android.util.Log;
+import android.view.Display;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.core.util.function.Consumer;
+
+import java.util.Objects;
+
+/**
+ * Controller class that keeps track of the status of the device state request
+ * to enable the rear display presentation feature. This controller notifies the session callback
+ * when the state request is active, and notifies the callback when the request is canceled.
+ *
+ * Clients are notified via {@link Consumer} provided with
+ * {@link androidx.window.extensions.area.WindowAreaComponent.WindowAreaStatus} values to signify
+ * when the request becomes active and cancelled.
+ */
+class RearDisplayPresentationController implements DeviceStateRequest.Callback {
+
+    private static final String TAG = "RearDisplayPresentationController";
+
+    // Original context that requested to enable rear display presentation mode
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final Consumer<@WindowAreaComponent.WindowAreaSessionState Integer> mStateConsumer;
+    @Nullable
+    private ExtensionWindowAreaPresentation mExtensionWindowAreaPresentation;
+    @NonNull
+    private final DisplayManager mDisplayManager;
+
+    /**
+     * Creates the RearDisplayPresentationController
+     * @param context Originating {@link android.content.Context} that is initiating the rear
+     *                display presentation session.
+     * @param stateConsumer {@link Consumer} that will be notified that the session is active when
+     *        the device state request is active and the session has been created. If the device
+     *        state request is cancelled, the callback will be notified that the session has been
+     *        ended. This could occur through a call to cancel the feature or if the device is
+     *        manipulated in a way that cancels any device state override.
+     */
+    RearDisplayPresentationController(@NonNull Context context,
+            @NonNull Consumer<@WindowAreaComponent.WindowAreaSessionState Integer> stateConsumer) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(stateConsumer);
+
+        mContext = context;
+        mStateConsumer = stateConsumer;
+        mDisplayManager = context.getSystemService(DisplayManager.class);
+    }
+
+    @Override
+    public void onRequestActivated(@NonNull DeviceStateRequest request) {
+        Display[] rearDisplays = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_REAR);
+        if (rearDisplays.length == 0) {
+            mStateConsumer.accept(SESSION_STATE_INACTIVE);
+            Log.e(TAG, "Rear display list should not be empty");
+            return;
+        }
+
+        mExtensionWindowAreaPresentation =
+                new RearDisplayPresentation(mContext, rearDisplays[0], mStateConsumer);
+        mStateConsumer.accept(SESSION_STATE_ACTIVE);
+    }
+
+    @Override
+    public void onRequestCanceled(@NonNull DeviceStateRequest request) {
+        mStateConsumer.accept(SESSION_STATE_INACTIVE);
+    }
+
+    @Nullable
+    public ExtensionWindowAreaPresentation getWindowAreaPresentation() {
+        return mExtensionWindowAreaPresentation;
+    }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationStatus.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationStatus.java
new file mode 100644
index 0000000..0b1423a
--- /dev/null
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationStatus.java
@@ -0,0 +1,62 @@
+/*
+ * 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 androidx.window.extensions.area;
+
+import android.util.DisplayMetrics;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Class that provides information around the current status of a window area feature. Contains
+ * the current {@link WindowAreaComponent.WindowAreaStatus} value corresponding to the
+ * rear display presentation feature, as well as the {@link DisplayMetrics} for the rear facing
+ * display.
+ */
+class RearDisplayPresentationStatus implements ExtensionWindowAreaStatus {
+
+    @WindowAreaComponent.WindowAreaStatus
+    private final int mWindowAreaStatus;
+
+    @NonNull
+    private final DisplayMetrics mDisplayMetrics;
+
+    RearDisplayPresentationStatus(@WindowAreaComponent.WindowAreaStatus int status,
+            @NonNull DisplayMetrics displayMetrics) {
+        mWindowAreaStatus = status;
+        mDisplayMetrics = displayMetrics;
+    }
+
+    /**
+     * Returns the {@link androidx.window.extensions.area.WindowAreaComponent.WindowAreaStatus}
+     * value that relates to the current status of a feature.
+     */
+    @Override
+    @WindowAreaComponent.WindowAreaStatus
+    public int getWindowAreaStatus() {
+        return mWindowAreaStatus;
+    }
+
+    /**
+     * Returns the {@link DisplayMetrics} that corresponds to the window area that a feature
+     * interacts with. This is converted to size class information provided to developers.
+     */
+    @Override
+    @NonNull
+    public DisplayMetrics getWindowAreaDisplayMetrics() {
+        return mDisplayMetrics;
+    }
+}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index 3adae70..274dcae 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -22,15 +22,22 @@
 import android.content.Context;
 import android.hardware.devicestate.DeviceStateManager;
 import android.hardware.devicestate.DeviceStateRequest;
+import android.hardware.display.DisplayManager;
 import android.util.ArraySet;
+import android.util.DisplayMetrics;
+import android.util.Pair;
+import android.view.Display;
+import android.view.DisplayAddress;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.window.extensions.core.util.function.Consumer;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
 
 import java.util.concurrent.Executor;
-import java.util.function.Consumer;
 
 /**
  * Reference implementation of androidx.window.extensions.area OEM interface for use with
@@ -46,61 +53,102 @@
 
     private final Object mLock = new Object();
 
+    @NonNull
     private final DeviceStateManager mDeviceStateManager;
+    @NonNull
+    private final DisplayManager mDisplayManager;
+    @NonNull
     private final Executor mExecutor;
 
     @GuardedBy("mLock")
     private final ArraySet<Consumer<Integer>> mRearDisplayStatusListeners = new ArraySet<>();
+    @GuardedBy("mLock")
+    private final ArraySet<Consumer<ExtensionWindowAreaStatus>>
+            mRearDisplayPresentationStatusListeners = new ArraySet<>();
     private final int mRearDisplayState;
+    private final int mConcurrentDisplayState;
+    @NonNull
+    private final int[] mFoldedDeviceStates;
+    @NonNull
+    private long mRearDisplayAddress = 0;
     @WindowAreaSessionState
     private int mRearDisplaySessionStatus = WindowAreaComponent.SESSION_STATE_INACTIVE;
 
     @GuardedBy("mLock")
     private int mCurrentDeviceState = INVALID_DEVICE_STATE;
     @GuardedBy("mLock")
-    private int mCurrentDeviceBaseState = INVALID_DEVICE_STATE;
+    private int[] mCurrentSupportedDeviceStates;
+
     @GuardedBy("mLock")
-    private DeviceStateRequest mDeviceStateRequest;
+    private DeviceStateRequest mRearDisplayStateRequest;
+    @GuardedBy("mLock")
+    private RearDisplayPresentationController mRearDisplayPresentationController;
+
+    @Nullable
+    @GuardedBy("mLock")
+    private DisplayMetrics mRearDisplayMetrics;
+
+    @WindowAreaSessionState
+    @GuardedBy("mLock")
+    private int mLastReportedRearDisplayPresentationStatus;
 
     public WindowAreaComponentImpl(@NonNull Context context) {
         mDeviceStateManager = context.getSystemService(DeviceStateManager.class);
+        mDisplayManager = context.getSystemService(DisplayManager.class);
         mExecutor = context.getMainExecutor();
 
+        mCurrentSupportedDeviceStates = mDeviceStateManager.getSupportedStates();
+        mFoldedDeviceStates = context.getResources().getIntArray(
+                R.array.config_foldedDeviceStates);
+
         // TODO(b/236022708) Move rear display state to device state config file
         mRearDisplayState = context.getResources().getInteger(
                 R.integer.config_deviceStateRearDisplay);
 
+        mConcurrentDisplayState = context.getResources().getInteger(
+                R.integer.config_deviceStateConcurrentRearDisplay);
+
         mDeviceStateManager.registerCallback(mExecutor, this);
+        if (mConcurrentDisplayState != INVALID_DEVICE_STATE) {
+            mRearDisplayAddress = Long.parseLong(context.getResources().getString(
+                    R.string.config_rearDisplayPhysicalAddress));
+        }
     }
 
     /**
      * Adds a listener interested in receiving updates on the RearDisplayStatus
      * of the device. Because this is being called from the OEM provided
-     * extensions, we will post the result of the listener on the executor
+     * extensions, the result of the listener will be posted on the executor
      * provided by the developer at the initial call site.
      *
-     * Depending on the initial state of the device, we will return either
+     * Rear display mode moves the calling application to the display on the device that is
+     * facing the same direction as the rear cameras. This would be the cover display on a fold-in
+     * style device when the device is opened.
+     *
+     * Depending on the initial state of the device, the {@link Consumer} will receive either
      * {@link WindowAreaComponent#STATUS_AVAILABLE} or
      * {@link WindowAreaComponent#STATUS_UNAVAILABLE} if the feature is supported or not in that
-     * state respectively. When the rear display feature is triggered, we update the status to be
-     * {@link WindowAreaComponent#STATUS_UNAVAILABLE}. TODO(b/240727590) Prefix with AREA_
+     * state respectively. When the rear display feature is triggered, the status is updated to be
+     * {@link WindowAreaComponent#STATUS_UNAVAILABLE}.
+     * TODO(b/240727590): Prefix with AREA_
      *
-     * TODO(b/239833099) Add a STATUS_ACTIVE option to let apps know if a feature is currently
-     * enabled.
+     * TODO(b/239833099): Add a STATUS_ACTIVE option to let apps know if a feature is currently
+     *  enabled.
      *
      * @param consumer {@link Consumer} interested in receiving updates to the status of
      * rear display mode.
      */
+    @Override
     public void addRearDisplayStatusListener(
             @NonNull Consumer<@WindowAreaStatus Integer> consumer) {
         synchronized (mLock) {
             mRearDisplayStatusListeners.add(consumer);
 
-            // If current device state is still invalid, we haven't gotten our initial value yet
+            // If current device state is still invalid, the initial value has not been provided.
             if (mCurrentDeviceState == INVALID_DEVICE_STATE) {
                 return;
             }
-            consumer.accept(getCurrentStatus());
+            consumer.accept(getCurrentRearDisplayModeStatus());
         }
     }
 
@@ -108,6 +156,7 @@
      * Removes a listener no longer interested in receiving updates.
      * @param consumer no longer interested in receiving updates to RearDisplayStatus
      */
+    @Override
     public void removeRearDisplayStatusListener(
             @NonNull Consumer<@WindowAreaStatus Integer> consumer) {
         synchronized (mLock) {
@@ -118,13 +167,17 @@
     /**
      * Creates and starts a rear display session and provides updates to the
      * callback provided. Because this is being called from the OEM provided
-     * extensions, we will post the result of the listener on the executor
+     * extensions, the result of the listener will be posted on the executor
      * provided by the developer at the initial call site.
      *
-     * When we enable rear display mode, we submit a request to {@link DeviceStateManager}
+     * Rear display mode moves the calling application to the display on the device that is
+     * facing the same direction as the rear cameras. This would be the cover display on a fold-in
+     * style device when the device is opened.
+     *
+     * When rear display mode is enabled, a request is made to {@link DeviceStateManager}
      * to override the device state to the state that corresponds to RearDisplay
-     * mode. When the {@link DeviceStateRequest} is activated, we let the
-     * consumer know that the session is active by sending
+     * mode. When the {@link DeviceStateRequest} is activated, the provided {@link Consumer} is
+     * notified that the session is active by receiving
      * {@link WindowAreaComponent#SESSION_STATE_ACTIVE}.
      *
      * @param activity to provide updates to the client on
@@ -132,19 +185,20 @@
      * @param rearDisplaySessionCallback to provide updates to the client on
      * the status of the Session
      */
+    @Override
     public void startRearDisplaySession(@NonNull Activity activity,
             @NonNull Consumer<@WindowAreaSessionState Integer> rearDisplaySessionCallback) {
         synchronized (mLock) {
-            if (mDeviceStateRequest != null) {
+            if (mRearDisplayStateRequest != null) {
                 // Rear display session is already active
                 throw new IllegalStateException(
                         "Unable to start new rear display session as one is already active");
             }
-            mDeviceStateRequest = DeviceStateRequest.newBuilder(mRearDisplayState).build();
+            mRearDisplayStateRequest = DeviceStateRequest.newBuilder(mRearDisplayState).build();
             mDeviceStateManager.requestState(
-                    mDeviceStateRequest,
+                    mRearDisplayStateRequest,
                     mExecutor,
-                    new DeviceStateRequestCallbackAdapter(rearDisplaySessionCallback)
+                    new RearDisplayStateRequestCallbackAdapter(rearDisplaySessionCallback)
             );
         }
     }
@@ -152,13 +206,14 @@
     /**
      * Ends the current rear display session and provides updates to the
      * callback provided. Because this is being called from the OEM provided
-     * extensions, we will post the result of the listener on the executor
-     * provided by the developer.
+     * extensions, the result of the listener will be posted on the executor
+     * provided by the developer at the initial call site.
      */
+    @Override
     public void endRearDisplaySession() {
         synchronized (mLock) {
-            if (mDeviceStateRequest != null || isRearDisplayActive()) {
-                mDeviceStateRequest = null;
+            if (mRearDisplayStateRequest != null || isRearDisplayActive()) {
+                mRearDisplayStateRequest = null;
                 mDeviceStateManager.cancelStateRequest();
             } else {
                 throw new IllegalStateException(
@@ -167,13 +222,176 @@
         }
     }
 
+    /**
+     * Adds a listener interested in receiving updates on the RearDisplayPresentationStatus
+     * of the device. Because this is being called from the OEM provided
+     * extensions, the result of the listener will be posted on the executor
+     * provided by the developer at the initial call site.
+     *
+     * Rear display presentation mode is a feature where an {@link Activity} can present
+     * additional content on a device with a second display that is facing the same direction
+     * as the rear camera (i.e. the cover display on a fold-in style device). The calling
+     * {@link Activity} does not move, whereas in rear display mode it does.
+     *
+     * This listener receives a {@link Pair} with the first item being the
+     * {@link WindowAreaComponent.WindowAreaStatus} that corresponds to the current status of the
+     * feature, and the second being the {@link DisplayMetrics} of the display that would be
+     * presented to when the feature is active.
+     *
+     * Depending on the initial state of the device, the {@link Consumer} will receive either
+     * {@link WindowAreaComponent#STATUS_AVAILABLE} or
+     * {@link WindowAreaComponent#STATUS_UNAVAILABLE} for the status value of the {@link Pair} if
+     * the feature is supported or not in that state respectively. Rear display presentation mode is
+     * currently not supported when the device is folded. When the rear display presentation feature
+     * is triggered, the status is updated to be {@link WindowAreaComponent#STATUS_UNAVAILABLE}.
+     * TODO(b/240727590): Prefix with AREA_
+     *
+     * TODO(b/239833099): Add a STATUS_ACTIVE option to let apps know if a feature is currently
+     *  enabled.
+     *
+     * @param consumer {@link Consumer} interested in receiving updates to the status of
+     * rear display presentation mode.
+     */
     @Override
-    public void onBaseStateChanged(int state) {
+    public void addRearDisplayPresentationStatusListener(
+            @NonNull Consumer<ExtensionWindowAreaStatus> consumer) {
         synchronized (mLock) {
-            mCurrentDeviceBaseState = state;
-            if (state == mCurrentDeviceState) {
-                updateStatusConsumers(getCurrentStatus());
+            mRearDisplayPresentationStatusListeners.add(consumer);
+
+            // If current device state is still invalid, the initial value has not been provided
+            if (mCurrentDeviceState == INVALID_DEVICE_STATE) {
+                return;
             }
+            @WindowAreaStatus int currentStatus = getCurrentRearDisplayPresentationModeStatus();
+            consumer.accept(
+                    new RearDisplayPresentationStatus(currentStatus, getRearDisplayMetrics()));
+        }
+    }
+
+    /**
+     * Removes a listener no longer interested in receiving updates.
+     * @param consumer no longer interested in receiving updates to RearDisplayPresentationStatus
+     */
+    @Override
+    public void removeRearDisplayPresentationStatusListener(
+            @NonNull Consumer<ExtensionWindowAreaStatus> consumer) {
+        synchronized (mLock) {
+            mRearDisplayPresentationStatusListeners.remove(consumer);
+        }
+    }
+
+    /**
+     * Creates and starts a rear display presentation session and sends state updates to the
+     * consumer provided. This consumer will receive a constant represented by
+     * {@link WindowAreaSessionState} to represent the state of the current rear display
+     * session. It will be translated to a more friendly interface in the library.
+     *
+     * Because this is being called from the OEM provided extensions, the library
+     * will post the result of the listener on the executor provided by the developer.
+     *
+     * Rear display presentation mode refers to a feature where an {@link Activity} can present
+     * additional content on a device with a second display that is facing the same direction
+     * as the rear camera (i.e. the cover display on a fold-in style device). The calling
+     * {@link Activity} stays on the user-facing display.
+     *
+     * @param activity that the OEM implementation will use as a base
+     * context and to identify the source display area of the request.
+     * The reference to the activity instance must not be stored in the OEM
+     * implementation to prevent memory leaks.
+     * @param consumer to provide updates to the client on the status of the session
+     * @throws UnsupportedOperationException if this method is called when rear display presentation
+     * mode is not available. This could be to an incompatible device state or when
+     * another process is currently in this mode.
+     */
+    @Override
+    public void startRearDisplayPresentationSession(@NonNull Activity activity,
+            @NonNull Consumer<@WindowAreaSessionState Integer> consumer) {
+        synchronized (mLock) {
+            if (mRearDisplayPresentationController != null) {
+                // Rear display presentation session is already active
+                throw new IllegalStateException(
+                        "Unable to start new rear display presentation session as one is already "
+                                + "active");
+            }
+            if (getCurrentRearDisplayPresentationModeStatus()
+                    != WindowAreaComponent.STATUS_AVAILABLE) {
+                throw new IllegalStateException(
+                        "Unable to start new rear display presentation session as the feature is "
+                                + "is not currently available");
+            }
+
+            mRearDisplayPresentationController = new RearDisplayPresentationController(activity,
+                    stateStatus -> {
+                        synchronized (mLock) {
+                            if (stateStatus == SESSION_STATE_INACTIVE) {
+                                // If the last reported session status was VISIBLE
+                                // then the INVISIBLE state should be dispatched before INACTIVE
+                                // due to not having a good mechanism to know when
+                                // the content is no longer visible before it's fully removed
+                                if (getLastReportedRearDisplayPresentationStatus()
+                                        == SESSION_STATE_VISIBLE) {
+                                    consumer.accept(SESSION_STATE_INVISIBLE);
+                                }
+                                mRearDisplayPresentationController = null;
+                            }
+                            mLastReportedRearDisplayPresentationStatus = stateStatus;
+                            consumer.accept(stateStatus);
+                        }
+                    });
+
+            DeviceStateRequest concurrentDisplayStateRequest = DeviceStateRequest.newBuilder(
+                    mConcurrentDisplayState).build();
+            mDeviceStateManager.requestState(
+                    concurrentDisplayStateRequest,
+                    mExecutor,
+                    mRearDisplayPresentationController
+            );
+        }
+    }
+
+    /**
+     * Ends the current rear display presentation session and provides updates to the
+     * callback provided. When this is ended, the presented content from the calling
+     * {@link Activity} will also be removed from the rear facing display.
+     * Because this is being called from the OEM provided extensions, the result of the listener
+     * will be posted on the executor provided by the developer at the initial call site.
+     *
+     * Cancelling the {@link DeviceStateRequest} and exiting the rear display presentation state,
+     * will remove the presentation window from the cover display as the cover display is no longer
+     * enabled.
+     */
+    @Override
+    public void endRearDisplayPresentationSession() {
+        synchronized (mLock) {
+            if (mRearDisplayPresentationController != null) {
+                mDeviceStateManager.cancelStateRequest();
+            } else {
+                throw new IllegalStateException(
+                        "Unable to cancel a rear display presentation session as there is no "
+                                + "active session");
+            }
+        }
+    }
+
+    @Nullable
+    @Override
+    public ExtensionWindowAreaPresentation getRearDisplayPresentation() {
+        synchronized (mLock) {
+            ExtensionWindowAreaPresentation presentation = null;
+            if (mRearDisplayPresentationController != null) {
+                presentation = mRearDisplayPresentationController.getWindowAreaPresentation();
+            }
+            return presentation;
+        }
+    }
+
+    @Override
+    public void onSupportedStatesChanged(int[] supportedStates) {
+        synchronized (mLock) {
+            mCurrentSupportedDeviceStates = supportedStates;
+            updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
+            updateRearDisplayPresentationStatusListeners(
+                    getCurrentRearDisplayPresentationModeStatus());
         }
     }
 
@@ -181,13 +399,17 @@
     public void onStateChanged(int state) {
         synchronized (mLock) {
             mCurrentDeviceState = state;
-            updateStatusConsumers(getCurrentStatus());
+            updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
+            updateRearDisplayPresentationStatusListeners(
+                    getCurrentRearDisplayPresentationModeStatus());
         }
     }
 
+
     @GuardedBy("mLock")
-    private int getCurrentStatus() {
+    private int getCurrentRearDisplayModeStatus() {
         if (mRearDisplaySessionStatus == WindowAreaComponent.SESSION_STATE_ACTIVE
+                || !ArrayUtils.contains(mCurrentSupportedDeviceStates, mRearDisplayState)
                 || isRearDisplayActive()) {
             return WindowAreaComponent.STATUS_UNAVAILABLE;
         }
@@ -196,19 +418,20 @@
 
     /**
      * Helper method to determine if a rear display session is currently active by checking
-     * if the current device configuration matches that of rear display. This would be true
-     * if there is a device override currently active (base state != current state) and the current
-     * state is that which corresponds to {@code mRearDisplayState}
-     * @return {@code true} if the device is in rear display mode and {@code false} if not
+     * if the current device state is that which corresponds to {@code mRearDisplayState}.
+     *
+     * @return {@code true} if the device is in rear display state {@code false} if not
      */
     @GuardedBy("mLock")
     private boolean isRearDisplayActive() {
-        return (mCurrentDeviceState != mCurrentDeviceBaseState) && (mCurrentDeviceState
-                == mRearDisplayState);
+        return mCurrentDeviceState == mRearDisplayState;
     }
 
     @GuardedBy("mLock")
-    private void updateStatusConsumers(@WindowAreaStatus int windowAreaStatus) {
+    private void updateRearDisplayStatusListeners(@WindowAreaStatus int windowAreaStatus) {
+        if (mRearDisplayState == INVALID_DEVICE_STATE) {
+            return;
+        }
         synchronized (mLock) {
             for (int i = 0; i < mRearDisplayStatusListeners.size(); i++) {
                 mRearDisplayStatusListeners.valueAt(i).accept(windowAreaStatus);
@@ -216,26 +439,95 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private int getCurrentRearDisplayPresentationModeStatus() {
+        if (mCurrentDeviceState == mConcurrentDisplayState
+                || !ArrayUtils.contains(mCurrentSupportedDeviceStates, mConcurrentDisplayState)
+                || isDeviceFolded()) {
+            return WindowAreaComponent.STATUS_UNAVAILABLE;
+        }
+        return WindowAreaComponent.STATUS_AVAILABLE;
+    }
+
+    @GuardedBy("mLock")
+    private boolean isDeviceFolded() {
+        return ArrayUtils.contains(mFoldedDeviceStates, mCurrentDeviceState);
+    }
+
+    @GuardedBy("mLock")
+    private void updateRearDisplayPresentationStatusListeners(
+            @WindowAreaStatus int windowAreaStatus) {
+        if (mConcurrentDisplayState == INVALID_DEVICE_STATE) {
+            return;
+        }
+        RearDisplayPresentationStatus consumerValue = new RearDisplayPresentationStatus(
+                windowAreaStatus, getRearDisplayMetrics());
+        synchronized (mLock) {
+            for (int i = 0; i < mRearDisplayPresentationStatusListeners.size(); i++) {
+                mRearDisplayPresentationStatusListeners.valueAt(i).accept(consumerValue);
+            }
+        }
+    }
+
+    /**
+     * Returns the{@link DisplayMetrics} associated with the rear facing display. If the rear facing
+     * display was not found in the display list, but we have already computed the
+     * {@link DisplayMetrics} for that display, we return the cached value.
+     *
+     * TODO(b/267563768): Update with guidance from Display team for missing displays.
+     *
+     * @throws IllegalArgumentException if the display is not found and there is no cached
+     * {@link DisplayMetrics} for this display.
+     */
+    @GuardedBy("mLock")
+    private DisplayMetrics getRearDisplayMetrics() {
+        Display[] displays = mDisplayManager.getDisplays(
+                DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+        for (int i = 0; i < displays.length; i++) {
+            DisplayAddress.Physical address =
+                    (DisplayAddress.Physical) displays[i].getAddress();
+            if (mRearDisplayAddress == address.getPhysicalDisplayId()) {
+                if (mRearDisplayMetrics == null) {
+                    mRearDisplayMetrics = new DisplayMetrics();
+                }
+                displays[i].getRealMetrics(mRearDisplayMetrics);
+                return mRearDisplayMetrics;
+            }
+        }
+        if (mRearDisplayMetrics != null) {
+            return mRearDisplayMetrics;
+        } else {
+            throw new IllegalArgumentException(
+                    "No display found with the provided display address");
+        }
+    }
+
+    @GuardedBy("mLock")
+    @WindowAreaSessionState
+    private int getLastReportedRearDisplayPresentationStatus() {
+        return mLastReportedRearDisplayPresentationStatus;
+    }
+
     /**
      * Callback for the {@link DeviceStateRequest} to be notified of when the request has been
      * activated or cancelled. This callback provides information to the client library
      * on the status of the RearDisplay session through {@code mRearDisplaySessionCallback}
      */
-    private class DeviceStateRequestCallbackAdapter implements DeviceStateRequest.Callback {
+    private class RearDisplayStateRequestCallbackAdapter implements DeviceStateRequest.Callback {
 
         private final Consumer<Integer> mRearDisplaySessionCallback;
 
-        DeviceStateRequestCallbackAdapter(@NonNull Consumer<Integer> callback) {
+        RearDisplayStateRequestCallbackAdapter(@NonNull Consumer<Integer> callback) {
             mRearDisplaySessionCallback = callback;
         }
 
         @Override
         public void onRequestActivated(@NonNull DeviceStateRequest request) {
             synchronized (mLock) {
-                if (request.equals(mDeviceStateRequest)) {
+                if (request.equals(mRearDisplayStateRequest)) {
                     mRearDisplaySessionStatus = WindowAreaComponent.SESSION_STATE_ACTIVE;
                     mRearDisplaySessionCallback.accept(mRearDisplaySessionStatus);
-                    updateStatusConsumers(getCurrentStatus());
+                    updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
                 }
             }
         }
@@ -243,12 +535,12 @@
         @Override
         public void onRequestCanceled(DeviceStateRequest request) {
             synchronized (mLock) {
-                if (request.equals(mDeviceStateRequest)) {
-                    mDeviceStateRequest = null;
+                if (request.equals(mRearDisplayStateRequest)) {
+                    mRearDisplayStateRequest = null;
                 }
                 mRearDisplaySessionStatus = WindowAreaComponent.SESSION_STATE_INACTIVE;
                 mRearDisplaySessionCallback.accept(mRearDisplaySessionStatus);
-                updateStatusConsumers(getCurrentStatus());
+                updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
             }
         }
     }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 67963a3..d94e8e4 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -154,7 +154,7 @@
                 activityOptions);
 
         // Set adjacent to each other so that the containers below will be invisible.
-        setAdjacentTaskFragments(wct, launchingFragmentToken, secondaryFragmentToken, rule);
+        setAdjacentTaskFragmentsWithRule(wct, launchingFragmentToken, secondaryFragmentToken, rule);
         setCompanionTaskFragment(wct, launchingFragmentToken, secondaryFragmentToken, rule,
                 false /* isStacked */);
     }
@@ -167,7 +167,7 @@
     void expandTaskFragment(@NonNull WindowContainerTransaction wct,
             @NonNull IBinder fragmentToken) {
         resizeTaskFragment(wct, fragmentToken, new Rect());
-        setAdjacentTaskFragments(wct, fragmentToken, null /* secondary */, null /* splitRule */);
+        clearAdjacentTaskFragments(wct, fragmentToken);
         updateWindowingMode(wct, fragmentToken, WINDOWING_MODE_UNDEFINED);
         updateAnimationParams(wct, fragmentToken, TaskFragmentAnimationParams.DEFAULT);
     }
@@ -238,26 +238,37 @@
         wct.reparentActivityToTaskFragment(fragmentToken, reparentActivityToken);
     }
 
-    void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
-            @NonNull IBinder primary, @Nullable IBinder secondary, @Nullable SplitRule splitRule) {
-        if (secondary == null) {
-            wct.clearAdjacentTaskFragments(primary);
-            return;
-        }
-
+    /**
+     * Sets the two given TaskFragments as adjacent to each other with respecting the given
+     * {@link SplitRule} for {@link WindowContainerTransaction.TaskFragmentAdjacentParams}.
+     */
+    void setAdjacentTaskFragmentsWithRule(@NonNull WindowContainerTransaction wct,
+            @NonNull IBinder primary, @NonNull IBinder secondary, @NonNull SplitRule splitRule) {
         WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = null;
         final boolean finishSecondaryWithPrimary =
-                splitRule != null && SplitContainer.shouldFinishSecondaryWithPrimary(splitRule);
+                SplitContainer.shouldFinishSecondaryWithPrimary(splitRule);
         final boolean finishPrimaryWithSecondary =
-                splitRule != null && SplitContainer.shouldFinishPrimaryWithSecondary(splitRule);
+                SplitContainer.shouldFinishPrimaryWithSecondary(splitRule);
         if (finishSecondaryWithPrimary || finishPrimaryWithSecondary) {
             adjacentParams = new WindowContainerTransaction.TaskFragmentAdjacentParams();
             adjacentParams.setShouldDelayPrimaryLastActivityRemoval(finishSecondaryWithPrimary);
             adjacentParams.setShouldDelaySecondaryLastActivityRemoval(finishPrimaryWithSecondary);
         }
+        setAdjacentTaskFragments(wct, primary, secondary, adjacentParams);
+    }
+
+    void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
+            @NonNull IBinder primary, @NonNull IBinder secondary,
+            @Nullable WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams) {
         wct.setAdjacentTaskFragments(primary, secondary, adjacentParams);
     }
 
+    void clearAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
+            @NonNull IBinder fragmentToken) {
+        // Clear primary will also clear secondary.
+        wct.clearAdjacentTaskFragments(fragmentToken);
+    }
+
     void setCompanionTaskFragment(@NonNull WindowContainerTransaction wct,
             @NonNull IBinder primary, @NonNull IBinder secondary, @NonNull SplitRule splitRule,
             boolean isStacked) {
@@ -268,7 +279,7 @@
         } else {
             finishPrimaryWithSecondary = shouldFinishPrimaryWithSecondary(splitRule);
         }
-        wct.setCompanionTaskFragment(primary, finishPrimaryWithSecondary ? secondary : null);
+        setCompanionTaskFragment(wct, primary, finishPrimaryWithSecondary ? secondary : null);
 
         final boolean finishSecondaryWithPrimary;
         if (isStacked) {
@@ -277,7 +288,12 @@
         } else {
             finishSecondaryWithPrimary = shouldFinishSecondaryWithPrimary(splitRule);
         }
-        wct.setCompanionTaskFragment(secondary, finishSecondaryWithPrimary ? primary : null);
+        setCompanionTaskFragment(wct, secondary, finishSecondaryWithPrimary ? primary : null);
+    }
+
+    void setCompanionTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder primary,
+            @Nullable IBinder secondary) {
+        wct.setCompanionTaskFragment(primary, secondary);
     }
 
     void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
index 77284c41..18497ad 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
@@ -17,12 +17,15 @@
 package androidx.window.extensions.embedding;
 
 import android.app.Activity;
-import android.content.res.Configuration;
+import android.os.Binder;
+import android.os.IBinder;
 import android.util.Pair;
 import android.util.Size;
+import android.window.TaskFragmentParentInfo;
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.NonNull;
+import androidx.window.extensions.core.util.function.Function;
 
 /**
  * Client-side descriptor of a split that holds two containers.
@@ -34,8 +37,14 @@
     private final TaskFragmentContainer mSecondaryContainer;
     @NonNull
     private final SplitRule mSplitRule;
+    /** @see SplitContainer#getCurrentSplitAttributes() */
     @NonNull
-    private SplitAttributes mSplitAttributes;
+    private SplitAttributes mCurrentSplitAttributes;
+    /** @see SplitContainer#getDefaultSplitAttributes() */
+    @NonNull
+    private SplitAttributes mDefaultSplitAttributes;
+    @NonNull
+    private final IBinder mToken;
 
     SplitContainer(@NonNull TaskFragmentContainer primaryContainer,
             @NonNull Activity primaryActivity,
@@ -45,7 +54,9 @@
         mPrimaryContainer = primaryContainer;
         mSecondaryContainer = secondaryContainer;
         mSplitRule = splitRule;
-        mSplitAttributes = splitAttributes;
+        mDefaultSplitAttributes = splitRule.getDefaultSplitAttributes();
+        mCurrentSplitAttributes = splitAttributes;
+        mToken = new Binder("SplitContainer");
 
         if (shouldFinishPrimaryWithSecondary(splitRule)) {
             if (mPrimaryContainer.getRunningActivityCount() == 1
@@ -78,19 +89,60 @@
         return mSplitRule;
     }
 
+    /**
+     * Returns the current {@link SplitAttributes} this {@code SplitContainer} is showing.
+     * <p>
+     * If the {@code SplitAttributes} calculator function is not set by
+     * {@link SplitController#setSplitAttributesCalculator(Function)}, the current
+     * {@code SplitAttributes} is either to expand the containers if the size constraints of
+     * {@link #getSplitRule()} are not satisfied,
+     * or the {@link #getDefaultSplitAttributes()}, otherwise.
+     * </p><p>
+     * If the {@code SplitAttributes} calculator function is set, the current
+     * {@code SplitAttributes} will be customized by the function, which can be any
+     * {@code SplitAttributes}.
+     * </p>
+     *
+     * @see SplitAttributes.SplitType.ExpandContainersSplitType
+     */
     @NonNull
-    SplitAttributes getSplitAttributes() {
-        return mSplitAttributes;
+    SplitAttributes getCurrentSplitAttributes() {
+        return mCurrentSplitAttributes;
+    }
+
+    /**
+     * Returns the default {@link SplitAttributes} when the parent task container bounds satisfy
+     * {@link #getSplitRule()} constraints.
+     * <p>
+     * The value is usually from {@link SplitRule#getDefaultSplitAttributes} unless it is overridden
+     * by {@link SplitController#updateSplitAttributes(IBinder, SplitAttributes)}.
+     */
+    @NonNull
+    SplitAttributes getDefaultSplitAttributes() {
+        return mDefaultSplitAttributes;
+    }
+
+    @NonNull
+    IBinder getToken() {
+        return mToken;
     }
 
     /**
      * Updates the {@link SplitAttributes} to this container.
      * It is usually used when there's a folding state change or
-     * {@link SplitController#onTaskFragmentParentInfoChanged(WindowContainerTransaction, int,
-     * Configuration)}.
+     * {@link SplitController#onTaskFragmentParentInfoChanged(WindowContainerTransaction,
+     * int, TaskFragmentParentInfo)}.
      */
-    void setSplitAttributes(@NonNull SplitAttributes splitAttributes) {
-        mSplitAttributes = splitAttributes;
+    void updateCurrentSplitAttributes(@NonNull SplitAttributes splitAttributes) {
+        mCurrentSplitAttributes = splitAttributes;
+    }
+
+    /**
+     * Overrides the default {@link SplitAttributes} to this container, which may be different
+     * from {@link SplitRule#getDefaultSplitAttributes}.
+     */
+    void updateDefaultSplitAttributes(@NonNull SplitAttributes splitAttributes) {
+        mDefaultSplitAttributes = splitAttributes;
     }
 
     @NonNull
@@ -112,7 +164,7 @@
     @NonNull
     SplitInfo toSplitInfo() {
         return new SplitInfo(mPrimaryContainer.toActivityStack(),
-                mSecondaryContainer.toActivityStack(), mSplitAttributes);
+                mSecondaryContainer.toActivityStack(), mCurrentSplitAttributes, mToken);
     }
 
     static boolean shouldFinishPrimaryWithSecondary(@NonNull SplitRule splitRule) {
@@ -171,9 +223,10 @@
     public String toString() {
         return "SplitContainer{"
                 + " primaryContainer=" + mPrimaryContainer
-                + " secondaryContainer=" + mSecondaryContainer
-                + " splitRule=" + mSplitRule
-                + " splitAttributes" + mSplitAttributes
+                + ", secondaryContainer=" + mSecondaryContainer
+                + ", splitRule=" + mSplitRule
+                + ", currentSplitAttributes" + mCurrentSplitAttributes
+                + ", defaultSplitAttributes" + mDefaultSplitAttributes
                 + "}";
     }
 }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 57ba6bb..2c1ddf7 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -87,6 +87,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -230,6 +231,14 @@
         return mSplitAttributesCalculator;
     }
 
+    @Override
+    @NonNull
+    public ActivityOptions setLaunchingActivityStack(@NonNull ActivityOptions options,
+            @NonNull IBinder token) {
+        options.setLaunchTaskFragmentToken(token);
+        return options;
+    }
+
     @NonNull
     @GuardedBy("mLock")
     @VisibleForTesting
@@ -271,6 +280,98 @@
         }
     }
 
+    @Override
+    public void finishActivityStacks(@NonNull Set<IBinder> activityStackTokens) {
+        if (activityStackTokens.isEmpty()) {
+            return;
+        }
+        synchronized (mLock) {
+            // Translate ActivityStack to TaskFragmentContainer.
+            final List<TaskFragmentContainer> pendingFinishingContainers =
+                    activityStackTokens.stream()
+                    .map(token -> {
+                        synchronized (mLock) {
+                            return getContainer(token);
+                        }
+                    }).filter(Objects::nonNull)
+                    .toList();
+
+            if (pendingFinishingContainers.isEmpty()) {
+                return;
+            }
+            // Start transaction with close transit type.
+            final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
+            transactionRecord.setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
+            final WindowContainerTransaction wct = transactionRecord.getTransaction();
+
+            forAllTaskContainers(taskContainer -> {
+                synchronized (mLock) {
+                    final List<TaskFragmentContainer> containers = taskContainer.mContainers;
+                    // Clean up the TaskFragmentContainers by the z-order from the lowest.
+                    for (int i = 0; i < containers.size() - 1; i++) {
+                        final TaskFragmentContainer container = containers.get(i);
+                        if (pendingFinishingContainers.contains(container)) {
+                            // Don't update records here to prevent double invocation.
+                            container.finish(false /* shouldFinishDependant */, mPresenter,
+                                    wct, this, false /* shouldRemoveRecord */);
+                        }
+                    }
+                    // Remove container records.
+                    removeContainers(taskContainer, pendingFinishingContainers);
+                    // Update the change to the client side.
+                    updateContainersInTaskIfVisible(wct, taskContainer.getTaskId());
+                }
+            });
+
+            // Apply the transaction.
+            transactionRecord.apply(false /* shouldApplyIndependently */);
+        }
+    }
+
+    @Override
+    public void invalidateTopVisibleSplitAttributes() {
+        synchronized (mLock) {
+            WindowContainerTransaction wct = mTransactionManager.startNewTransaction()
+                    .getTransaction();
+            forAllTaskContainers(taskContainer -> {
+                synchronized (mLock) {
+                    updateContainersInTaskIfVisible(wct, taskContainer.getTaskId());
+                }
+            });
+            mTransactionManager.getCurrentTransactionRecord()
+                    .apply(false /* shouldApplyIndependently */);
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void forAllTaskContainers(@NonNull Consumer<TaskContainer> callback) {
+        for (int i = mTaskContainers.size() - 1; i >= 0; --i) {
+            callback.accept(mTaskContainers.valueAt(i));
+        }
+    }
+
+    @Override
+    public void updateSplitAttributes(@NonNull IBinder splitInfoToken,
+            @NonNull SplitAttributes splitAttributes) {
+        synchronized (mLock) {
+            final SplitContainer splitContainer = getSplitContainer(splitInfoToken);
+            if (splitContainer == null) {
+                Log.w(TAG, "Cannot find SplitContainer for token:" + splitInfoToken);
+                return;
+            }
+            WindowContainerTransaction wct = mTransactionManager.startNewTransaction()
+                    .getTransaction();
+            if (updateSplitContainerIfNeeded(splitContainer, wct, splitAttributes)) {
+                splitContainer.updateDefaultSplitAttributes(splitAttributes);
+                mTransactionManager.getCurrentTransactionRecord()
+                        .apply(false /* shouldApplyIndependently */);
+            } else {
+                // Abort if the SplitContainer wasn't updated.
+                mTransactionManager.getCurrentTransactionRecord().abort();
+            }
+        }
+    }
+
     /**
      * Called when the transaction is ready so that the organizer can update the TaskFragments based
      * on the changes in transaction.
@@ -424,6 +525,9 @@
             // All overrides will be cleanup.
             container.setLastRequestedBounds(null /* bounds */);
             container.setLastRequestedWindowingMode(WINDOWING_MODE_UNDEFINED);
+            container.clearLastAdjacentTaskFragment();
+            container.setLastCompanionTaskFragment(null /* fragmentToken */);
+            container.setLastRequestAnimationParams(TaskFragmentAnimationParams.DEFAULT);
             cleanupForEnterPip(wct, container);
         } else if (wasInPip) {
             // Exit PIP.
@@ -640,35 +744,6 @@
         }
     }
 
-    /** Returns whether the given {@link TaskContainer} may show in split. */
-    // Suppress GuardedBy warning because lint asks to mark this method as
-    // @GuardedBy(mPresenter.mController.mLock), which is mLock itself
-    @SuppressWarnings("GuardedBy")
-    @GuardedBy("mLock")
-    private boolean mayShowSplit(@NonNull TaskContainer taskContainer) {
-        // No split inside PIP.
-        if (taskContainer.isInPictureInPicture()) {
-            return false;
-        }
-        // Always assume the TaskContainer if SplitAttributesCalculator is set
-        if (mSplitAttributesCalculator != null) {
-            return true;
-        }
-        // Check if the parent container bounds can support any split rule.
-        for (EmbeddingRule rule : mSplitRules) {
-            if (!(rule instanceof SplitRule)) {
-                continue;
-            }
-            final SplitRule splitRule = (SplitRule) rule;
-            final SplitAttributes splitAttributes = mPresenter.computeSplitAttributes(
-                    taskContainer.getTaskProperties(), splitRule, null /* minDimensionsPair */);
-            if (shouldShowSplit(splitAttributes)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     @VisibleForTesting
     @GuardedBy("mLock")
     void onActivityCreated(@NonNull WindowContainerTransaction wct,
@@ -1352,20 +1427,33 @@
      * Removes the container from bookkeeping records.
      */
     void removeContainer(@NonNull TaskFragmentContainer container) {
+        removeContainers(container.getTaskContainer(), Collections.singletonList(container));
+    }
+
+    /**
+     * Removes containers from bookkeeping records.
+     */
+    void removeContainers(@NonNull TaskContainer taskContainer,
+            @NonNull List<TaskFragmentContainer> containers) {
         // Remove all split containers that included this one
-        final TaskContainer taskContainer = container.getTaskContainer();
-        taskContainer.mContainers.remove(container);
+        taskContainer.mContainers.removeAll(containers);
         // Marked as a pending removal which will be removed after it is actually removed on the
         // server side (#onTaskFragmentVanished).
         // In this way, we can keep track of the Task bounds until we no longer have any
         // TaskFragment there.
-        taskContainer.mFinishedContainer.add(container.getTaskFragmentToken());
+        taskContainer.mFinishedContainer.addAll(containers.stream().map(
+                TaskFragmentContainer::getTaskFragmentToken).toList());
 
         // Cleanup any split references.
         final List<SplitContainer> containersToRemove = new ArrayList<>();
         for (SplitContainer splitContainer : taskContainer.mSplitContainers) {
-            if (container.equals(splitContainer.getSecondaryContainer())
-                    || container.equals(splitContainer.getPrimaryContainer())) {
+            if (containersToRemove.contains(splitContainer)) {
+                // Don't need to check because it has been in the remove list.
+                continue;
+            }
+            if (containers.stream().anyMatch(container ->
+                    splitContainer.getPrimaryContainer().equals(container)
+                            || splitContainer.getSecondaryContainer().equals(container))) {
                 containersToRemove.add(splitContainer);
             }
         }
@@ -1373,7 +1461,7 @@
 
         // Cleanup any dependent references.
         for (TaskFragmentContainer containerToUpdate : taskContainer.mContainers) {
-            containerToUpdate.removeContainerToFinishOnExit(container);
+            containerToUpdate.removeContainersToFinishOnExit(containers);
         }
     }
 
@@ -1453,26 +1541,53 @@
         if (splitContainer == null) {
             return;
         }
+
+        updateSplitContainerIfNeeded(splitContainer, wct, null /* splitAttributes */);
+    }
+
+    /**
+     * Updates {@link SplitContainer} with the given {@link SplitAttributes} if the
+     * {@link SplitContainer} is the top most and not finished. If passed {@link SplitAttributes}
+     * are {@code null}, the {@link SplitAttributes} will be calculated with
+     * {@link SplitPresenter#computeSplitAttributes(TaskContainer.TaskProperties, SplitRule, Pair)}.
+     *
+     * @param splitContainer The {@link SplitContainer} to update
+     * @param splitAttributes Update with this {@code splitAttributes} if it is not {@code null}.
+     *                        Otherwise, use the value calculated by
+     *                        {@link SplitPresenter#computeSplitAttributes(
+     *                        TaskContainer.TaskProperties, SplitRule, Pair)}
+     *
+     * @return {@code true} if the update succeed. Otherwise, returns {@code false}.
+     */
+    @GuardedBy("mLock")
+    private boolean updateSplitContainerIfNeeded(@NonNull SplitContainer splitContainer,
+            @NonNull WindowContainerTransaction wct, @Nullable SplitAttributes splitAttributes) {
         if (!isTopMostSplit(splitContainer)) {
             // Skip position update - it isn't the topmost split.
-            return;
+            return false;
         }
         if (splitContainer.getPrimaryContainer().isFinished()
                 || splitContainer.getSecondaryContainer().isFinished()) {
             // Skip position update - one or both containers are finished.
-            return;
+            return false;
         }
-        final TaskContainer taskContainer = splitContainer.getTaskContainer();
-        final SplitRule splitRule = splitContainer.getSplitRule();
-        final Pair<Size, Size> minDimensionsPair = splitContainer.getMinDimensionsPair();
-        final SplitAttributes splitAttributes = mPresenter.computeSplitAttributes(
-                taskContainer.getTaskProperties(), splitRule, minDimensionsPair);
-        splitContainer.setSplitAttributes(splitAttributes);
+        if (splitAttributes == null) {
+            final TaskContainer.TaskProperties taskProperties = splitContainer.getTaskContainer()
+                    .getTaskProperties();
+            final SplitRule splitRule = splitContainer.getSplitRule();
+            final SplitAttributes defaultSplitAttributes = splitContainer
+                    .getDefaultSplitAttributes();
+            final Pair<Size, Size> minDimensionsPair = splitContainer.getMinDimensionsPair();
+            splitAttributes = mPresenter.computeSplitAttributes(taskProperties, splitRule,
+                    defaultSplitAttributes, minDimensionsPair);
+        }
+        splitContainer.updateCurrentSplitAttributes(splitAttributes);
         if (dismissPlaceholderIfNecessary(wct, splitContainer)) {
             // Placeholder was finished, the positions will be updated when its container is emptied
-            return;
+            return true;
         }
-        mPresenter.updateSplitContainer(splitContainer, container, wct);
+        mPresenter.updateSplitContainer(splitContainer, wct);
+        return true;
     }
 
     /** Whether the given split is the topmost split in the Task. */
@@ -1568,7 +1683,7 @@
         final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(activity,
                 placeholderRule.getPlaceholderIntent());
         final SplitAttributes splitAttributes = mPresenter.computeSplitAttributes(taskProperties,
-                placeholderRule, minDimensionsPair);
+                placeholderRule, placeholderRule.getDefaultSplitAttributes(), minDimensionsPair);
         if (!SplitPresenter.shouldShowSplit(splitAttributes)) {
             return false;
         }
@@ -1647,7 +1762,7 @@
             // The placeholder should remain after it was first shown.
             return false;
         }
-        final SplitAttributes splitAttributes = splitContainer.getSplitAttributes();
+        final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes();
         if (SplitPresenter.shouldShowSplit(splitAttributes)) {
             return false;
         }
@@ -1791,6 +1906,20 @@
 
     @Nullable
     @GuardedBy("mLock")
+    SplitContainer getSplitContainer(@NonNull IBinder token) {
+        for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
+            final List<SplitContainer> containers = mTaskContainers.valueAt(i).mSplitContainers;
+            for (SplitContainer container : containers) {
+                if (container.getToken().equals(token)) {
+                    return container;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Nullable
+    @GuardedBy("mLock")
     TaskContainer getTaskContainer(int taskId) {
         return mTaskContainers.get(taskId);
     }
@@ -2064,6 +2193,7 @@
                     transactionRecord.apply(false /* shouldApplyIndependently */);
                     // Amend the request to let the WM know that the activity should be placed in
                     // the dedicated container.
+                    // TODO(b/229680885): skip override launching TaskFragment token by split-rule
                     options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN,
                             launchedInTaskFragment.getTaskFragmentToken());
                     mCurrentIntent = intent;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 2b93682..0408511 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -179,7 +179,7 @@
         final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(
                 primaryActivity, secondaryIntent);
         final SplitAttributes splitAttributes = computeSplitAttributes(taskProperties, rule,
-                minDimensionsPair);
+                rule.getDefaultSplitAttributes(), minDimensionsPair);
         final Rect primaryRelBounds = getRelBoundsForPosition(POSITION_START, taskProperties,
                 splitAttributes);
         final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
@@ -225,7 +225,7 @@
         final Pair<Size, Size> minDimensionsPair = getActivitiesMinDimensionsPair(primaryActivity,
                 secondaryActivity);
         final SplitAttributes splitAttributes = computeSplitAttributes(taskProperties, rule,
-                minDimensionsPair);
+                rule.getDefaultSplitAttributes(), minDimensionsPair);
         final Rect primaryRelBounds = getRelBoundsForPosition(POSITION_START, taskProperties,
                 splitAttributes);
         final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
@@ -334,11 +334,9 @@
     /**
      * Updates the positions of containers in an existing split.
      * @param splitContainer The split container to be updated.
-     * @param updatedContainer The task fragment that was updated and caused this split update.
      * @param wct WindowContainerTransaction that this update should be performed with.
      */
     void updateSplitContainer(@NonNull SplitContainer splitContainer,
-            @NonNull TaskFragmentContainer updatedContainer,
             @NonNull WindowContainerTransaction wct) {
         // Getting the parent configuration using the updated container - it will have the recent
         // value.
@@ -348,8 +346,9 @@
         if (activity == null) {
             return;
         }
-        final TaskProperties taskProperties = getTaskProperties(updatedContainer);
-        final SplitAttributes splitAttributes = splitContainer.getSplitAttributes();
+        final TaskContainer taskContainer = splitContainer.getTaskContainer();
+        final TaskProperties taskProperties = taskContainer.getTaskProperties();
+        final SplitAttributes splitAttributes = splitContainer.getCurrentSplitAttributes();
         final Rect primaryRelBounds = getRelBoundsForPosition(POSITION_START, taskProperties,
                 splitAttributes);
         final Rect secondaryRelBounds = getRelBoundsForPosition(POSITION_END, taskProperties,
@@ -370,7 +369,6 @@
             // When placeholder is shown in split, we should keep the focus on the primary.
             wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
         }
-        final TaskContainer taskContainer = updatedContainer.getTaskContainer();
         final int windowingMode = taskContainer.getWindowingModeForSplitTaskFragment(
                 primaryRelBounds);
         updateTaskFragmentWindowingModeIfRegistered(wct, primaryContainer, windowingMode);
@@ -387,10 +385,9 @@
         // secondaryContainer could not be finished.
         boolean isStacked = !shouldShowSplit(splitAttributes);
         if (isStacked) {
-            setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
-                    null /* secondary */, null /* splitRule */);
+            clearAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken());
         } else {
-            setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
+            setAdjacentTaskFragmentsWithRule(wct, primaryContainer.getTaskFragmentToken(),
                     secondaryContainer.getTaskFragmentToken(), splitRule);
         }
         setCompanionTaskFragment(wct, primaryContainer.getTaskFragmentToken(),
@@ -427,7 +424,7 @@
                 fragmentOptions.getFragmentToken());
         if (container == null) {
             throw new IllegalStateException(
-                    "Creating a task fragment that is not registered with controller.");
+                    "Creating a TaskFragment that is not registered with controller.");
         }
 
         container.setLastRequestedBounds(fragmentOptions.getInitialRelativeBounds());
@@ -441,7 +438,7 @@
         TaskFragmentContainer container = mController.getContainer(fragmentToken);
         if (container == null) {
             throw new IllegalStateException(
-                    "Resizing a task fragment that is not registered with controller.");
+                    "Resizing a TaskFragment that is not registered with controller.");
         }
 
         if (container.areLastRequestedBoundsEqual(relBounds)) {
@@ -458,7 +455,7 @@
             @NonNull IBinder fragmentToken, @WindowingMode int windowingMode) {
         final TaskFragmentContainer container = mController.getContainer(fragmentToken);
         if (container == null) {
-            throw new IllegalStateException("Setting windowing mode for a task fragment that is"
+            throw new IllegalStateException("Setting windowing mode for a TaskFragment that is"
                     + " not registered with controller.");
         }
 
@@ -476,7 +473,7 @@
             @NonNull IBinder fragmentToken, @NonNull TaskFragmentAnimationParams animationParams) {
         final TaskFragmentContainer container = mController.getContainer(fragmentToken);
         if (container == null) {
-            throw new IllegalStateException("Setting animation params for a task fragment that is"
+            throw new IllegalStateException("Setting animation params for a TaskFragment that is"
                     + " not registered with controller.");
         }
 
@@ -489,6 +486,64 @@
         super.updateAnimationParams(wct, fragmentToken, animationParams);
     }
 
+    @Override
+    void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
+            @NonNull IBinder primary, @NonNull IBinder secondary,
+            @Nullable WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams) {
+        final TaskFragmentContainer primaryContainer = mController.getContainer(primary);
+        final TaskFragmentContainer secondaryContainer = mController.getContainer(secondary);
+        if (primaryContainer == null || secondaryContainer == null) {
+            throw new IllegalStateException("setAdjacentTaskFragments on TaskFragment that is"
+                    + " not registered with controller.");
+        }
+
+        if (primaryContainer.isLastAdjacentTaskFragmentEqual(secondary, adjacentParams)
+                && secondaryContainer.isLastAdjacentTaskFragmentEqual(primary, adjacentParams)) {
+            // Return early if the same adjacent TaskFragments were already requested
+            return;
+        }
+
+        primaryContainer.setLastAdjacentTaskFragment(secondary, adjacentParams);
+        secondaryContainer.setLastAdjacentTaskFragment(primary, adjacentParams);
+        super.setAdjacentTaskFragments(wct, primary, secondary, adjacentParams);
+    }
+
+    @Override
+    void clearAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
+            @NonNull IBinder fragmentToken) {
+        final TaskFragmentContainer container = mController.getContainer(fragmentToken);
+        if (container == null) {
+            throw new IllegalStateException("clearAdjacentTaskFragments on TaskFragment that is"
+                    + " not registered with controller.");
+        }
+
+        if (container.isLastAdjacentTaskFragmentEqual(null /* fragmentToken*/, null /* params */)) {
+            // Return early if no adjacent TaskFragment was yet requested
+            return;
+        }
+
+        container.clearLastAdjacentTaskFragment();
+        super.clearAdjacentTaskFragments(wct, fragmentToken);
+    }
+
+    @Override
+    void setCompanionTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder primary,
+            @Nullable IBinder secondary) {
+        final TaskFragmentContainer container = mController.getContainer(primary);
+        if (container == null) {
+            throw new IllegalStateException("setCompanionTaskFragment on TaskFragment that is"
+                    + " not registered with controller.");
+        }
+
+        if (container.isLastCompanionTaskFragmentEqual(secondary)) {
+            // Return early if the same companion TaskFragment was already requested
+            return;
+        }
+
+        container.setLastCompanionTaskFragment(secondary);
+        super.setCompanionTaskFragment(wct, primary, secondary);
+    }
+
     /**
      * Expands the split container if the current split bounds are smaller than the Activity or
      * Intent that is added to the container.
@@ -515,9 +570,9 @@
         // Expand the splitContainer if minimum dimensions are not satisfied.
         final TaskContainer taskContainer = splitContainer.getTaskContainer();
         final SplitAttributes splitAttributes = sanitizeSplitAttributes(
-                taskContainer.getTaskProperties(), splitContainer.getSplitAttributes(),
+                taskContainer.getTaskProperties(), splitContainer.getCurrentSplitAttributes(),
                 minDimensionsPair);
-        splitContainer.setSplitAttributes(splitAttributes);
+        splitContainer.updateCurrentSplitAttributes(splitAttributes);
         if (!shouldShowSplit(splitAttributes)) {
             // If the client side hasn't received TaskFragmentInfo yet, we can't change TaskFragment
             // bounds. Return failure to create a new SplitContainer which fills task bounds.
@@ -540,7 +595,7 @@
     }
 
     static boolean shouldShowSplit(@NonNull SplitContainer splitContainer) {
-        return shouldShowSplit(splitContainer.getSplitAttributes());
+        return shouldShowSplit(splitContainer.getCurrentSplitAttributes());
     }
 
     static boolean shouldShowSplit(@NonNull SplitAttributes splitAttributes) {
@@ -549,12 +604,12 @@
 
     @NonNull
     SplitAttributes computeSplitAttributes(@NonNull TaskProperties taskProperties,
-            @NonNull SplitRule rule, @Nullable Pair<Size, Size> minDimensionsPair) {
+            @NonNull SplitRule rule, @NonNull SplitAttributes defaultSplitAttributes,
+            @Nullable Pair<Size, Size> minDimensionsPair) {
         final Configuration taskConfiguration = taskProperties.getConfiguration();
         final WindowMetrics taskWindowMetrics = getTaskWindowMetrics(taskConfiguration);
         final Function<SplitAttributesCalculatorParams, SplitAttributes> calculator =
                 mController.getSplitAttributesCalculator();
-        final SplitAttributes defaultSplitAttributes = rule.getDefaultSplitAttributes();
         final boolean areDefaultConstraintsSatisfied = rule.checkParentMetrics(taskWindowMetrics);
         if (calculator == null) {
             if (!areDefaultConstraintsSatisfied) {
@@ -957,11 +1012,6 @@
     }
 
     @NonNull
-    static TaskProperties getTaskProperties(@NonNull TaskFragmentContainer container) {
-        return container.getTaskContainer().getTaskProperties();
-    }
-
-    @NonNull
     TaskProperties getTaskProperties(@NonNull Activity activity) {
         final TaskContainer taskContainer = mController.getTaskContainer(
                 mController.getTaskId(activity));
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index f41295b..4b15bb1 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -108,12 +108,6 @@
     }
 
     @NonNull
-    Configuration getConfiguration() {
-        // Make a copy in case the config is updated unexpectedly.
-        return new Configuration(mConfiguration);
-    }
-
-    @NonNull
     TaskProperties getTaskProperties() {
         return new TaskProperties(mDisplayId, mConfiguration);
     }
@@ -157,7 +151,7 @@
 
     @WindowingMode
     private int getWindowingMode() {
-        return getConfiguration().windowConfiguration.getWindowingMode();
+        return mConfiguration.windowConfiguration.getWindowingMode();
     }
 
     /** Whether there is any {@link TaskFragmentContainer} below this Task. */
@@ -220,10 +214,7 @@
         }
     }
 
-    /**
-     * A wrapper class which contains the display ID and {@link Configuration} of a
-     * {@link TaskContainer}
-     */
+    /** A wrapper class which contains the information of {@link TaskContainer} */
     static final class TaskProperties {
         private final int mDisplayId;
         @NonNull
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 861cb49..b38f824 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -37,8 +37,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Client-side container for a stack of activities. Corresponds to an instance of TaskFragment
@@ -116,6 +118,27 @@
     private TaskFragmentAnimationParams mLastAnimationParams = TaskFragmentAnimationParams.DEFAULT;
 
     /**
+     * TaskFragment token that was requested last via
+     * {@link android.window.TaskFragmentOperation#OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS}.
+     */
+    @Nullable
+    private IBinder mLastAdjacentTaskFragment;
+
+    /**
+     * {@link WindowContainerTransaction.TaskFragmentAdjacentParams} token that was requested last
+     * via {@link android.window.TaskFragmentOperation#OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS}.
+     */
+    @Nullable
+    private WindowContainerTransaction.TaskFragmentAdjacentParams mLastAdjacentParams;
+
+    /**
+     * TaskFragment token that was requested last via
+     * {@link android.window.TaskFragmentOperation#OP_TYPE_SET_COMPANION_TASK_FRAGMENT}.
+     */
+    @Nullable
+    private IBinder mLastCompanionTaskFragment;
+
+    /**
      * When the TaskFragment has appeared in server, but is empty, we should remove the TaskFragment
      * if it is still empty after the timeout.
      */
@@ -243,7 +266,7 @@
 
     @NonNull
     ActivityStack toActivityStack() {
-        return new ActivityStack(collectNonFinishingActivities(), isEmpty());
+        return new ActivityStack(collectNonFinishingActivities(), isEmpty(), mToken);
     }
 
     /** Adds the activity that will be reparented to this container. */
@@ -436,10 +459,17 @@
      * Removes a container that should be finished when this container is finished.
      */
     void removeContainerToFinishOnExit(@NonNull TaskFragmentContainer containerToRemove) {
+        removeContainersToFinishOnExit(Collections.singletonList(containerToRemove));
+    }
+
+    /**
+     * Removes container list that should be finished when this container is finished.
+     */
+    void removeContainersToFinishOnExit(@NonNull List<TaskFragmentContainer> containersToRemove) {
         if (mIsFinished) {
             return;
         }
-        mContainersToFinishOnExit.remove(containerToRemove);
+        mContainersToFinishOnExit.removeAll(containersToRemove);
     }
 
     /**
@@ -478,6 +508,16 @@
     @GuardedBy("mController.mLock")
     void finish(boolean shouldFinishDependent, @NonNull SplitPresenter presenter,
             @NonNull WindowContainerTransaction wct, @NonNull SplitController controller) {
+        finish(shouldFinishDependent, presenter, wct, controller, true /* shouldRemoveRecord */);
+    }
+
+    /**
+     * Removes all activities that belong to this process and finishes other containers/activities
+     * configured to finish together.
+     */
+    void finish(boolean shouldFinishDependent, @NonNull SplitPresenter presenter,
+            @NonNull WindowContainerTransaction wct, @NonNull SplitController controller,
+            boolean shouldRemoveRecord) {
         if (!mIsFinished) {
             mIsFinished = true;
             if (mAppearEmptyTimeout != null) {
@@ -494,8 +534,10 @@
 
         // Cleanup the visuals
         presenter.deleteTaskFragment(wct, getTaskFragmentToken());
-        // Cleanup the records
-        controller.removeContainer(this);
+        if (shouldRemoveRecord) {
+            // Cleanup the records
+            controller.removeContainer(this);
+        }
         // Clean up task fragment information
         mInfo = null;
     }
@@ -571,6 +613,7 @@
     /**
      * Checks if last requested bounds are equal to the provided value.
      * The requested bounds are relative bounds in parent coordinate.
+     * @see WindowContainerTransaction#setRelativeBounds
      */
     boolean areLastRequestedBoundsEqual(@Nullable Rect relBounds) {
         return (relBounds == null && mLastRequestedBounds.isEmpty())
@@ -580,6 +623,7 @@
     /**
      * Updates the last requested bounds.
      * The requested bounds are relative bounds in parent coordinate.
+     * @see WindowContainerTransaction#setRelativeBounds
      */
     void setLastRequestedBounds(@Nullable Rect relBounds) {
         if (relBounds == null) {
@@ -589,13 +633,9 @@
         }
     }
 
-    @NonNull
-    Rect getLastRequestedBounds() {
-        return mLastRequestedBounds;
-    }
-
     /**
      * Checks if last requested windowing mode is equal to the provided value.
+     * @see WindowContainerTransaction#setWindowingMode
      */
     boolean isLastRequestedWindowingModeEqual(@WindowingMode int windowingMode) {
         return mLastRequestedWindowingMode == windowingMode;
@@ -603,6 +643,7 @@
 
     /**
      * Updates the last requested windowing mode.
+     * @see WindowContainerTransaction#setWindowingMode
      */
     void setLastRequestedWindowingMode(@WindowingMode int windowingModes) {
         mLastRequestedWindowingMode = windowingModes;
@@ -610,6 +651,7 @@
 
     /**
      * Checks if last requested {@link TaskFragmentAnimationParams} are equal to the provided value.
+     * @see android.window.TaskFragmentOperation#OP_TYPE_SET_ANIMATION_PARAMS
      */
     boolean areLastRequestedAnimationParamsEqual(
             @NonNull TaskFragmentAnimationParams animationParams) {
@@ -618,11 +660,66 @@
 
     /**
      * Updates the last requested {@link TaskFragmentAnimationParams}.
+     * @see android.window.TaskFragmentOperation#OP_TYPE_SET_ANIMATION_PARAMS
      */
     void setLastRequestAnimationParams(@NonNull TaskFragmentAnimationParams animationParams) {
         mLastAnimationParams = animationParams;
     }
 
+    /**
+     * Checks if last requested adjacent TaskFragment token and params are equal to the provided
+     * values.
+     * @see android.window.TaskFragmentOperation#OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS
+     * @see android.window.TaskFragmentOperation#OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS
+     */
+    boolean isLastAdjacentTaskFragmentEqual(@Nullable IBinder fragmentToken,
+            @Nullable WindowContainerTransaction.TaskFragmentAdjacentParams params) {
+        return Objects.equals(mLastAdjacentTaskFragment, fragmentToken)
+                && Objects.equals(mLastAdjacentParams, params);
+    }
+
+    /**
+     * Updates the last requested adjacent TaskFragment token and params.
+     * @see android.window.TaskFragmentOperation#OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS
+     */
+    void setLastAdjacentTaskFragment(@NonNull IBinder fragmentToken,
+            @NonNull WindowContainerTransaction.TaskFragmentAdjacentParams params) {
+        mLastAdjacentTaskFragment = fragmentToken;
+        mLastAdjacentParams = params;
+    }
+
+    /**
+     * Clears the last requested adjacent TaskFragment token and params.
+     * @see android.window.TaskFragmentOperation#OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS
+     */
+    void clearLastAdjacentTaskFragment() {
+        final TaskFragmentContainer lastAdjacentTaskFragment = mLastAdjacentTaskFragment != null
+                ? mController.getContainer(mLastAdjacentTaskFragment)
+                : null;
+        mLastAdjacentTaskFragment = null;
+        mLastAdjacentParams = null;
+        if (lastAdjacentTaskFragment != null) {
+            // Clear the previous adjacent TaskFragment as well.
+            lastAdjacentTaskFragment.clearLastAdjacentTaskFragment();
+        }
+    }
+
+    /**
+     * Checks if last requested companion TaskFragment token is equal to the provided value.
+     * @see android.window.TaskFragmentOperation#OP_TYPE_SET_COMPANION_TASK_FRAGMENT
+     */
+    boolean isLastCompanionTaskFragmentEqual(@Nullable IBinder fragmentToken) {
+        return Objects.equals(mLastCompanionTaskFragment, fragmentToken);
+    }
+
+    /**
+     * Updates the last requested companion TaskFragment token.
+     * @see android.window.TaskFragmentOperation#OP_TYPE_SET_COMPANION_TASK_FRAGMENT
+     */
+    void setLastCompanionTaskFragment(@Nullable IBinder fragmentToken) {
+        mLastCompanionTaskFragment = fragmentToken;
+    }
+
     /** Gets the parent leaf Task id. */
     int getTaskId() {
         return mTaskContainer.getTaskId();
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index a26311e..17909d4 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -275,7 +275,8 @@
 
         assertNotNull(tf);
         assertNotNull(taskContainer);
-        assertEquals(TASK_BOUNDS, taskContainer.getConfiguration().windowConfiguration.getBounds());
+        assertEquals(TASK_BOUNDS, taskContainer.getTaskProperties().getConfiguration()
+                .windowConfiguration.getBounds());
     }
 
     @Test
@@ -288,7 +289,7 @@
         doReturn(true).when(tf).isEmpty();
         doReturn(true).when(mSplitController).launchPlaceholderIfNecessary(mTransaction,
                 mActivity, false /* isOnCreated */);
-        doNothing().when(mSplitPresenter).updateSplitContainer(any(), any(), any());
+        doNothing().when(mSplitPresenter).updateSplitContainer(any(), any());
 
         mSplitController.updateContainer(mTransaction, tf);
 
@@ -341,7 +342,7 @@
 
         mSplitController.updateContainer(mTransaction, tf);
 
-        verify(mSplitPresenter, never()).updateSplitContainer(any(), any(), any());
+        verify(mSplitPresenter, never()).updateSplitContainer(any(), any());
 
         // Verify if the top active split is updated if both of its containers are not finished.
         doReturn(false).when(mSplitController)
@@ -349,7 +350,7 @@
 
         mSplitController.updateContainer(mTransaction, tf);
 
-        verify(mSplitPresenter).updateSplitContainer(splitContainer, tf, mTransaction);
+        verify(mSplitPresenter).updateSplitContainer(splitContainer, mTransaction);
     }
 
     @Test
@@ -366,14 +367,14 @@
         doReturn(false).when(taskContainer).isVisible();
         mSplitController.updateContainer(mTransaction, taskFragmentContainer);
 
-        verify(mSplitPresenter, never()).updateSplitContainer(any(), any(), any());
+        verify(mSplitPresenter, never()).updateSplitContainer(any(), any());
 
         // Update the split when the Task is visible.
         doReturn(true).when(taskContainer).isVisible();
         mSplitController.updateContainer(mTransaction, taskFragmentContainer);
 
         verify(mSplitPresenter).updateSplitContainer(taskContainer.mSplitContainers.get(0),
-                taskFragmentContainer, mTransaction);
+                mTransaction);
     }
 
     @Test
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index a41e63f..8330156 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -177,6 +177,64 @@
     }
 
     @Test
+    public void testSetAdjacentTaskFragments() {
+        final TaskFragmentContainer container0 = mController.newContainer(mActivity, TASK_ID);
+        final TaskFragmentContainer container1 = mController.newContainer(mActivity, TASK_ID);
+
+        mPresenter.setAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken(),
+                container1.getTaskFragmentToken(), null /* adjacentParams */);
+        verify(mTransaction).setAdjacentTaskFragments(container0.getTaskFragmentToken(),
+                container1.getTaskFragmentToken(), null /* adjacentParams */);
+
+        // No request to set the same adjacent TaskFragments.
+        clearInvocations(mTransaction);
+        mPresenter.setAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken(),
+                container1.getTaskFragmentToken(), null /* adjacentParams */);
+
+        verify(mTransaction, never()).setAdjacentTaskFragments(any(), any(), any());
+    }
+
+    @Test
+    public void testClearAdjacentTaskFragments() {
+        final TaskFragmentContainer container0 = mController.newContainer(mActivity, TASK_ID);
+        final TaskFragmentContainer container1 = mController.newContainer(mActivity, TASK_ID);
+
+        // No request to clear as it is not set by default.
+        mPresenter.clearAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken());
+        verify(mTransaction, never()).clearAdjacentTaskFragments(any());
+
+        mPresenter.setAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken(),
+                container1.getTaskFragmentToken(), null /* adjacentParams */);
+        mPresenter.clearAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken());
+        verify(mTransaction).clearAdjacentTaskFragments(container0.getTaskFragmentToken());
+
+        // No request to clear on either of the previous cleared TasKFragments.
+        clearInvocations(mTransaction);
+        mPresenter.clearAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken());
+        mPresenter.clearAdjacentTaskFragments(mTransaction, container1.getTaskFragmentToken());
+
+        verify(mTransaction, never()).clearAdjacentTaskFragments(any());
+    }
+
+    @Test
+    public void testSetCompanionTaskFragment() {
+        final TaskFragmentContainer container0 = mController.newContainer(mActivity, TASK_ID);
+        final TaskFragmentContainer container1 = mController.newContainer(mActivity, TASK_ID);
+
+        mPresenter.setCompanionTaskFragment(mTransaction, container0.getTaskFragmentToken(),
+                container1.getTaskFragmentToken());
+        verify(mTransaction).setCompanionTaskFragment(container0.getTaskFragmentToken(),
+                container1.getTaskFragmentToken());
+
+        // No request to set the same adjacent TaskFragments.
+        clearInvocations(mTransaction);
+        mPresenter.setCompanionTaskFragment(mTransaction, container0.getTaskFragmentToken(),
+                container1.getTaskFragmentToken());
+
+        verify(mTransaction, never()).setCompanionTaskFragment(any(), any());
+    }
+
+    @Test
     public void testUpdateAnimationParams() {
         final TaskFragmentContainer container = mController.newContainer(mActivity, TASK_ID);
 
@@ -228,7 +286,7 @@
 
     @Test
     public void testGetRelBoundsForPosition_expandContainers() {
-        final TaskContainer.TaskProperties taskProperties = getTaskProperty();
+        final TaskContainer.TaskProperties taskProperties = getTaskProperties();
         final SplitAttributes splitAttributes = new SplitAttributes.Builder()
                 .setSplitType(new SplitAttributes.SplitType.ExpandContainersSplitType())
                 .build();
@@ -248,7 +306,7 @@
 
     @Test
     public void testGetRelBoundsForPosition_expandContainers_isRelativeToParent() {
-        final TaskContainer.TaskProperties taskProperties = getTaskProperty(
+        final TaskContainer.TaskProperties taskProperties = getTaskProperties(
                 new Rect(100, 100, 500, 1000));
         final SplitAttributes splitAttributes = new SplitAttributes.Builder()
                 .setSplitType(new SplitAttributes.SplitType.ExpandContainersSplitType())
@@ -273,7 +331,7 @@
                 false /* splitHorizontally */);
         final Rect secondaryBounds = getSplitBounds(false /* isPrimary */,
                 false /* splitHorizontally */);
-        final TaskContainer.TaskProperties taskProperties = getTaskProperty();
+        final TaskContainer.TaskProperties taskProperties = getTaskProperties();
         SplitAttributes splitAttributes = new SplitAttributes.Builder()
                 .setSplitType(SplitAttributes.SplitType.RatioSplitType.splitEqually())
                 .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
@@ -339,7 +397,7 @@
         // Offset TaskBounds to 100, 100. The returned rel bounds shouldn't be affected.
         final Rect taskBounds = new Rect(TASK_BOUNDS);
         taskBounds.offset(100, 100);
-        final TaskContainer.TaskProperties taskProperties = getTaskProperty(taskBounds);
+        final TaskContainer.TaskProperties taskProperties = getTaskProperties(taskBounds);
         SplitAttributes splitAttributes = new SplitAttributes.Builder()
                 .setSplitType(SplitAttributes.SplitType.RatioSplitType.splitEqually())
                 .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
@@ -400,7 +458,7 @@
                 true /* splitHorizontally */);
         final Rect secondaryBounds = getSplitBounds(false /* isPrimary */,
                 true /* splitHorizontally */);
-        final TaskContainer.TaskProperties taskProperties = getTaskProperty();
+        final TaskContainer.TaskProperties taskProperties = getTaskProperties();
         SplitAttributes splitAttributes = new SplitAttributes.Builder()
                 .setSplitType(SplitAttributes.SplitType.RatioSplitType.splitEqually())
                 .setLayoutDirection(SplitAttributes.LayoutDirection.TOP_TO_BOTTOM)
@@ -442,7 +500,7 @@
                 false /* splitHorizontally */);
         final Rect secondaryBounds = getSplitBounds(false /* isPrimary */,
                 false /* splitHorizontally */);
-        final TaskContainer.TaskProperties taskProperties = getTaskProperty();
+        final TaskContainer.TaskProperties taskProperties = getTaskProperties();
         final SplitAttributes splitAttributes = new SplitAttributes.Builder()
                 .setSplitType(new SplitAttributes.SplitType.HingeSplitType(
                         SplitAttributes.SplitType.RatioSplitType.splitEqually()
@@ -506,7 +564,7 @@
 
     @Test
     public void testGetRelBoundsForPosition_fallbackToExpandContainers() {
-        final TaskContainer.TaskProperties taskProperties = getTaskProperty();
+        final TaskContainer.TaskProperties taskProperties = getTaskProperties();
         final SplitAttributes splitAttributes = new SplitAttributes.Builder()
                 .setSplitType(new SplitAttributes.SplitType.HingeSplitType(
                         new SplitAttributes.SplitType.ExpandContainersSplitType()
@@ -528,7 +586,7 @@
 
     @Test
     public void testGetRelBoundsForPosition_useHingeSplitType() {
-        final TaskContainer.TaskProperties taskProperties = getTaskProperty();
+        final TaskContainer.TaskProperties taskProperties = getTaskProperties();
         final SplitAttributes splitAttributes = new SplitAttributes.Builder()
                 .setSplitType(new SplitAttributes.SplitType.HingeSplitType(
                         new SplitAttributes.SplitType.ExpandContainersSplitType()
@@ -581,13 +639,13 @@
                 splitContainer, mActivity, secondaryActivity, null /* secondaryIntent */));
         verify(mPresenter, never()).expandTaskFragment(any(), any());
 
-        splitContainer.setSplitAttributes(SPLIT_ATTRIBUTES);
+        splitContainer.updateCurrentSplitAttributes(SPLIT_ATTRIBUTES);
         doReturn(createActivityInfoWithMinDimensions()).when(secondaryActivity).getActivityInfo();
         assertEquals(RESULT_EXPAND_FAILED_NO_TF_INFO, mPresenter.expandSplitContainerIfNeeded(
                 mTransaction, splitContainer, mActivity, secondaryActivity,
                 null /* secondaryIntent */));
 
-        splitContainer.setSplitAttributes(SPLIT_ATTRIBUTES);
+        splitContainer.updateCurrentSplitAttributes(SPLIT_ATTRIBUTES);
         primaryTf.setInfo(mTransaction, createMockTaskFragmentInfo(primaryTf, mActivity));
         secondaryTf.setInfo(mTransaction,
                 createMockTaskFragmentInfo(secondaryTf, secondaryActivity));
@@ -597,7 +655,7 @@
         verify(mPresenter).expandTaskFragment(mTransaction, primaryTf.getTaskFragmentToken());
         verify(mPresenter).expandTaskFragment(mTransaction, secondaryTf.getTaskFragmentToken());
 
-        splitContainer.setSplitAttributes(SPLIT_ATTRIBUTES);
+        splitContainer.updateCurrentSplitAttributes(SPLIT_ATTRIBUTES);
         clearInvocations(mPresenter);
 
         assertEquals(RESULT_EXPANDED, mPresenter.expandSplitContainerIfNeeded(mTransaction,
@@ -639,37 +697,35 @@
                 .setFinishPrimaryWithSecondary(DEFAULT_FINISH_PRIMARY_WITH_SECONDARY)
                 .setDefaultSplitAttributes(SPLIT_ATTRIBUTES)
                 .build();
-        final TaskContainer.TaskProperties taskProperties = getTaskProperty();
+        final TaskContainer.TaskProperties taskProperties = getTaskProperties();
 
         assertEquals(SPLIT_ATTRIBUTES, mPresenter.computeSplitAttributes(taskProperties,
-                splitPairRule, null /* minDimensionsPair */));
+                splitPairRule, SPLIT_ATTRIBUTES,  null /* minDimensionsPair */));
 
         final Pair<Size, Size> minDimensionsPair = new Pair<>(
                 new Size(TASK_BOUNDS.width(), TASK_BOUNDS.height()), null);
 
         assertEquals(EXPAND_CONTAINERS_ATTRIBUTES, mPresenter.computeSplitAttributes(taskProperties,
-                splitPairRule, minDimensionsPair));
+                splitPairRule, SPLIT_ATTRIBUTES, minDimensionsPair));
 
         taskProperties.getConfiguration().windowConfiguration.setBounds(new Rect(
                 TASK_BOUNDS.left + 1, TASK_BOUNDS.top + 1, TASK_BOUNDS.right + 1,
                 TASK_BOUNDS.bottom + 1));
 
         assertEquals(EXPAND_CONTAINERS_ATTRIBUTES, mPresenter.computeSplitAttributes(taskProperties,
-                splitPairRule, null /* minDimensionsPair */));
+                splitPairRule, SPLIT_ATTRIBUTES, null /* minDimensionsPair */));
 
         final SplitAttributes splitAttributes = new SplitAttributes.Builder()
-                .setSplitType(
-                        new SplitAttributes.SplitType.HingeSplitType(
-                                SplitAttributes.SplitType.RatioSplitType.splitEqually()
-                        )
-                ).build();
+                .setSplitType(new SplitAttributes.SplitType.HingeSplitType(
+                        SplitAttributes.SplitType.RatioSplitType.splitEqually()))
+                .build();
         final Function<SplitAttributesCalculatorParams, SplitAttributes> calculator =
                 params -> splitAttributes;
 
         mController.setSplitAttributesCalculator(calculator);
 
         assertEquals(splitAttributes, mPresenter.computeSplitAttributes(taskProperties,
-                splitPairRule, null /* minDimensionsPair */));
+                splitPairRule, SPLIT_ATTRIBUTES, null /* minDimensionsPair */));
     }
 
     @Test
@@ -696,14 +752,15 @@
         doReturn(activityConfig).when(mActivityResources).getConfiguration();
         doReturn(new ActivityInfo()).when(activity).getActivityInfo();
         doReturn(mock(IBinder.class)).when(activity).getActivityToken();
+        doReturn(TASK_ID).when(activity).getTaskId();
         return activity;
     }
 
-    private static TaskContainer.TaskProperties getTaskProperty() {
-        return getTaskProperty(TASK_BOUNDS);
+    private static TaskContainer.TaskProperties getTaskProperties() {
+        return getTaskProperties(TASK_BOUNDS);
     }
 
-    private static TaskContainer.TaskProperties getTaskProperty(@NonNull Rect taskBounds) {
+    private static TaskContainer.TaskProperties getTaskProperties(@NonNull Rect taskBounds) {
         final Configuration configuration = new Configuration();
         configuration.windowConfiguration.setBounds(taskBounds);
         return new TaskContainer.TaskProperties(DEFAULT_DISPLAY, configuration);
diff --git a/libs/WindowManager/Jetpack/window-extensions-release.aar b/libs/WindowManager/Jetpack/window-extensions-release.aar
index cddbf469..7cd5dd6 100644
--- a/libs/WindowManager/Jetpack/window-extensions-release.aar
+++ b/libs/WindowManager/Jetpack/window-extensions-release.aar
Binary files differ
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index a93f090..6fbebe2 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dubbeltik buite ’n program om dit te herposisioneer"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Het dit"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Vou uit vir meer inligting."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Herbegin vir ’n beter aansig?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Jy kan die app herbegin sodat dit beter op jou skerm lyk, maar jy sal dalk jou vordering of enige ongestoorde veranderinge verloor"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Kanselleer"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Herbegin"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Moenie weer wys nie"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimeer"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Maak klein"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Maak toe"</string>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index 032767e..9e06c54 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ቦታውን ለመቀየር ከመተግበሪያው ውጪ ሁለቴ መታ ያድርጉ"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"ገባኝ"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ለተጨማሪ መረጃ ይዘርጉ።"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"ለተሻለ ዕይታ እንደገና ይጀመር?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"በማያ ገጽዎ ላይ የተሻለ ሆኖ እንዲታይ መተግበሪያውን እንደገና ማስጀመር ይችላሉ ነገር ግን የደረሱበትን የሂደት ደረጃ ወይም ማናቸውንም ያልተቀመጡ ለውጦች ሊያጡ ይችላሉ"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"ይቅር"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"እንደገና ያስጀምሩ"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"ዳግም አታሳይ"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"አስፋ"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"አሳንስ"</string>
     <string name="close_button_text" msgid="2913281996024033299">"ዝጋ"</string>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 9bbee53..edf1c28 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"انقر مرّتين خارج تطبيق لتغيير موضعه."</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"حسنًا"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"التوسيع للحصول على مزيد من المعلومات"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"هل تريد إعادة تشغيل التطبيق لعرضه بشكل أفضل؟"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"يمكنك إعادة تشغيل التطبيق حتى يظهر بشكل أفضل على شاشتك، ولكن قد تفقد تقدمك أو أي تغييرات غير محفوظة."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"إلغاء"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"إعادة التشغيل"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"عدم عرض مربّع حوار التأكيد مجددًا"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"تكبير"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"تصغير"</string>
     <string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index f7ea139..66e85a7 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"এপ্‌টোৰ স্থান সলনি কৰিবলৈ ইয়াৰ বাহিৰত দুবাৰ টিপক"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"বুজি পালোঁ"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"অধিক তথ্যৰ বাবে বিস্তাৰ কৰক।"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"উন্নতভাৱে দেখা পাবলৈ ৰিষ্টাৰ্ট কৰিবনে?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"আপোনাৰ স্ক্ৰীনত উন্নতভাৱে দেখা পাবলৈ আপুনি এপ্‌টো ৰিষ্টাৰ্ট কৰিব পাৰে, কিন্তু আপুনি আপোনাৰ অগ্ৰগতি অথবা ছেভ নকৰা যিকোনো সালসলনি হেৰুৱাব পাৰে"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"বাতিল কৰক"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"ৰিষ্টাৰ্ট কৰক"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"পুনৰাই নেদেখুৱাব"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"সৰ্বাধিক মাত্ৰালৈ বঢ়াওক"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"মিনিমাইজ কৰক"</string>
     <string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 86b7714..7df6797 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tətbiqin yerini dəyişmək üçün kənarına iki dəfə toxunun"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ətraflı məlumat üçün genişləndirin."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Daha yaxşı görünüş üçün yenidən başladılsın?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Tətbiqi yenidən başlada bilərsiniz ki, ekranınızda daha yaxşı görünsün, lakin irəliləyişi və ya yadda saxlanmamış dəyişiklikləri itirə bilərsiniz"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Ləğv edin"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Yenidən başladın"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Yenidən göstərməyin"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Böyüdün"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Kiçildin"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Bağlayın"</string>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index 4a1ee7a..f46dddc 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvaput dodirnite izvan aplikacije da biste promenili njenu poziciju"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Važi"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite za još informacija."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Želite li da restartujete radi boljeg prikaza?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Možete da restartujete aplikaciju da bi izgledala bolje na ekranu, s tim što možete da izgubite ono što ste uradili ili nesačuvane promene, ako ih ima"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Otkaži"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Restartuj"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne prikazuj ponovo"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Uvećajte"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Umanjite"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Zatvorite"</string>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index 1986699..0dc0a62 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Двойчы націсніце экран па-за праграмай, каб перамясціць яе"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Зразумела"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Разгарнуць для дадатковай інфармацыі"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Перазапусціць?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Вы можаце перазапусціць праграму, каб яна выглядала лепш на вашым экране, але пры гэтым могуць знікнуць даныя пра ваш прагрэс або незахаваныя змяненні"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Скасаваць"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Перазапусціць"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Больш не паказваць"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Разгарнуць"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Згарнуць"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Закрыць"</string>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index b8a0316..71036cc 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Докоснете два пъти извън дадено приложение, за да промените позицията му"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Разбрах"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Разгъване за още информация."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Да се рестартира ли с цел подобряване на изгледа?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Можете да рестартирате приложението, за да изглежда по-добре на екрана. Възможно е обаче да загубите напредъка си или незапазените промени"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Отказ"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Рестартиране"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Да не се показва отново"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Увеличаване"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Намаляване"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index 40395fa..0dc30ed 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"কোনও অ্যাপের স্থান পরিবর্তন করতে তার বাইরে ডবল ট্যাপ করুন"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"বুঝেছি"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"আরও তথ্যের জন্য বড় করুন।"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"আরও ভালভাবে দেখার জন্য রিস্টার্ট করবেন?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"স্ক্রিনে আরও ভালভাবে দেখার জন্য আপনি অ্যাপ রিস্টার্ট করতে পারবেন, এর ফলে চলতে থাকা কোনও প্রক্রিয়া বা সেভ না করা পরিবর্তন হারিয়ে যেতে পারে"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"বাতিল করুন"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"রিস্টার্ট করুন"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"আর দেখতে চাই না"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"বড় করুন"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"ছোট করুন"</string>
     <string name="close_button_text" msgid="2913281996024033299">"বন্ধ করুন"</string>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index daef1a0..ae817b0 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvaput dodirnite izvan aplikacije da promijenite njen položaj"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Razumijem"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite za više informacija."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Ponovo pokrenuti za bolji prikaz?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Možete ponovo pokrenuti aplikaciju da bolje izgleda na ekranu, ali možete izgubiti napredak ili izmjene koje nisu sačuvane"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Otkaži"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Ponovo pokreni"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne prikazuj ponovo"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiziranje"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimiziranje"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Zatvaranje"</string>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 85edc20..cbc23c0 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Fes doble toc fora d\'una aplicació per canviar-ne la posició"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entesos"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Desplega per obtenir més informació."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Vols reiniciar per a una millor visualització?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Pots reiniciar l\'aplicació perquè es vegi millor en pantalla, però és possible que perdis el teu progrés o qualsevol canvi que no hagis desat"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Cancel·la"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Reinicia"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"No ho tornis a mostrar"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximitza"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimitza"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Tanca"</string>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index ce11197..92481dd 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvojitým klepnutím mimo aplikaci změníte její umístění"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Rozbalením zobrazíte další informace."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Restartovat pro lepší zobrazení?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Aplikaci můžete restartovat, aby na obrazovce vypadala lépe, ale můžete přijít o svůj postup nebo o neuložené změny"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Zrušit"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Restartovat"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Tuto zprávu příště nezobrazovat"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximalizovat"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimalizovat"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Zavřít"</string>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 38acf45..6cfb5c1 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tryk to gange uden for en app for at justere dens placering"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Udvid for at få flere oplysninger."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Vil du genstarte for at få en bedre visning?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Du kan genstarte appen, så den ser bedre ud på din skærm, men du mister muligvis dine fremskridt og de ændringer, der ikke gemt"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Annuller"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Genstart"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Vis ikke igen"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimér"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Luk"</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index d455fc6..56cac8a 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Außerhalb einer App doppeltippen, um die Position zu ändern"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ok"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Für weitere Informationen maximieren."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Für bessere Darstellung neu starten?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Du kannst die App neu starten, damit sie an die Bildschirmabmessungen deines Geräts angepasst dargestellt wird – jedoch können dadurch dein Fortschritt oder nicht gespeicherte Änderungen verloren gehen."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Abbrechen"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Neu starten"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Nicht mehr anzeigen"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximieren"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimieren"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Schließen"</string>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index 051a20d..9393681 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Πατήστε δύο φορές έξω από μια εφαρμογή για να αλλάξετε τη θέση της"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Το κατάλαβα"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ανάπτυξη για περισσότερες πληροφορίες."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Επανεκκίνηση για καλύτερη προβολή;"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Μπορείτε να επανεκκινήσετε την εφαρμογή για να προβάλλεται καλύτερα στην οθόνη σας, αλλά η πρόοδός σας και τυχόν μη αποθηκευμένες αλλαγές ενδέχεται να χαθούν."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Ακύρωση"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Επανεκκίνηση"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Να μην εμφανιστεί ξανά"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Μεγιστοποίηση"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Ελαχιστοποίηση"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Κλείσιμο"</string>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index 7b569f2..0a83f65 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Presiona dos veces fuera de una app para cambiar su ubicación"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expande para obtener más información."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"¿Quieres reiniciar para que se vea mejor?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Puedes reiniciar la app para que se vea mejor en la pantalla, pero podrías perder tu progreso o cualquier cambio que no hayas guardado"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Cancelar"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Reiniciar"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"No volver a mostrar"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index b9ee866..610aa18 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toca dos veces fuera de una aplicación para cambiarla de posición"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Mostrar más información"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"¿Reiniciar para que se vea mejor?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Puedes reiniciar la aplicación para que se vea mejor en la pantalla, pero puedes perder tu progreso o cualquier cambio que no hayas guardado"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Cancelar"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Reiniciar"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"No volver a mostrar"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index de569e6..8ec8a6c 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Topeltpuudutage rakendusest väljaspool, et selle asendit muuta"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Selge"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Laiendage lisateabe saamiseks."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Kas taaskäivitada parema vaate saavutamiseks?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Saate rakenduse taaskäivitada, et see näeks ekraanikuval parem välja, kuid võite kaotada edenemise või salvestamata muudatused"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Tühista"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Taaskäivita"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ära kuva uuesti"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimeeri"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimeeri"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Sule"</string>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index c05b3c7..86596c4 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Aplikazioaren posizioa aldatzeko, sakatu birritan haren kanpoaldea"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ados"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Informazio gehiago lortzeko, zabaldu hau."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Aplikazioa berrabiarazi nahi duzu itxura hobea izan dezan?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Aplikazioa berrabiarazi egin dezakezu itxura hobea izan dezan, baina agian garapena edo gorde gabeko aldaketak galduko dituzu"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Utzi"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Berrabiarazi"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ez erakutsi berriro"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximizatu"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizatu"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Itxi"</string>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index f7d52f9..c3b9e37 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"برای جابه‌جا کردن برنامه، بیرون از آن دوضربه بزنید"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"متوجه‌ام"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"برای اطلاعات بیشتر، گسترده کنید."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"برای نمایش بهتر بازراه‌اندازی شود؟"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"می‌توانید برنامه را بازراه‌اندازی کنید تا بهتر روی صفحه‌نمایش نشان داده شود، اما ممکن است پیشرفت یا تغییرات ذخیره‌نشده را ازدست بدهید"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"لغو کردن"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"بازراه‌اندازی"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"دوباره نشان داده نشود"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"بزرگ کردن"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"کوچک کردن"</string>
     <string name="close_button_text" msgid="2913281996024033299">"بستن"</string>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index 91120d4..7ef1449 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Kaksoisnapauta sovelluksen ulkopuolella, jos haluat siirtää sitä"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Katso lisätietoja laajentamalla."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Käynnistetäänkö sovellus uudelleen, niin saat paremman näkymän?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Voit käynnistää sovelluksen uudelleen, jotta se näyttää paremmalta näytöllä, mutta saatat menettää edistymisesi tai tallentamattomat muutokset"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Peru"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Käynnistä uudelleen"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Älä näytä uudelleen"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Suurenna"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Pienennä"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Sulje"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 59bd339..2a64e9d 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Touchez deux fois à côté d\'une application pour la repositionner"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développer pour en savoir plus."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Redémarrer pour un meilleur affichage?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Vous pouvez redémarrer l\'application pour qu\'elle s\'affiche mieux sur votre écran, mais il se peut que vous perdiez votre progression ou toute modification non enregistrée"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Annuler"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Redémarrer"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne plus afficher"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Agrandir"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Réduire"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index 41de4db..0655af8 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Appuyez deux fois en dehors d\'une appli pour la repositionner"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développez pour obtenir plus d\'informations"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Redémarrer pour améliorer l\'affichage ?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Vous pouvez redémarrer l\'appli pour en améliorer son aspect sur votre écran, mais vous risquez de perdre votre progression ou les modifications non enregistrées"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Annuler"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Redémarrer"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne plus afficher"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Agrandir"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Réduire"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index 573e17e..d7dbdfb 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toca dúas veces fóra da aplicación para cambiala de posición"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Despregar para obter máis información."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Queres reiniciar a aplicación para que se vexa mellor?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Podes reiniciar a aplicación para que se vexa mellor na pantalla, pero podes perder o progreso que levas feito ou calquera cambio que non gardases"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Cancelar"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Reiniciar"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Non mostrar outra vez"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Pechar"</string>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index 35e9607..78abb5d 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"કોઈ ઍપની જગ્યા બદલવા માટે, તેની બહાર બે વાર ટૅપ કરો"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"સમજાઈ ગયું"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"વધુ માહિતી માટે મોટું કરો."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"બહેતર વ્યૂ માટે ફરીથી શરૂ કરીએ?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"તમે ઍપને ફરીથી શરૂ કરી શકો છો, જેથી તે તમારી સ્ક્રીન પર વધુ સારી રીતે દેખાય, પરંતુ આમ કરવાથી તમે તમારી ઍપ પર કરી હોય એવી કોઈ પ્રક્રિયાની પ્રગતિ અથવા સાચવ્યા ન હોય એવો કોઈપણ ફેરફાર ગુમાવી શકો છો"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"રદ કરો"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"ફરી શરૂ કરો"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"ફરીથી બતાવશો નહીં"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"મોટું કરો"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"નાનું કરો"</string>
     <string name="close_button_text" msgid="2913281996024033299">"બંધ કરો"</string>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index 173029a..4ff3236 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"किसी ऐप्लिकेशन की जगह बदलने के लिए, उसके बाहर दो बार टैप करें"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"ठीक है"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ज़्यादा जानकारी के लिए बड़ा करें."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"बेहतर व्यू पाने के लिए ऐप्लिकेशन को रीस्टार्ट करना है?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"स्क्रीन पर ऐप्लिकेशन का बेहतर व्यू पाने के लिए उसे रीस्टार्ट करें. हालांकि, आपने जो बदलाव सेव नहीं किए हैं या अब तक जो काम किए हैं उनका डेटा, ऐप्लिकेशन रीस्टार्ट करने पर मिट सकता है"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"रद्द करें"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"रीस्टार्ट करें"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"फिर से न दिखाएं"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"बड़ा करें"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"विंडो छोटी करें"</string>
     <string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index c45bb56..c2dc967 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvaput dodirnite izvan aplikacije da biste je premjestili"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Shvaćam"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite da biste saznali više."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Želite li ponovno pokrenuti za bolji pregled?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Možete ponovno pokrenuti aplikaciju tako da bolje izgleda na zaslonu, no mogli biste izgubiti napredak ili sve nespremljene promjene"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Odustani"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Pokreni ponovno"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne prikazuj ponovno"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiziraj"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimiziraj"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Zatvori"</string>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index 7c45113..fc86b4e 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Koppintson duplán az alkalmazáson kívül az áthelyezéséhez"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Értem"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Kibontással további információkhoz juthat."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Újraindítja a jobb megjelenítés érdekében?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Újraindíthatja az alkalmazást a képernyőn való jobb megjelenítés érdekében, de elveszítheti az előrehaladását és az esetleges nem mentett változásokat"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Mégse"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Újraindítás"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne jelenjen meg többé"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Teljes méret"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Kis méret"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Bezárás"</string>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index c26c540..b7b5315 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Կրկնակի հպեք հավելվածի կողքին՝ այն տեղափոխելու համար"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Եղավ"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ծավալեք՝ ավելին իմանալու համար։"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Վերագործարկե՞լ հավելվածը"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Դուք կարող եք վերագործարկել հավելվածը, որպեսզի այն ավելի լավ ցուցադրվի ձեր էկրանին, սակայն ձեր առաջընթացը և չպահված փոփոխությունները կկորեն"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Չեղարկել"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Վերագործարկել"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Այլևս ցույց չտալ"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Ծավալել"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Ծալել"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Փակել"</string>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index 8247309..4fec321 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ketuk dua kali di luar aplikasi untuk mengubah posisinya"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Oke"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Luaskan untuk melihat informasi selengkapnya."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Mulai ulang untuk tampilan yang lebih baik?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Anda dapat memulai ulang aplikasi agar terlihat lebih baik di layar, tetapi Anda mungkin kehilangan progres atau perubahan yang belum disimpan"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Batal"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Mulai ulang"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Jangan tampilkan lagi"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimalkan"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimalkan"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index b64f2d5..54aaf4a 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ýttu tvisvar utan við forrit til að færa það"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ég skil"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Stækka til að sjá frekari upplýsingar."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Viltu endurræsa til að fá betri sýn?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Þú getur endurræst forritið svo það falli betur að skjánum en þú gætir tapað framvindunni eða óvistuðum breytingum"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Hætta við"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Endurræsa"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ekki sýna þetta aftur"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Stækka"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minnka"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Loka"</string>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 5f204b2..2a093fc 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"צריך להקיש הקשה כפולה מחוץ לאפליקציה כדי למקם אותה מחדש"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"הבנתי"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"מרחיבים כדי לקבל מידע נוסף."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"להפעיל מחדש לתצוגה טובה יותר?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"אפשר להפעיל מחדש את האפליקציה כדי שהיא תוצג באופן טוב יותר במסך, אבל ייתכן שההתקדמות שלך או כל שינוי שלא נשמר יאבדו"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"ביטול"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"הפעלה מחדש"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"אין צורך להציג את זה שוב"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"הגדלה"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"מזעור"</string>
     <string name="close_button_text" msgid="2913281996024033299">"סגירה"</string>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 82048c9..04804e4 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ორმაგად შეეხეთ აპის გარშემო სივრცეს, რათა ის სხვაგან გადაიტანოთ"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"გასაგებია"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"დამატებითი ინფორმაციისთვის გააფართოეთ."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"გსურთ გადატვირთვა უკეთესი ხედისთვის?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"შეგიძლიათ გადატვირთოთ აპი იმისათვის, რომ თქვენს ეკრანზე უკეთესად გამოჩნდეს, თუმცა თქვენ მიერ შესრულებული მოქმედებები შეიძლება დაიკარგოს ან ცვლილებების შენახვა ვერ მოხერხდეს"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"გაუქმება"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"გადატვირთვა"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"აღარ გამოჩნდეს"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"მაქსიმალურად გაშლა"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"ჩაკეცვა"</string>
     <string name="close_button_text" msgid="2913281996024033299">"დახურვა"</string>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index ed4a14b..4aca751 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Қолданбаның орнын өзгерту үшін одан тыс жерді екі рет түртіңіз."</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Түсінікті"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Толығырақ ақпарат алу үшін терезені жайыңыз."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Көріністі жақсарту үшін өшіріп қосу керек пе?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Экранда жақсырақ көрінуі үшін қолданбаны өшіріп қосуыңызға болады, бірақ мұндайда ағымдағы прогресс өшіп қалуы немесе сақталмаған өзгерістерді жоғалтуыңыз мүмкін."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Бас тарту"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Өшіріп қосу"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Қайта көрсетілмесін"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Жаю"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Кішірейту"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Жабу"</string>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index e705301..619f120 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ចុចពីរដង​នៅ​ក្រៅ​កម្មវិធី ដើម្បី​ប្ដូរ​ទីតាំង​កម្មវិធី​នោះ"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"យល់ហើយ"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ពង្រីកដើម្បីទទួលបានព័ត៌មានបន្ថែម។"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"ចាប់ផ្ដើម​ឡើងវិញ ដើម្បីទទួលបានទិដ្ឋភាពកាន់តែស្អាតឬ?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"អ្នកអាចចាប់ផ្ដើម​កម្មវិធីឡើងវិញ ដើម្បីឱ្យកម្មវិធីនេះមើលទៅស្អាតជាងមុននៅលើអេក្រង់របស់អ្នក ប៉ុន្តែអ្នកអាចនឹងបាត់បង់ដំណើរការរបស់អ្នក ឬការកែប្រែណាមួយដែលអ្នកមិនបានរក្សាទុក"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"បោះបង់"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"ចាប់ផ្ដើម​ឡើង​វិញ"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"កុំ​បង្ហាញ​ម្ដង​ទៀត"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"ពង្រីក"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"បង្រួម"</string>
     <string name="close_button_text" msgid="2913281996024033299">"បិទ"</string>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index bebf0c0..d3b53b4b 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ಆ್ಯಪ್ ಒಂದರ ಸ್ಥಾನವನ್ನು ಬದಲಾಯಿಸಲು ಅದರ ಹೊರಗೆ ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"ಸರಿ"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ಇನ್ನಷ್ಟು ಮಾಹಿತಿಗಾಗಿ ವಿಸ್ತೃತಗೊಳಿಸಿ."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"ಉತ್ತಮ ವೀಕ್ಷಣೆಗಾಗಿ ಆ್ಯಪ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಬೇಕೆ?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಬಹುದು, ಇದರಿಂದ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ಆ್ಯಪ್ ಉತ್ತಮವಾಗಿ ಕಾಣಿಸುತ್ತದೆ, ಆದರೆ ನಿಮ್ಮ ಪ್ರಗತಿಯನ್ನು ಅಥವಾ ಯಾವುದೇ ಉಳಿಸದ ಬದಲಾವಣೆಗಳನ್ನು ನೀವು ಕಳೆದುಕೊಳ್ಳಬಹುದು"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"ರದ್ದುಮಾಡಿ"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"ಮರುಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"ಮತ್ತೊಮ್ಮೆ ತೋರಿಸಬೇಡಿ"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"ಹಿಗ್ಗಿಸಿ"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"ಕುಗ್ಗಿಸಿ"</string>
     <string name="close_button_text" msgid="2913281996024033299">"ಮುಚ್ಚಿರಿ"</string>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 6c58c31..8293911 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"앱 위치를 조정하려면 앱 외부를 두 번 탭합니다."</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"확인"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"추가 정보는 펼쳐서 확인하세요."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"화면에 맞게 보도록 다시 시작할까요?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"앱을 다시 시작하면 화면에 더 잘 맞게 볼 수는 있지만 진행 상황 또는 저장되지 않은 변경사항을 잃을 수도 있습니다."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"취소"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"다시 시작"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"다시 표시 안함"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"최대화"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"최소화"</string>
     <string name="close_button_text" msgid="2913281996024033299">"닫기"</string>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 9f4dbb5..dda81a4 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Колдонмону жылдыруу үчүн сырт жагын эки жолу таптаңыз"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Түшүндүм"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Толук маалымат алуу үчүн жайып көрүңүз."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Жакшыраак көрүү үчүн өчүрүп күйгүзөсүзбү?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Экранда жакшыраак көрүү үчүн колдонмону өчүрүп күйгүзө аласыз, бирок аткарылган иш же сакталбаган өзгөрүүлөр өчүрүлүшү мүмкүн"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Токтотуу"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Өчүрүп күйгүзүү"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Экинчи көрүнбөсүн"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Чоңойтуу"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Кичирейтүү"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Жабуу"</string>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 97a7344..d7cbcbe 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ແຕະສອງເທື່ອໃສ່ນອກແອັບໃດໜຶ່ງເພື່ອຈັດຕຳແໜ່ງຂອງມັນຄືນໃໝ່"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"ເຂົ້າໃຈແລ້ວ"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ຂະຫຍາຍເພື່ອເບິ່ງຂໍ້ມູນເພີ່ມເຕີມ."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"ຣີສະຕາດເພື່ອໃຫ້ມີມຸມມອງທີ່ດີຂຶ້ນບໍ?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"ທ່ານສາມາດຣີສະຕາດແອັບໄດ້ເພື່ອໃຫ້ມັນເບິ່ງດີຂຶ້ນໃນໜ້າຈໍຂອງທ່ານ ແຕ່ທ່ານອາດຈະສູນເສຍຄວາມຄືບໜ້າ ຫຼື ການປ່ຽນແປງທີ່ບໍ່ໄດ້ບັນທຶກໄວ້"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"ຍົກເລີກ"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"ຣີສະຕາດ"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"ບໍ່ຕ້ອງສະແດງອີກ"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"ຂະຫຍາຍໃຫຍ່ສຸດ"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"ຫຍໍ້ລົງ"</string>
     <string name="close_button_text" msgid="2913281996024033299">"ປິດ"</string>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index a89545d..ef53df6 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Lai pārvietotu lietotni, veiciet dubultskārienu ārpus lietotnes"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Labi"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Izvērsiet, lai iegūtu plašāku informāciju."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Vai restartēt, lai uzlabotu skatu?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Varat restartēt lietotni, lai tā labāk izskatītos ekrānā, taču, iespējams, zaudēsiet paveikto vai nesaglabātas izmaiņas (ja tādas ir)."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Atcelt"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Restartēt"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Vairs nerādīt"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimizēt"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizēt"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Aizvērt"</string>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index f74738b..f1be597 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ആപ്പിന്റെ സ്ഥാനം മാറ്റാൻ അതിന് പുറത്ത് ഡബിൾ ടാപ്പ് ചെയ്യുക"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"മനസ്സിലായി"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"കൂടുതൽ വിവരങ്ങൾക്ക് വികസിപ്പിക്കുക."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"മെച്ചപ്പെട്ട കാഴ്‌ചയ്‌ക്കായി റീസ്റ്റാർട്ട് ചെയ്യണോ?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"ആപ്പ് റീസ്റ്റാർട്ട് ചെയ്യുകയാണെങ്കിൽ ഇത് നിങ്ങളുടെ സ്‌ക്രീനിൽ മെച്ചപ്പെട്ടതായി കാണും, എന്നാൽ ഇതുവരെയുള്ള പുരോഗതിയും സംരക്ഷിക്കാത്ത മാറ്റങ്ങളും നിങ്ങൾക്ക് നഷ്‌ടമാകും"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"റദ്ദാക്കുക"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"റീസ്റ്റാർട്ട് ചെയ്യൂ"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"വീണ്ടും കാണിക്കരുത്"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"വലുതാക്കുക"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"ചെറുതാക്കുക"</string>
     <string name="close_button_text" msgid="2913281996024033299">"അടയ്ക്കുക"</string>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index 51c4584..b5773a2 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Аппыг дахин байрлуулахын тулд гадна талд нь хоёр товшино"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ойлголоо"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Нэмэлт мэдээлэл авах бол дэлгэнэ үү."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Харагдах байдлыг сайжруулахын тулд дахин эхлүүлэх үү?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Та аппыг дахин эхлүүлэх боломжтой бөгөөд ингэснээр энэ нь таны дэлгэцэд илүү сайн харагдах хэдий ч та явцаа эсвэл хадгалаагүй аливаа өөрчлөлтөө алдаж магадгүй"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Цуцлах"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Дахин эхлүүлэх"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Дахиж бүү харуул"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Томруулах"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Багасгах"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Хаах"</string>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index cbde558..65a7a762 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ॲपची स्थिती पुन्हा बदलण्यासाठी, त्याच्या बाहेर दोनदा टॅप करा"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"समजले"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"अधिक माहितीसाठी विस्तार करा."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"आणखी चांगल्या प्रकारे दिसावे यासाठी रीस्टार्ट करायचे आहे का?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"तुम्ही अ‍ॅप रीस्टार्ट करू शकता, जेणेकरून ते तुमच्या स्क्रीनवर आणखी चांगल्या प्रकारे दिसेल, पण तुमची प्रगती किंवा कोणतेही सेव्ह न केलेले बदल तुम्ही गमवाल"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"रद्द करा"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"रीस्टार्ट करा"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"पुन्हा दाखवू नका"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"मोठे करा"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"लहान करा"</string>
     <string name="close_button_text" msgid="2913281996024033299">"बंद करा"</string>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index 23f7e52..d21b815 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ketik dua kali di luar apl untuk menempatkan semula apl itu"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Kembangkan untuk mendapatkan maklumat lanjut."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Mulakan semula untuk mendapatkan paparan yang lebih baik?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Anda boleh memulakan semula apl supaya apl kelihatan lebih baik pada skrin anda tetapi anda mungkin akan hilang kemajuan anda atau apa-apa perubahan yang belum disimpan"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Batal"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Mulakan semula"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Jangan tunjukkan lagi"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimumkan"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimumkan"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index 2fae552..71a4ff4 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"နေရာပြန်ချရန် အက်ပ်အပြင်ဘက်ကို နှစ်ချက်တို့ပါ"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"နားလည်ပြီ"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"နောက်ထပ်အချက်အလက်များအတွက် ချဲ့နိုင်သည်။"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"ပိုကောင်းသောမြင်ကွင်းအတွက် ပြန်စမလား။"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"အက်ပ်ကို ပြန်စပါက ၎င်းသည် စခရင်ပေါ်တွင် ပိုကြည့်ကောင်းသွားသော်လည်း သင်၏ လုပ်ငန်းစဉ် (သို့) မသိမ်းရသေးသော အပြောင်းအလဲများကို ဆုံးရှုံးနိုင်သည်"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"မလုပ်တော့"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"ပြန်စရန်"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"နောက်ထပ်မပြပါနှင့်"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"ချဲ့ရန်"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"ချုံ့ရန်"</string>
     <string name="close_button_text" msgid="2913281996024033299">"ပိတ်ရန်"</string>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index b34e134..3dbe6de 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dobbelttrykk utenfor en app for å flytte den"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Greit"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Vis for å få mer informasjon."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Vil du starte på nytt for bedre visning?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Du kan starte appen på nytt, slik at den ser bedre ut på skjermen, men du kan miste fremdrift eller ulagrede endringer"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Avbryt"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Start på nytt"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ikke vis dette igjen"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimer"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Lukk"</string>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 7bcca1a..c32460d 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"तपाईं जुन एपको स्थिति मिलाउन चाहनुहुन्छ सोही एपको बाहिर डबल ट्याप गर्नुहोस्"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"बुझेँ"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"थप जानकारी प्राप्त गर्न चाहनुहुन्छ भने एक्स्पान्ड गर्नुहोस्।"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"अझ राम्रोसँग देखिने बनाउन एप रिस्टार्ट गर्ने हो?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"यो एप तपाईंको स्क्रिनमा अझ राम्रोसँग देखियोस् भन्नाका लागि तपाईं सो एप रिस्टार्ट गर्न सक्नुहुन्छ तर तपाईंले अहिलेसम्म गरेका क्रियाकलाप वा सेभ गर्न बाँकी परिवर्तनहरू हट्न सक्छन्"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"रद्द गर्नुहोस्"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"रिस्टार्ट गर्नुहोस्"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"फेरि नदेखाइयोस्"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"ठुलो बनाउनुहोस्"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"मिनिमाइज गर्नुहोस्"</string>
     <string name="close_button_text" msgid="2913281996024033299">"बन्द गर्नुहोस्"</string>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index 6ec4739..e1aaaab 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dubbeltik naast een app om deze opnieuw te positioneren"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Uitvouwen voor meer informatie."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Opnieuw opstarten voor een betere weergave?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Je kunt de app opnieuw opstarten zodat deze er beter uitziet op je scherm, maar je kunt je voortgang of niet-opgeslagen wijzigingen kwijtraken"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Annuleren"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Opnieuw opstarten"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Niet opnieuw tonen"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximaliseren"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimaliseren"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Sluiten"</string>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index 0f27984..b85d447 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ଏକ ଆପକୁ ରିପୋଜିସନ କରିବା ପାଇଁ ଏହାର ବାହାରେ ଦୁଇଥର-ଟାପ କରନ୍ତୁ"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"ବୁଝିଗଲି"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ଅଧିକ ସୂଚନା ପାଇଁ ବିସ୍ତାର କରନ୍ତୁ।"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"ଏକ ଭଲ ଭ୍ୟୁ ପାଇଁ ରିଷ୍ଟାର୍ଟ କରିବେ?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"ଆପଣ ଆପକୁ ରିଷ୍ଟାର୍ଟ କରିପାରିବେ ଯାହା ଫଳରେ ଏହା ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଆହୁରି ଭଲ ଦେଖାଯିବ, କିନ୍ତୁ ଆପଣ ଆପଣଙ୍କ ପ୍ରଗତି କିମ୍ବା ସେଭ ହୋଇନଥିବା ଯେ କୌଣସି ପରିବର୍ତ୍ତନ ହରାଇପାରନ୍ତି"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"ବାତିଲ କରନ୍ତୁ"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"ପୁଣି ଦେଖାନ୍ତୁ ନାହିଁ"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"ବଡ଼ କରନ୍ତୁ"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"ଛୋଟ କରନ୍ତୁ"</string>
     <string name="close_button_text" msgid="2913281996024033299">"ବନ୍ଦ କରନ୍ତୁ"</string>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 2baec3c..ada30e2 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ਕਿਸੇ ਐਪ ਦੀ ਜਗ੍ਹਾ ਬਦਲਣ ਲਈ ਉਸ ਦੇ ਬਾਹਰ ਡਬਲ ਟੈਪ ਕਰੋ"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"ਸਮਝ ਲਿਆ"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਵਿਸਤਾਰ ਕਰੋ।"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"ਕੀ ਬਿਹਤਰ ਦ੍ਰਿਸ਼ ਲਈ ਐਪ ਨੂੰ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਨਾ ਹੈ?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"ਤੁਸੀਂ ਐਪ ਨੂੰ ਮੁੜ-ਸ਼ੁਰੂ ਕਰ ਸਕਦੇ ਹੋ ਤਾਂ ਜੋ ਇਹ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਬਿਹਤਰ ਦਿਸੇ, ਪਰ ਤੁਸੀਂ ਆਪਣੀ ਪ੍ਰਗਤੀ ਜਾਂ ਕਿਸੇ ਅਣਰੱਖਿਅਤ ਤਬਦੀਲੀ ਨੂੰ ਗੁਆ ਸਕਦੇ ਹੋ"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"ਰੱਦ ਕਰੋ"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"ਦੁਬਾਰਾ ਨਾ ਦਿਖਾਓ"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"ਵੱਡਾ ਕਰੋ"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"ਛੋਟਾ ਕਰੋ"</string>
     <string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index ecf6b4d..481f902 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Kliknij dwukrotnie poza aplikacją, aby ją przenieść"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Rozwiń, aby wyświetlić więcej informacji."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Uruchomić ponownie dla lepszego wyglądu?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Możesz ponownie uruchomić aplikację, aby lepiej wyglądała na ekranie, ale istnieje ryzyko, że utracisz postępy i niezapisane zmiany"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Anuluj"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Uruchom ponownie"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Nie pokazuj ponownie"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksymalizuj"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimalizuj"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Zamknij"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 847573b..d13f3dd 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toque duas vezes fora de um app para reposicionar"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendi"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Abra para ver mais informações."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Reiniciar para melhorar a visualização?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Você pode reiniciar o app para melhorar a visualização dele, mas talvez perca seu progresso ou mudanças não salvas"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Cancelar"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Reiniciar"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Não mostrar novamente"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index b684c6c..3c5346d 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toque duas vezes fora de uma app para a reposicionar"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expandir para obter mais informações"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Reiniciar para uma melhor visualização?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Pode reiniciar a app para ficar com um melhor aspeto no seu ecrã, mas pode perder o seu progresso ou eventuais alterações não guardadas"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Cancelar"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Reiniciar"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Não mostrar de novo"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 847573b..d13f3dd 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toque duas vezes fora de um app para reposicionar"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendi"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Abra para ver mais informações."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Reiniciar para melhorar a visualização?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Você pode reiniciar o app para melhorar a visualização dele, mas talvez perca seu progresso ou mudanças não salvas"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Cancelar"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Reiniciar"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Não mostrar novamente"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 5342dfb..f838d6d 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Atinge de două ori lângă o aplicație pentru a o repoziționa"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Extinde pentru mai multe informații"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Repornești pentru o vizualizare mai bună?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Poți să repornești aplicația ca să arate mai bine pe ecran, dar este posibil să pierzi progresul sau modificările nesalvate"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Anulează"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Repornește"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Nu mai afișa"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximizează"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizează"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Închide"</string>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index 71925a1..22a85b0 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Чтобы переместить приложение, дважды нажмите рядом с ним."</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"ОК"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Развернуть, чтобы узнать больше."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Перезапустить приложение?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Вы можете перезапустить приложение, чтобы оно лучше смотрелось на экране. При этом ваш прогресс или несохраненные изменения могут быть утеряны."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Отмена"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Перезапустить"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Больше не показывать"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Развернуть"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Свернуть"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Закрыть"</string>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index 188a137..0a1e7be 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"යෙදුමක් නැවත ස්ථානගත කිරීමට පිටතින් දෙවරක් තට්ටු කරන්න"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"තේරුණා"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"වැඩිදුර තොරතුරු සඳහා දිග හරින්න"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"වඩා හොඳ දසුනක් සඳහා යළි අරඹන්න ද?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"ඔබට එය ඔබේ තිරයෙහි වඩා හොඳින් පෙනෙන පරිදි යෙදුම යළි ඇරඹිය හැකි නමුත්, ඔබට ඔබේ ප්‍රගතිය හෝ නොසුරකින ලද වෙනස්කම් අහිමි විය හැක"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"අවලංගු කරන්න"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"යළි අරඹන්න"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"නැවත නොපෙන්වන්න"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"විහිදන්න"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"කුඩා කරන්න"</string>
     <string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index 0aa4f30..2e00484 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvojitým klepnutím mimo aplikácie zmeníte jej pozíciu"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Dobre"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Po rozbalení sa dozviete viac."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Chcete ju reštartovať, aby mala lepší vzhľad?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Aplikáciu môžete reštartovať, aby mala na obrazovke lepší vzhľad, ale môžete prísť o postup a všetky neuložené zmeny."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Zrušiť"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Reštartovať"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Už nezobrazovať"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maximalizovať"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimalizovať"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Zavrieť"</string>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index a4eb3d0..34c0c95 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvakrat se dotaknite zunaj aplikacije, če jo želite prestaviti."</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"V redu"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Razširitev za več informacij"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Želite znova zagnati za boljši pregled?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Če znova zaženete aplikacijo, bo prikaz na zaslonu boljši, vendar lahko izgubite napredek ali neshranjene spremembe."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Prekliči"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Znova zaženi"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ne prikaži več"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiraj"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimiraj"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Zapri"</string>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index cc4b7a4..211323e 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Trokit dy herë jashtë një aplikacioni për ta ripozicionuar"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"E kuptova"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Zgjeroje për më shumë informacion."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Rinis për një pamje më të mirë?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Mund të rinisësh aplikacionin në mënyrë që të duket më mirë në ekranin tënd, por mund të humbësh progresin ose çdo ndryshim të paruajtur"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Anulo"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Rinis"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Mos e shfaq përsëri"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Maksimizo"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimizo"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Mbyll"</string>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 80f7aa6..82177bc 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Двапут додирните изван апликације да бисте променили њену позицију"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Важи"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Проширите за још информација."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Желите ли да рестартујете ради бољег приказа?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Можете да рестартујете апликацију да би изгледала боље на екрану, с тим што можете да изгубите оно што сте урадили или несачуване промене, ако их има"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Откажи"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Рестартуј"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Не приказуј поново"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Увећајте"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Умањите"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Затворите"</string>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 4a4b6c9..dc3f415 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tryck snabbt två gånger utanför en app för att flytta den"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Utöka för mer information."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Vill du starta om för en bättre vy?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Du kan starta om appen så den passar bättre på skärmen men du kan förlora dina framsteg och eventuella osparade ändringar."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Avbryt"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Starta om"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Visa inte igen"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Utöka"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Minimera"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Stäng"</string>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index ad33144..b76f4c8 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Gusa mara mbili nje ya programu ili uihamishe"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Nimeelewa"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Panua ili upate maelezo zaidi."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Ungependa kuzima kisha uwashe ili upate mwonekano bora zaidi?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Unaweza kuzima kisha uwashe programu yako ili ifanye kazi vizuri zaidi kwenye skrini yako, lakini unaweza kupoteza maendeleo yako au mabadiliko yoyote ambayo hayajahifadhiwa"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Ghairi"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Zima kisha uwashe"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Usionyeshe tena"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Panua"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Punguza"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Funga"</string>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 52f5e22..c6a22a6 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ஆப்ஸை இடம் மாற்ற அதன் வெளியில் இருமுறை தட்டலாம்"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"சரி"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"கூடுதல் தகவல்களுக்கு விரிவாக்கலாம்."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"சரியான விதத்தில் காட்டப்பட மீண்டும் தொடங்கவா?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"ஆப்ஸை மீண்டும் தொடங்குவதன் மூலம் திரையில் அது சரியான விதத்தில் தோற்றமளிக்கும். ஆனால் செயல்நிலையையோ சேமிக்கப்படாமல் இருக்கும் மாற்றங்களையோ நீங்கள் இழக்கக்கூடும்."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"ரத்துசெய்"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"மீண்டும் தொடங்கு"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"மீண்டும் காட்டாதே"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"பெரிதாக்கும்"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"சிறிதாக்கும்"</string>
     <string name="close_button_text" msgid="2913281996024033299">"மூடும்"</string>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 2eb739d..78081c8 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"యాప్ స్థానాన్ని మార్చడానికి దాని వెలుపల డబుల్-ట్యాప్ చేయండి"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"అర్థమైంది"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"మరింత సమాచారం కోసం విస్తరించండి."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"మెరుగైన వీక్షణ కోసం రీస్టార్ట్ చేయాలా?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"మీరు యాప్‌ని రీస్టార్ట్ చేయవచ్చు, తద్వారా ఇది మీ స్క్రీన్‌పై మెరుగ్గా కనిపిస్తుంది, కానీ మీరు మీ ప్రోగ్రెస్‌ను గానీ లేదా సేవ్ చేయని ఏవైనా మార్పులను గానీ కోల్పోవచ్చు"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"రద్దు చేయండి"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"రీస్టార్ట్ చేయండి"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"మళ్లీ చూపవద్దు"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"గరిష్టీకరించండి"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"కుదించండి"</string>
     <string name="close_button_text" msgid="2913281996024033299">"మూసివేయండి"</string>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index c19e083..c88e2cb 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Yeniden konumlandırmak için uygulamanın dışına iki kez dokunun"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Daha fazla bilgi için genişletin."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Daha iyi bir görünüm için yeniden başlatılsın mı?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Ekranınızda daha iyi görünmesi için uygulamayı yeniden başlatabilirsiniz, ancak ilerlemenizi ve kaydedilmemiş değişikliklerinizi kaybedebilirsiniz"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"İptal"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Yeniden başlat"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Bir daha gösterme"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Ekranı Kapla"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Küçült"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Kapat"</string>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 6869401..898ea99 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Щоб перемістити додаток, двічі торкніться області поза ним"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"ОK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Розгорніть, щоб дізнатися більше."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Перезапустити для зручнішого перегляду?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Ви можете перезапустити додаток, щоб покращити його вигляд на екрані, але ваші досягнення або незбережені зміни може бути втрачено"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Скасувати"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Перезапустити"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Більше не показувати"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Збільшити"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Згорнути"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Закрити"</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index e3a22eb..e1a0bf4 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"کسی ایپ کی پوزیشن تبدیل کرنے کے لیے اس ایپ کے باہر دو بار تھپتھپائیں"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"سمجھ آ گئی"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"مزید معلومات کے لیے پھیلائیں۔"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"بہتر منظر کے لیے ری سٹارٹ کریں؟"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"آپ ایپ کو ری سٹارٹ کر سکتے ہیں تاکہ یہ آپ کی اسکرین پر بہتر نظر آئے، تاہم آپ اپنی پیشرفت سے یا کسی غیر محفوظ شدہ تبدیلیوں سے محروم ہو سکتے ہیں"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"منسوخ کریں"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"ری اسٹارٹ کریں"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"دوبارہ نہ دکھائیں"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"بڑا کریں"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"چھوٹا کریں"</string>
     <string name="close_button_text" msgid="2913281996024033299">"بند کریں"</string>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index d12dac3..b54912f 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Qayta joylash uchun ilova tashqarisiga ikki marta bosing"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Batafsil axborot olish uchun kengaytiring."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Yaxshi koʻrinishi uchun qayta ishga tushirilsinmi?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Ilovani ekranda yaxshiroq koʻrinishi uchun qayta ishga tushirishingiz mumkin. Bunda jarayonlar yoki saqlanmagan oʻzgarishlar yoʻqolishi mumkin."</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Bekor qilish"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Qaytadan"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Boshqa chiqmasin"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Yoyish"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Kichraytirish"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Yopish"</string>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 39de38c..a0cfc29 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Nhấn đúp bên ngoài ứng dụng để đặt lại vị trí"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Mở rộng để xem thêm thông tin."</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Khởi động lại để ứng dụng trông vừa vặn hơn?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Bạn có thể khởi động lại ứng dụng để ứng dụng nhìn đẹp hơn trên màn hình. Tuy nhiên, nếu làm vậy, bạn có thể mất tiến trình hoặc mọi thay đổi chưa lưu"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Huỷ"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Khởi động lại"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Không hiện lại"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Phóng to"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Thu nhỏ"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Đóng"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index c787f61..e18b029 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在某个应用外连续点按两次,即可调整它的位置"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展开即可了解详情。"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"重启以改进外观?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"您可以重启应用,使其在屏幕上的显示效果更好,但您可能会丢失进度或任何未保存的更改"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"取消"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"重启"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"不再显示"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
     <string name="close_button_text" msgid="2913281996024033299">"关闭"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 395b2a9..30cd5b6 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在應用程式外輕按兩下即可調整位置"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展開即可查看詳情。"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"要重新啟動改善檢視畫面嗎?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"您可重新啟動應用程式,讓系統更新檢視畫面;但系統可能不會儲存目前進度及您作出的任何變更"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"取消"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"重新啟動"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"不要再顯示"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
     <string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index 8a84f15..053ecc0 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在應用程式外輕觸兩下即可調整位置"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"我知道了"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展開即可查看詳細資訊。"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"要重新啟動改善檢視畫面嗎?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"你可以重新啟動應用程式,讓系統更新檢視畫面。不過,系統可能不會儲存目前進度及你所做的任何變更"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"取消"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"重新啟動"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"不要再顯示"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string>
     <string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index fca5a7a..bc80d10 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -84,16 +84,11 @@
     <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Thepha kabili ngaphandle kwe-app ukuze uyimise kabusha"</string>
     <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ngiyezwa"</string>
     <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Nweba ukuze uthole ulwazi olwengeziwe"</string>
-    <!-- no translation found for letterbox_restart_dialog_title (8543049527871033505) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_description (6096946078246557848) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_cancel (1342209132692537805) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_restart (8529976234412442973) -->
-    <skip />
-    <!-- no translation found for letterbox_restart_dialog_checkbox_title (5252918008140768386) -->
-    <skip />
+    <string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Qala kabusha ukuze uthole ukubuka okungcono?"</string>
+    <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Ungakwazi ukuqala kabusha i-app ukuze ibukeke kangcono esikrinini sakho, kodwa ungase ulahlekelwe ukuqhubeka kwakho nanoma yiziphi izinguquko ezingalondoloziwe"</string>
+    <string name="letterbox_restart_cancel" msgid="1342209132692537805">"Khansela"</string>
+    <string name="letterbox_restart_restart" msgid="8529976234412442973">"Qala kabusha"</string>
+    <string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Ungabonisi futhi"</string>
     <string name="maximize_button_text" msgid="1650859196290301963">"Khulisa"</string>
     <string name="minimize_button_text" msgid="271592547935841753">"Nciphisa"</string>
     <string name="close_button_text" msgid="2913281996024033299">"Vala"</string>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index 3fd97ef..29f3766 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -105,6 +105,15 @@
     <!-- Accessibility action for moving docked stack divider to make the bottom screen full screen [CHAR LIMIT=NONE] -->
     <string name="accessibility_action_divider_bottom_full">Bottom full screen</string>
 
+    <!-- Accessibility label for splitting to the left drop zone [CHAR LIMIT=NONE] -->
+    <string name="accessibility_split_left">Split left</string>
+    <!-- Accessibility label for splitting to the right drop zone [CHAR LIMIT=NONE] -->
+    <string name="accessibility_split_right">Split right</string>
+    <!-- Accessibility label for splitting to the top drop zone [CHAR LIMIT=NONE] -->
+    <string name="accessibility_split_top">Split top</string>
+    <!-- Accessibility label for splitting to the bottom drop zone [CHAR LIMIT=NONE] -->
+    <string name="accessibility_split_bottom">Split bottom</string>
+
     <!-- One-Handed Tutorial title [CHAR LIMIT=60] -->
     <string name="one_handed_tutorial_title">Using one-handed mode</string>
     <!-- One-Handed Tutorial description [CHAR LIMIT=NONE] -->
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
index 5d451a5..7a6aec7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
@@ -173,7 +173,7 @@
      */
     public void onLocationChanged() {
         getBoundsOnScreen(mTmpRect);
-        mTaskViewTaskController.onLocationChanged(mTmpRect);
+        mTaskViewTaskController.setWindowBounds(mTmpRect);
     }
 
     /**
@@ -198,7 +198,7 @@
     public void surfaceChanged(@androidx.annotation.NonNull SurfaceHolder holder, int format,
             int width, int height) {
         getBoundsOnScreen(mTmpRect);
-        mTaskViewTaskController.surfaceChanged(mTmpRect);
+        mTaskViewTaskController.setWindowBounds(mTmpRect);
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTaskController.java
index 69ce35f..1f223a6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTaskController.java
@@ -183,26 +183,6 @@
     }
 
     /**
-     * Call when view position or size has changed. Do not call when animating.
-     */
-    public void onLocationChanged(Rect newBounds) {
-        if (mTaskToken == null) {
-            return;
-        }
-        // Sync Transactions can't operate simultaneously with shell transition collection.
-        // The transition animation (upon showing) will sync the location itself.
-        if (isUsingShellTransitions() && mTaskViewTransitions.hasPending()) return;
-
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        updateWindowBounds(wct);
-        mSyncQueue.queue(wct);
-    }
-
-    private void updateWindowBounds(WindowContainerTransaction wct) {
-        wct.setBounds(mTaskToken, mTaskViewBase.getCurrentBoundsOnScreen());
-    }
-
-    /**
      * Release this container if it is initialized.
      */
     public void release() {
@@ -394,15 +374,24 @@
     }
 
     /**
-     * Should be called when the client surface is changed.
+     * Sets the window bounds to {@code boundsOnScreen}.
+     * Call when view position or size has changed. Can also be called before the animation when
+     * the final bounds are known.
+     * Do not call during the animation.
      *
      * @param boundsOnScreen the on screen bounds of the surface view.
      */
-    public void surfaceChanged(Rect boundsOnScreen) {
+    public void setWindowBounds(Rect boundsOnScreen) {
         if (mTaskToken == null) {
             return;
         }
-        onLocationChanged(boundsOnScreen);
+        // Sync Transactions can't operate simultaneously with shell transition collection.
+        // The transition animation (upon showing) will sync the location itself.
+        if (isUsingShellTransitions() && mTaskViewTransitions.hasPending()) return;
+
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        wct.setBounds(mTaskToken, boundsOnScreen);
+        mSyncQueue.queue(wct);
     }
 
     /** Should be called when the client surface is destroyed. */
@@ -493,7 +482,7 @@
                     .setPosition(mTaskLeash, 0, 0)
                     .apply();
 
-            updateWindowBounds(wct);
+            wct.setBounds(mTaskToken, mTaskViewBase.getCurrentBoundsOnScreen());
         } else {
             // The surface has already been destroyed before the task has appeared,
             // so go ahead and hide the task entirely
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 57a0fd5..ee5d205 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -78,7 +78,7 @@
      /** Flag for U animation features */
     public static boolean IS_U_ANIMATION_ENABLED =
             SystemProperties.getInt("persist.wm.debug.predictive_back_anim",
-                    SETTING_VALUE_OFF) == SETTING_VALUE_ON;
+                    SETTING_VALUE_ON) == SETTING_VALUE_ON;
     /** Predictive back animation developer option */
     private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false);
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
index 38f1e28..da113cb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
@@ -370,13 +370,7 @@
 
         @Override
         public void onBackCancelled() {
-            // End the fade in animation.
             mProgressAnimator.onBackCancelled(CrossActivityAnimation.this::finishAnimation);
-            mEnteringProgressSpring.cancel();
-            mLeavingProgressSpring.cancel();
-            // TODO (b259608500): Let BackProgressAnimator could play cancel animation.
-            mProgressAnimator.reset();
-            finishAnimation();
         }
 
         @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 2534498..e24c228 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -126,7 +126,7 @@
     private Icon mIcon;
     private boolean mIsBubble;
     private boolean mIsTextChanged;
-    private boolean mIsClearable;
+    private boolean mIsDismissable;
     private boolean mShouldSuppressNotificationDot;
     private boolean mShouldSuppressNotificationList;
     private boolean mShouldSuppressPeek;
@@ -181,7 +181,7 @@
     @VisibleForTesting(visibility = PRIVATE)
     public Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo,
             final int desiredHeight, final int desiredHeightResId, @Nullable final String title,
-            int taskId, @Nullable final String locus, boolean isClearable, Executor mainExecutor,
+            int taskId, @Nullable final String locus, boolean isDismissable, Executor mainExecutor,
             final Bubbles.BubbleMetadataFlagListener listener) {
         Objects.requireNonNull(key);
         Objects.requireNonNull(shortcutInfo);
@@ -190,7 +190,7 @@
         mKey = key;
         mGroupKey = null;
         mLocusId = locus != null ? new LocusId(locus) : null;
-        mIsClearable = isClearable;
+        mIsDismissable = isDismissable;
         mFlags = 0;
         mUser = shortcutInfo.getUserHandle();
         mPackageName = shortcutInfo.getPackage();
@@ -248,8 +248,8 @@
     }
 
     @Hide
-    public boolean isClearable() {
-        return mIsClearable;
+    public boolean isDismissable() {
+        return mIsDismissable;
     }
 
     /**
@@ -533,7 +533,7 @@
             mDeleteIntent = entry.getBubbleMetadata().getDeleteIntent();
         }
 
-        mIsClearable = entry.isClearable();
+        mIsDismissable = entry.isDismissable();
         mShouldSuppressNotificationDot = entry.shouldSuppressNotificationDot();
         mShouldSuppressNotificationList = entry.shouldSuppressNotificationList();
         mShouldSuppressPeek = entry.shouldSuppressPeek();
@@ -612,7 +612,7 @@
      * Whether this notification should be shown in the shade.
      */
     boolean showInShade() {
-        return !shouldSuppressNotification() || !mIsClearable;
+        return !shouldSuppressNotification() || !mIsDismissable;
     }
 
     /**
@@ -877,7 +877,7 @@
         pw.print("  desiredHeight: "); pw.println(getDesiredHeightString());
         pw.print("  suppressNotif: "); pw.println(shouldSuppressNotification());
         pw.print("  autoExpand:    "); pw.println(shouldAutoExpand());
-        pw.print("  isClearable:   "); pw.println(mIsClearable);
+        pw.print("  isDismissable: "); pw.println(mIsDismissable);
         pw.println("  bubbleMetadataFlagListener null: " + (mBubbleMetadataFlagListener == null));
         if (mExpandedView != null) {
             mExpandedView.dump(pw);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 360bfe7..36c0cb6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -68,10 +68,14 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
+import android.view.IWindowManager;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowInsets;
 import android.view.WindowManager;
+import android.window.ScreenCapture;
+import android.window.ScreenCapture.ScreenCaptureListener;
+import android.window.ScreenCapture.ScreenshotSync;
 
 import androidx.annotation.MainThread;
 import androidx.annotation.Nullable;
@@ -143,6 +147,7 @@
     private final SyncTransactionQueue mSyncQueue;
     private final ShellController mShellController;
     private final ShellCommandHandler mShellCommandHandler;
+    private final IWindowManager mWmService;
 
     // Used to post to main UI thread
     private final ShellExecutor mMainExecutor;
@@ -237,7 +242,8 @@
             @ShellMainThread Handler mainHandler,
             @ShellBackgroundThread ShellExecutor bgExecutor,
             TaskViewTransitions taskViewTransitions,
-            SyncTransactionQueue syncQueue) {
+            SyncTransactionQueue syncQueue,
+            IWindowManager wmService) {
         mContext = context;
         mShellCommandHandler = shellCommandHandler;
         mShellController = shellController;
@@ -269,6 +275,7 @@
         mOneHandedOptional = oneHandedOptional;
         mDragAndDropController = dragAndDropController;
         mSyncQueue = syncQueue;
+        mWmService = wmService;
         shellInit.addInitCallback(this::onInit, this);
     }
 
@@ -1037,6 +1044,26 @@
     }
 
     /**
+     * Performs a screenshot that may exclude the bubble layer, if one is present. The screenshot
+     * can be access via the supplied {@link ScreenshotSync#get()} asynchronously.
+     *
+     * TODO(b/267324693): Implement the exclude layer functionality in screenshot.
+     */
+    public void getScreenshotExcludingBubble(int displayId,
+            Pair<ScreenCaptureListener, ScreenshotSync> screenCaptureListener) {
+        try {
+            mWmService.captureDisplay(displayId, null, screenCaptureListener.first);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to capture screenshot");
+        }
+    }
+
+    /** Sets the app bubble's taskId which is cached for SysUI. */
+    public void setAppBubbleTaskId(int taskId) {
+        mImpl.mCachedState.setAppBubbleTaskId(taskId);
+    }
+
+    /**
      * Fills the overflow bubbles by loading them from disk.
      */
     void loadOverflowBubblesFromDisk() {
@@ -1614,6 +1641,7 @@
             private HashSet<String> mSuppressedBubbleKeys = new HashSet<>();
             private HashMap<String, String> mSuppressedGroupToNotifKeys = new HashMap<>();
             private HashMap<String, Bubble> mShortcutIdToBubble = new HashMap<>();
+            private int mAppBubbleTaskId = INVALID_TASK_ID;
 
             private ArrayList<Bubble> mTmpBubbles = new ArrayList<>();
 
@@ -1645,12 +1673,22 @@
 
                 mSuppressedBubbleKeys.clear();
                 mShortcutIdToBubble.clear();
+                mAppBubbleTaskId = INVALID_TASK_ID;
                 for (Bubble b : mTmpBubbles) {
                     mShortcutIdToBubble.put(b.getShortcutId(), b);
                     updateBubbleSuppressedState(b);
+
+                    if (KEY_APP_BUBBLE.equals(b.getKey())) {
+                        mAppBubbleTaskId = b.getTaskId();
+                    }
                 }
             }
 
+            /** Sets the app bubble's taskId which is cached for SysUI. */
+            synchronized void setAppBubbleTaskId(int taskId) {
+                mAppBubbleTaskId = taskId;
+            }
+
             /**
              * Updates a specific bubble suppressed state.  This is used mainly because notification
              * suppression changes don't go through the same BubbleData update mechanism.
@@ -1700,6 +1738,8 @@
                 for (String key : mSuppressedGroupToNotifKeys.keySet()) {
                     pw.println("   suppressing: " + key);
                 }
+
+                pw.print("mAppBubbleTaskId: " + mAppBubbleTaskId);
             }
         }
 
@@ -1750,6 +1790,24 @@
         }
 
         @Override
+        public boolean isAppBubbleTaskId(int taskId) {
+            return mCachedState.mAppBubbleTaskId == taskId;
+        }
+
+        @Override
+        @Nullable
+        public ScreenshotSync getScreenshotExcludingBubble(int displayId) {
+            Pair<ScreenCaptureListener, ScreenshotSync> screenCaptureListener =
+                    ScreenCapture.createSyncCaptureListener();
+
+            mMainExecutor.execute(
+                    () -> BubbleController.this.getScreenshotExcludingBubble(displayId,
+                            screenCaptureListener));
+
+            return screenCaptureListener.second;
+        }
+
+        @Override
         public boolean handleDismissalInterception(BubbleEntry entry,
                 @Nullable List<BubbleEntry> children, IntConsumer removeCallback,
                 Executor callbackExecutor) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt
index e3aefa5..e37c785 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt
@@ -110,7 +110,7 @@
                     b.title,
                     b.taskId,
                     b.locusId?.id,
-                    b.isClearable
+                    b.isDismissable
             )
         }
     }
@@ -206,7 +206,7 @@
                                 entity.title,
                                 entity.taskId,
                                 entity.locus,
-                                entity.isClearable,
+                                entity.isDismissable,
                                 mainExecutor,
                                 bubbleMetadataFlagListener
                         )
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleEntry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleEntry.java
index 5f42826..afe19c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleEntry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleEntry.java
@@ -38,18 +38,18 @@
     private StatusBarNotification mSbn;
     private Ranking mRanking;
 
-    private boolean mIsClearable;
+    private boolean mIsDismissable;
     private boolean mShouldSuppressNotificationDot;
     private boolean mShouldSuppressNotificationList;
     private boolean mShouldSuppressPeek;
 
     public BubbleEntry(@NonNull StatusBarNotification sbn,
-            Ranking ranking, boolean isClearable, boolean shouldSuppressNotificationDot,
+            Ranking ranking, boolean isDismissable, boolean shouldSuppressNotificationDot,
             boolean shouldSuppressNotificationList, boolean shouldSuppressPeek) {
         mSbn = sbn;
         mRanking = ranking;
 
-        mIsClearable = isClearable;
+        mIsDismissable = isDismissable;
         mShouldSuppressNotificationDot = shouldSuppressNotificationDot;
         mShouldSuppressNotificationList = shouldSuppressNotificationList;
         mShouldSuppressPeek = shouldSuppressPeek;
@@ -115,9 +115,9 @@
         return mRanking.canBubble();
     }
 
-    /** @return true if this notification is clearable. */
-    public boolean isClearable() {
-        return mIsClearable;
+    /** @return true if this notification can be dismissed. */
+    public boolean isDismissable() {
+        return mIsDismissable;
     }
 
     /** @return true if {@link Policy#SUPPRESSED_EFFECT_BADGE} set for this notification. */
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 1feff18..57c7731 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
@@ -278,6 +278,11 @@
             // The taskId is saved to use for removeTask, preventing appearance in recent tasks.
             mTaskId = taskId;
 
+            if (Bubble.KEY_APP_BUBBLE.equals(getBubbleKey())) {
+                // Let the controller know sooner what the taskId is.
+                mController.setAppBubbleTaskId(mTaskId);
+            }
+
             // With the task org, the taskAppeared callback will only happen once the task has
             // already drawn
             setContentVisibility(true);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index df43257..1753cda 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -16,6 +16,8 @@
 
 package com.android.wm.shell.bubbles;
 
+import static android.window.ScreenCapture.ScreenshotSync;
+
 import static java.lang.annotation.ElementType.FIELD;
 import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
 import static java.lang.annotation.ElementType.PARAMETER;
@@ -24,11 +26,13 @@
 import android.app.NotificationChannel;
 import android.content.Intent;
 import android.content.pm.UserInfo;
+import android.hardware.HardwareBuffer;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.util.Pair;
 import android.util.SparseArray;
+import android.window.ScreenCapture.ScreenshotHardwareBuffer;
 
 import androidx.annotation.IntDef;
 import androidx.annotation.Nullable;
@@ -132,6 +136,18 @@
      */
     void showOrHideAppBubble(Intent intent);
 
+    /** @return true if the specified {@code taskId} corresponds to app bubble's taskId. */
+    boolean isAppBubbleTaskId(int taskId);
+
+    /**
+     * @return a {@link ScreenshotSync} after performing a screenshot that may exclude the bubble
+     * layer, if one is present. The underlying {@link ScreenshotHardwareBuffer} can be access via
+     * {@link ScreenshotSync#get()} asynchronously and care should be taken to
+     * {@link HardwareBuffer#close()} the associated
+     * {@link ScreenshotHardwareBuffer#getHardwareBuffer()} when no longer required.
+     */
+    ScreenshotSync getScreenshotExcludingBubble(int displayId);
+
     /**
      * @return a bubble that matches the provided shortcutId, if one exists.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt
index f3abc27..9b2e263 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleEntity.kt
@@ -28,5 +28,5 @@
     val title: String? = null,
     val taskId: Int,
     val locus: String? = null,
-    val isClearable: Boolean = false
+    val isDismissable: Boolean = false
 )
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt
index 14c053c..48d8ccf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelper.kt
@@ -43,9 +43,7 @@
 private const val ATTR_TITLE = "t"
 private const val ATTR_TASK_ID = "tid"
 private const val ATTR_LOCUS = "l"
-
-// TODO rename it to dismissable to follow NotificationEntry namings
-private const val ATTR_CLEARABLE = "d"
+private const val ATTR_DISMISSABLE = "d"
 
 /**
  * Writes the bubbles in xml format into given output stream.
@@ -87,7 +85,7 @@
         bubble.title?.let { serializer.attribute(null, ATTR_TITLE, it) }
         serializer.attribute(null, ATTR_TASK_ID, bubble.taskId.toString())
         bubble.locus?.let { serializer.attribute(null, ATTR_LOCUS, it) }
-        serializer.attribute(null, ATTR_CLEARABLE, bubble.isClearable.toString())
+        serializer.attribute(null, ATTR_DISMISSABLE, bubble.isDismissable.toString())
         serializer.endTag(null, TAG_BUBBLE)
     } catch (e: IOException) {
         throw RuntimeException(e)
@@ -147,7 +145,7 @@
             parser.getAttributeWithName(ATTR_TITLE),
             parser.getAttributeWithName(ATTR_TASK_ID)?.toInt() ?: INVALID_TASK_ID,
             parser.getAttributeWithName(ATTR_LOCUS),
-            parser.getAttributeWithName(ATTR_CLEARABLE)?.toBoolean() ?: false
+            parser.getAttributeWithName(ATTR_DISMISSABLE)?.toBoolean() ?: false
     )
 }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index d0aef20..2ea4316 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -141,7 +141,7 @@
         if (pd == null) {
             return false;
         }
-        final InsetsSource imeSource = pd.mInsetsState.getSource(InsetsState.ITYPE_IME);
+        final InsetsSource imeSource = pd.mInsetsState.peekSource(InsetsSource.ID_IME);
         return imeSource != null && pd.mImeSourceControl != null && imeSource.isVisible();
     }
 
@@ -245,14 +245,17 @@
                 return;
             }
 
-            updateImeVisibility(insetsState.getSourceOrDefaultVisibility(InsetsState.ITYPE_IME));
+            updateImeVisibility(insetsState.isSourceOrDefaultVisible(InsetsSource.ID_IME,
+                    WindowInsets.Type.ime()));
 
-            final InsetsSource newSource = insetsState.getSource(InsetsState.ITYPE_IME);
-            final Rect newFrame = newSource.getFrame();
-            final Rect oldFrame = mInsetsState.getSource(InsetsState.ITYPE_IME).getFrame();
+            final InsetsSource newSource = insetsState.peekSource(InsetsSource.ID_IME);
+            final Rect newFrame = newSource != null ? newSource.getFrame() : null;
+            final boolean newSourceVisible = newSource != null && newSource.isVisible();
+            final InsetsSource oldSource = mInsetsState.peekSource(InsetsSource.ID_IME);
+            final Rect oldFrame = oldSource != null ? oldSource.getFrame() : null;
 
             mInsetsState.set(insetsState, true /* copySources */);
-            if (mImeShowing && !newFrame.equals(oldFrame) && newSource.isVisible()) {
+            if (mImeShowing && !Objects.equals(oldFrame, newFrame) && newSourceVisible) {
                 if (DEBUG) Slog.d(TAG, "insetsChanged when IME showing, restart animation");
                 startAnimation(mImeShowing, true /* forceRestart */, null /* statsToken */);
             }
@@ -351,7 +354,7 @@
          * Sends the local visibility state back to window manager. Needed for legacy adjustForIme.
          */
         private void setVisibleDirectly(boolean visible) {
-            mInsetsState.getSource(InsetsState.ITYPE_IME).setVisible(visible);
+            mInsetsState.setSourceVisible(InsetsSource.ID_IME, visible);
             mRequestedVisibleTypes = visible
                     ? mRequestedVisibleTypes | WindowInsets.Type.ime()
                     : mRequestedVisibleTypes & ~WindowInsets.Type.ime();
@@ -382,9 +385,9 @@
 
         private void startAnimation(final boolean show, final boolean forceRestart,
                 @Nullable ImeTracker.Token statsToken) {
-            final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME);
+            final InsetsSource imeSource = mInsetsState.peekSource(InsetsSource.ID_IME);
             if (imeSource == null || mImeSourceControl == null) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
+                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
                 return;
             }
             final Rect newFrame = imeSource.getFrame();
@@ -407,7 +410,8 @@
             }
             if ((!forceRestart && (mAnimationDirection == DIRECTION_SHOW && show))
                     || (mAnimationDirection == DIRECTION_HIDE && !show)) {
-                ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
+                ImeTracker.forLogging().onCancelled(
+                        statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
                 return;
             }
             boolean seek = false;
@@ -451,7 +455,7 @@
                 mTransactionPool.release(t);
             });
             mAnimation.setInterpolator(INTERPOLATOR);
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
             mAnimation.addListener(new AnimatorListenerAdapter() {
                 private boolean mCancelled = false;
                 @Nullable
@@ -474,7 +478,7 @@
                             : 1.f;
                     t.setAlpha(mImeSourceControl.getLeash(), alpha);
                     if (mAnimationDirection == DIRECTION_SHOW) {
-                        ImeTracker.get().onProgress(mStatsToken,
+                        ImeTracker.forLogging().onProgress(mStatsToken,
                                 ImeTracker.PHASE_WM_ANIMATION_RUNNING);
                         t.show(mImeSourceControl.getLeash());
                     }
@@ -511,15 +515,15 @@
                     }
                     dispatchEndPositioning(mDisplayId, mCancelled, t);
                     if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
-                        ImeTracker.get().onProgress(mStatsToken,
+                        ImeTracker.forLogging().onProgress(mStatsToken,
                                 ImeTracker.PHASE_WM_ANIMATION_RUNNING);
                         t.hide(mImeSourceControl.getLeash());
                         removeImeSurface();
-                        ImeTracker.get().onHidden(mStatsToken);
+                        ImeTracker.forLogging().onHidden(mStatsToken);
                     } else if (mAnimationDirection == DIRECTION_SHOW && !mCancelled) {
-                        ImeTracker.get().onShown(mStatsToken);
+                        ImeTracker.forLogging().onShown(mStatsToken);
                     } else if (mCancelled) {
-                        ImeTracker.get().onCancelled(mStatsToken,
+                        ImeTracker.forLogging().onCancelled(mStatsToken,
                                 ImeTracker.PHASE_WM_ANIMATION_RUNNING);
                     }
                     if (DEBUG_IME_VISIBILITY) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
index 8759301..9bdda14 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
@@ -162,10 +162,12 @@
                 @Nullable ImeTracker.Token statsToken) {
             CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
             if (listeners == null) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+                ImeTracker.forLogging().onFailed(
+                        statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
                 return;
             }
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+            ImeTracker.forLogging().onProgress(
+                    statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
             for (OnInsetsChangedListener listener : listeners) {
                 listener.showInsets(types, fromIme, statsToken);
             }
@@ -175,10 +177,12 @@
                 @Nullable ImeTracker.Token statsToken) {
             CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
             if (listeners == null) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+                ImeTracker.forLogging().onFailed(
+                        statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
                 return;
             }
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+            ImeTracker.forLogging().onProgress(
+                    statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
             for (OnInsetsChangedListener listener : listeners) {
                 listener.hideInsets(types, fromIme, statsToken);
             }
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 8484013..b8e8363 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
@@ -372,7 +372,7 @@
 
         // Only navigation bar
         if (hasNavigationBar) {
-            final InsetsSource extraNavBar = insetsState.getSource(ITYPE_EXTRA_NAVIGATION_BAR);
+            final InsetsSource extraNavBar = insetsState.peekSource(ITYPE_EXTRA_NAVIGATION_BAR);
             final boolean hasExtraNav = extraNavBar != null && extraNavBar.isVisible();
             int position = navigationBarPosition(res, displayWidth, displayHeight, displayRotation);
             int navBarSize =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index c634198..5933ac2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -37,6 +37,7 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@@ -216,13 +217,14 @@
     void onInsetsChanged(InsetsState insetsState, boolean animate) {
         mSplitLayout.getDividerBounds(mTempRect);
         final InsetsSource taskBarInsetsSource =
-                insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
+                insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
         // Only insets the divider bar with task bar when it's expanded so that the rounded corners
         // will be drawn against task bar.
         // But there is no need to do it when IME showing because there are no rounded corners at
         // the bottom. This also avoids the problem of task bar height not changing when IME
         // floating.
-        if (!insetsState.getSourceOrDefaultVisibility(InsetsState.ITYPE_IME)
+        if (!insetsState.isSourceOrDefaultVisible(InsetsSource.ID_IME, WindowInsets.Type.ime())
+                && taskBarInsetsSource != null
                 && taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) {
             mTempRect.inset(taskBarInsetsSource.calculateVisibleInsets(mTempRect));
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 45b234a..f616e6f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -699,19 +699,6 @@
         return bounds.width() > bounds.height();
     }
 
-    /** Reverse the split position. */
-    @SplitPosition
-    public static int reversePosition(@SplitPosition int position) {
-        switch (position) {
-            case SPLIT_POSITION_TOP_OR_LEFT:
-                return SPLIT_POSITION_BOTTOM_OR_RIGHT;
-            case SPLIT_POSITION_BOTTOM_OR_RIGHT:
-                return SPLIT_POSITION_TOP_OR_LEFT;
-            default:
-                return SPLIT_POSITION_UNDEFINED;
-        }
-    }
-
     /**
      * Return if this layout is landscape.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java
new file mode 100644
index 0000000..042721c9
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenUtils.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common.split;
+
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.wm.shell.ShellTaskOrganizer;
+
+/** Helper utility class for split screen components to use. */
+public class SplitScreenUtils {
+    /** Reverse the split position. */
+    @SplitScreenConstants.SplitPosition
+    public static int reverseSplitPosition(@SplitScreenConstants.SplitPosition int position) {
+        switch (position) {
+            case SPLIT_POSITION_TOP_OR_LEFT:
+                return SPLIT_POSITION_BOTTOM_OR_RIGHT;
+            case SPLIT_POSITION_BOTTOM_OR_RIGHT:
+                return SPLIT_POSITION_TOP_OR_LEFT;
+            case SPLIT_POSITION_UNDEFINED:
+            default:
+                return SPLIT_POSITION_UNDEFINED;
+        }
+    }
+
+    /** Returns true if the task is valid for split screen. */
+    public static boolean isValidToSplit(ActivityManager.RunningTaskInfo taskInfo) {
+        return taskInfo != null && taskInfo.supportsMultiWindow
+                && ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
+                && ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode());
+    }
+
+    /** Retrieve package name from an intent */
+    @Nullable
+    public static String getPackageName(Intent intent) {
+        if (intent == null || intent.getComponent() == null) {
+            return null;
+        }
+        return intent.getComponent().getPackageName();
+    }
+
+    /** Retrieve package name from a PendingIntent */
+    @Nullable
+    public static String getPackageName(PendingIntent pendingIntent) {
+        if (pendingIntent == null || pendingIntent.getIntent() == null) {
+            return null;
+        }
+        return getPackageName(pendingIntent.getIntent());
+    }
+
+    /** Retrieve package name from a taskId */
+    @Nullable
+    public static String getPackageName(int taskId, ShellTaskOrganizer taskOrganizer) {
+        final ActivityManager.RunningTaskInfo taskInfo = taskOrganizer.getRunningTaskInfo(taskId);
+        return taskInfo != null ? getPackageName(taskInfo.baseIntent) : null;
+    }
+
+    /** Returns true if they are the same package. */
+    public static boolean samePackage(String packageName1, String packageName2) {
+        return packageName1 != null && packageName1.equals(packageName2);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 4879d86..d83f1eb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -21,6 +21,7 @@
 import android.os.Handler;
 import android.os.UserManager;
 import android.view.Choreographer;
+import android.view.IWindowManager;
 import android.view.WindowManager;
 
 import com.android.internal.jank.InteractionJankMonitor;
@@ -170,14 +171,15 @@
             @ShellMainThread Handler mainHandler,
             @ShellBackgroundThread ShellExecutor bgExecutor,
             TaskViewTransitions taskViewTransitions,
-            SyncTransactionQueue syncQueue) {
+            SyncTransactionQueue syncQueue,
+            IWindowManager wmService) {
         return new BubbleController(context, shellInit, shellCommandHandler, shellController, data,
                 null /* synchronizer */, floatingContentCoordinator,
                 new BubbleDataRepository(context, launcherApps, mainExecutor),
                 statusBarService, windowManager, windowManagerShellWrapper, userManager,
                 launcherApps, logger, taskStackListener, organizer, positioner, displayController,
                 oneHandedOptional, dragAndDropController, mainExecutor, mainHandler, bgExecutor,
-                taskViewTransitions, syncQueue);
+                taskViewTransitions, syncQueue, wmService);
     }
 
     //
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index 55378a8..3ade1ed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -22,6 +22,10 @@
 
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM;
+import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT;
+import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT;
+import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -315,6 +319,25 @@
                 // Switching between targets
                 mDropZoneView1.animateSwitch();
                 mDropZoneView2.animateSwitch();
+                // Announce for accessibility.
+                switch (target.type) {
+                    case TYPE_SPLIT_LEFT:
+                        mDropZoneView1.announceForAccessibility(
+                                mContext.getString(R.string.accessibility_split_left));
+                        break;
+                    case TYPE_SPLIT_RIGHT:
+                        mDropZoneView2.announceForAccessibility(
+                                mContext.getString(R.string.accessibility_split_right));
+                        break;
+                    case TYPE_SPLIT_TOP:
+                        mDropZoneView1.announceForAccessibility(
+                                mContext.getString(R.string.accessibility_split_top));
+                        break;
+                    case TYPE_SPLIT_BOTTOM:
+                        mDropZoneView2.announceForAccessibility(
+                                mContext.getString(R.string.accessibility_split_bottom));
+                        break;
+                }
             }
             mCurrentTarget = target;
         }
@@ -424,12 +447,10 @@
     }
 
     private void animateHighlight(DragAndDropPolicy.Target target) {
-        if (target.type == DragAndDropPolicy.Target.TYPE_SPLIT_LEFT
-                || target.type == DragAndDropPolicy.Target.TYPE_SPLIT_TOP) {
+        if (target.type == TYPE_SPLIT_LEFT || target.type == TYPE_SPLIT_TOP) {
             mDropZoneView1.setShowingHighlight(true);
             mDropZoneView2.setShowingHighlight(false);
-        } else if (target.type == DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT
-                || target.type == DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM) {
+        } else if (target.type == TYPE_SPLIT_RIGHT || target.type == TYPE_SPLIT_BOTTOM) {
             mDropZoneView1.setShowingHighlight(false);
             mDropZoneView2.setShowingHighlight(true);
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index 6728c00..d9ac76e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -28,6 +28,7 @@
 import android.annotation.NonNull;
 import android.app.TaskInfo;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.graphics.Rect;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -361,22 +362,26 @@
         }
 
         void setColorContentOverlay(Context context) {
-            final SurfaceControl.Transaction tx =
-                    mSurfaceControlTransactionFactory.getTransaction();
-            if (mContentOverlay != null) {
-                mContentOverlay.detach(tx);
-            }
-            mContentOverlay = new PipContentOverlay.PipColorOverlay(context);
-            mContentOverlay.attach(tx, mLeash);
+            reattachContentOverlay(new PipContentOverlay.PipColorOverlay(context));
         }
 
         void setSnapshotContentOverlay(TaskSnapshot snapshot, Rect sourceRectHint) {
+            reattachContentOverlay(
+                    new PipContentOverlay.PipSnapshotOverlay(snapshot, sourceRectHint));
+        }
+
+        void setAppIconContentOverlay(Context context, Rect bounds, ActivityInfo activityInfo) {
+            reattachContentOverlay(
+                    new PipContentOverlay.PipAppIconOverlay(context, bounds, activityInfo));
+        }
+
+        private void reattachContentOverlay(PipContentOverlay overlay) {
             final SurfaceControl.Transaction tx =
                     mSurfaceControlTransactionFactory.getTransaction();
             if (mContentOverlay != null) {
                 mContentOverlay.detach(tx);
             }
-            mContentOverlay = new PipContentOverlay.PipSnapshotOverlay(snapshot, sourceRectHint);
+            mContentOverlay = overlay;
             mContentOverlay.attach(tx, mLeash);
         }
 
@@ -570,8 +575,9 @@
                     final Rect base = getBaseValue();
                     final Rect start = getStartValue();
                     final Rect end = getEndValue();
+                    Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
                     if (mContentOverlay != null) {
-                        mContentOverlay.onAnimationUpdate(tx, fraction);
+                        mContentOverlay.onAnimationUpdate(tx, bounds, fraction);
                     }
                     if (rotatedEndRect != null) {
                         // Animate the bounds in a different orientation. It only happens when
@@ -579,7 +585,6 @@
                         applyRotation(tx, leash, fraction, start, end);
                         return;
                     }
-                    Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
                     float angle = (1.0f - fraction) * startingAngle;
                     setCurrentValue(bounds);
                     if (inScaleTransition() || sourceHintRect == null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java
index 283b1ec..480bf93 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java
@@ -16,11 +16,21 @@
 
 package com.android.wm.shell.pip;
 
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.TypedValue;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.window.TaskSnapshot;
@@ -51,9 +61,11 @@
      * Animates the internal {@link #mLeash} by a given fraction.
      * @param atomicTx {@link SurfaceControl.Transaction} to operate, you should not explicitly
      *                 call apply on this transaction, it should be applied on the caller side.
+     * @param currentBounds {@link Rect} of the current animation bounds.
      * @param fraction progress of the animation ranged from 0f to 1f.
      */
-    public abstract void onAnimationUpdate(SurfaceControl.Transaction atomicTx, float fraction);
+    public abstract void onAnimationUpdate(SurfaceControl.Transaction atomicTx,
+            Rect currentBounds, float fraction);
 
     /**
      * Callback when reaches the end of animation on the internal {@link #mLeash}.
@@ -66,13 +78,15 @@
 
     /** A {@link PipContentOverlay} uses solid color. */
     public static final class PipColorOverlay extends PipContentOverlay {
+        private static final String TAG = PipColorOverlay.class.getSimpleName();
+
         private final Context mContext;
 
         public PipColorOverlay(Context context) {
             mContext = context;
             mLeash = new SurfaceControl.Builder(new SurfaceSession())
-                    .setCallsite("PipAnimation")
-                    .setName(PipColorOverlay.class.getSimpleName())
+                    .setCallsite(TAG)
+                    .setName(TAG)
                     .setColorLayer()
                     .build();
         }
@@ -88,7 +102,8 @@
         }
 
         @Override
-        public void onAnimationUpdate(SurfaceControl.Transaction atomicTx, float fraction) {
+        public void onAnimationUpdate(SurfaceControl.Transaction atomicTx,
+                Rect currentBounds, float fraction) {
             atomicTx.setAlpha(mLeash, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2);
         }
 
@@ -114,6 +129,8 @@
 
     /** A {@link PipContentOverlay} uses {@link TaskSnapshot}. */
     public static final class PipSnapshotOverlay extends PipContentOverlay {
+        private static final String TAG = PipSnapshotOverlay.class.getSimpleName();
+
         private final TaskSnapshot mSnapshot;
         private final Rect mSourceRectHint;
 
@@ -121,8 +138,8 @@
             mSnapshot = snapshot;
             mSourceRectHint = new Rect(sourceRectHint);
             mLeash = new SurfaceControl.Builder(new SurfaceSession())
-                    .setCallsite("PipAnimation")
-                    .setName(PipSnapshotOverlay.class.getSimpleName())
+                    .setCallsite(TAG)
+                    .setName(TAG)
                     .build();
         }
 
@@ -143,7 +160,8 @@
         }
 
         @Override
-        public void onAnimationUpdate(SurfaceControl.Transaction atomicTx, float fraction) {
+        public void onAnimationUpdate(SurfaceControl.Transaction atomicTx,
+                Rect currentBounds, float fraction) {
             // Do nothing. Keep the snapshot till animation ends.
         }
 
@@ -152,4 +170,113 @@
             atomicTx.remove(mLeash);
         }
     }
+
+    /** A {@link PipContentOverlay} shows app icon on solid color background. */
+    public static final class PipAppIconOverlay extends PipContentOverlay {
+        private static final String TAG = PipAppIconOverlay.class.getSimpleName();
+        private static final int APP_ICON_SIZE_DP = 48;
+
+        private final Context mContext;
+        private final int mAppIconSizePx;
+        private final Rect mAppBounds;
+        private final Matrix mTmpTransform = new Matrix();
+        private final float[] mTmpFloat9 = new float[9];
+
+        private Bitmap mBitmap;
+
+        public PipAppIconOverlay(Context context, Rect appBounds, ActivityInfo activityInfo) {
+            mContext = context;
+            mAppIconSizePx = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, APP_ICON_SIZE_DP,
+                    context.getResources().getDisplayMetrics());
+            mAppBounds = new Rect(appBounds);
+            mBitmap = Bitmap.createBitmap(appBounds.width(), appBounds.height(),
+                    Bitmap.Config.ARGB_8888);
+            prepareAppIconOverlay(activityInfo);
+            mLeash = new SurfaceControl.Builder(new SurfaceSession())
+                    .setCallsite(TAG)
+                    .setName(TAG)
+                    .build();
+        }
+
+        @Override
+        public void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash) {
+            tx.show(mLeash);
+            tx.setLayer(mLeash, Integer.MAX_VALUE);
+            tx.setBuffer(mLeash, mBitmap.getHardwareBuffer());
+            tx.reparent(mLeash, parentLeash);
+            tx.apply();
+        }
+
+        @Override
+        public void onAnimationUpdate(SurfaceControl.Transaction atomicTx,
+                Rect currentBounds, float fraction) {
+            mTmpTransform.reset();
+            // Scale back the bitmap with the pivot point at center.
+            mTmpTransform.postScale(
+                    (float) mAppBounds.width() / currentBounds.width(),
+                    (float) mAppBounds.height() / currentBounds.height(),
+                    mAppBounds.centerX(),
+                    mAppBounds.centerY());
+            atomicTx.setMatrix(mLeash, mTmpTransform, mTmpFloat9)
+                    .setAlpha(mLeash, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2);
+        }
+
+        @Override
+        public void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds) {
+            atomicTx.remove(mLeash);
+        }
+
+        @Override
+        public void detach(SurfaceControl.Transaction tx) {
+            super.detach(tx);
+            if (mBitmap != null && !mBitmap.isRecycled()) {
+                mBitmap.recycle();
+            }
+        }
+
+        private void prepareAppIconOverlay(ActivityInfo activityInfo) {
+            final Canvas canvas = new Canvas();
+            canvas.setBitmap(mBitmap);
+            final TypedArray ta = mContext.obtainStyledAttributes(new int[] {
+                    android.R.attr.colorBackground });
+            try {
+                int colorAccent = ta.getColor(0, 0);
+                canvas.drawRGB(
+                        Color.red(colorAccent),
+                        Color.green(colorAccent),
+                        Color.blue(colorAccent));
+            } finally {
+                ta.recycle();
+            }
+            final Drawable appIcon = loadActivityInfoIcon(activityInfo,
+                    mContext.getResources().getConfiguration().densityDpi);
+            final Rect appIconBounds = new Rect(
+                    mAppBounds.centerX() - mAppIconSizePx / 2,
+                    mAppBounds.centerY() - mAppIconSizePx / 2,
+                    mAppBounds.centerX() + mAppIconSizePx / 2,
+                    mAppBounds.centerY() + mAppIconSizePx / 2);
+            appIcon.setBounds(appIconBounds);
+            appIcon.draw(canvas);
+            mBitmap = mBitmap.copy(Bitmap.Config.HARDWARE, false /* mutable */);
+        }
+
+        // Copied from com.android.launcher3.icons.IconProvider#loadActivityInfoIcon
+        private Drawable loadActivityInfoIcon(ActivityInfo ai, int density) {
+            final int iconRes = ai.getIconResource();
+            Drawable icon = null;
+            // Get the preferred density icon from the app's resources
+            if (density != 0 && iconRes != 0) {
+                try {
+                    final Resources resources = mContext.getPackageManager()
+                            .getResourcesForApplication(ai.applicationInfo);
+                    icon = resources.getDrawableForDensity(iconRes, density);
+                } catch (PackageManager.NameNotFoundException | Resources.NotFoundException exc) { }
+            }
+            // Get the default density icon
+            if (icon == null) {
+                icon = ai.loadIcon(mContext.getPackageManager());
+            }
+            return icon;
+        }
+    }
 }
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 8ba2583..aad27b9 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
@@ -62,6 +62,7 @@
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.util.Log;
 import android.view.Choreographer;
 import android.view.Display;
@@ -1568,7 +1569,13 @@
             // Similar to auto-enter-pip transition, we use content overlay when there is no
             // source rect hint to enter PiP use bounds animation.
             if (sourceHintRect == null) {
-                animator.setColorContentOverlay(mContext);
+                if (SystemProperties.getBoolean(
+                        "persist.wm.debug.enable_pip_app_icon_overlay", false)) {
+                    animator.setAppIconContentOverlay(
+                            mContext, currentBounds, mTaskInfo.topActivityInfo);
+                } else {
+                    animator.setColorContentOverlay(mContext);
+                }
             } else {
                 final TaskSnapshot snapshot = PipUtils.getTaskSnapshot(
                         mTaskInfo.launchIntoPipHostTaskId, false /* isLowResolution */);
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 83158ff..d9d1009 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
@@ -50,6 +50,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.os.SystemProperties;
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
@@ -792,7 +793,13 @@
             if (sourceHintRect == null) {
                 // We use content overlay when there is no source rect hint to enter PiP use bounds
                 // animation.
-                animator.setColorContentOverlay(mContext);
+                if (SystemProperties.getBoolean(
+                        "persist.wm.debug.enable_pip_app_icon_overlay", false)) {
+                    animator.setAppIconContentOverlay(
+                            mContext, currentBounds, taskInfo.topActivityInfo);
+                } else {
+                    animator.setColorContentOverlay(mContext);
+                }
             }
         } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
             animator = mPipAnimationController.getAnimator(taskInfo, leash, destinationBounds,
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 a906522..e787ed9 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
@@ -45,8 +45,9 @@
     @VisibleForTesting
     final SizeSpecSource mSizeSpecSourceImpl;
 
-    /** The preferred minimum (and default) size specified by apps. */
+    /** The preferred minimum (and default minimum) size specified by apps. */
     @Nullable private Size mOverrideMinSize;
+    private int mOverridableMinSize;
 
     /** Used to store values obtained from resource files. */
     private Point mScreenEdgeInsets;
@@ -386,6 +387,8 @@
 
         mDefaultMinSize = res.getDimensionPixelSize(
                 R.dimen.default_minimal_size_pip_resizable_task);
+        mOverridableMinSize = res.getDimensionPixelSize(
+                R.dimen.overridable_minimal_size_pip_resizable_task);
 
         final String screenEdgeInsetsDpString = res.getString(
                 R.string.config_defaultPictureInPictureScreenEdgeInsets);
@@ -443,13 +446,19 @@
     /** Returns the preferred minimal size specified by the activity in PIP. */
     @Nullable
     public Size getOverrideMinSize() {
+        if (mOverrideMinSize != null
+                && (mOverrideMinSize.getWidth() < mOverridableMinSize
+                || mOverrideMinSize.getHeight() < mOverridableMinSize)) {
+            return new Size(mOverridableMinSize, mOverridableMinSize);
+        }
+
         return mOverrideMinSize;
     }
 
     /** Returns the minimum edge size of the override minimum size, or 0 if not set. */
     public int getOverrideMinEdgeSize() {
         if (mOverrideMinSize == null) return 0;
-        return Math.min(mOverrideMinSize.getWidth(), mOverrideMinSize.getHeight());
+        return Math.min(getOverrideMinSize().getWidth(), getOverrideMinSize().getHeight());
     }
 
     public int getMinEdgeSize() {
@@ -505,7 +514,7 @@
         if (mOverrideMinSize == null) {
             return null;
         }
-        final Size size = mOverrideMinSize;
+        final Size size = getOverrideMinSize();
         final float sizeAspectRatio = size.getWidth() / (float) size.getHeight();
         if (sizeAspectRatio > aspectRatio) {
             // Size is wider, fix the width and increase the height
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index 8490f9f..0d9faa3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -308,7 +308,6 @@
             rawMapping.put(taskInfo.taskId, taskInfo);
         }
 
-        boolean desktopModeActive = DesktopModeStatus.isActive(mContext);
         ArrayList<ActivityManager.RecentTaskInfo> freeformTasks = new ArrayList<>();
 
         // Pull out the pairs as we iterate back in the list
@@ -320,7 +319,7 @@
                 continue;
             }
 
-            if (desktopModeActive && mDesktopModeTaskRepository.isPresent()
+            if (DesktopModeStatus.isProto2Enabled() && mDesktopModeTaskRepository.isPresent()
                     && mDesktopModeTaskRepository.get().isActiveTask(taskInfo.taskId)) {
                 // Freeform tasks will be added as a separate entry
                 freeformTasks.add(taskInfo);
@@ -328,7 +327,7 @@
             }
 
             final int pairedTaskId = mSplitTasks.get(taskInfo.taskId);
-            if (!desktopModeActive && pairedTaskId != INVALID_TASK_ID && rawMapping.contains(
+            if (pairedTaskId != INVALID_TASK_ID && rawMapping.contains(
                     pairedTaskId)) {
                 final ActivityManager.RecentTaskInfo pairedTaskInfo = rawMapping.get(pairedTaskId);
                 rawMapping.remove(pairedTaskId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
index 56aa742..81e118a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
@@ -122,9 +122,9 @@
      * Start a pair of intents using legacy transition system.
      */
     oneway void startIntentsWithLegacyTransition(in PendingIntent pendingIntent1,
-            in Bundle options1, in PendingIntent pendingIntent2, in Bundle options2,
-            int splitPosition, float splitRatio, in RemoteAnimationAdapter adapter,
-            in InstanceId instanceId) = 18;
+            in ShortcutInfo shortcutInfo1, in Bundle options1, in PendingIntent pendingIntent2,
+            in ShortcutInfo shortcutInfo2, in Bundle options2, int splitPosition, float splitRatio,
+            in RemoteAnimationAdapter adapter, in InstanceId instanceId) = 18;
 
     /**
      * Start a pair of intents in one transition.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 21eeaa2..36da4cf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -28,6 +28,9 @@
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+import static com.android.wm.shell.common.split.SplitScreenUtils.isValidToSplit;
+import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
+import static com.android.wm.shell.common.split.SplitScreenUtils.samePackage;
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
 import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN;
@@ -39,11 +42,8 @@
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.PendingIntent;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.LauncherApps;
 import android.content.pm.ShortcutInfo;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -82,8 +82,8 @@
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.annotations.ExternalThread;
-import com.android.wm.shell.common.split.SplitLayout;
 import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
+import com.android.wm.shell.common.split.SplitScreenUtils;
 import com.android.wm.shell.draganddrop.DragAndDropController;
 import com.android.wm.shell.draganddrop.DragAndDropPolicy;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -318,10 +318,6 @@
         return mStageCoordinator;
     }
 
-    public boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
-        return mStageCoordinator.isValidToEnterSplitScreen(taskInfo);
-    }
-
     @Nullable
     public ActivityManager.RunningTaskInfo getTaskInfo(@SplitPosition int splitPosition) {
         if (!isSplitScreenVisible() || splitPosition == SPLIT_POSITION_UNDEFINED) {
@@ -480,39 +476,54 @@
     @Override
     public void startShortcut(String packageName, String shortcutId, @SplitPosition int position,
             @Nullable Bundle options, UserHandle user) {
-        IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
-            @Override
-            public void onAnimationStart(@WindowManager.TransitionOldType int transit,
-                    RemoteAnimationTarget[] apps,
-                    RemoteAnimationTarget[] wallpapers,
-                    RemoteAnimationTarget[] nonApps,
-                    final IRemoteAnimationFinishedCallback finishedCallback) {
-                try {
-                    finishedCallback.onAnimationFinished();
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Failed to invoke onAnimationFinished", e);
-                }
-                final WindowContainerTransaction evictWct = new WindowContainerTransaction();
-                mStageCoordinator.prepareEvictNonOpeningChildTasks(position, apps, evictWct);
-                mSyncQueue.queue(evictWct);
+        if (options == null) options = new Bundle();
+        final ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
+
+        if (samePackage(packageName, getPackageName(reverseSplitPosition(position)))) {
+            if (supportMultiInstancesSplit(packageName)) {
+                activityOptions.setApplyMultipleTaskFlagForShortcut(true);
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
+            } else if (isSplitScreenVisible()) {
+                mStageCoordinator.switchSplitPosition("startShortcut");
+                return;
+            } else {
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
+                        "Cancel entering split as not supporting multi-instances");
+                Toast.makeText(mContext, R.string.dock_multi_instances_not_supported_text,
+                        Toast.LENGTH_SHORT).show();
+                return;
             }
-            @Override
-            public void onAnimationCancelled(boolean isKeyguardOccluded) {
-            }
-        };
-        options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options,
-                null /* wct */);
-        RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(wrapper,
-                0 /* duration */, 0 /* statusBarTransitionDelay */);
-        ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
-        activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
-        try {
-            LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
-            launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
-                    activityOptions.toBundle(), user);
-        } catch (ActivityNotFoundException e) {
-            Slog.e(TAG, "Failed to launch shortcut", e);
         }
+
+        mStageCoordinator.startShortcut(packageName, shortcutId, position,
+                activityOptions.toBundle(), user);
+    }
+
+    void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo,
+            @Nullable Bundle options1, int taskId, @Nullable Bundle options2,
+            @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
+            InstanceId instanceId) {
+        if (options1 == null) options1 = new Bundle();
+        final ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
+
+        final String packageName1 = shortcutInfo.getPackage();
+        final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
+        if (samePackage(packageName1, packageName2)) {
+            if (supportMultiInstancesSplit(shortcutInfo.getPackage())) {
+                activityOptions.setApplyMultipleTaskFlagForShortcut(true);
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
+            } else {
+                taskId = INVALID_TASK_ID;
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
+                        "Cancel entering split as not supporting multi-instances");
+                Toast.makeText(mContext, R.string.dock_multi_instances_not_supported_text,
+                        Toast.LENGTH_SHORT).show();
+            }
+        }
+
+        mStageCoordinator.startShortcutAndTaskWithLegacyTransition(shortcutInfo,
+                activityOptions.toBundle(), taskId, options2, splitPosition, splitRatio, adapter,
+                instanceId);
     }
 
     /**
@@ -530,8 +541,10 @@
             @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
             InstanceId instanceId) {
         Intent fillInIntent = null;
-        if (launchSameAppAdjacently(pendingIntent, taskId)) {
-            if (supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) {
+        final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent);
+        final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
+        if (samePackage(packageName1, packageName2)) {
+            if (supportMultiInstancesSplit(packageName1)) {
                 fillInIntent = new Intent();
                 fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
                 ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
@@ -551,8 +564,10 @@
             int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
             float splitRatio, @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
         Intent fillInIntent = null;
-        if (launchSameAppAdjacently(pendingIntent, taskId)) {
-            if (supportMultiInstancesSplit(pendingIntent.getIntent().getComponent())) {
+        final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent);
+        final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
+        if (samePackage(packageName1, packageName2)) {
+            if (supportMultiInstancesSplit(packageName1)) {
                 fillInIntent = new Intent();
                 fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
                 ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
@@ -568,13 +583,16 @@
     }
 
     private void startIntentsWithLegacyTransition(PendingIntent pendingIntent1,
-            @Nullable Bundle options1, PendingIntent pendingIntent2,
-            @Nullable Bundle options2, @SplitPosition int splitPosition,
-            float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
+            @Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
+            PendingIntent pendingIntent2, @Nullable ShortcutInfo shortcutInfo2,
+            @Nullable Bundle options2, @SplitPosition int splitPosition, float splitRatio,
+            RemoteAnimationAdapter adapter, InstanceId instanceId) {
         Intent fillInIntent1 = null;
         Intent fillInIntent2 = null;
-        if (launchSameAppAdjacently(pendingIntent1, pendingIntent2)) {
-            if (supportMultiInstancesSplit(pendingIntent1.getIntent().getComponent())) {
+        final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent1);
+        final String packageName2 = SplitScreenUtils.getPackageName(pendingIntent2);
+        if (samePackage(packageName1, packageName2)) {
+            if (supportMultiInstancesSplit(packageName1)) {
                 fillInIntent1 = new Intent();
                 fillInIntent1.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
                 fillInIntent2 = new Intent();
@@ -588,9 +606,9 @@
                         Toast.LENGTH_SHORT).show();
             }
         }
-        mStageCoordinator.startIntentsWithLegacyTransition(pendingIntent1, fillInIntent1, options1,
-                pendingIntent2, fillInIntent2, options2, splitPosition, splitRatio, adapter,
-                instanceId);
+        mStageCoordinator.startIntentsWithLegacyTransition(pendingIntent1, fillInIntent1,
+                shortcutInfo1, options1, pendingIntent2, fillInIntent2, shortcutInfo2, options2,
+                splitPosition, splitRatio, adapter, instanceId);
     }
 
     @Override
@@ -602,13 +620,15 @@
         if (fillInIntent == null) fillInIntent = new Intent();
         fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
 
-        if (launchSameAppAdjacently(position, intent)) {
-            final ComponentName launching = intent.getIntent().getComponent();
-            if (supportMultiInstancesSplit(launching)) {
+        final String packageName1 = SplitScreenUtils.getPackageName(intent);
+        final String packageName2 = getPackageName(reverseSplitPosition(position));
+        if (SplitScreenUtils.samePackage(packageName1, packageName2)) {
+            if (supportMultiInstancesSplit(packageName1)) {
                 // To prevent accumulating large number of instances in the background, reuse task
                 // in the background with priority.
                 final ActivityManager.RecentTaskInfo taskInfo = mRecentTasksOptional
-                        .map(recentTasks -> recentTasks.findTaskInBackground(launching))
+                        .map(recentTasks -> recentTasks.findTaskInBackground(
+                                intent.getIntent().getComponent()))
                         .orElse(null);
                 if (taskInfo != null) {
                     startTask(taskInfo.taskId, position, options);
@@ -636,63 +656,32 @@
         mStageCoordinator.startIntent(intent, fillInIntent, position, options);
     }
 
+    /** Retrieve package name of a specific split position if split screen is activated, otherwise
+     *  returns the package name of the top running task. */
     @Nullable
-    private String getPackageName(Intent intent) {
-        if (intent == null || intent.getComponent() == null) {
-            return null;
-        }
-        return intent.getComponent().getPackageName();
-    }
-
-    private boolean launchSameAppAdjacently(@SplitPosition int position,
-            PendingIntent pendingIntent) {
-        ActivityManager.RunningTaskInfo adjacentTaskInfo = null;
+    private String getPackageName(@SplitPosition int position) {
+        ActivityManager.RunningTaskInfo taskInfo;
         if (isSplitScreenVisible()) {
-            adjacentTaskInfo = getTaskInfo(SplitLayout.reversePosition(position));
+            taskInfo = getTaskInfo(position);
         } else {
-            adjacentTaskInfo = mRecentTasksOptional
-                    .map(recentTasks -> recentTasks.getTopRunningTask()).orElse(null);
-            if (!isValidToEnterSplitScreen(adjacentTaskInfo)) {
-                return false;
+            taskInfo = mRecentTasksOptional
+                    .map(recentTasks -> recentTasks.getTopRunningTask())
+                    .orElse(null);
+            if (!isValidToSplit(taskInfo)) {
+                return null;
             }
         }
 
-        if (adjacentTaskInfo == null) {
-            return false;
-        }
-
-        final String targetPackageName = getPackageName(pendingIntent.getIntent());
-        final String adjacentPackageName = getPackageName(adjacentTaskInfo.baseIntent);
-        return targetPackageName != null && targetPackageName.equals(adjacentPackageName);
-    }
-
-    private boolean launchSameAppAdjacently(PendingIntent pendingIntent, int taskId) {
-        final ActivityManager.RunningTaskInfo adjacentTaskInfo =
-                mTaskOrganizer.getRunningTaskInfo(taskId);
-        if (adjacentTaskInfo == null) {
-            return false;
-        }
-        final String targetPackageName = getPackageName(pendingIntent.getIntent());
-        final String adjacentPackageName = getPackageName(adjacentTaskInfo.baseIntent);
-        return targetPackageName != null && targetPackageName.equals(adjacentPackageName);
-    }
-
-    private boolean launchSameAppAdjacently(PendingIntent pendingIntent1,
-            PendingIntent pendingIntent2) {
-        final String targetPackageName = getPackageName(pendingIntent1.getIntent());
-        final String adjacentPackageName = getPackageName(pendingIntent2.getIntent());
-        return targetPackageName != null && targetPackageName.equals(adjacentPackageName);
+        return taskInfo != null ? SplitScreenUtils.getPackageName(taskInfo.baseIntent) : null;
     }
 
     @VisibleForTesting
-    /** Returns {@code true} if the component supports multi-instances split. */
-    boolean supportMultiInstancesSplit(@Nullable ComponentName launching) {
-        if (launching == null) return false;
-
-        final String packageName = launching.getPackageName();
-        for (int i = 0; i < mAppsSupportMultiInstances.length; i++) {
-            if (mAppsSupportMultiInstances[i].equals(packageName)) {
-                return true;
+    boolean supportMultiInstancesSplit(String packageName) {
+        if (packageName != null) {
+            for (int i = 0; i < mAppsSupportMultiInstances.length; i++) {
+                if (mAppsSupportMultiInstances[i].equals(packageName)) {
+                    return true;
+                }
             }
         }
 
@@ -1011,7 +1000,7 @@
                 InstanceId instanceId) {
             executeRemoteCallWithTaskPermission(mController,
                     "startShortcutAndTaskWithLegacyTransition", (controller) ->
-                            controller.mStageCoordinator.startShortcutAndTaskWithLegacyTransition(
+                            controller.startShortcutAndTaskWithLegacyTransition(
                                     shortcutInfo, options1, taskId, options2, splitPosition,
                                     splitRatio, adapter, instanceId));
         }
@@ -1049,13 +1038,14 @@
 
         @Override
         public void startIntentsWithLegacyTransition(PendingIntent pendingIntent1,
-                @Nullable Bundle options1, PendingIntent pendingIntent2, @Nullable Bundle options2,
-                @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
-                InstanceId instanceId) {
+                @Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
+                PendingIntent pendingIntent2, @Nullable ShortcutInfo shortcutInfo2,
+                @Nullable Bundle options2, @SplitPosition int splitPosition, float splitRatio,
+                RemoteAnimationAdapter adapter, InstanceId instanceId) {
             executeRemoteCallWithTaskPermission(mController, "startIntentsWithLegacyTransition",
                     (controller) ->
-                        controller.startIntentsWithLegacyTransition(
-                                pendingIntent1, options1, pendingIntent2, options2, splitPosition,
+                        controller.startIntentsWithLegacyTransition(pendingIntent1, shortcutInfo1,
+                                options1, pendingIntent2, shortcutInfo2, options2, splitPosition,
                                 splitRatio, adapter, instanceId)
                     );
         }
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 39cf5f1..2a4bae9 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
@@ -36,12 +36,11 @@
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
 
 import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER;
-import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
-import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
 import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
@@ -76,8 +75,10 @@
 import android.app.IActivityTaskManager;
 import android.app.PendingIntent;
 import android.app.WindowConfiguration;
+import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.LauncherApps;
 import android.content.pm.ShortcutInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
@@ -87,6 +88,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 import android.util.Slog;
 import android.view.Choreographer;
@@ -370,7 +372,7 @@
         int sideStagePosition;
         if (stageType == STAGE_TYPE_MAIN) {
             targetStage = mMainStage;
-            sideStagePosition = SplitLayout.reversePosition(stagePosition);
+            sideStagePosition = reverseSplitPosition(stagePosition);
         } else if (stageType == STAGE_TYPE_SIDE) {
             targetStage = mSideStage;
             sideStagePosition = stagePosition;
@@ -428,6 +430,72 @@
         return mLogger;
     }
 
+    void startShortcut(String packageName, String shortcutId, @SplitPosition int position,
+            Bundle options, UserHandle user) {
+        final boolean isEnteringSplit = !isSplitActive();
+
+        IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
+            @Override
+            public void onAnimationStart(@WindowManager.TransitionOldType int transit,
+                    RemoteAnimationTarget[] apps,
+                    RemoteAnimationTarget[] wallpapers,
+                    RemoteAnimationTarget[] nonApps,
+                    final IRemoteAnimationFinishedCallback finishedCallback) {
+                boolean openingToSide = false;
+                if (apps != null) {
+                    for (int i = 0; i < apps.length; ++i) {
+                        if (apps[i].mode == MODE_OPENING
+                                && mSideStage.containsTask(apps[i].taskId)) {
+                            openingToSide = true;
+                            break;
+                        }
+                    }
+                }
+
+                if (isEnteringSplit && !openingToSide) {
+                    mMainExecutor.execute(() -> exitSplitScreen(
+                            mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
+                            EXIT_REASON_UNKNOWN));
+                }
+
+                if (finishedCallback != null) {
+                    try {
+                        finishedCallback.onAnimationFinished();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Error finishing legacy transition: ", e);
+                    }
+                }
+
+                if (!isEnteringSplit && openingToSide) {
+                    final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+                    prepareEvictNonOpeningChildTasks(position, apps, evictWct);
+                    mSyncQueue.queue(evictWct);
+                }
+            }
+            @Override
+            public void onAnimationCancelled(boolean isKeyguardOccluded) {
+                if (isEnteringSplit) {
+                    mMainExecutor.execute(() -> exitSplitScreen(
+                            mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
+                            EXIT_REASON_UNKNOWN));
+                }
+            }
+        };
+        options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options,
+                null /* wct */);
+        RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(wrapper,
+                0 /* duration */, 0 /* statusBarTransitionDelay */);
+        ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
+        activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
+        try {
+            LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
+            launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
+                    activityOptions.toBundle(), user);
+        } catch (ActivityNotFoundException e) {
+            Slog.e(TAG, "Failed to launch shortcut", e);
+        }
+    }
+
     /** Launches an activity into split. */
     void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position,
             @Nullable Bundle options) {
@@ -624,9 +692,11 @@
 
     /** Starts a pair of intents using legacy transition. */
     void startIntentsWithLegacyTransition(PendingIntent pendingIntent1, Intent fillInIntent1,
-            @Nullable Bundle options1, PendingIntent pendingIntent2, Intent fillInIntent2,
-            @Nullable Bundle options2, @SplitPosition int splitPosition, float splitRatio,
-            RemoteAnimationAdapter adapter, InstanceId instanceId) {
+            @Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
+            @Nullable PendingIntent pendingIntent2, Intent fillInIntent2,
+            @Nullable ShortcutInfo shortcutInfo2, @Nullable Bundle options2,
+            @SplitPosition int splitPosition, float splitRatio, RemoteAnimationAdapter adapter,
+            InstanceId instanceId) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (options1 == null) options1 = new Bundle();
         if (pendingIntent2 == null) {
@@ -635,15 +705,23 @@
             activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
             options1 = activityOptions.toBundle();
             addActivityOptions(options1, null /* launchTarget */);
-            wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
+            if (shortcutInfo1 != null) {
+                wct.startShortcut(mContext.getPackageName(), shortcutInfo1, options1);
+            } else {
+                wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
+            }
             mSyncQueue.queue(wct);
             return;
         }
 
         addActivityOptions(options1, mSideStage);
-        wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
-        startWithLegacyTransition(wct, pendingIntent2, fillInIntent2, options2, splitPosition,
-                splitRatio, adapter, instanceId);
+        if (shortcutInfo1 != null) {
+            wct.startShortcut(mContext.getPackageName(), shortcutInfo1, options1);
+        } else {
+            wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
+        }
+        startWithLegacyTransition(wct, pendingIntent2, fillInIntent2, shortcutInfo2, options2,
+                splitPosition, splitRatio, adapter, instanceId);
     }
 
     void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent,
@@ -695,18 +773,19 @@
 
     private void startWithLegacyTransition(WindowContainerTransaction wct,
             @Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
-            @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio,
-            RemoteAnimationAdapter adapter, InstanceId instanceId) {
+            @Nullable ShortcutInfo mainShortcutInfo, @Nullable Bundle mainOptions,
+            @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter,
+            InstanceId instanceId) {
         startWithLegacyTransition(wct, INVALID_TASK_ID, mainPendingIntent, mainFillInIntent,
-                mainOptions, sidePosition, splitRatio, adapter, instanceId);
+                mainShortcutInfo, mainOptions, sidePosition, splitRatio, adapter, instanceId);
     }
 
     private void startWithLegacyTransition(WindowContainerTransaction wct, int mainTaskId,
             @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio,
             RemoteAnimationAdapter adapter, InstanceId instanceId) {
         startWithLegacyTransition(wct, mainTaskId, null /* mainPendingIntent */,
-                null /* mainFillInIntent */, mainOptions, sidePosition, splitRatio, adapter,
-                instanceId);
+                null /* mainFillInIntent */, null /* mainShortcutInfo */, mainOptions, sidePosition,
+                splitRatio, adapter, instanceId);
     }
 
     /**
@@ -716,8 +795,9 @@
      */
     private void startWithLegacyTransition(WindowContainerTransaction wct, int mainTaskId,
             @Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
-            @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio,
-            RemoteAnimationAdapter adapter, InstanceId instanceId) {
+            @Nullable ShortcutInfo mainShortcutInfo, @Nullable Bundle options,
+            @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter,
+            InstanceId instanceId) {
         if (!isSplitScreenVisible()) {
             exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
         }
@@ -741,15 +821,19 @@
             mMainStage.activate(wct, false /* reparent */);
         }
 
-        if (mainOptions == null) mainOptions = new Bundle();
-        addActivityOptions(mainOptions, mMainStage);
-        mainOptions = wrapAsSplitRemoteAnimation(adapter, mainOptions);
+        if (options == null) options = new Bundle();
+        addActivityOptions(options, mMainStage);
+        options = wrapAsSplitRemoteAnimation(adapter, options);
 
         updateWindowBounds(mSplitLayout, wct);
-        if (mainTaskId == INVALID_TASK_ID) {
-            wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, mainOptions);
+
+        // TODO(b/268008375): Merge APIs to start a split pair into one.
+        if (mainTaskId != INVALID_TASK_ID) {
+            wct.startTask(mainTaskId, options);
+        } else if (mainShortcutInfo != null) {
+            wct.startShortcut(mContext.getPackageName(), mainShortcutInfo, options);
         } else {
-            wct.startTask(mainTaskId, mainOptions);
+            wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, options);
         }
 
         wct.reorder(mRootTaskInfo.token, true);
@@ -899,7 +983,7 @@
             case STAGE_TYPE_MAIN: {
                 if (position != SPLIT_POSITION_UNDEFINED) {
                     // Set the side stage opposite of what we want to the main stage.
-                    setSideStagePosition(SplitLayout.reversePosition(position), wct);
+                    setSideStagePosition(reverseSplitPosition(position), wct);
                 } else {
                     position = getMainStagePosition();
                 }
@@ -923,7 +1007,7 @@
 
     @SplitPosition
     int getMainStagePosition() {
-        return SplitLayout.reversePosition(mSideStagePosition);
+        return reverseSplitPosition(mSideStagePosition);
     }
 
     int getTaskId(@SplitPosition int splitPosition) {
@@ -950,7 +1034,7 @@
         mSplitLayout.splitSwitching(t, topLeftStage.mRootLeash, bottomRightStage.mRootLeash,
                 insets -> {
                     WindowContainerTransaction wct = new WindowContainerTransaction();
-                    setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition), wct);
+                    setSideStagePosition(reverseSplitPosition(mSideStagePosition), wct);
                     mSyncQueue.queue(wct);
                     mSyncQueue.runInSync(st -> {
                         updateSurfaceBounds(mSplitLayout, st, false /* applyResizingOffset */);
@@ -1694,12 +1778,6 @@
         }
     }
 
-    boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
-        return taskInfo.supportsMultiWindow
-                && ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
-                && ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode());
-    }
-
     @Override
     public void onSnappedToDismiss(boolean bottomOrRight, int reason) {
         final boolean mainStageToTop =
@@ -2108,7 +2186,7 @@
 
             // Use normal animations.
             return false;
-        } else if (mMixedHandler != null && hasDisplayChange(info)) {
+        } else if (mMixedHandler != null && Transitions.hasDisplayChange(info)) {
             // A display-change has been un-expectedly inserted into the transition. Redirect
             // handling to the mixed-handler to deal with splitting it up.
             if (mMixedHandler.animatePendingSplitWithDisplayChange(transition, info,
@@ -2151,15 +2229,6 @@
         return true;
     }
 
-    private boolean hasDisplayChange(TransitionInfo info) {
-        boolean has = false;
-        for (int iC = 0; iC < info.getChanges().size() && !has; ++iC) {
-            final TransitionInfo.Change change = info.getChanges().get(iC);
-            has = change.getMode() == TRANSIT_CHANGE && (change.getFlags() & FLAG_IS_DISPLAY) != 0;
-        }
-        return has;
-    }
-
     /** Called to clean-up state and do house-keeping after the animation is done. */
     public void onTransitionAnimationComplete() {
         // If still playing, let it finish.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index b4e0584..02f19eb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -93,6 +93,11 @@
             @NonNull SurfaceControl.Transaction startTransaction,
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
+        if (!Transitions.SHELL_TRANSITIONS_ROTATION && Transitions.hasDisplayChange(info)) {
+            // Note that if the remote doesn't have permission ACCESS_SURFACE_FLINGER, some
+            // operations of the start transaction may be ignored.
+            return false;
+        }
         RemoteTransition pendingRemote = mRequestedRemotes.get(transition);
         if (pendingRemote == null) {
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition %s doesn't have "
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 44d6a0d..b2f61c2 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
@@ -24,6 +24,7 @@
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.view.WindowManager.fixScale;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
 import static android.window.TransitionInfo.FLAG_IS_OCCLUDED;
 import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
 import static android.window.TransitionInfo.FLAG_NO_ANIMATION;
@@ -328,6 +329,17 @@
         return type == TRANSIT_CLOSE || type == TRANSIT_TO_BACK;
     }
 
+    /** Returns {@code true} if the transition has a display change. */
+    public static boolean hasDisplayChange(@NonNull TransitionInfo info) {
+        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+            final TransitionInfo.Change change = info.getChanges().get(i);
+            if (change.getMode() == TRANSIT_CHANGE && change.hasFlags(FLAG_IS_DISPLAY)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Sets up visibility/alpha/transforms to resemble the starting state of an animation.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
index eab82f0..87e447b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
@@ -85,7 +85,7 @@
 
     @Override
     public void insetsChanged(InsetsState insetsState) {
-        mTaskbarInsetsSource = insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
+        mTaskbarInsetsSource = insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
         for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) {
             AnimationContext context = mAnimationContextByTaskId.valueAt(i);
             context.update(mTaskbarInsetsSource, context.mTaskInfo);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
index 6e10ebe..8a0fbe3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
@@ -126,7 +126,7 @@
 
     @Override
     public void insetsChanged(InsetsState insetsState) {
-        mTaskbarInsetsSource = insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
+        mTaskbarInsetsSource = insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
         updateContexts();
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 476a7ec..2981f5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -36,6 +36,7 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.transition.Transitions;
 
 /**
  * View model for the window decoration with a caption and shadows. Works with
@@ -65,6 +66,9 @@
         mTaskOrganizer = taskOrganizer;
         mDisplayController = displayController;
         mSyncQueue = syncQueue;
+        if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
+            mTaskOperations = new TaskOperations(null, mContext, mSyncQueue);
+        }
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 606cf28..db6cbdc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -301,18 +301,11 @@
                     mDragPositioningCallback.onDragPositioningEnd(
                             e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
                     if (e.getRawY(dragPointerIdx) <= statusBarHeight) {
-                        if (DesktopModeStatus.isProto2Enabled()) {
-                            if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
-                                // Switch a single task to fullscreen
-                                mDesktopTasksController.ifPresent(
-                                        c -> c.moveToFullscreen(taskInfo));
-                            }
-                        } else if (DesktopModeStatus.isProto1Enabled()) {
-                            if (DesktopModeStatus.isActive(mContext)) {
-                                // Turn off desktop mode
-                                mDesktopModeController.ifPresent(
-                                        c -> c.setDesktopModeActive(false));
-                            }
+                        if (DesktopModeStatus.isProto2Enabled()
+                                && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+                            // Switch a single task to fullscreen
+                            mDesktopTasksController.ifPresent(
+                                    c -> c.moveToFullscreen(taskInfo));
                         }
                     }
                     break;
@@ -402,10 +395,6 @@
                     || focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
                 handleCaptionThroughStatusBar(ev);
             }
-        } else if (DesktopModeStatus.isProto1Enabled()) {
-            if (!DesktopModeStatus.isActive(mContext)) {
-                handleCaptionThroughStatusBar(ev);
-            }
         }
         handleEventOutsideFocusedCaption(ev);
         // Prevent status bar from reacting to a caption drag.
@@ -451,9 +440,6 @@
                         // In proto2 any full screen task can be dragged to freeform
                         dragFromStatusBarAllowed = focusedDecor.mTaskInfo.getWindowingMode()
                                 == WINDOWING_MODE_FULLSCREEN;
-                    } else if (DesktopModeStatus.isProto1Enabled()) {
-                        // In proto1 task can be dragged to freeform when not in desktop mode
-                        dragFromStatusBarAllowed = !DesktopModeStatus.isActive(mContext);
                     }
 
                     if (dragFromStatusBarAllowed && focusedDecor.checkTouchEventInHandle(ev)) {
@@ -524,7 +510,7 @@
 
     private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
         if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true;
-        return DesktopModeStatus.isAnyEnabled()
+        return DesktopModeStatus.isProto2Enabled()
                 && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD
                 && mDisplayController.getDisplayContext(taskInfo.displayId)
                 .getResources().getConfiguration().smallestScreenWidthDp >= 600;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
index 907977c..3734487 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
@@ -29,7 +29,8 @@
  */
 public interface WindowDecorViewModel {
     /**
-     * Sets the transition starter that starts freeform task transitions.
+     * Sets the transition starter that starts freeform task transitions. Only called when
+     * {@link com.android.wm.shell.transition.Transitions#ENABLE_SHELL_TRANSITIONS} is {@code true}.
      *
      * @param transitionStarter the transition starter that starts freeform task transitions
      */
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
index 122c18d..aafd7ed 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
@@ -32,7 +32,7 @@
 import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
 import com.android.server.wm.flicker.taskBarLayerIsVisibleAtStartAndEnd
 import com.android.server.wm.flicker.taskBarWindowIsAlwaysVisible
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.Assume
 import org.junit.Test
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 5186914..bd18108 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -22,7 +22,7 @@
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.traces.layers.LayerTraceEntrySubject
 import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
 import com.android.server.wm.traces.common.region.Region
 import com.android.server.wm.traces.common.service.PlatformConsts
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index 651d935..e9c805e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -18,7 +18,7 @@
 
 package com.android.wm.shell.flicker
 
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 
 const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
 const val LAUNCHER_UI_PACKAGE_NAME = "com.google.android.apps.nexuslauncher"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt
similarity index 96%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt
index b3a2ad3..7358da3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt
@@ -45,7 +45,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-open class MultiBubblesScreen(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
+open class ChangeActiveActivityFromBubbleTest(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
 
     @Before
     open fun before() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt
similarity index 88%
copy from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
copy to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt
index 69eb06f..1a0fbe4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt
@@ -23,4 +23,5 @@
 
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-open class MultiBubblesScreenCfArm(flicker: FlickerTest) : MultiBubblesScreen(flicker)
+open class ChangeActiveActivityFromBubbleTestCfArm(flicker: FlickerTest) :
+    ChangeActiveActivityFromBubbleTest(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt
similarity index 91%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenShellTransit.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt
index 191f4fa..cf696c8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt
@@ -30,7 +30,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FlakyTest(bugId = 217777115)
-class MultiBubblesScreenShellTransit(flicker: FlickerTest) : MultiBubblesScreen(flicker) {
+class ChangeActiveActivityFromBubbleTestShellTransit(flicker: FlickerTest) :
+    ChangeActiveActivityFromBubbleTest(flicker) {
     @Before
     override fun before() {
         Assume.assumeTrue(isShellTransitionsEnabled)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenCfArm.kt
deleted file mode 100644
index 315e021..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenCfArm.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.wm.shell.flicker.bubble
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-class DismissBubbleScreenCfArm(flicker: FlickerTest) : DismissBubbleScreen(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
similarity index 96%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
index 7a86c25..9367a8a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
@@ -44,7 +44,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-open class DismissBubbleScreen(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
+open class DragToDismissBubbleScreenTest(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
 
     private val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
     private val displaySize = DisplayMetrics()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt
similarity index 89%
copy from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
copy to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt
index 69eb06f..85a534c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt
@@ -23,4 +23,5 @@
 
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-open class MultiBubblesScreenCfArm(flicker: FlickerTest) : MultiBubblesScreen(flicker)
+class DragToDismissBubbleScreenTestCfArm(flicker: FlickerTest) :
+    DragToDismissBubbleScreenTest(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenCfArm.kt
deleted file mode 100644
index 26e6273..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenCfArm.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.wm.shell.flicker.bubble
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-class ExpandBubbleScreenCfArm(flicker: FlickerTest) : ExpandBubbleScreen(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenCfArm.kt
deleted file mode 100644
index ec6a9c1..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenCfArm.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.wm.shell.flicker.bubble
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-open class LaunchBubbleScreenCfArm(flicker: FlickerTest) : LaunchBubbleScreen(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLockreenTest.kt
similarity index 97%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLockreenTest.kt
index 379d5e9..0b1382b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLockreenTest.kt
@@ -46,7 +46,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-class LaunchBubbleFromLockScreen(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
+class OpenActivityFromBubbleOnLockreenTest(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt
similarity index 95%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt
index 0cda626..50507bf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt
@@ -42,7 +42,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-open class ExpandBubbleScreen(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
+open class OpenActivityFromBubbleTest(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt
similarity index 90%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt
index 69eb06f..94147e8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt
@@ -23,4 +23,4 @@
 
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-open class MultiBubblesScreenCfArm(flicker: FlickerTest) : MultiBubblesScreen(flicker)
+class OpenActivityFromBubbleTestCfArm(flicker: FlickerTest) : OpenActivityFromBubbleTest(flicker)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt
similarity index 95%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt
index 5c0f854..4be4dcd 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt
@@ -41,7 +41,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-open class LaunchBubbleScreen(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
+open class SendBubbleNotificationTest(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt
similarity index 89%
copy from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
copy to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt
index 69eb06f..7efbcdb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt
@@ -23,4 +23,5 @@
 
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-open class MultiBubblesScreenCfArm(flicker: FlickerTest) : MultiBubblesScreen(flicker)
+open class SendBubbleNotificationTestCfArm(flicker: FlickerTest) :
+    SendBubbleNotificationTest(flicker)
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 4f3facb..88cf15e 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
@@ -54,7 +54,7 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @FlakyTest(bugId = 238367575)
-class AutoEnterPipOnGoToHomeTest(flicker: FlickerTest) : EnterPipTest(flicker) {
+class AutoEnterPipOnGoToHomeTest(flicker: FlickerTest) : EnterPipViaAppUiButtonTest(flicker) {
     /** Defines the transition used to run the test */
     override val transition: FlickerBuilder.() -> Unit
         get() = {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
similarity index 80%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
index 54ad991..88542d5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
@@ -20,10 +20,8 @@
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -54,7 +52,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class ExitPipWithSwipeDownTest(flicker: FlickerTest) : ExitPipTransition(flicker) {
+open class ClosePipBySwipingDownTest(flicker: FlickerTest) : ClosePipTransition(flicker) {
     override val transition: FlickerBuilder.() -> Unit
         get() = {
             super.transition(this)
@@ -76,7 +74,9 @@
                         ?.height
                         ?: error("Couldn't find Nav or Task bar layer")
                 // The dismiss button doesn't appear at the complete bottom of the screen,
-                val displayY = device.displayHeight - barLayerHeight
+                // 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
@@ -94,20 +94,4 @@
     fun focusDoesNotChange() {
         flicker.assertEventLog { this.focusDoesNotChange() }
     }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
-         * and navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
-            )
-        }
-    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt
similarity index 94%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt
index 03dfa5b..fb1eb01 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt
@@ -28,7 +28,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitPipViaIntentTestCfArm(flicker: FlickerTest) : ExitPipViaIntentTest(flicker) {
+class ClosePipBySwipingDownTestCfArm(flicker: FlickerTest) : ClosePipBySwipingDownTest(flicker) {
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
similarity index 79%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
index 1b5c227..080e033 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
@@ -19,14 +19,16 @@
 import android.platform.test.annotations.Presubmit
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.LAUNCHER
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.LAUNCHER
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Test
+import org.junit.runners.Parameterized
 
 /** Base class for exiting pip (closing pip window) without returning to the app */
-abstract class ExitPipTransition(flicker: FlickerTest) : PipTransition(flicker) {
+abstract class ClosePipTransition(flicker: FlickerTest) : PipTransition(flicker) {
     override val transition: FlickerBuilder.() -> Unit
         get() = buildTransition {
             setup { this.setRotation(flicker.scenario.startRotation) }
@@ -77,4 +79,20 @@
                 .isVisible(LAUNCHER)
         }
     }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
+         * and navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+            )
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
similarity index 77%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
index 8a1a31a..f27fa4a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
@@ -20,9 +20,7 @@
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -54,7 +52,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class ExitPipWithDismissButtonTest(flicker: FlickerTest) : ExitPipTransition(flicker) {
+open class ClosePipWithDismissButtonTest(flicker: FlickerTest) : ClosePipTransition(flicker) {
 
     override val transition: FlickerBuilder.() -> Unit
         get() = {
@@ -71,20 +69,4 @@
     fun focusChanges() {
         flicker.assertEventLog { this.focusChanges("PipMenuView", "NexusLauncherActivity") }
     }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
-         * and navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
-            )
-        }
-    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt
similarity index 93%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTestCfArm.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt
index a3f214c..fbada69 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt
@@ -28,8 +28,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class ExitPipWithDismissButtonTestCfArm(flicker: FlickerTest) :
-    ExitPipWithDismissButtonTest(flicker) {
+open class ClosePipWithDismissButtonTestCfArm(flicker: FlickerTest) :
+    ClosePipWithDismissButtonTest(flicker) {
     companion object {
         /**
          * Creates the test configurations.
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 7aa40e7..47537c6 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
@@ -52,7 +52,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class EnterPipOnUserLeaveHintTest(flicker: FlickerTest) : EnterPipTest(flicker) {
+open class EnterPipOnUserLeaveHintTest(flicker: FlickerTest) : EnterPipTransition(flicker) {
     /** Defines the transition used to run the test */
     override val transition: FlickerBuilder.() -> Unit
         get() = {
@@ -82,13 +82,33 @@
 
     @Presubmit
     @Test
-    override fun pipAppLayerAlwaysVisible() {
-        if (!flicker.scenario.isGesturalNavigation) super.pipAppLayerAlwaysVisible()
-        else {
-            // pip layer in gesture nav will disappear during transition
-            flicker.assertLayers {
-                this.isVisible(pipApp).then().isInvisible(pipApp).then().isVisible(pipApp)
-            }
+    override fun pipAppLayerOrOverlayAlwaysVisible() {
+        // pip layer in gesture nav will disappear during transition
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.pipAppLayerOrOverlayAlwaysVisible()
+    }
+
+    @Presubmit
+    @Test
+    fun pipAppWindowVisibleChanges() {
+        // pip layer in gesture nav will disappear during transition
+        Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
+        flicker.assertWm {
+            this.isAppWindowVisible(pipApp)
+                .then()
+                .isAppWindowInvisible(pipApp, isOptional = true)
+                .then()
+                .isAppWindowVisible(pipApp, isOptional = true)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun pipAppLayerVisibleChanges() {
+        Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
+        // pip layer in gesture nav will disappear during transition
+        flicker.assertLayers {
+            this.isVisible(pipApp).then().isInvisible(pipApp).then().isVisible(pipApp)
         }
     }
 
@@ -116,12 +136,19 @@
 
     @Presubmit
     @Test
-    override fun pipLayerRemainInsideVisibleBounds() {
-        if (!flicker.scenario.isGesturalNavigation) super.pipLayerRemainInsideVisibleBounds()
-        else {
-            // pip layer in gesture nav will disappear during transition
-            flicker.assertLayersStart { this.visibleRegion(pipApp).coversAtMost(displayBounds) }
-            flicker.assertLayersEnd { this.visibleRegion(pipApp).coversAtMost(displayBounds) }
-        }
+    override fun pipLayerOrOverlayRemainInsideVisibleBounds() {
+        // pip layer in gesture nav will disappear during transition
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.pipLayerOrOverlayRemainInsideVisibleBounds()
+    }
+
+    @Presubmit
+    @Test
+    fun pipLayerRemainInsideVisibleBounds() {
+        // pip layer in gesture nav will disappear during transition
+        Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
+        // pip layer in gesture nav will disappear during transition
+        flicker.assertLayersStart { this.visibleRegion(pipApp).coversAtMost(displayBounds) }
+        flicker.assertLayersEnd { this.visibleRegion(pipApp).coversAtMost(displayBounds) }
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTestCfArm.kt
deleted file mode 100644
index d2e8645..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTestCfArm.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.wm.shell.flicker.pip
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class EnterPipTestCfArm(flicker: FlickerTest) : EnterPipTest(flicker) {
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
-         * and navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
-            )
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
similarity index 96%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
index 02d50f4..db50489 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
@@ -17,6 +17,7 @@
 package com.android.wm.shell.flicker.pip
 
 import android.app.Activity
+import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import androidx.test.filters.RequiresDevice
@@ -29,7 +30,7 @@
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.testapp.ActivityOptions.Pip.ACTION_ENTER_PIP
 import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
 import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
@@ -66,7 +67,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class EnterPipToOtherOrientationTest(flicker: FlickerTest) : PipTransition(flicker) {
+open class EnterPipToOtherOrientation(flicker: FlickerTest) : PipTransition(flicker) {
     private val testApp = FixedOrientationAppHelper(instrumentation)
     private val startingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_90)
     private val endingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_0)
@@ -178,8 +179,7 @@
     fun pipAppLayerPlusLetterboxCoversFullScreenOnStartTablet() {
         Assume.assumeFalse(tapl.isTablet)
         flicker.assertLayersStart {
-            visibleRegion(pipApp.or(ComponentNameMatcher.LETTERBOX))
-                .coversExactly(startingBounds)
+            visibleRegion(pipApp.or(ComponentNameMatcher.LETTERBOX)).coversExactly(startingBounds)
         }
     }
 
@@ -197,7 +197,7 @@
     }
 
     /** {@inheritDoc} */
-    @Presubmit
+    @FlakyTest(bugId = 267424412)
     @Test
     override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
         super.visibleLayersShownMoreThanOneConsecutiveEntry()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt
similarity index 93%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTestCfArm.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt
index 39aab6e..ec5f13c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt
@@ -29,8 +29,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class EnterPipToOtherOrientationTestCfArm(flicker: FlickerTest) :
-    EnterPipToOtherOrientationTest(flicker) {
+open class EnterPipToOtherOrientationCfArm(flicker: FlickerTest) :
+    EnterPipToOtherOrientation(flicker) {
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
similarity index 69%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
index 5d7003f..3ef66d7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -17,51 +17,20 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
-import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
-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 by interacting with the app UI
- *
- * To run this test: `atest WMShellFlickerTests:EnterPipTest`
- *
- * Actions:
- * ```
- *     Launch an app in full screen
- *     Press an "enter pip" button to put [pipApp] in pip mode
- * ```
- * Notes:
- * ```
- *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
- *        are inherited from [PipTransition]
- *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
- *        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)
-open class EnterPipTest(flicker: FlickerTest) : PipTransition(flicker) {
-
+abstract class EnterPipTransition(flicker: FlickerTest) : PipTransition(flicker) {
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit
         get() = {
             setup { pipApp.launchViaIntent(wmHelper) }
             teardown { pipApp.exit(wmHelper) }
-            transitions { pipApp.clickEnterPipButton(wmHelper) }
         }
 
     /** Checks [pipApp] window remains visible throughout the animation */
@@ -74,8 +43,14 @@
     /** Checks [pipApp] layer remains visible throughout the animation */
     @Presubmit
     @Test
-    open fun pipAppLayerAlwaysVisible() {
-        flicker.assertLayers { this.isVisible(pipApp) }
+    open fun pipAppLayerOrOverlayAlwaysVisible() {
+        flicker.assertLayers {
+            this.isVisible(pipApp)
+                .then()
+                .isVisible(ComponentNameMatcher.PIP_CONTENT_OVERLAY)
+                .then()
+                .isVisible(pipApp)
+        }
     }
 
     /**
@@ -94,8 +69,10 @@
      */
     @Presubmit
     @Test
-    open fun pipLayerRemainInsideVisibleBounds() {
-        flicker.assertLayersVisibleRegion(pipApp) { coversAtMost(displayBounds) }
+    open fun pipLayerOrOverlayRemainInsideVisibleBounds() {
+        flicker.assertLayersVisibleRegion(pipApp.or(ComponentNameMatcher.PIP_CONTENT_OVERLAY)) {
+            coversAtMost(displayBounds)
+        }
     }
 
     /** Checks that the visible region of [pipApp] always reduces during the animation */
@@ -121,7 +98,7 @@
         }
     }
 
-    /** Checks [ComponentMatcher.LAUNCHER] layer remains visible throughout the animation */
+    /** Checks [ComponentNameMatcher.LAUNCHER] layer remains visible throughout the animation */
     @Presubmit
     @Test
     fun launcherLayerBecomesVisible() {
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
new file mode 100644
index 0000000..c3c705e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerBuilder
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test entering pip from an app by interacting with the app UI
+ *
+ * To run this test: `atest WMShellFlickerTests:EnterPipTest`
+ *
+ * Actions:
+ * ```
+ *     Launch an app in full screen
+ *     Press an "enter pip" button to put [pipApp] in pip mode
+ * ```
+ * Notes:
+ * ```
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited from [PipTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        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)
+open class EnterPipViaAppUiButtonTest(flicker: FlickerTest) : EnterPipTransition(flicker) {
+
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            super.transition(this)
+            transitions { pipApp.clickEnterPipButton(wmHelper) }
+        }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt
similarity index 94%
copy from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt
copy to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt
index 03dfa5b..b487ff4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt
@@ -28,7 +28,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitPipViaIntentTestCfArm(flicker: FlickerTest) : ExitPipViaIntentTest(flicker) {
+class EnterPipViaAppUiButtonTestCfArm(flicker: FlickerTest) : EnterPipViaAppUiButtonTest(flicker) {
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index 7466916..f88f8d6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -18,8 +18,12 @@
 
 import android.platform.test.annotations.Presubmit
 import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Test
+import org.junit.runners.Parameterized
 
 /** Base class for pip expand tests */
 abstract class ExitPipToAppTransition(flicker: FlickerTest) : PipTransition(flicker) {
@@ -32,7 +36,9 @@
     @Presubmit
     @Test
     open fun pipAppWindowRemainInsideVisibleBounds() {
-        flicker.assertWmVisibleRegion(pipApp) { coversAtMost(displayBounds) }
+        flicker.assertWmVisibleRegion(pipApp.or(ComponentNameMatcher.TRANSITION_SNAPSHOT)) {
+            coversAtMost(displayBounds)
+        }
     }
 
     /**
@@ -42,7 +48,9 @@
     @Presubmit
     @Test
     open fun pipAppLayerRemainInsideVisibleBounds() {
-        flicker.assertLayersVisibleRegion(pipApp) { coversAtMost(displayBounds) }
+        flicker.assertLayersVisibleRegion(pipApp.or(ComponentNameMatcher.TRANSITION_SNAPSHOT)) {
+            coversAtMost(displayBounds)
+        }
     }
 
     /**
@@ -72,7 +80,11 @@
     @Test
     open fun showBothAppLayersThenHidePip() {
         flicker.assertLayers {
-            isVisible(testApp).isVisible(pipApp).then().isInvisible(testApp).isVisible(pipApp)
+            isVisible(testApp)
+                .isVisible(pipApp.or(ComponentNameMatcher.TRANSITION_SNAPSHOT))
+                .then()
+                .isInvisible(testApp)
+                .isVisible(pipApp)
         }
     }
 
@@ -113,4 +125,20 @@
 
     /** {@inheritDoc} */
     @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+            )
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
similarity index 82%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
index 3bfcde3..d2fbb2a2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
@@ -21,10 +21,8 @@
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -58,7 +56,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class ExitPipViaExpandButtonClickTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
+open class ExitPipToAppViaExpandButtonTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
 
     /** Defines the transition used to run the test */
     override val transition: FlickerBuilder.() -> Unit
@@ -89,20 +87,4 @@
         Assume.assumeTrue(isShellTransitionsEnabled)
         super.pipLayerExpands()
     }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
-            )
-        }
-    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt
similarity index 93%
copy from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestCfArm.kt
copy to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt
index 5feb73e..8b3755e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt
@@ -28,7 +28,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExpandPipOnDoubleClickTestCfArm(flicker: FlickerTest) : ExpandPipOnDoubleClickTest(flicker) {
+class ExitPipToAppViaExpandButtonTestCfArm(flicker: FlickerTest) :
+    ExitPipToAppViaExpandButtonTest(flicker) {
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
similarity index 83%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
index 2c5455f..a9eb18d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
@@ -21,10 +21,8 @@
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -57,7 +55,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class ExitPipViaIntentTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
+open class ExitPipToAppViaIntentTest(flicker: FlickerTest) : ExitPipToAppTransition(flicker) {
 
     /** Defines the transition used to run the test */
     override val transition: FlickerBuilder.() -> Unit
@@ -106,20 +104,4 @@
         Assume.assumeTrue(isShellTransitionsEnabled)
         super.pipLayerExpands()
     }
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
-         * and navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
-            )
-        }
-    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt
similarity index 94%
copy from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt
copy to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt
index 03dfa5b..39b1c82 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt
@@ -28,7 +28,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitPipViaIntentTestCfArm(flicker: FlickerTest) : ExitPipViaIntentTest(flicker) {
+class ExitPipToAppViaIntentTestCfArm(flicker: FlickerTest) : ExitPipToAppViaIntentTest(flicker) {
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTestCfArm.kt
deleted file mode 100644
index f77e335..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTestCfArm.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.wm.shell.flicker.pip
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitPipViaExpandButtonClickTestCfArm(flicker: FlickerTest) :
-    ExitPipViaExpandButtonClickTest(flicker) {
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
-            )
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTestCfArm.kt
deleted file mode 100644
index 9f26018..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTestCfArm.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.wm.shell.flicker.pip
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitPipWithSwipeDownTestCfArm(flicker: FlickerTest) : ExitPipWithSwipeDownTest(flicker) {
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring repetitions, screen orientation
-         * and navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
-            )
-        }
-    }
-}
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 eff2df8..d577b4f 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
@@ -22,7 +22,7 @@
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -31,7 +31,7 @@
 import org.junit.runners.Parameterized
 
 /**
- * Test expanding a pip window by double clicking it
+ * Test expanding a pip window by double-clicking it
  *
  * To run this test: `atest WMShellFlickerTests:ExpandPipOnDoubleClickTest`
  *
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt
similarity index 93%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestCfArm.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt
index 5feb73e..08db8ae 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt
@@ -28,7 +28,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExpandPipOnDoubleClickTestCfArm(flicker: FlickerTest) : ExpandPipOnDoubleClickTest(flicker) {
+class ExpandPipOnDoubleClickTestTestCfArm(flicker: FlickerTest) :
+    ExpandPipOnDoubleClickTest(flicker) {
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
similarity index 78%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
index 16acc11..39ac49f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
@@ -20,9 +20,7 @@
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
 import com.android.wm.shell.flicker.Direction
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -56,8 +54,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class MovePipDownShelfHeightChangeTest(flicker: FlickerTest) :
-    MovePipShelfHeightTransition(flicker) {
+class MovePipDownOnShelfHeightChange(flicker: FlickerTest) : MovePipShelfHeightTransition(flicker) {
     /** Defines the transition used to run the test */
     override val transition: FlickerBuilder.() -> Unit
         get() = buildTransition {
@@ -73,20 +70,4 @@
 
     /** Checks that the visible region of [pipApp] layer always moves down during the animation. */
     @Presubmit @Test fun pipLayerMovesDown() = pipLayerMoves(Direction.DOWN)
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
-            )
-        }
-    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
similarity index 94%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
index 3939e7f..7db80a8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
@@ -26,7 +26,7 @@
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume.assumeFalse
 import org.junit.Before
@@ -41,7 +41,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class PipKeyboardTest(flicker: FlickerTest) : PipTransition(flicker) {
+open class MovePipOnImeVisibilityChangeTest(flicker: FlickerTest) : PipTransition(flicker) {
     private val imeApp = ImeAppHelper(instrumentation)
 
     @Before
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt
similarity index 92%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestCfArm.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt
index 9e2d27d..be3bd60 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt
@@ -28,7 +28,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipKeyboardTestCfArm(flicker: FlickerTest) : PipKeyboardTest(flicker) {
+class MovePipOnImeVisibilityChangeTestCfArm(flicker: FlickerTest) :
+    MovePipOnImeVisibilityChangeTest(flicker) {
     companion object {
         private const val TAG_IME_VISIBLE = "imeIsVisible"
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt
similarity index 92%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt
index 901814e..ef9920c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt
@@ -33,7 +33,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipKeyboardTestShellTransit(flicker: FlickerTest) : PipKeyboardTest(flicker) {
+class MovePipOnImeVisibilityChangeTestShellTransit(flicker: FlickerTest) :
+    MovePipOnImeVisibilityChangeTest(flicker) {
 
     @Before
     override fun before() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
index 35525cb..77a8c3c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
@@ -18,10 +18,13 @@
 
 import android.platform.test.annotations.Presubmit
 import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
 import com.android.server.wm.flicker.traces.region.RegionSubject
+import com.android.server.wm.traces.common.service.PlatformConsts
 import com.android.wm.shell.flicker.Direction
 import org.junit.Test
+import org.junit.runners.Parameterized
 
 /** Base class for pip tests with Launcher shelf height change */
 abstract class MovePipShelfHeightTransition(flicker: FlickerTest) : PipTransition(flicker) {
@@ -103,4 +106,20 @@
         regions.zipWithNext { previous, current -> current.isHigherOrEqual(previous.region) }
         regions.last().isHigher(regions.first())
     }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+            )
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
similarity index 80%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
index 3a12a34..511a651 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
@@ -20,9 +20,7 @@
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
 import com.android.wm.shell.flicker.Direction
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -56,7 +54,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class MovePipUpShelfHeightChangeTest(flicker: FlickerTest) :
+open class MovePipUpOnShelfHeightChangeTest(flicker: FlickerTest) :
     MovePipShelfHeightTransition(flicker) {
     /** Defines the transition used to run the test */
     override val transition: FlickerBuilder.() -> Unit
@@ -72,20 +70,4 @@
 
     /** Checks that the visible region of [pipApp] layer always moves up during the animation. */
     @Presubmit @Test fun pipLayerMovesUp() = pipLayerMoves(Direction.UP)
-
-    companion object {
-        /**
-         * Creates the test configurations.
-         *
-         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
-         * navigation modes.
-         */
-        @Parameterized.Parameters(name = "{0}")
-        @JvmStatic
-        fun getParams(): List<FlickerTest> {
-            return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
-            )
-        }
-    }
 }
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 415c270..166416a 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
@@ -26,7 +26,7 @@
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import com.android.wm.shell.flicker.BaseTest
 import com.google.common.truth.Truth
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
similarity index 96%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
index 871515b..3f5d067 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
@@ -46,7 +46,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class SetRequestedOrientationWhilePinnedTest(flicker: FlickerTest) : PipTransition(flicker) {
+open class SetRequestedOrientationWhilePinned(flicker: FlickerTest) : PipTransition(flicker) {
     private val startingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_0)
     private val endingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_90)
 
@@ -71,9 +71,7 @@
                     .withStatusBarVisible()
                     .waitForAndVerify()
             }
-            teardown {
-                pipApp.exit(wmHelper)
-            }
+            teardown { pipApp.exit(wmHelper) }
             transitions {
                 // Launch the activity back into fullscreen and ensure that it is now in landscape
                 pipApp.launchViaIntent(wmHelper)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
similarity index 98%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
index 4557a15..720fe72 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
@@ -57,7 +57,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class PipRotationTest(flicker: FlickerTest) : PipTransition(flicker) {
+open class ShowPipAndRotateDisplay(flicker: FlickerTest) : PipTransition(flicker) {
     private val testApp = SimpleAppHelper(instrumentation)
     private val screenBoundsStart = WindowUtils.getDisplayBounds(flicker.scenario.startRotation)
     private val screenBoundsEnd = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt
similarity index 94%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestCfArm.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt
index e72d604..daf3e1b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt
@@ -27,7 +27,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipRotationTestCfArm(flicker: FlickerTest) : PipRotationTest(flicker) {
+class ShowPipAndRotateDisplayCfArm(flicker: FlickerTest) : ShowPipAndRotateDisplay(flicker) {
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
index 70a1523..247403a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
@@ -24,8 +24,8 @@
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
-import com.android.server.wm.traces.common.EdgeExtensionComponentMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.EdgeExtensionComponentMatcher
 import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
 import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
@@ -116,7 +116,6 @@
     /** {@inheritDoc} */
     @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
 
-
     /** {@inheritDoc} */
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
index f3927d4..4f8cfca 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
@@ -34,9 +34,9 @@
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.helpers.StandardAppHelper
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
-import com.android.server.wm.traces.common.IComponentMatcher
-import com.android.server.wm.traces.common.IComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
+import com.android.server.wm.traces.common.component.matchers.IComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import com.android.wm.shell.flicker.LAUNCHER_UI_PACKAGE_NAME
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt
index c02e2d1..3bfbcd2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/storage/BubbleXmlHelperTest.kt
@@ -35,7 +35,7 @@
 
     private val user0Bubbles = listOf(
             BubbleEntity(0, "com.example.messenger", "shortcut-1", "0k1", 120, 0, null, 1,
-                    isClearable = true),
+                    isDismissable = true),
             BubbleEntity(10, "com.example.chat", "alice and bob", "0k2", 0, 16537428, "title", 2,
                     null),
             BubbleEntity(0, "com.example.messenger", "shortcut-2", "0k3", 120, 0, null,
@@ -44,7 +44,7 @@
 
     private val user1Bubbles = listOf(
             BubbleEntity(1, "com.example.messenger", "shortcut-1", "1k1", 120, 0, null, 3,
-                    isClearable = true),
+                    isDismissable = true),
             BubbleEntity(12, "com.example.chat", "alice and bob", "1k2", 0, 16537428, "title", 4,
                     null),
             BubbleEntity(1, "com.example.messenger", "shortcut-2", "1k3", 120, 0, null,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java
index ffb1a4d..01e2f98 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java
@@ -17,7 +17,7 @@
 package com.android.wm.shell.common;
 
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.Surface.ROTATION_0;
 import static android.view.WindowInsets.Type.ime;
 
@@ -138,15 +138,15 @@
     private InsetsSourceControl[] insetsSourceControl() {
         return new InsetsSourceControl[]{
                 new InsetsSourceControl(
-                        ITYPE_IME, ime(), mock(SurfaceControl.class), false, new Point(0, 0),
+                        ID_IME, ime(), mock(SurfaceControl.class), false, new Point(0, 0),
                         Insets.NONE)
         };
     }
 
     private InsetsState insetsStateWithIme(boolean visible) {
         InsetsState state = new InsetsState();
-        state.addSource(new InsetsSource(ITYPE_IME, ime()));
-        state.setSourceVisible(ITYPE_IME, visible);
+        state.addSource(new InsetsSource(ID_IME, ime()));
+        state.setSourceVisible(ID_IME, visible);
         return state;
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
index 3d8cd2e..ec264a6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
@@ -300,9 +300,9 @@
                 (MAX_ASPECT_RATIO + DEFAULT_ASPECT_RATIO) / 2
         };
         final Size[] minimalSizes = new Size[] {
-                new Size((int) (100 * aspectRatios[0]), 100),
-                new Size((int) (100 * aspectRatios[1]), 100),
-                new Size((int) (100 * aspectRatios[2]), 100)
+                new Size((int) (200 * aspectRatios[0]), 200),
+                new Size((int) (200 * aspectRatios[1]), 200),
+                new Size((int) (200 * aspectRatios[2]), 200)
         };
         for (int i = 0; i < aspectRatios.length; i++) {
             final float aspectRatio = aspectRatios[i];
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
index ede5bde..341a451 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
@@ -162,10 +162,10 @@
     @Test
     public void testSetOverrideMinSize_notChanged_callbackNotInvoked() {
         final Runnable callback = mock(Runnable.class);
-        mPipBoundsState.setOverrideMinSize(new Size(5, 5));
+        mPipBoundsState.setOverrideMinSize(new Size(100, 150));
         mPipBoundsState.setOnMinimalSizeChangeCallback(callback);
 
-        mPipBoundsState.setOverrideMinSize(new Size(5, 5));
+        mPipBoundsState.setOverrideMinSize(new Size(100, 150));
 
         verify(callback, never()).run();
     }
@@ -175,11 +175,11 @@
         mPipBoundsState.setOverrideMinSize(null);
         assertEquals(0, mPipBoundsState.getOverrideMinEdgeSize());
 
-        mPipBoundsState.setOverrideMinSize(new Size(5, 10));
-        assertEquals(5, mPipBoundsState.getOverrideMinEdgeSize());
+        mPipBoundsState.setOverrideMinSize(new Size(100, 110));
+        assertEquals(100, mPipBoundsState.getOverrideMinEdgeSize());
 
-        mPipBoundsState.setOverrideMinSize(new Size(15, 10));
-        assertEquals(10, mPipBoundsState.getOverrideMinEdgeSize());
+        mPipBoundsState.setOverrideMinSize(new Size(150, 200));
+        assertEquals(150, mPipBoundsState.getOverrideMinEdgeSize());
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index 82392ad9..b542fae 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -253,10 +253,10 @@
     }
 
     @Test
-    public void testGetRecentTasks_groupActiveFreeformTasks() {
+    public void testGetRecentTasks_hasActiveDesktopTasks_proto2Enabled_groupFreeformTasks() {
         StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
                 DesktopModeStatus.class).startMocking();
-        when(DesktopModeStatus.isActive(any())).thenReturn(true);
+        when(DesktopModeStatus.isProto2Enabled()).thenReturn(true);
 
         ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
         ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
@@ -293,6 +293,39 @@
     }
 
     @Test
+    public void testGetRecentTasks_hasActiveDesktopTasks_proto2Disabled_doNotGroupFreeformTasks() {
+        StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
+                DesktopModeStatus.class).startMocking();
+        when(DesktopModeStatus.isProto2Enabled()).thenReturn(false);
+
+        ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
+        ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
+        ActivityManager.RecentTaskInfo t3 = makeTaskInfo(3);
+        ActivityManager.RecentTaskInfo t4 = makeTaskInfo(4);
+        setRawList(t1, t2, t3, t4);
+
+        when(mDesktopModeTaskRepository.isActiveTask(1)).thenReturn(true);
+        when(mDesktopModeTaskRepository.isActiveTask(3)).thenReturn(true);
+
+        ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks(
+                MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0);
+
+        // Expect no grouping of tasks
+        assertEquals(4, recentTasks.size());
+        assertEquals(GroupedRecentTaskInfo.TYPE_SINGLE, recentTasks.get(0).getType());
+        assertEquals(GroupedRecentTaskInfo.TYPE_SINGLE, recentTasks.get(1).getType());
+        assertEquals(GroupedRecentTaskInfo.TYPE_SINGLE, recentTasks.get(2).getType());
+        assertEquals(GroupedRecentTaskInfo.TYPE_SINGLE, recentTasks.get(3).getType());
+
+        assertEquals(t1, recentTasks.get(0).getTaskInfo1());
+        assertEquals(t2, recentTasks.get(1).getTaskInfo1());
+        assertEquals(t3, recentTasks.get(2).getTaskInfo1());
+        assertEquals(t4, recentTasks.get(3).getTaskInfo1());
+
+        mockitoSession.finishMocking();
+    }
+
+    @Test
     public void testRemovedTaskRemovesSplit() {
         ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
         ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
index ea3af9d..d0e2601 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
@@ -27,8 +27,6 @@
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -201,7 +199,6 @@
         ActivityManager.RunningTaskInfo topRunningTask =
                 createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
         doReturn(topRunningTask).when(mRecentTasks).getTopRunningTask();
-        doReturn(true).when(mStageCoordinator).isValidToEnterSplitScreen(any());
 
         mSplitScreenController.startIntent(pendingIntent, null, SPLIT_POSITION_TOP_OR_LEFT, null);
 
@@ -222,7 +219,6 @@
         ActivityManager.RunningTaskInfo topRunningTask =
                 createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
         doReturn(topRunningTask).when(mRecentTasks).getTopRunningTask();
-        doReturn(true).when(mStageCoordinator).isValidToEnterSplitScreen(any());
         // Put the same component into a task in the background
         ActivityManager.RecentTaskInfo sameTaskInfo = new ActivityManager.RecentTaskInfo();
         doReturn(sameTaskInfo).when(mRecentTasks).findTaskInBackground(any());
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index dd6c2bc..9e3f115 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -511,6 +511,7 @@
         "canvas/CanvasOpBuffer.cpp",
         "canvas/CanvasOpRasterizer.cpp",
         "effects/StretchEffect.cpp",
+        "effects/GainmapRenderer.cpp",
         "pipeline/skia/HolePunch.cpp",
         "pipeline/skia/SkiaDisplayList.cpp",
         "pipeline/skia/SkiaRecordingCanvas.cpp",
@@ -553,6 +554,7 @@
         "RootRenderNode.cpp",
         "SkiaCanvas.cpp",
         "SkiaInterpolator.cpp",
+        "Tonemapper.cpp",
         "VectorDrawable.cpp",
     ],
 
@@ -611,7 +613,6 @@
                 "ProfileData.cpp",
                 "ProfileDataContainer.cpp",
                 "Readback.cpp",
-                "Tonemapper.cpp",
                 "TreeInfo.cpp",
                 "WebViewFunctorManager.cpp",
                 "protos/graphicsstats.proto",
diff --git a/libs/hwui/CanvasTransform.h b/libs/hwui/CanvasTransform.h
index c46a2d3..291f4cf 100644
--- a/libs/hwui/CanvasTransform.h
+++ b/libs/hwui/CanvasTransform.h
@@ -45,4 +45,4 @@
 SkColor transformColor(ColorTransform transform, SkColor color);
 SkColor transformColorInverse(ColorTransform transform, SkColor color);
 
-}  // namespace android::uirenderer;
\ No newline at end of file
+}  // namespace android::uirenderer
diff --git a/libs/hwui/ColorMode.h b/libs/hwui/ColorMode.h
index 3df5c3c..959cf74 100644
--- a/libs/hwui/ColorMode.h
+++ b/libs/hwui/ColorMode.h
@@ -25,9 +25,10 @@
     // WideColorGamut selects the most optimal colorspace & format for the device's display
     // Most commonly DisplayP3 + RGBA_8888 currently.
     WideColorGamut = 1,
-    // HDR Rec2020 + F16
+    // Extended range Display P3
     Hdr = 2,
-    // HDR Rec2020 + 1010102
+    // Extended range Display P3 10-bit
+    // for test purposes only, not shippable due to insuffient alpha
     Hdr10 = 3,
     // Alpha 8
     A8 = 4,
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 3f7c4f0..659aec0 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -19,9 +19,9 @@
 #include <GrRecordingContext.h>
 #include <SkMesh.h>
 #include <hwui/Paint.h>
+#include <log/log.h>
 
 #include <experimental/type_traits>
-#include <log/log.h>
 #include <utility>
 
 #include "SkAndroidFrameworkUtils.h"
@@ -43,8 +43,10 @@
 #include "SkRegion.h"
 #include "SkTextBlob.h"
 #include "SkVertices.h"
+#include "Tonemapper.h"
 #include "VectorDrawable.h"
-#include "include/gpu/GpuTypes.h" // from Skia
+#include "effects/GainmapRenderer.h"
+#include "include/gpu/GpuTypes.h"  // from Skia
 #include "include/gpu/GrDirectContext.h"
 #include "pipeline/skia/AnimatedDrawables.h"
 #include "pipeline/skia/FunctorDrawable.h"
@@ -331,9 +333,15 @@
 
 struct DrawImage final : Op {
     static const auto kType = Type::DrawImage;
-    DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y,
-              const SkSamplingOptions& sampling, const SkPaint* paint, BitmapPalette palette)
-            : image(std::move(image)), x(x), y(y), sampling(sampling), palette(palette) {
+    DrawImage(DrawImagePayload&& payload, SkScalar x, SkScalar y, const SkSamplingOptions& sampling,
+              const SkPaint* paint)
+            : image(std::move(payload.image))
+            , x(x)
+            , y(y)
+            , sampling(sampling)
+            , palette(payload.palette)
+            , gainmap(std::move(payload.gainmapImage))
+            , gainmapInfo(payload.gainmapInfo) {
         if (paint) {
             this->paint = *paint;
         }
@@ -343,17 +351,34 @@
     SkSamplingOptions sampling;
     SkPaint paint;
     BitmapPalette palette;
+    sk_sp<const SkImage> gainmap;
+    SkGainmapInfo gainmapInfo;
+
     void draw(SkCanvas* c, const SkMatrix&) const {
-        c->drawImage(image.get(), x, y, sampling, &paint);
+        if (gainmap) {
+            SkRect src = SkRect::MakeWH(image->width(), image->height());
+            SkRect dst = SkRect::MakeXYWH(x, y, src.width(), src.height());
+            DrawGainmapBitmap(c, image, src, dst, sampling, &paint,
+                              SkCanvas::kFast_SrcRectConstraint, gainmap, gainmapInfo);
+        } else {
+            SkPaint newPaint = paint;
+            tonemapPaint(image->imageInfo(), c->imageInfo(), -1, newPaint);
+            c->drawImage(image.get(), x, y, sampling, &newPaint);
+        }
     }
 };
 struct DrawImageRect final : Op {
     static const auto kType = Type::DrawImageRect;
-    DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst,
+    DrawImageRect(DrawImagePayload&& payload, const SkRect* src, const SkRect& dst,
                   const SkSamplingOptions& sampling, const SkPaint* paint,
-                  SkCanvas::SrcRectConstraint constraint, BitmapPalette palette)
-            : image(std::move(image)), dst(dst), sampling(sampling), constraint(constraint)
-            , palette(palette) {
+                  SkCanvas::SrcRectConstraint constraint)
+            : image(std::move(payload.image))
+            , dst(dst)
+            , sampling(sampling)
+            , constraint(constraint)
+            , palette(payload.palette)
+            , gainmap(std::move(payload.gainmapImage))
+            , gainmapInfo(payload.gainmapInfo) {
         this->src = src ? *src : SkRect::MakeIWH(this->image->width(), this->image->height());
         if (paint) {
             this->paint = *paint;
@@ -365,23 +390,32 @@
     SkPaint paint;
     SkCanvas::SrcRectConstraint constraint;
     BitmapPalette palette;
+    sk_sp<const SkImage> gainmap;
+    SkGainmapInfo gainmapInfo;
+
     void draw(SkCanvas* c, const SkMatrix&) const {
-        c->drawImageRect(image.get(), src, dst, sampling, &paint, constraint);
+        if (gainmap) {
+            DrawGainmapBitmap(c, image, src, dst, sampling, &paint, constraint, gainmap,
+                              gainmapInfo);
+        } else {
+            SkPaint newPaint = paint;
+            tonemapPaint(image->imageInfo(), c->imageInfo(), -1, newPaint);
+            c->drawImageRect(image.get(), src, dst, sampling, &newPaint, constraint);
+        }
     }
 };
 struct DrawImageLattice final : Op {
     static const auto kType = Type::DrawImageLattice;
-    DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, int fs, const SkIRect& src,
-                     const SkRect& dst, SkFilterMode filter, const SkPaint* paint,
-                     BitmapPalette palette)
-            : image(std::move(image))
+    DrawImageLattice(DrawImagePayload&& payload, int xs, int ys, int fs, const SkIRect& src,
+                     const SkRect& dst, SkFilterMode filter, const SkPaint* paint)
+            : image(std::move(payload.image))
             , xs(xs)
             , ys(ys)
             , fs(fs)
             , src(src)
             , dst(dst)
             , filter(filter)
-            , palette(palette) {
+            , palette(payload.palette) {
         if (paint) {
             this->paint = *paint;
         }
@@ -394,13 +428,17 @@
     SkPaint paint;
     BitmapPalette palette;
     void draw(SkCanvas* c, const SkMatrix&) const {
+        // TODO: Support drawing a gainmap 9-patch?
+
         auto xdivs = pod<int>(this, 0), ydivs = pod<int>(this, xs * sizeof(int));
         auto colors = (0 == fs) ? nullptr : pod<SkColor>(this, (xs + ys) * sizeof(int));
         auto flags =
                 (0 == fs) ? nullptr : pod<SkCanvas::Lattice::RectType>(
                                               this, (xs + ys) * sizeof(int) + fs * sizeof(SkColor));
-        c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys, &src, colors}, dst,
-                            filter, &paint);
+        SkPaint newPaint = paint;
+        tonemapPaint(image->imageInfo(), c->imageInfo(), -1, newPaint);
+        c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys, &src, colors}, dst, filter,
+                            &newPaint);
     }
 };
 
@@ -774,27 +812,25 @@
                                   const SkPaint* paint) {
     this->push<DrawPicture>(0, picture, matrix, paint);
 }
-void DisplayListData::drawImage(sk_sp<const SkImage> image, SkScalar x, SkScalar y,
-                                const SkSamplingOptions& sampling, const SkPaint* paint,
-                                BitmapPalette palette) {
-    this->push<DrawImage>(0, std::move(image), x, y, sampling, paint, palette);
+void DisplayListData::drawImage(DrawImagePayload&& payload, SkScalar x, SkScalar y,
+                                const SkSamplingOptions& sampling, const SkPaint* paint) {
+    this->push<DrawImage>(0, std::move(payload), x, y, sampling, paint);
 }
-void DisplayListData::drawImageRect(sk_sp<const SkImage> image, const SkRect* src,
+void DisplayListData::drawImageRect(DrawImagePayload&& payload, const SkRect* src,
                                     const SkRect& dst, const SkSamplingOptions& sampling,
-                                    const SkPaint* paint, SkCanvas::SrcRectConstraint constraint,
-                                    BitmapPalette palette) {
-    this->push<DrawImageRect>(0, std::move(image), src, dst, sampling, paint, constraint, palette);
+                                    const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
+    this->push<DrawImageRect>(0, std::move(payload), src, dst, sampling, paint, constraint);
 }
-void DisplayListData::drawImageLattice(sk_sp<const SkImage> image, const SkCanvas::Lattice& lattice,
-                                       const SkRect& dst, SkFilterMode filter, const SkPaint* paint,
-                                       BitmapPalette palette) {
+void DisplayListData::drawImageLattice(DrawImagePayload&& payload, const SkCanvas::Lattice& lattice,
+                                       const SkRect& dst, SkFilterMode filter,
+                                       const SkPaint* paint) {
     int xs = lattice.fXCount, ys = lattice.fYCount;
     int fs = lattice.fRectTypes ? (xs + 1) * (ys + 1) : 0;
     size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::RectType) +
                    fs * sizeof(SkColor);
     LOG_FATAL_IF(!lattice.fBounds);
-    void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds,
-                                             dst, filter, paint, palette);
+    void* pod = this->push<DrawImageLattice>(bytes, std::move(payload), xs, ys, fs,
+                                             *lattice.fBounds, dst, filter, paint);
     copy_v(pod, lattice.fXDivs, xs, lattice.fYDivs, ys, lattice.fColors, fs, lattice.fRectTypes,
            fs);
 }
@@ -1101,57 +1137,55 @@
     fDL->drawRippleDrawable(params);
 }
 
-void RecordingCanvas::drawImage(const sk_sp<SkImage>& image, SkScalar x, SkScalar y,
-                                const SkSamplingOptions& sampling, const SkPaint* paint,
-                                BitmapPalette palette) {
-    fDL->drawImage(image, x, y, sampling, paint, palette);
+void RecordingCanvas::drawImage(DrawImagePayload&& payload, SkScalar x, SkScalar y,
+                                const SkSamplingOptions& sampling, const SkPaint* paint) {
+    fDL->drawImage(std::move(payload), x, y, sampling, paint);
 }
 
-void RecordingCanvas::drawImageRect(const sk_sp<SkImage>& image, const SkRect& src,
+void RecordingCanvas::drawImageRect(DrawImagePayload&& payload, const SkRect& src,
                                     const SkRect& dst, const SkSamplingOptions& sampling,
-                                    const SkPaint* paint, SrcRectConstraint constraint,
-                                    BitmapPalette palette) {
-    fDL->drawImageRect(image, &src, dst, sampling, paint, constraint, palette);
+                                    const SkPaint* paint, SrcRectConstraint constraint) {
+    fDL->drawImageRect(std::move(payload), &src, dst, sampling, paint, constraint);
 }
 
-void RecordingCanvas::drawImageLattice(const sk_sp<SkImage>& image, const Lattice& lattice,
-                                       const SkRect& dst, SkFilterMode filter, const SkPaint* paint,
-                                       BitmapPalette palette) {
-    if (!image || dst.isEmpty()) {
+void RecordingCanvas::drawImageLattice(DrawImagePayload&& payload, const Lattice& lattice,
+                                       const SkRect& dst, SkFilterMode filter,
+                                       const SkPaint* paint) {
+    if (!payload.image || dst.isEmpty()) {
         return;
     }
 
     SkIRect bounds;
     Lattice latticePlusBounds = lattice;
     if (!latticePlusBounds.fBounds) {
-        bounds = SkIRect::MakeWH(image->width(), image->height());
+        bounds = SkIRect::MakeWH(payload.image->width(), payload.image->height());
         latticePlusBounds.fBounds = &bounds;
     }
 
-    if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
-        fDL->drawImageLattice(image, latticePlusBounds, dst, filter, paint, palette);
+    if (SkLatticeIter::Valid(payload.image->width(), payload.image->height(), latticePlusBounds)) {
+        fDL->drawImageLattice(std::move(payload), latticePlusBounds, dst, filter, paint);
     } else {
         SkSamplingOptions sampling(filter, SkMipmapMode::kNone);
-        fDL->drawImageRect(image, nullptr, dst, sampling, paint, kFast_SrcRectConstraint, palette);
+        fDL->drawImageRect(std::move(payload), nullptr, dst, sampling, paint,
+                           kFast_SrcRectConstraint);
     }
 }
 
 void RecordingCanvas::onDrawImage2(const SkImage* img, SkScalar x, SkScalar y,
                                    const SkSamplingOptions& sampling, const SkPaint* paint) {
-    fDL->drawImage(sk_ref_sp(img), x, y, sampling, paint, BitmapPalette::Unknown);
+    fDL->drawImage(DrawImagePayload(img), x, y, sampling, paint);
 }
 
 void RecordingCanvas::onDrawImageRect2(const SkImage* img, const SkRect& src, const SkRect& dst,
                                        const SkSamplingOptions& sampling, const SkPaint* paint,
                                        SrcRectConstraint constraint) {
-    fDL->drawImageRect(sk_ref_sp(img), &src, dst, sampling, paint, constraint,
-                       BitmapPalette::Unknown);
+    fDL->drawImageRect(DrawImagePayload(img), &src, dst, sampling, paint, constraint);
 }
 
 void RecordingCanvas::onDrawImageLattice2(const SkImage* img, const SkCanvas::Lattice& lattice,
                                           const SkRect& dst, SkFilterMode filter,
                                           const SkPaint* paint) {
-    fDL->drawImageLattice(sk_ref_sp(img), lattice, dst, filter, paint, BitmapPalette::Unknown);
+    fDL->drawImageLattice(DrawImagePayload(img), lattice, dst, filter, paint);
 }
 
 void RecordingCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index b7d4dc9..8409e13 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -16,6 +16,14 @@
 
 #pragma once
 
+#include <SkCanvas.h>
+#include <SkCanvasVirtualEnforcer.h>
+#include <SkDrawable.h>
+#include <SkGainmapInfo.h>
+#include <SkNoDrawCanvas.h>
+#include <SkPaint.h>
+#include <SkPath.h>
+#include <SkRect.h>
 #include <SkRuntimeEffect.h>
 #include <log/log.h>
 
@@ -23,13 +31,7 @@
 #include <vector>
 
 #include "CanvasTransform.h"
-#include "SkCanvas.h"
-#include "SkCanvasVirtualEnforcer.h"
-#include "SkDrawable.h"
-#include "SkNoDrawCanvas.h"
-#include "SkPaint.h"
-#include "SkPath.h"
-#include "SkRect.h"
+#include "Gainmap.h"
 #include "hwui/Bitmap.h"
 #include "pipeline/skia/AnimatedDrawables.h"
 #include "utils/AutoMalloc.h"
@@ -64,6 +66,32 @@
 
 static_assert(sizeof(DisplayListOp) == 4);
 
+struct DrawImagePayload {
+    explicit DrawImagePayload(Bitmap& bitmap)
+            : image(bitmap.makeImage()), palette(bitmap.palette()) {
+        if (bitmap.hasGainmap()) {
+            auto gainmap = bitmap.gainmap();
+            gainmapInfo = gainmap->info;
+            gainmapImage = gainmap->bitmap->makeImage();
+        }
+    }
+
+    explicit DrawImagePayload(const SkImage* image)
+            : image(sk_ref_sp(image)), palette(BitmapPalette::Unknown) {}
+
+    DrawImagePayload(const DrawImagePayload&) = default;
+    DrawImagePayload(DrawImagePayload&&) = default;
+    DrawImagePayload& operator=(const DrawImagePayload&) = default;
+    DrawImagePayload& operator=(DrawImagePayload&&) = default;
+    ~DrawImagePayload() = default;
+
+    sk_sp<SkImage> image;
+    BitmapPalette palette;
+
+    sk_sp<SkImage> gainmapImage;
+    SkGainmapInfo gainmapInfo;
+};
+
 class RecordingCanvas;
 
 class DisplayListData final {
@@ -122,13 +150,12 @@
 
     void drawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&);
 
-    void drawImage(sk_sp<const SkImage>, SkScalar, SkScalar, const SkSamplingOptions&,
-                   const SkPaint*, BitmapPalette palette);
-    void drawImageNine(sk_sp<const SkImage>, const SkIRect&, const SkRect&, const SkPaint*);
-    void drawImageRect(sk_sp<const SkImage>, const SkRect*, const SkRect&, const SkSamplingOptions&,
-                       const SkPaint*, SkCanvas::SrcRectConstraint, BitmapPalette palette);
-    void drawImageLattice(sk_sp<const SkImage>, const SkCanvas::Lattice&, const SkRect&,
-                          SkFilterMode, const SkPaint*, BitmapPalette);
+    void drawImage(DrawImagePayload&&, SkScalar, SkScalar, const SkSamplingOptions&,
+                   const SkPaint*);
+    void drawImageRect(DrawImagePayload&&, const SkRect*, const SkRect&, const SkSamplingOptions&,
+                       const SkPaint*, SkCanvas::SrcRectConstraint);
+    void drawImageLattice(DrawImagePayload&&, const SkCanvas::Lattice&, const SkRect&, SkFilterMode,
+                          const SkPaint*);
 
     void drawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode,
                    const SkPaint&);
@@ -195,14 +222,14 @@
 
     void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override;
 
-    void drawImage(const sk_sp<SkImage>&, SkScalar left, SkScalar top, const SkSamplingOptions&,
-                   const SkPaint* paint, BitmapPalette pallete);
     void drawRippleDrawable(const skiapipeline::RippleDrawableParams& params);
 
-    void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
-                       const SkSamplingOptions&, const SkPaint*, SrcRectConstraint, BitmapPalette);
-    void drawImageLattice(const sk_sp<SkImage>& image, const Lattice& lattice, const SkRect& dst,
-                          SkFilterMode, const SkPaint* paint, BitmapPalette palette);
+    void drawImage(DrawImagePayload&&, SkScalar, SkScalar, const SkSamplingOptions&,
+                   const SkPaint*);
+    void drawImageRect(DrawImagePayload&&, const SkRect&, const SkRect&, const SkSamplingOptions&,
+                       const SkPaint*, SrcRectConstraint);
+    void drawImageLattice(DrawImagePayload&&, const Lattice& lattice, const SkRect&, SkFilterMode,
+                          const SkPaint*);
 
     void onDrawImage2(const SkImage*, SkScalar, SkScalar, const SkSamplingOptions&,
                       const SkPaint*) override;
diff --git a/libs/hwui/Tonemapper.cpp b/libs/hwui/Tonemapper.cpp
index a7e76b6..0d39f0e 100644
--- a/libs/hwui/Tonemapper.cpp
+++ b/libs/hwui/Tonemapper.cpp
@@ -18,7 +18,10 @@
 
 #include <SkRuntimeEffect.h>
 #include <log/log.h>
+// libshaders only exists on Android devices
+#ifdef __ANDROID__
 #include <shaders/shaders.h>
+#endif
 
 #include "utils/Color.h"
 
@@ -26,6 +29,8 @@
 
 namespace {
 
+// custom tonemapping only exists on Android devices
+#ifdef __ANDROID__
 class ColorFilterRuntimeEffectBuilder : public SkRuntimeEffectBuilder {
 public:
     explicit ColorFilterRuntimeEffectBuilder(sk_sp<SkRuntimeEffect> effect)
@@ -59,20 +64,21 @@
     return effectBuilder.makeColorFilter();
 }
 
-static bool extractTransfer(ui::Dataspace dataspace) {
-    return dataspace & HAL_DATASPACE_TRANSFER_MASK;
+static ui::Dataspace extractTransfer(ui::Dataspace dataspace) {
+    return static_cast<ui::Dataspace>(dataspace & HAL_DATASPACE_TRANSFER_MASK);
 }
 
 static bool isHdrDataspace(ui::Dataspace dataspace) {
     const auto transfer = extractTransfer(dataspace);
 
-    return transfer == HAL_DATASPACE_TRANSFER_ST2084 || transfer == HAL_DATASPACE_TRANSFER_HLG;
+    return transfer == ui::Dataspace::TRANSFER_ST2084 || transfer == ui::Dataspace::TRANSFER_HLG;
 }
 
 static ui::Dataspace getDataspace(const SkImageInfo& image) {
     return static_cast<ui::Dataspace>(
             ColorSpaceToADataSpace(image.colorSpace(), image.colorType()));
 }
+#endif
 
 }  // namespace
 
@@ -80,6 +86,8 @@
 // shader and tag it on the supplied paint.
 void tonemapPaint(const SkImageInfo& source, const SkImageInfo& destination, float maxLuminanceNits,
                   SkPaint& paint) {
+// custom tonemapping only exists on Android devices
+#ifdef __ANDROID__
     const auto sourceDataspace = getDataspace(source);
     const auto destinationDataspace = getDataspace(destination);
 
@@ -102,6 +110,9 @@
             paint.setColorFilter(colorFilter);
         }
     }
+#else
+    return;
+#endif
 }
 
 }  // namespace android::uirenderer
diff --git a/libs/hwui/effects/GainmapRenderer.cpp b/libs/hwui/effects/GainmapRenderer.cpp
new file mode 100644
index 0000000..a544ae8
--- /dev/null
+++ b/libs/hwui/effects/GainmapRenderer.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GainmapRenderer.h"
+
+#include <SkGainmapShader.h>
+
+#include "Gainmap.h"
+#include "Rect.h"
+#include "utils/Trace.h"
+
+#ifdef __ANDROID__
+#include "renderthread/CanvasContext.h"
+#endif
+
+namespace android::uirenderer {
+
+using namespace renderthread;
+
+void DrawGainmapBitmap(SkCanvas* c, const sk_sp<const SkImage>& image, const SkRect& src,
+                       const SkRect& dst, const SkSamplingOptions& sampling, const SkPaint* paint,
+                       SkCanvas::SrcRectConstraint constraint,
+                       const sk_sp<const SkImage>& gainmapImage, const SkGainmapInfo& gainmapInfo) {
+    ATRACE_CALL();
+#ifdef __ANDROID__
+    CanvasContext* context = CanvasContext::getActiveContext();
+    float targetSdrHdrRatio = context ? context->targetSdrHdrRatio() : 1.f;
+    if (targetSdrHdrRatio > 1.f && gainmapImage) {
+        SkPaint gainmapPaint = *paint;
+        float sX = gainmapImage->width() / (float)image->width();
+        float sY = gainmapImage->height() / (float)image->height();
+        SkRect gainmapSrc = src;
+        // TODO: Tweak rounding?
+        gainmapSrc.fLeft *= sX;
+        gainmapSrc.fRight *= sX;
+        gainmapSrc.fTop *= sY;
+        gainmapSrc.fBottom *= sY;
+        // TODO: Temporary workaround for SkGainmapShader::Make not having a const variant
+        sk_sp<SkImage> mutImage = sk_ref_sp(const_cast<SkImage*>(image.get()));
+        sk_sp<SkImage> mutGainmap = sk_ref_sp(const_cast<SkImage*>(gainmapImage.get()));
+        auto shader = SkGainmapShader::Make(mutImage, src, sampling, mutGainmap, gainmapSrc,
+                                            sampling, gainmapInfo, dst, targetSdrHdrRatio,
+                                            c->imageInfo().refColorSpace());
+        gainmapPaint.setShader(shader);
+        c->drawRect(dst, gainmapPaint);
+    } else
+#endif
+        c->drawImageRect(image.get(), src, dst, sampling, paint, constraint);
+}
+
+}  // namespace android::uirenderer
\ No newline at end of file
diff --git a/libs/hwui/effects/GainmapRenderer.h b/libs/hwui/effects/GainmapRenderer.h
new file mode 100644
index 0000000..7c56d94
--- /dev/null
+++ b/libs/hwui/effects/GainmapRenderer.h
@@ -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.
+ */
+
+#pragma once
+
+#include <SkCanvas.h>
+#include <SkGainmapInfo.h>
+#include <SkImage.h>
+#include <SkPaint.h>
+
+#include "hwui/Bitmap.h"
+
+namespace android::uirenderer {
+
+void DrawGainmapBitmap(SkCanvas* c, const sk_sp<const SkImage>& image, const SkRect& src,
+                       const SkRect& dst, const SkSamplingOptions& sampling, const SkPaint* paint,
+                       SkCanvas::SrcRectConstraint constraint,
+                       const sk_sp<const SkImage>& gainmapImage, const SkGainmapInfo& gainmapInfo);
+
+}  // namespace android::uirenderer
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 0a755f0..cbebae9 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -41,6 +41,7 @@
 #include <SkHighContrastFilter.h>
 #include <SkImageEncoder.h>
 #include <SkImagePriv.h>
+#include <SkJpegGainmapEncoder.h>
 #include <SkPixmap.h>
 #include <SkRect.h>
 #include <SkStream.h>
@@ -458,6 +459,16 @@
 }
 
 bool Bitmap::compress(JavaCompressFormat format, int32_t quality, SkWStream* stream) {
+#ifdef __ANDROID__  // TODO: This isn't built for host for some reason?
+    if (hasGainmap() && format == JavaCompressFormat::Jpeg) {
+        SkBitmap baseBitmap = getSkBitmap();
+        SkBitmap gainmapBitmap = gainmap()->bitmap->getSkBitmap();
+        SkJpegEncoder::Options options{.fQuality = quality};
+        return SkJpegGainmapEncoder::EncodeJpegR(stream, baseBitmap.pixmap(), options,
+                                                 gainmapBitmap.pixmap(), options, gainmap()->info);
+    }
+#endif
+
     SkBitmap skbitmap;
     getSkBitmap(&skbitmap);
     return compress(skbitmap, format, quality, stream);
diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp
index b1abe85..6d7c727 100644
--- a/libs/hwui/hwui/ImageDecoder.cpp
+++ b/libs/hwui/hwui/ImageDecoder.cpp
@@ -504,6 +504,8 @@
     ImageDecoder decoder{std::move(gainmapCodec)};
     // Gainmap inherits the origin of the containing image
     decoder.mOverrideOrigin.emplace(getOrigin());
+    // Update mDecodeSize / mTargetSize for the overridden origin
+    decoder.setTargetSize(decoder.width(), decoder.height());
 
     const bool isScaled = width() != mTargetSize.width() || height() != mTargetSize.height();
 
diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp
index 0d5995a..571ab83 100644
--- a/libs/hwui/jni/BitmapFactory.cpp
+++ b/libs/hwui/jni/BitmapFactory.cpp
@@ -2,6 +2,20 @@
 #define LOG_TAG "BitmapFactory"
 
 #include "BitmapFactory.h"
+
+#include <Gainmap.h>
+#include <HardwareBitmapUploader.h>
+#include <androidfw/Asset.h>
+#include <androidfw/ResourceTypes.h>
+#include <cutils/compiler.h>
+#include <fcntl.h>
+#include <nativehelper/JNIPlatformHelp.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include <memory>
+
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "FrontBufferedStream.h"
 #include "GraphicsJNI.h"
@@ -13,6 +27,7 @@
 #include "SkCanvas.h"
 #include "SkColorSpace.h"
 #include "SkEncodedImageFormat.h"
+#include "SkGainmapInfo.h"
 #include "SkImageInfo.h"
 #include "SkPaint.h"
 #include "SkPixelRef.h"
@@ -24,17 +39,6 @@
 #include "SkString.h"
 #include "Utils.h"
 
-#include <HardwareBitmapUploader.h>
-#include <nativehelper/JNIPlatformHelp.h>
-#include <androidfw/Asset.h>
-#include <androidfw/ResourceTypes.h>
-#include <cutils/compiler.h>
-#include <fcntl.h>
-#include <memory>
-#include <stdio.h>
-#include <stdint.h>
-#include <sys/stat.h>
-
 jfieldID gOptions_justBoundsFieldID;
 jfieldID gOptions_sampleSizeFieldID;
 jfieldID gOptions_configFieldID;
@@ -182,6 +186,115 @@
            needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
 }
 
+static bool decodeGainmap(std::unique_ptr<SkStream> gainmapStream, const SkGainmapInfo& gainmapInfo,
+                          sp<uirenderer::Gainmap>* outGainmap, const int sampleSize, float scale) {
+    std::unique_ptr<SkAndroidCodec> codec;
+    codec = SkAndroidCodec::MakeFromStream(std::move(gainmapStream), nullptr);
+    if (!codec) {
+        ALOGE("Can not create a codec for Gainmap.");
+        return false;
+    }
+    SkColorType decodeColorType = codec->computeOutputColorType(kN32_SkColorType);
+    sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace(decodeColorType, nullptr);
+
+    SkISize size = codec->getSampledDimensions(sampleSize);
+
+    int scaledWidth = size.width();
+    int scaledHeight = size.height();
+    bool willScale = false;
+
+    // Apply a fine scaling step if necessary.
+    if (needsFineScale(codec->getInfo().dimensions(), size, sampleSize) || scale != 1.0f) {
+        willScale = true;
+        // The operation below may loose precision (integer division), but it is put this way to
+        // mimic main image scale calculation
+        scaledWidth = static_cast<int>((codec->getInfo().width() / sampleSize) * scale + 0.5f);
+        scaledHeight = static_cast<int>((codec->getInfo().height() / sampleSize) * scale + 0.5f);
+    }
+
+    SkAlphaType alphaType = codec->computeOutputAlphaType(false);
+
+    const SkImageInfo decodeInfo = SkImageInfo::Make(size.width(), size.height(), decodeColorType,
+                                                     alphaType, decodeColorSpace);
+
+    const SkImageInfo& bitmapInfo = decodeInfo;
+    SkBitmap decodeBitmap;
+    sk_sp<Bitmap> nativeBitmap = nullptr;
+
+    if (!decodeBitmap.setInfo(bitmapInfo)) {
+        ALOGE("Failed to setInfo.");
+        return false;
+    }
+
+    if (willScale) {
+        if (!decodeBitmap.tryAllocPixels(nullptr)) {
+            ALOGE("OOM allocating gainmap pixels.");
+            return false;
+        }
+    } else {
+        nativeBitmap = android::Bitmap::allocateHeapBitmap(&decodeBitmap);
+        if (!nativeBitmap) {
+            ALOGE("OOM allocating gainmap pixels.");
+            return false;
+        }
+    }
+
+    // Use SkAndroidCodec to perform the decode.
+    SkAndroidCodec::AndroidOptions codecOptions;
+    codecOptions.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
+    codecOptions.fSampleSize = sampleSize;
+    SkCodec::Result result = codec->getAndroidPixels(decodeInfo, decodeBitmap.getPixels(),
+                                                     decodeBitmap.rowBytes(), &codecOptions);
+    switch (result) {
+        case SkCodec::kSuccess:
+        case SkCodec::kIncompleteInput:
+            break;
+        default:
+            ALOGE("Error decoding gainmap.");
+            return false;
+    }
+
+    if (willScale) {
+        SkBitmap gainmapBitmap;
+        const float scaleX = scaledWidth / float(decodeBitmap.width());
+        const float scaleY = scaledHeight / float(decodeBitmap.height());
+
+        SkColorType scaledColorType = decodeBitmap.colorType();
+        gainmapBitmap.setInfo(
+                bitmapInfo.makeWH(scaledWidth, scaledHeight).makeColorType(scaledColorType));
+
+        nativeBitmap = android::Bitmap::allocateHeapBitmap(&gainmapBitmap);
+        if (!nativeBitmap) {
+            ALOGE("OOM allocating gainmap pixels.");
+            return false;
+        }
+
+        SkPaint paint;
+        // kSrc_Mode instructs us to overwrite the uninitialized pixels in
+        // outputBitmap.  Otherwise we would blend by default, which is not
+        // what we want.
+        paint.setBlendMode(SkBlendMode::kSrc);
+
+        SkCanvas canvas(gainmapBitmap, SkCanvas::ColorBehavior::kLegacy);
+        canvas.scale(scaleX, scaleY);
+        decodeBitmap.setImmutable();  // so .asImage() doesn't make a copy
+        canvas.drawImage(decodeBitmap.asImage(), 0.0f, 0.0f,
+                         SkSamplingOptions(SkFilterMode::kLinear), &paint);
+    }
+
+    auto gainmap = sp<uirenderer::Gainmap>::make();
+    if (!gainmap) {
+        ALOGE("OOM allocating Gainmap");
+        return false;
+    }
+
+    gainmap->info = gainmapInfo;
+    gainmap->bitmap = std::move(nativeBitmap);
+    *outGainmap = std::move(gainmap);
+
+    return true;
+}
+
 static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,
                         jobject padding, jobject options, jlong inBitmapHandle,
                         jlong colorSpaceHandle) {
@@ -485,6 +598,19 @@
         return nullObjectReturn("Got null SkPixelRef");
     }
 
+    bool hasGainmap = false;
+    SkGainmapInfo gainmapInfo;
+    std::unique_ptr<SkStream> gainmapStream = nullptr;
+    sp<uirenderer::Gainmap> gainmap = nullptr;
+    if (result == SkCodec::kSuccess) {
+        hasGainmap = codec->getAndroidGainmap(&gainmapInfo, &gainmapStream);
+    }
+
+    if (hasGainmap) {
+        hasGainmap =
+                decodeGainmap(std::move(gainmapStream), gainmapInfo, &gainmap, sampleSize, scale);
+    }
+
     if (!isMutable && javaBitmap == NULL) {
         // promise we will never change our pixels (great for sharing and pictures)
         outputBitmap.setImmutable();
@@ -492,6 +618,9 @@
 
     bool isPremultiplied = !requireUnpremultiplied;
     if (javaBitmap != nullptr) {
+        if (hasGainmap) {
+            reuseBitmap->setGainmap(std::move(gainmap));
+        }
         bitmap::reinitBitmap(env, javaBitmap, outputBitmap.info(), isPremultiplied);
         outputBitmap.notifyPixelsChanged();
         // If a java bitmap was passed in for reuse, pass it back
@@ -507,13 +636,22 @@
         if (!hardwareBitmap.get()) {
             return nullObjectReturn("Failed to allocate a hardware bitmap");
         }
+        if (hasGainmap) {
+            hardwareBitmap->setGainmap(std::move(gainmap));
+        }
+
         return bitmap::createBitmap(env, hardwareBitmap.release(), bitmapCreateFlags,
                 ninePatchChunk, ninePatchInsets, -1);
     }
 
+    Bitmap* heapBitmap = defaultAllocator.getStorageObjAndReset();
+    if (hasGainmap && heapBitmap != nullptr) {
+        heapBitmap->setGainmap(std::move(gainmap));
+    }
+
     // now create the java bitmap
-    return bitmap::createBitmap(env, defaultAllocator.getStorageObjAndReset(),
-            bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1);
+    return bitmap::createBitmap(env, heapBitmap, bitmapCreateFlags, ninePatchChunk, ninePatchInsets,
+                                -1);
 }
 
 static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
diff --git a/libs/hwui/jni/BitmapRegionDecoder.cpp b/libs/hwui/jni/BitmapRegionDecoder.cpp
index eb56ae3..f93be03 100644
--- a/libs/hwui/jni/BitmapRegionDecoder.cpp
+++ b/libs/hwui/jni/BitmapRegionDecoder.cpp
@@ -17,17 +17,7 @@
 #undef LOG_TAG
 #define LOG_TAG "BitmapRegionDecoder"
 
-#include "BitmapFactory.h"
-#include "CreateJavaOutputStreamAdaptor.h"
-#include "GraphicsJNI.h"
-#include "Utils.h"
-
 #include "BitmapRegionDecoder.h"
-#include "SkBitmap.h"
-#include "SkCodec.h"
-#include "SkColorSpace.h"
-#include "SkData.h"
-#include "SkStream.h"
 
 #include <HardwareBitmapUploader.h>
 #include <androidfw/Asset.h>
@@ -35,10 +25,131 @@
 
 #include <memory>
 
+#include "BitmapFactory.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+#include "Gainmap.h"
+#include "GraphicsJNI.h"
+#include "SkBitmap.h"
+#include "SkCodec.h"
+#include "SkColorSpace.h"
+#include "SkData.h"
+#include "SkGainmapInfo.h"
+#include "SkStream.h"
+#include "SkStreamPriv.h"
+#include "Utils.h"
+
 using namespace android;
 
+namespace android {
+class BitmapRegionDecoderWrapper {
+public:
+    static std::unique_ptr<BitmapRegionDecoderWrapper> Make(sk_sp<SkData> data) {
+        std::unique_ptr<skia::BitmapRegionDecoder> mainImageBRD =
+                skia::BitmapRegionDecoder::Make(std::move(data));
+        if (!mainImageBRD) {
+            return nullptr;
+        }
+
+        SkGainmapInfo gainmapInfo;
+        std::unique_ptr<SkStream> gainmapStream;
+        std::unique_ptr<skia::BitmapRegionDecoder> gainmapBRD = nullptr;
+        if (mainImageBRD->getAndroidGainmap(&gainmapInfo, &gainmapStream)) {
+            sk_sp<SkData> data = nullptr;
+            if (gainmapStream->getMemoryBase()) {
+                // It is safe to make without copy because we'll hold onto the stream.
+                data = SkData::MakeWithoutCopy(gainmapStream->getMemoryBase(),
+                                               gainmapStream->getLength());
+            } else {
+                data = SkCopyStreamToData(gainmapStream.get());
+                // We don't need to hold the stream anymore
+                gainmapStream = nullptr;
+            }
+            gainmapBRD = skia::BitmapRegionDecoder::Make(std::move(data));
+        }
+
+        return std::unique_ptr<BitmapRegionDecoderWrapper>(
+                new BitmapRegionDecoderWrapper(std::move(mainImageBRD), std::move(gainmapBRD),
+                                               gainmapInfo, std::move(gainmapStream)));
+    }
+
+    SkEncodedImageFormat getEncodedFormat() { return mMainImageBRD->getEncodedFormat(); }
+
+    SkColorType computeOutputColorType(SkColorType requestedColorType) {
+        return mMainImageBRD->computeOutputColorType(requestedColorType);
+    }
+
+    sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,
+                                                sk_sp<SkColorSpace> prefColorSpace = nullptr) {
+        return mMainImageBRD->computeOutputColorSpace(outputColorType, prefColorSpace);
+    }
+
+    bool decodeRegion(SkBitmap* bitmap, skia::BRDAllocator* allocator, const SkIRect& desiredSubset,
+                      int sampleSize, SkColorType colorType, bool requireUnpremul,
+                      sk_sp<SkColorSpace> prefColorSpace) {
+        return mMainImageBRD->decodeRegion(bitmap, allocator, desiredSubset, sampleSize, colorType,
+                                           requireUnpremul, prefColorSpace);
+    }
+
+    bool decodeGainmapRegion(sp<uirenderer::Gainmap>* outGainmap, const SkIRect& desiredSubset,
+                             int sampleSize, bool requireUnpremul) {
+        SkColorType decodeColorType = mGainmapBRD->computeOutputColorType(kN32_SkColorType);
+        sk_sp<SkColorSpace> decodeColorSpace =
+                mGainmapBRD->computeOutputColorSpace(decodeColorType, nullptr);
+        SkBitmap bm;
+        HeapAllocator heapAlloc;
+        if (!mGainmapBRD->decodeRegion(&bm, &heapAlloc, desiredSubset, sampleSize, decodeColorType,
+                                       requireUnpremul, decodeColorSpace)) {
+            ALOGE("Error decoding Gainmap region");
+            return false;
+        }
+        sk_sp<Bitmap> nativeBitmap(heapAlloc.getStorageObjAndReset());
+        if (!nativeBitmap) {
+            ALOGE("OOM allocating Bitmap for Gainmap");
+            return false;
+        }
+        auto gainmap = sp<uirenderer::Gainmap>::make();
+        if (!gainmap) {
+            ALOGE("OOM allocating Gainmap");
+            return false;
+        }
+        gainmap->info = mGainmapInfo;
+        gainmap->bitmap = std::move(nativeBitmap);
+        *outGainmap = std::move(gainmap);
+        return true;
+    }
+
+    SkIRect calculateGainmapRegion(const SkIRect& mainImageRegion) {
+        const float scaleX = ((float)mGainmapBRD->width()) / mMainImageBRD->width();
+        const float scaleY = ((float)mGainmapBRD->height()) / mMainImageBRD->height();
+        // TODO: Account for rounding error?
+        return SkIRect::MakeLTRB(mainImageRegion.left() * scaleX, mainImageRegion.top() * scaleY,
+                                 mainImageRegion.right() * scaleX,
+                                 mainImageRegion.bottom() * scaleY);
+    }
+
+    bool hasGainmap() { return mGainmapBRD != nullptr; }
+
+    int width() const { return mMainImageBRD->width(); }
+    int height() const { return mMainImageBRD->height(); }
+
+private:
+    BitmapRegionDecoderWrapper(std::unique_ptr<skia::BitmapRegionDecoder> mainImageBRD,
+                               std::unique_ptr<skia::BitmapRegionDecoder> gainmapBRD,
+                               SkGainmapInfo info, std::unique_ptr<SkStream> stream)
+            : mMainImageBRD(std::move(mainImageBRD))
+            , mGainmapBRD(std::move(gainmapBRD))
+            , mGainmapInfo(info)
+            , mGainmapStream(std::move(stream)) {}
+
+    std::unique_ptr<skia::BitmapRegionDecoder> mMainImageBRD;
+    std::unique_ptr<skia::BitmapRegionDecoder> mGainmapBRD;
+    SkGainmapInfo mGainmapInfo;
+    std::unique_ptr<SkStream> mGainmapStream;
+};
+}  // namespace android
+
 static jobject createBitmapRegionDecoder(JNIEnv* env, sk_sp<SkData> data) {
-    auto brd = skia::BitmapRegionDecoder::Make(std::move(data));
+    auto brd = android::BitmapRegionDecoderWrapper::Make(std::move(data));
     if (!brd) {
         doThrowIOE(env, "Image format not supported");
         return nullObjectReturn("CreateBitmapRegionDecoder returned null");
@@ -136,7 +247,7 @@
         recycledBytes = recycledBitmap->getAllocationByteCount();
     }
 
-    auto* brd = reinterpret_cast<skia::BitmapRegionDecoder*>(brdHandle);
+    auto* brd = reinterpret_cast<BitmapRegionDecoderWrapper*>(brdHandle);
     SkColorType decodeColorType = brd->computeOutputColorType(colorType);
 
     if (isHardware) {
@@ -196,9 +307,22 @@
                 GraphicsJNI::getColorSpace(env, decodeColorSpace.get(), decodeColorType));
     }
 
+    sp<uirenderer::Gainmap> gainmap;
+    bool hasGainmap = brd->hasGainmap();
+    if (hasGainmap) {
+        SkIRect gainmapSubset = brd->calculateGainmapRegion(subset);
+        if (!brd->decodeGainmapRegion(&gainmap, gainmapSubset, sampleSize, requireUnpremul)) {
+            // If there is an error decoding Gainmap - we don't fail. We just don't provide Gainmap
+            hasGainmap = false;
+        }
+    }
+
     // If we may have reused a bitmap, we need to indicate that the pixels have changed.
     if (javaBitmap) {
         recycleAlloc.copyIfNecessary();
+        if (hasGainmap) {
+            recycledBitmap->setGainmap(std::move(gainmap));
+        }
         bitmap::reinitBitmap(env, javaBitmap, recycledBitmap->info(), !requireUnpremul);
         return javaBitmap;
     }
@@ -209,23 +333,30 @@
     }
     if (isHardware) {
         sk_sp<Bitmap> hardwareBitmap = Bitmap::allocateHardwareBitmap(bitmap);
+        if (hasGainmap) {
+            hardwareBitmap->setGainmap(std::move(gainmap));
+        }
         return bitmap::createBitmap(env, hardwareBitmap.release(), bitmapCreateFlags);
     }
-    return android::bitmap::createBitmap(env, heapAlloc.getStorageObjAndReset(), bitmapCreateFlags);
+    Bitmap* heapBitmap = heapAlloc.getStorageObjAndReset();
+    if (hasGainmap && heapBitmap != nullptr) {
+        heapBitmap->setGainmap(std::move(gainmap));
+    }
+    return android::bitmap::createBitmap(env, heapBitmap, bitmapCreateFlags);
 }
 
 static jint nativeGetHeight(JNIEnv* env, jobject, jlong brdHandle) {
-    auto* brd = reinterpret_cast<skia::BitmapRegionDecoder*>(brdHandle);
+    auto* brd = reinterpret_cast<BitmapRegionDecoderWrapper*>(brdHandle);
     return static_cast<jint>(brd->height());
 }
 
 static jint nativeGetWidth(JNIEnv* env, jobject, jlong brdHandle) {
-    auto* brd = reinterpret_cast<skia::BitmapRegionDecoder*>(brdHandle);
+    auto* brd = reinterpret_cast<BitmapRegionDecoderWrapper*>(brdHandle);
     return static_cast<jint>(brd->width());
 }
 
 static void nativeClean(JNIEnv* env, jobject, jlong brdHandle) {
-    auto* brd = reinterpret_cast<skia::BitmapRegionDecoder*>(brdHandle);
+    auto* brd = reinterpret_cast<BitmapRegionDecoderWrapper*>(brdHandle);
     delete brd;
 }
 
diff --git a/libs/hwui/jni/Graphics.cpp b/libs/hwui/jni/Graphics.cpp
index f5cd793..28d78b4 100644
--- a/libs/hwui/jni/Graphics.cpp
+++ b/libs/hwui/jni/Graphics.cpp
@@ -516,8 +516,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 
-jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, skia::BitmapRegionDecoder* bitmap)
-{
+jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, BitmapRegionDecoderWrapper* bitmap) {
     ALOG_ASSERT(bitmap != NULL);
 
     jobject obj = env->NewObject(gBitmapRegionDecoder_class,
diff --git a/libs/hwui/jni/GraphicsJNI.h b/libs/hwui/jni/GraphicsJNI.h
index c4a61cc..6b983c1 100644
--- a/libs/hwui/jni/GraphicsJNI.h
+++ b/libs/hwui/jni/GraphicsJNI.h
@@ -20,9 +20,7 @@
 struct SkFontMetrics;
 
 namespace android {
-namespace skia {
-    class BitmapRegionDecoder;
-}
+class BitmapRegionDecoderWrapper;
 class Canvas;
 class Paint;
 struct Typeface;
@@ -119,7 +117,7 @@
     static jobject createRegion(JNIEnv* env, SkRegion* region);
 
     static jobject createBitmapRegionDecoder(JNIEnv* env,
-                                             android::skia::BitmapRegionDecoder* bitmap);
+                                             android::BitmapRegionDecoderWrapper* bitmap);
 
     /**
      * Given a bitmap we natively allocate a memory block to store the contents
diff --git a/libs/hwui/jni/Mesh.cpp b/libs/hwui/jni/Mesh.cpp
index 3aac48d..b13d9ba 100644
--- a/libs/hwui/jni/Mesh.cpp
+++ b/libs/hwui/jni/Mesh.cpp
@@ -38,8 +38,8 @@
 }
 
 static jlong make(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject vertexBuffer,
-                  jboolean isDirect, jint vertexCount, jint vertexOffset, jint left, jint top,
-                  jint right, jint bottom) {
+                  jboolean isDirect, jint vertexCount, jint vertexOffset, jfloat left, jfloat top,
+                  jfloat right, jfloat bottom) {
     auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
     sk_sp<SkMesh::VertexBuffer> skVertexBuffer =
             genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isDirect);
@@ -60,7 +60,7 @@
 static jlong makeIndexed(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject vertexBuffer,
                          jboolean isVertexDirect, jint vertexCount, jint vertexOffset,
                          jobject indexBuffer, jboolean isIndexDirect, jint indexCount,
-                         jint indexOffset, jint left, jint top, jint right, jint bottom) {
+                         jint indexOffset, jfloat left, jfloat top, jfloat right, jfloat bottom) {
     auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
     sk_sp<SkMesh::VertexBuffer> skVertexBuffer =
             genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isVertexDirect);
@@ -210,8 +210,8 @@
 
 static const JNINativeMethod gMeshMethods[] = {
         {"nativeGetFinalizer", "()J", (void*)getMeshFinalizer},
-        {"nativeMake", "(JILjava/nio/Buffer;ZIIIIII)J", (void*)make},
-        {"nativeMakeIndexed", "(JILjava/nio/Buffer;ZIILjava/nio/ShortBuffer;ZIIIIII)J",
+        {"nativeMake", "(JILjava/nio/Buffer;ZIIFFFF)J", (void*)make},
+        {"nativeMakeIndexed", "(JILjava/nio/Buffer;ZIILjava/nio/ShortBuffer;ZIIFFFF)J",
          (void*)makeIndexed},
         {"nativeUpdateMesh", "(JZ)V", (void*)updateMesh},
         {"nativeUpdateUniforms", "(JLjava/lang/String;[FZ)V", (void*)updateFloatArrayUniforms},
diff --git a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
index 4886fdd..3e453e6 100644
--- a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
@@ -79,7 +79,7 @@
     return (jlong)proxy;
 }
 
-static void HardwareBufferRenderer_destroy(jobject renderProxy) {
+static void HardwareBufferRenderer_destroy(jlong renderProxy) {
     auto* proxy = reinterpret_cast<RenderProxy*>(renderProxy);
     delete proxy;
 }
@@ -109,7 +109,7 @@
     return matrix;
 }
 
-static int android_graphics_HardwareBufferRenderer_render(JNIEnv* env, jobject, jobject renderProxy,
+static int android_graphics_HardwareBufferRenderer_render(JNIEnv* env, jobject, jlong renderProxy,
                                                           jint transform, jint width, jint height,
                                                           jlong colorspacePtr, jobject consumer) {
     auto* proxy = reinterpret_cast<RenderProxy*>(renderProxy);
@@ -119,11 +119,17 @@
     auto colorSpace = GraphicsJNI::getNativeColorSpace(colorspacePtr);
     proxy->setHardwareBufferRenderParams(
             HardwareBufferRenderParams(matrix, colorSpace, createRenderCallback(env, consumer)));
+    nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
+    UiFrameInfoBuilder(proxy->frameInfo())
+                .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID,
+                    UiFrameInfoBuilder::UNKNOWN_DEADLINE,
+                    UiFrameInfoBuilder::UNKNOWN_FRAME_INTERVAL)
+                .addFlag(FrameInfoFlags::SurfaceCanvas);
     return proxy->syncAndDrawFrame();
 }
 
 static void android_graphics_HardwareBufferRenderer_setLightGeometry(JNIEnv*, jobject,
-                                                                     jobject renderProxyPtr,
+                                                                     jlong renderProxyPtr,
                                                                      jfloat lightX, jfloat lightY,
                                                                      jfloat lightZ,
                                                                      jfloat lightRadius) {
@@ -132,7 +138,7 @@
 }
 
 static void android_graphics_HardwareBufferRenderer_setLightAlpha(JNIEnv* env, jobject,
-                                                                  jobject renderProxyPtr,
+                                                                  jlong renderProxyPtr,
                                                                   jfloat ambientShadowAlpha,
                                                                   jfloat spotShadowAlpha) {
     auto* proxy = reinterpret_cast<RenderProxy*>(renderProxyPtr);
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 5892308..d6aad7d 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -232,10 +232,16 @@
     proxy->setOpaque(opaque);
 }
 
-static void android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jint colorMode) {
+static jfloat android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject clazz, jlong proxyPtr,
+                                                         jint colorMode) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->setColorMode(static_cast<ColorMode>(colorMode));
+    return proxy->setColorMode(static_cast<ColorMode>(colorMode));
+}
+
+static void android_view_ThreadedRenderer_setTargetSdrHdrRatio(JNIEnv* env, jobject clazz,
+                                                               jlong proxyPtr, jfloat ratio) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    return proxy->setRenderSdrHdrRatio(ratio);
 }
 
 static void android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv* env, jobject clazz,
@@ -924,7 +930,9 @@
         {"nSetLightAlpha", "(JFF)V", (void*)android_view_ThreadedRenderer_setLightAlpha},
         {"nSetLightGeometry", "(JFFFF)V", (void*)android_view_ThreadedRenderer_setLightGeometry},
         {"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque},
-        {"nSetColorMode", "(JI)V", (void*)android_view_ThreadedRenderer_setColorMode},
+        {"nSetColorMode", "(JI)F", (void*)android_view_ThreadedRenderer_setColorMode},
+        {"nSetTargetSdrHdrRatio", "(JF)V",
+         (void*)android_view_ThreadedRenderer_setTargetSdrHdrRatio},
         {"nSetSdrWhitePoint", "(JF)V", (void*)android_view_ThreadedRenderer_setSdrWhitePoint},
         {"nSetIsHighEndGfx", "(Z)V", (void*)android_view_ThreadedRenderer_setIsHighEndGfx},
         {"nSetIsLowRam", "(Z)V", (void*)android_view_ThreadedRenderer_setIsLowRam},
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 3692f09..6628463 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -642,12 +642,14 @@
             mSurfaceColorSpace = DeviceInfo::get()->getWideColorSpace();
             break;
         case ColorMode::Hdr:
-            mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType;
-            mSurfaceColorSpace = SkColorSpace::MakeRGB(GetPQSkTransferFunction(), SkNamedGamut::kRec2020);
+            mSurfaceColorType = SkColorType::kN32_SkColorType;
+            mSurfaceColorSpace = SkColorSpace::MakeRGB(
+                    GetExtendedTransferFunction(mTargetSdrHdrRatio), SkNamedGamut::kDisplayP3);
             break;
         case ColorMode::Hdr10:
             mSurfaceColorType = SkColorType::kRGBA_1010102_SkColorType;
-            mSurfaceColorSpace = SkColorSpace::MakeRGB(GetPQSkTransferFunction(), SkNamedGamut::kRec2020);
+            mSurfaceColorSpace = SkColorSpace::MakeRGB(
+                    GetExtendedTransferFunction(mTargetSdrHdrRatio), SkNamedGamut::kDisplayP3);
             break;
         case ColorMode::A8:
             mSurfaceColorType = SkColorType::kAlpha_8_SkColorType;
@@ -656,6 +658,16 @@
     }
 }
 
+void SkiaPipeline::setTargetSdrHdrRatio(float ratio) {
+    if (mColorMode == ColorMode::Hdr || mColorMode == ColorMode::Hdr10) {
+        mTargetSdrHdrRatio = ratio;
+        mSurfaceColorSpace = SkColorSpace::MakeRGB(GetExtendedTransferFunction(mTargetSdrHdrRatio),
+                                                   SkNamedGamut::kDisplayP3);
+    } else {
+        mTargetSdrHdrRatio = 1.f;
+    }
+}
+
 // Overdraw debugging
 
 // These colors should be kept in sync with Caches::getOverdrawColor() with a few differences.
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 4f93346..befee89 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -78,6 +78,8 @@
     virtual void setHardwareBuffer(AHardwareBuffer* buffer) override;
     bool hasHardwareBuffer() override { return mHardwareBuffer != nullptr; }
 
+    void setTargetSdrHdrRatio(float ratio) override;
+
 protected:
     sk_sp<SkSurface> getBufferSkSurface(
             const renderthread::HardwareBufferRenderParams& bufferParams);
@@ -92,6 +94,7 @@
     ColorMode mColorMode = ColorMode::Default;
     SkColorType mSurfaceColorType;
     sk_sp<SkColorSpace> mSurfaceColorSpace;
+    float mTargetSdrHdrRatio = 1.f;
 
     bool isCapturingSkp() const { return mCaptureMode != CaptureMode::None; }
 
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index c9d79ab..e1c8877 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -208,40 +208,52 @@
     }
 }
 
+void SkiaRecordingCanvas::handleMutableImages(Bitmap& bitmap, DrawImagePayload& payload) {
+    // if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
+    // it is not safe to store a raw SkImage pointer, because the image object will be destroyed
+    // when this function ends.
+    if (!bitmap.isImmutable() && payload.image.get() && !payload.image->unique()) {
+        mDisplayList->mMutableImages.push_back(payload.image.get());
+    }
+
+    if (bitmap.hasGainmap()) {
+        auto gainmapBitmap = bitmap.gainmap()->bitmap;
+        // Not all DrawImagePayload receivers will store the gainmap (such as DrawImageLattice),
+        // so only store it in the mutable list if it was actually recorded
+        if (!gainmapBitmap->isImmutable() && payload.gainmapImage.get() &&
+            !payload.gainmapImage->unique()) {
+            mDisplayList->mMutableImages.push_back(payload.gainmapImage.get());
+        }
+    }
+}
+
 void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) {
-    sk_sp<SkImage> image = bitmap.makeImage();
+    auto payload = DrawImagePayload(bitmap);
 
     applyLooper(
             paint,
             [&](const Paint& p) {
-                mRecorder.drawImage(image, left, top, p.sampling(), &p, bitmap.palette());
+                mRecorder.drawImage(DrawImagePayload(payload), left, top, p.sampling(), &p);
             },
             FilterForImage);
 
-    // if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
-    // it is not safe to store a raw SkImage pointer, because the image object will be destroyed
-    // when this function ends.
-    if (!bitmap.isImmutable() && image.get() && !image->unique()) {
-        mDisplayList->mMutableImages.push_back(image.get());
-    }
+    handleMutableImages(bitmap, payload);
 }
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* paint) {
     SkAutoCanvasRestore acr(&mRecorder, true);
     concat(matrix);
 
-    sk_sp<SkImage> image = bitmap.makeImage();
+    auto payload = DrawImagePayload(bitmap);
 
     applyLooper(
             paint,
             [&](const Paint& p) {
-                mRecorder.drawImage(image, 0, 0, p.sampling(), &p, bitmap.palette());
+                mRecorder.drawImage(DrawImagePayload(payload), 0, 0, p.sampling(), &p);
             },
             FilterForImage);
 
-    if (!bitmap.isImmutable() && image.get() && !image->unique()) {
-        mDisplayList->mMutableImages.push_back(image.get());
-    }
+    handleMutableImages(bitmap, payload);
 }
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
@@ -250,20 +262,17 @@
     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
 
-    sk_sp<SkImage> image = bitmap.makeImage();
+    auto payload = DrawImagePayload(bitmap);
 
     applyLooper(
             paint,
             [&](const Paint& p) {
-                mRecorder.drawImageRect(image, srcRect, dstRect, p.sampling(), &p,
-                                        SkCanvas::kFast_SrcRectConstraint, bitmap.palette());
+                mRecorder.drawImageRect(DrawImagePayload(payload), srcRect, dstRect, p.sampling(),
+                                        &p, SkCanvas::kFast_SrcRectConstraint);
             },
             FilterForImage);
 
-    if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
-        !dstRect.isEmpty()) {
-        mDisplayList->mMutableImages.push_back(image.get());
-    }
+    handleMutableImages(bitmap, payload);
 }
 
 void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft,
@@ -291,7 +300,7 @@
 
     lattice.fBounds = nullptr;
     SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
-    sk_sp<SkImage> image = bitmap.makeImage();
+    auto payload = DrawImagePayload(bitmap);
 
     // HWUI always draws 9-patches with linear filtering, regardless of the Paint.
     const SkFilterMode filter = SkFilterMode::kLinear;
@@ -299,13 +308,11 @@
     applyLooper(
             paint,
             [&](const SkPaint& p) {
-                mRecorder.drawImageLattice(image, lattice, dst, filter, &p, bitmap.palette());
+                mRecorder.drawImageLattice(DrawImagePayload(payload), lattice, dst, filter, &p);
             },
             FilterForImage);
 
-    if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
-        mDisplayList->mMutableImages.push_back(image.get());
-    }
+    handleMutableImages(bitmap, payload);
 }
 
 double SkiaRecordingCanvas::drawAnimatedImage(AnimatedImageDrawable* animatedImage) {
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 7844e2c..3fd8fa3 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -102,6 +102,8 @@
      */
     void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height);
 
+    void handleMutableImages(Bitmap& bitmap, DrawImagePayload& payload);
+
     using INHERITED = SkiaCanvas;
 };
 
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index b94b6cf..99298bc 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -185,6 +185,13 @@
     return mVkSurface != nullptr;
 }
 
+void SkiaVulkanPipeline::setTargetSdrHdrRatio(float ratio) {
+    SkiaPipeline::setTargetSdrHdrRatio(ratio);
+    if (mVkSurface) {
+        mVkSurface->setColorSpace(mSurfaceColorSpace);
+    }
+}
+
 bool SkiaVulkanPipeline::isSurfaceReady() {
     return CC_UNLIKELY(mVkSurface != nullptr);
 }
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 2c7b268..d921ddb 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -53,6 +53,8 @@
     void onStop() override;
     bool isSurfaceReady() override;
     bool isContextReady() override;
+    bool supportsExtendedRangeHdr() const override { return true; }
+    void setTargetSdrHdrRatio(float ratio) override;
 
     static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
     static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread,
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index db4d1dc..f10b2b2 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -194,8 +194,6 @@
     ATRACE_CALL();
 
     if (window) {
-        // Ensure the hint session is running here, away from any critical paths
-        mHintSessionWrapper.init();
         mNativeSurface = std::make_unique<ReliableSurface>(window);
         mNativeSurface->init();
         if (enableTimeout) {
@@ -301,9 +299,43 @@
     mOpaque = opaque;
 }
 
-void CanvasContext::setColorMode(ColorMode mode) {
-    mRenderPipeline->setSurfaceColorProperties(mode);
-    setupPipelineSurface();
+float CanvasContext::setColorMode(ColorMode mode) {
+    if (mode != mColorMode) {
+        const bool isHdr = mode == ColorMode::Hdr || mode == ColorMode::Hdr10;
+        if (isHdr && !mRenderPipeline->supportsExtendedRangeHdr()) {
+            mode = ColorMode::WideColorGamut;
+        }
+        mColorMode = mode;
+        mRenderPipeline->setSurfaceColorProperties(mode);
+        setupPipelineSurface();
+    }
+    switch (mColorMode) {
+        case ColorMode::Hdr:
+            return 3.f;  // TODO: Refine this number
+        case ColorMode::Hdr10:
+            return 10.f;
+        default:
+            return 1.f;
+    }
+}
+
+float CanvasContext::targetSdrHdrRatio() const {
+    if (mColorMode == ColorMode::Hdr || mColorMode == ColorMode::Hdr10) {
+        return mTargetSdrHdrRatio;
+    } else {
+        return 1.f;
+    }
+}
+
+void CanvasContext::setTargetSdrHdrRatio(float ratio) {
+    if (mTargetSdrHdrRatio == ratio) return;
+
+    mTargetSdrHdrRatio = ratio;
+    mRenderPipeline->setTargetSdrHdrRatio(ratio);
+    // We don't actually but we need to behave as if we do. Specifically we need to ensure
+    // all buffers in the swapchain are fully re-rendered as any partial updates to them will
+    // result in mixed target white points which looks really bad & flickery
+    mHaveNewSurface = true;
 }
 
 bool CanvasContext::makeCurrent() {
@@ -1033,6 +1065,10 @@
     mSyncDelayDuration = duration;
 }
 
+void CanvasContext::startHintSession() {
+    mHintSessionWrapper.init();
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index a274d2f..b26c018 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -137,7 +137,9 @@
     void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
     void setLightGeometry(const Vector3& lightCenter, float lightRadius);
     void setOpaque(bool opaque);
-    void setColorMode(ColorMode mode);
+    float setColorMode(ColorMode mode);
+    float targetSdrHdrRatio() const;
+    void setTargetSdrHdrRatio(float ratio);
     bool makeCurrent();
     void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target);
     // Returns the DequeueBufferDuration.
@@ -227,6 +229,8 @@
 
     void setSyncDelayDuration(nsecs_t duration);
 
+    void startHintSession();
+
 private:
     CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
                   IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline,
@@ -352,6 +356,9 @@
     nsecs_t mLastDequeueBufferDuration = 0;
     nsecs_t mSyncDelayDuration = 0;
     nsecs_t mIdleDuration = 0;
+
+    ColorMode mColorMode = ColorMode::Default;
+    float mTargetSdrHdrRatio = 1.f;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index b06c5dd..fab2f46 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -91,6 +91,7 @@
     ATRACE_FORMAT("DrawFrames %" PRId64, vsyncId);
 
     mContext->setSyncDelayDuration(systemTime(SYSTEM_TIME_MONOTONIC) - mSyncQueued);
+    mContext->setTargetSdrHdrRatio(mRenderSdrHdrRatio);
 
     auto hardwareBufferParams = mHardwareBufferParams;
     mContext->setHardwareBufferRenderParams(hardwareBufferParams);
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index c5c5fe2..4130d4a 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -100,6 +100,8 @@
         mHardwareBufferParams = params;
     }
 
+    void setRenderSdrHdrRatio(float ratio) { mRenderSdrHdrRatio = ratio; }
+
 private:
     void postAndWait();
     bool syncFrameState(TreeInfo& info);
@@ -112,6 +114,7 @@
     CanvasContext* mContext;
     RenderNode* mTargetNode = nullptr;
     Rect mContentDrawBounds;
+    float mRenderSdrHdrRatio = 1.f;
 
     /*********************************************
      *  Single frame data
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 02257db..4fb114b 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -450,6 +450,12 @@
                 case ColorMode::Default:
                     attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
                     break;
+                // Extended Range HDR requires being able to manipulate the dataspace in ways
+                // we cannot easily do while going through EGLSurface. Given this requires
+                // composer3 support, just treat HDR as equivalent to wide color gamut if
+                // the GLES path is still being hit
+                case ColorMode::Hdr:
+                case ColorMode::Hdr10:
                 case ColorMode::WideColorGamut: {
                     skcms_Matrix3x3 colorGamut;
                     LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&colorGamut),
@@ -466,14 +472,6 @@
                     }
                     break;
                 }
-                case ColorMode::Hdr:
-                    config = mEglConfigF16;
-                    attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
-                    break;
-                case ColorMode::Hdr10:
-                    config = mEglConfig1010102;
-                    attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
-                    break;
                 case ColorMode::A8:
                     LOG_ALWAYS_FATAL("Unreachable: A8 doesn't use a color space");
                     break;
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 715c17d..c68fcdf 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -95,6 +95,9 @@
     virtual void setPictureCapturedCallback(
             const std::function<void(sk_sp<SkPicture>&&)>& callback) = 0;
 
+    virtual bool supportsExtendedRangeHdr() const { return false; }
+    virtual void setTargetSdrHdrRatio(float ratio) = 0;
+
     virtual ~IRenderPipeline() {}
 };
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 5edb0b1..31b4b20 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -45,8 +45,12 @@
     pid_t uiThreadId = pthread_gettid_np(pthread_self());
     pid_t renderThreadId = getRenderThreadTid();
     mContext = mRenderThread.queue().runSync([=, this]() -> CanvasContext* {
-        return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory,
-                                     uiThreadId, renderThreadId);
+        CanvasContext* context = CanvasContext::create(mRenderThread, translucent, rootRenderNode,
+                                                       contextFactory, uiThreadId, renderThreadId);
+        if (context != nullptr) {
+            mRenderThread.queue().post([=] { context->startHintSession(); });
+        }
+        return context;
     });
     mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
 }
@@ -143,8 +147,20 @@
     mRenderThread.queue().post([=]() { mContext->setOpaque(opaque); });
 }
 
-void RenderProxy::setColorMode(ColorMode mode) {
-    mRenderThread.queue().post([=]() { mContext->setColorMode(mode); });
+float RenderProxy::setColorMode(ColorMode mode) {
+    // We only need to figure out what the renderer supports for HDR, otherwise this can stay
+    // an async call since we already know the return value
+    if (mode == ColorMode::Hdr || mode == ColorMode::Hdr10) {
+        return mRenderThread.queue().runSync(
+                [=]() -> float { return mContext->setColorMode(mode); });
+    } else {
+        mRenderThread.queue().post([=]() { mContext->setColorMode(mode); });
+        return 1.f;
+    }
+}
+
+void RenderProxy::setRenderSdrHdrRatio(float ratio) {
+    mDrawFrameTask.setRenderSdrHdrRatio(ratio);
 }
 
 int64_t* RenderProxy::frameInfo() {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 2aafe76..82072a6 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -87,7 +87,8 @@
     void setLightGeometry(const Vector3& lightCenter, float lightRadius);
     void setHardwareBufferRenderParams(const HardwareBufferRenderParams& params);
     void setOpaque(bool opaque);
-    void setColorMode(ColorMode mode);
+    float setColorMode(ColorMode mode);
+    void setRenderSdrHdrRatio(float ratio);
     int64_t* frameInfo();
     void forceDrawNextFrame();
     int syncAndDrawFrame();
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 7dd3561..21b6c44 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -199,7 +199,14 @@
 
     outWindowInfo->bufferFormat = ColorTypeToBufferFormat(colorType);
     outWindowInfo->colorspace = colorSpace;
-    outWindowInfo->dataspace = ColorSpaceToADataSpace(colorSpace.get(), colorType);
+    outWindowInfo->colorMode = colorMode;
+
+    if (colorMode == ColorMode::Hdr || colorMode == ColorMode::Hdr10) {
+        outWindowInfo->dataspace =
+                static_cast<android_dataspace>(STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_EXTENDED);
+    } else {
+        outWindowInfo->dataspace = ColorSpaceToADataSpace(colorSpace.get(), colorType);
+    }
     LOG_ALWAYS_FATAL_IF(
             outWindowInfo->dataspace == HAL_DATASPACE_UNKNOWN && colorType != kAlpha_8_SkColorType,
             "Unsupported colorspace");
@@ -496,6 +503,33 @@
     return currentBuffer.hasValidContents ? (mPresentCount - currentBuffer.lastPresentedCount) : 0;
 }
 
+void VulkanSurface::setColorSpace(sk_sp<SkColorSpace> colorSpace) {
+    mWindowInfo.colorspace = std::move(colorSpace);
+    for (int i = 0; i < kNumBufferSlots; i++) {
+        mNativeBuffers[i].skSurface.reset();
+    }
+
+    if (mWindowInfo.colorMode == ColorMode::Hdr || mWindowInfo.colorMode == ColorMode::Hdr10) {
+        mWindowInfo.dataspace =
+                static_cast<android_dataspace>(STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_EXTENDED);
+    } else {
+        mWindowInfo.dataspace = ColorSpaceToADataSpace(
+                mWindowInfo.colorspace.get(), BufferFormatToColorType(mWindowInfo.bufferFormat));
+    }
+    LOG_ALWAYS_FATAL_IF(mWindowInfo.dataspace == HAL_DATASPACE_UNKNOWN &&
+                                mWindowInfo.bufferFormat != AHARDWAREBUFFER_FORMAT_R8_UNORM,
+                        "Unsupported colorspace");
+
+    if (mNativeWindow) {
+        int err = ANativeWindow_setBuffersDataSpace(mNativeWindow.get(), mWindowInfo.dataspace);
+        if (err != 0) {
+            ALOGE("VulkanSurface::setColorSpace() native_window_set_buffers_data_space(%d) "
+                  "failed: %s (%d)",
+                  mWindowInfo.dataspace, strerror(-err), err);
+        }
+    }
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 2648666..e2ddc6b 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -46,6 +46,8 @@
     }
     const SkMatrix& getCurrentPreTransform() { return mWindowInfo.preTransform; }
 
+    void setColorSpace(sk_sp<SkColorSpace> colorSpace);
+
 private:
     /*
      * All structs/methods in this private section are specifically for use by the VulkanManager
@@ -94,6 +96,7 @@
         uint32_t bufferFormat;
         android_dataspace dataspace;
         sk_sp<SkColorSpace> colorspace;
+        ColorMode colorMode;
         int transform;
         size_t bufferCount;
         uint64_t windowUsageFlags;
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 4485044..bffe137 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -101,6 +101,26 @@
             return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
     }
 }
+
+SkColorType BufferFormatToColorType(uint32_t format) {
+    switch (format) {
+        case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
+            return kN32_SkColorType;
+        case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
+            return kN32_SkColorType;
+        case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
+            return kRGB_565_SkColorType;
+        case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
+            return kRGBA_1010102_SkColorType;
+        case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
+            return kRGBA_F16_SkColorType;
+        case AHARDWAREBUFFER_FORMAT_R8_UNORM:
+            return kAlpha_8_SkColorType;
+        default:
+            ALOGV("Unsupported format: %d, return unknown by default", format);
+            return kUnknown_SkColorType;
+    }
+}
 #endif
 
 namespace {
@@ -385,6 +405,27 @@
     return fn;
 }
 
+static skcms_TransferFunction trfn_apply_gain(const skcms_TransferFunction trfn, float gain) {
+    float pow_gain_ginv = sk_float_pow(gain, 1 / trfn.g);
+    skcms_TransferFunction result;
+    result.g = trfn.g;
+    result.a = trfn.a * pow_gain_ginv;
+    result.b = trfn.b * pow_gain_ginv;
+    result.c = trfn.c * gain;
+    result.d = trfn.d;
+    result.e = trfn.e * gain;
+    result.f = trfn.f * gain;
+    return result;
+}
+
+skcms_TransferFunction GetExtendedTransferFunction(float sdrHdrRatio) {
+    if (sdrHdrRatio <= 1.f) {
+        return SkNamedTransferFn::kSRGB;
+    }
+    // Scale the transfer by the sdrHdrRatio
+    return trfn_apply_gain(SkNamedTransferFn::kSRGB, sdrHdrRatio);
+}
+
 // Skia skcms' default HLG maps encoded [0, 1] to linear [1, 12] in order to follow ARIB
 // but LinearEffect expects a decoded [0, 1] range instead to follow Rec 2100.
 std::optional<skcms_TransferFunction> GetHLGScaleTransferFunction() {
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 00f910f..0fd61c7 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -100,6 +100,7 @@
                                          sk_sp<SkColorSpace> colorSpace);
 
 uint32_t ColorTypeToBufferFormat(SkColorType colorType);
+SkColorType BufferFormatToColorType(uint32_t bufferFormat);
 #endif
 
 ANDROID_API sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace);
@@ -129,6 +130,7 @@
 Lab sRGBToLab(SkColor color);
 SkColor LabToSRGB(const Lab& lab, SkAlpha alpha);
 skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level = 0.f);
+skcms_TransferFunction GetExtendedTransferFunction(float sdrHdrRatio);
 std::optional<skcms_TransferFunction> GetHLGScaleTransferFunction();
 
 } /* namespace uirenderer */
diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp
index a835167..24cfc9d 100644
--- a/libs/input/MouseCursorController.cpp
+++ b/libs/input/MouseCursorController.cpp
@@ -38,6 +38,8 @@
       : mContext(context) {
     std::scoped_lock lock(mLock);
 
+    mLocked.stylusHoverMode = false;
+
     mLocked.animationFrameIndex = 0;
     mLocked.lastFrameUpdatedTime = 0;
 
@@ -47,7 +49,8 @@
     mLocked.pointerAlpha = 0.0f; // pointer is initially faded
     mLocked.pointerSprite = mContext.getSpriteController()->createSprite();
     mLocked.updatePointerIcon = false;
-    mLocked.requestedPointerType = mContext.getPolicy()->getDefaultPointerIconId();
+    mLocked.requestedPointerType = PointerIconStyle::TYPE_NOT_SPECIFIED;
+    mLocked.resolvedPointerType = PointerIconStyle::TYPE_NOT_SPECIFIED;
 
     mLocked.resourcesLoaded = false;
 
@@ -184,6 +187,15 @@
     }
 }
 
+void MouseCursorController::setStylusHoverMode(bool stylusHoverMode) {
+    std::scoped_lock lock(mLock);
+
+    if (mLocked.stylusHoverMode != stylusHoverMode) {
+        mLocked.stylusHoverMode = stylusHoverMode;
+        mLocked.updatePointerIcon = true;
+    }
+}
+
 void MouseCursorController::reloadPointerResources(bool getAdditionalMouseResources) {
     std::scoped_lock lock(mLock);
 
@@ -339,7 +351,7 @@
 
 bool MouseCursorController::doBitmapAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
     std::map<PointerIconStyle, PointerAnimation>::const_iterator iter =
-            mLocked.animationResources.find(mLocked.requestedPointerType);
+            mLocked.animationResources.find(mLocked.resolvedPointerType);
     if (iter == mLocked.animationResources.end()) {
         return false;
     }
@@ -381,14 +393,23 @@
     }
 
     if (mLocked.updatePointerIcon) {
-        if (mLocked.requestedPointerType == mContext.getPolicy()->getDefaultPointerIconId()) {
+        mLocked.resolvedPointerType = mLocked.requestedPointerType;
+        const PointerIconStyle defaultPointerIconId =
+                mContext.getPolicy()->getDefaultPointerIconId();
+        if (mLocked.resolvedPointerType == PointerIconStyle::TYPE_NOT_SPECIFIED) {
+            mLocked.resolvedPointerType = mLocked.stylusHoverMode
+                    ? mContext.getPolicy()->getDefaultStylusIconId()
+                    : defaultPointerIconId;
+        }
+
+        if (mLocked.resolvedPointerType == defaultPointerIconId) {
             mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
         } else {
             std::map<PointerIconStyle, SpriteIcon>::const_iterator iter =
-                    mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
+                    mLocked.additionalMouseResources.find(mLocked.resolvedPointerType);
             if (iter != mLocked.additionalMouseResources.end()) {
                 std::map<PointerIconStyle, PointerAnimation>::const_iterator anim_iter =
-                        mLocked.animationResources.find(mLocked.requestedPointerType);
+                        mLocked.animationResources.find(mLocked.resolvedPointerType);
                 if (anim_iter != mLocked.animationResources.end()) {
                     mLocked.animationFrameIndex = 0;
                     mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -396,7 +417,7 @@
                 }
                 mLocked.pointerSprite->setIcon(iter->second);
             } else {
-                ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
+                ALOGW("Can't find the resource for icon id %d", mLocked.resolvedPointerType);
                 mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
             }
         }
diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h
index 208d33d..db0ab56 100644
--- a/libs/input/MouseCursorController.h
+++ b/libs/input/MouseCursorController.h
@@ -53,6 +53,7 @@
     void fade(PointerControllerInterface::Transition transition);
     void unfade(PointerControllerInterface::Transition transition);
     void setDisplayViewport(const DisplayViewport& viewport, bool getAdditionalMouseResources);
+    void setStylusHoverMode(bool stylusHoverMode);
 
     void updatePointerIcon(PointerIconStyle iconId);
     void setCustomPointerIcon(const SpriteIcon& icon);
@@ -74,6 +75,7 @@
 
     struct Locked {
         DisplayViewport viewport;
+        bool stylusHoverMode;
 
         size_t animationFrameIndex;
         nsecs_t lastFrameUpdatedTime;
@@ -92,6 +94,7 @@
         std::map<PointerIconStyle, PointerAnimation> animationResources;
 
         PointerIconStyle requestedPointerType;
+        PointerIconStyle resolvedPointerType;
 
         int32_t buttonState;
 
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 099efd3..fedf58d 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -195,7 +195,11 @@
         return;
     }
 
-    if (presentation == Presentation::POINTER) {
+    if (presentation == Presentation::POINTER || presentation == Presentation::STYLUS_HOVER) {
+        // For now, we support stylus hover using the mouse cursor implementation.
+        // TODO: Add proper support for stylus hover icons.
+        mCursorController.setStylusHoverMode(presentation == Presentation::STYLUS_HOVER);
+
         mCursorController.getAdditionalMouseResources();
         clearSpotsLocked();
     }
@@ -249,7 +253,8 @@
 
     if (mCursorController.resourcesLoaded()) {
         bool getAdditionalMouseResources = false;
-        if (mLocked.presentation == PointerController::Presentation::POINTER) {
+        if (mLocked.presentation == PointerController::Presentation::POINTER ||
+            mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
             getAdditionalMouseResources = true;
         }
         mCursorController.reloadPointerResources(getAdditionalMouseResources);
@@ -260,7 +265,8 @@
     std::scoped_lock lock(getLock());
 
     bool getAdditionalMouseResources = false;
-    if (mLocked.presentation == PointerController::Presentation::POINTER) {
+    if (mLocked.presentation == PointerController::Presentation::POINTER ||
+        mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
         getAdditionalMouseResources = true;
     }
     mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
diff --git a/libs/input/PointerControllerContext.h b/libs/input/PointerControllerContext.h
index 1797428..96d83a5 100644
--- a/libs/input/PointerControllerContext.h
+++ b/libs/input/PointerControllerContext.h
@@ -79,6 +79,7 @@
             std::map<PointerIconStyle, PointerAnimation>* outAnimationResources,
             int32_t displayId) = 0;
     virtual PointerIconStyle getDefaultPointerIconId() = 0;
+    virtual PointerIconStyle getDefaultStylusIconId() = 0;
     virtual PointerIconStyle getCustomPointerIconId() = 0;
     virtual void onPointerDisplayIdChanged(int32_t displayId, float xPos, float yPos) = 0;
 };
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index a6a4115..c820d00 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -35,6 +35,7 @@
     CURSOR_TYPE_ANCHOR,
     CURSOR_TYPE_ADDITIONAL,
     CURSOR_TYPE_ADDITIONAL_ANIM,
+    CURSOR_TYPE_STYLUS,
     CURSOR_TYPE_CUSTOM = -1,
 };
 
@@ -57,6 +58,7 @@
             std::map<PointerIconStyle, PointerAnimation>* outAnimationResources,
             int32_t displayId) override;
     virtual PointerIconStyle getDefaultPointerIconId() override;
+    virtual PointerIconStyle getDefaultStylusIconId() override;
     virtual PointerIconStyle getCustomPointerIconId() override;
     virtual void onPointerDisplayIdChanged(int32_t displayId, float xPos, float yPos) override;
 
@@ -105,6 +107,11 @@
     (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
     (*outAnimationResources)[static_cast<PointerIconStyle>(cursorType)] = anim;
 
+    // CURSOR_TYPE_STYLUS doesn't have animation resource.
+    cursorType = CURSOR_TYPE_STYLUS;
+    loadPointerIconForType(&icon, cursorType);
+    (*outResources)[static_cast<PointerIconStyle>(cursorType)] = icon;
+
     additionalMouseResourcesLoaded = true;
 }
 
@@ -112,6 +119,10 @@
     return static_cast<PointerIconStyle>(CURSOR_TYPE_DEFAULT);
 }
 
+PointerIconStyle MockPointerControllerPolicyInterface::getDefaultStylusIconId() {
+    return static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS);
+}
+
 PointerIconStyle MockPointerControllerPolicyInterface::getCustomPointerIconId() {
     return static_cast<PointerIconStyle>(CURSOR_TYPE_CUSTOM);
 }
@@ -214,6 +225,21 @@
     mPointerController->reloadPointerResources();
 }
 
+TEST_F(PointerControllerTest, useStylusTypeForStylusHover) {
+    ensureDisplayViewportIsSet();
+    mPointerController->setPresentation(PointerController::Presentation::STYLUS_HOVER);
+    mPointerController->unfade(PointerController::Transition::IMMEDIATE);
+    std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_STYLUS);
+    EXPECT_CALL(*mPointerSprite, setVisible(true));
+    EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
+    EXPECT_CALL(*mPointerSprite,
+                setIcon(AllOf(Field(&SpriteIcon::style,
+                                    static_cast<PointerIconStyle>(CURSOR_TYPE_STYLUS)),
+                              Field(&SpriteIcon::hotSpotX, hotspot.first),
+                              Field(&SpriteIcon::hotSpotY, hotspot.second))));
+    mPointerController->reloadPointerResources();
+}
+
 TEST_F(PointerControllerTest, updatePointerIcon) {
     ensureDisplayViewportIsSet();
     mPointerController->setPresentation(PointerController::Presentation::POINTER);
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index dea6097..b0cdb05 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -1275,7 +1275,10 @@
                     || (preset == MediaRecorder.AudioSource.VOICE_UPLINK)
                     || (preset == MediaRecorder.AudioSource.VOICE_CALL)
                     || (preset == MediaRecorder.AudioSource.ECHO_REFERENCE)
-                    || (preset == MediaRecorder.AudioSource.ULTRASOUND)) {
+                    || (preset == MediaRecorder.AudioSource.ULTRASOUND)
+                    // AUDIO_SOURCE_INVALID is used by convention on default initialized
+                    // audio attributes
+                    || (preset == MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID)) {
                 mSource = preset;
             } else {
                 setCapturePreset(preset);
diff --git a/media/java/android/media/AudioDeviceVolumeManager.java b/media/java/android/media/AudioDeviceVolumeManager.java
index 77fa9dc..bf3612d 100644
--- a/media/java/android/media/AudioDeviceVolumeManager.java
+++ b/media/java/android/media/AudioDeviceVolumeManager.java
@@ -146,13 +146,16 @@
          * @param register true for registering, false for unregistering
          * @param device device for which volume is monitored
          */
+        @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+                android.Manifest.permission.BLUETOOTH_PRIVILEGED })
         public void register(boolean register, @NonNull AudioDeviceAttributes device,
-                @NonNull List<VolumeInfo> volumes, boolean handlesVolumeAdjustment) {
+                @NonNull List<VolumeInfo> volumes, boolean handlesVolumeAdjustment,
+                @AudioManager.AbsoluteDeviceVolumeBehavior int behavior) {
             try {
                 getService().registerDeviceVolumeDispatcherForAbsoluteVolume(register,
                         this, mPackageName,
                         Objects.requireNonNull(device), Objects.requireNonNull(volumes),
-                        handlesVolumeAdjustment);
+                        handlesVolumeAdjustment, behavior);
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
             }
@@ -234,6 +237,77 @@
             @NonNull @CallbackExecutor Executor executor,
             @NonNull OnAudioDeviceVolumeChangedListener vclistener,
             boolean handlesVolumeAdjustment) {
+        baseSetDeviceAbsoluteMultiVolumeBehavior(device, volumes, executor, vclistener,
+                handlesVolumeAdjustment, AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
+    }
+
+    /**
+     * @hide
+     * Configures a device to use absolute volume model, and registers a listener for receiving
+     * volume updates to apply on that device.
+     *
+     * Should be used instead of {@link #setDeviceAbsoluteVolumeBehavior} when there is no reliable
+     * way to set the device's volume to a percentage.
+     *
+     * @param device the audio device set to absolute volume mode
+     * @param volume the type of volume this device responds to
+     * @param executor the Executor used for receiving volume updates through the listener
+     * @param vclistener the callback for volume updates
+     */
+    @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+            android.Manifest.permission.BLUETOOTH_PRIVILEGED })
+    public void setDeviceAbsoluteVolumeAdjustOnlyBehavior(
+            @NonNull AudioDeviceAttributes device,
+            @NonNull VolumeInfo volume,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnAudioDeviceVolumeChangedListener vclistener,
+            boolean handlesVolumeAdjustment) {
+        final ArrayList<VolumeInfo> volumes = new ArrayList<>(1);
+        volumes.add(volume);
+        setDeviceAbsoluteMultiVolumeAdjustOnlyBehavior(device, volumes, executor, vclistener,
+                handlesVolumeAdjustment);
+    }
+
+    /**
+     * @hide
+     * Configures a device to use absolute volume model applied to different volume types, and
+     * registers a listener for receiving volume updates to apply on that device.
+     *
+     * Should be used instead of {@link #setDeviceAbsoluteMultiVolumeBehavior} when there is
+     * no reliable way to set the device's volume to a percentage.
+     *
+     * @param device the audio device set to absolute multi-volume mode
+     * @param volumes the list of volumes the given device responds to
+     * @param executor the Executor used for receiving volume updates through the listener
+     * @param vclistener the callback for volume updates
+     */
+    @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+            android.Manifest.permission.BLUETOOTH_PRIVILEGED })
+    public void setDeviceAbsoluteMultiVolumeAdjustOnlyBehavior(
+            @NonNull AudioDeviceAttributes device,
+            @NonNull List<VolumeInfo> volumes,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnAudioDeviceVolumeChangedListener vclistener,
+            boolean handlesVolumeAdjustment) {
+        baseSetDeviceAbsoluteMultiVolumeBehavior(device, volumes, executor, vclistener,
+                handlesVolumeAdjustment, AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY);
+    }
+
+    /**
+     * Base method for configuring a device to use absolute volume behavior, or one of its variants.
+     * See {@link AudioManager#AbsoluteDeviceVolumeBehavior} for a list of allowed behaviors.
+     *
+     * @param behavior the variant of absolute device volume behavior to adopt
+     */
+    @RequiresPermission(anyOf = { android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+            android.Manifest.permission.BLUETOOTH_PRIVILEGED })
+    private void baseSetDeviceAbsoluteMultiVolumeBehavior(
+            @NonNull AudioDeviceAttributes device,
+            @NonNull List<VolumeInfo> volumes,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnAudioDeviceVolumeChangedListener vclistener,
+            boolean handlesVolumeAdjustment,
+            @AudioManager.AbsoluteDeviceVolumeBehavior int behavior) {
         Objects.requireNonNull(device);
         Objects.requireNonNull(volumes);
         Objects.requireNonNull(executor);
@@ -253,7 +327,8 @@
                 mDeviceVolumeListeners.removeIf(info -> info.mDevice.equalTypeAddress(device));
             }
             mDeviceVolumeListeners.add(listenerInfo);
-            mDeviceVolumeDispatcherStub.register(true, device, volumes, handlesVolumeAdjustment);
+            mDeviceVolumeDispatcherStub.register(true, device, volumes, handlesVolumeAdjustment,
+                    behavior);
         }
     }
 
@@ -375,6 +450,8 @@
                 return "DEVICE_VOLUME_BEHAVIOR_ABSOLUTE";
             case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE:
                 return "DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE";
+            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY:
+                return "DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY";
             default:
                 return "invalid volume behavior " + behavior;
         }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 0636451..7de3abc3 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1422,7 +1422,7 @@
     public int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) {
         Preconditions.checkNotNull(attributes, "Audio Attributes must not be null");
         return AudioProductStrategy.getVolumeGroupIdForAudioAttributes(attributes,
-                /* fallbackOnDefault= */ false);
+                /* fallbackOnDefault= */ true);
     }
 
     /**
@@ -6231,6 +6231,15 @@
     @SystemApi
     public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE = 4;
 
+    /**
+     * @hide
+     * A variant of {@link #DEVICE_VOLUME_BEHAVIOR_ABSOLUTE} where the host cannot reliably set
+     * the volume percentage of the audio device. Specifically, {@link #setStreamVolume} will have
+     * no effect, or an unreliable effect.
+     */
+    @SystemApi
+    public static final int DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY = 5;
+
     /** @hide */
     @IntDef({
             DEVICE_VOLUME_BEHAVIOR_VARIABLE,
@@ -6238,6 +6247,7 @@
             DEVICE_VOLUME_BEHAVIOR_FIXED,
             DEVICE_VOLUME_BEHAVIOR_ABSOLUTE,
             DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE,
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DeviceVolumeBehavior {}
@@ -6250,11 +6260,23 @@
             DEVICE_VOLUME_BEHAVIOR_FIXED,
             DEVICE_VOLUME_BEHAVIOR_ABSOLUTE,
             DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE,
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DeviceVolumeBehaviorState {}
 
     /**
+     * Variants of absolute volume behavior that are set in {@link AudioDeviceVolumeManager}.
+     * @hide
+     */
+    @IntDef({
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE,
+            DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AbsoluteDeviceVolumeBehavior {}
+
+    /**
      * @hide
      * Throws IAE on an invalid volume behavior value
      * @param volumeBehavior behavior value to check
@@ -6266,6 +6288,7 @@
             case DEVICE_VOLUME_BEHAVIOR_FIXED:
             case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE:
             case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE:
+            case DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY:
                 return;
             default:
                 throw new IllegalArgumentException("Illegal volume behavior " + volumeBehavior);
@@ -6305,6 +6328,16 @@
 
     /**
      * @hide
+     * Controls whether DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY may be returned by
+     * getDeviceVolumeBehavior. If this is disabled, DEVICE_VOLUME_BEHAVIOR_FULL is returned
+     * in its place.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    public static final long RETURN_DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY = 240663182L;
+
+    /**
+     * @hide
      * Returns the volume device behavior for the given audio device
      * @param device the audio device
      * @return the volume behavior for the device
@@ -6322,7 +6355,12 @@
         // communicate with service
         final IAudioService service = getService();
         try {
-            return service.getDeviceVolumeBehavior(device);
+            int behavior = service.getDeviceVolumeBehavior(device);
+            if (!CompatChanges.isChangeEnabled(RETURN_DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY)
+                    && behavior == DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY) {
+                return AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL;
+            }
+            return behavior;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 3e0356f..1c517e7 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -629,12 +629,13 @@
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)")
     int[] getActiveAssistantServiceUids();
 
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)")
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
     void registerDeviceVolumeDispatcherForAbsoluteVolume(boolean register,
             in IAudioDeviceVolumeDispatcher cb,
             in String packageName,
             in AudioDeviceAttributes device, in List<VolumeInfo> volumes,
-            boolean handlesvolumeAdjustment);
+            boolean handlesvolumeAdjustment,
+            int volumeBehavior);
 
     AudioHalVersionInfo getHalVersion();
 
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 015602e..5bc8c04 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -41,6 +41,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
 import android.util.Log;
 import android.util.Singleton;
 
@@ -360,14 +361,14 @@
         @Override
         public void handleMessage(Message msg) {
             if (msg.what == MSG_CAS_EVENT) {
-                mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2,
-                        toBytes((ArrayList<Byte>) msg.obj));
+                byte[] data = (msg.obj == null) ? new byte[0] : (byte[]) msg.obj;
+                mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2, data);
             } else if (msg.what == MSG_CAS_SESSION_EVENT) {
                 Bundle bundle = msg.getData();
                 byte[] sessionId = bundle.getByteArray(SESSION_KEY);
-                mListener.onSessionEvent(MediaCas.this,
-                        createFromSessionId(sessionId), msg.arg1, msg.arg2,
-                        bundle.getByteArray(DATA_KEY));
+                byte[] data = bundle.getByteArray(DATA_KEY);
+                mListener.onSessionEvent(
+                        MediaCas.this, createFromSessionId(sessionId), msg.arg1, msg.arg2, data);
             } else if (msg.what == MSG_CAS_STATUS_EVENT) {
                 if ((msg.arg1 == PLUGIN_STATUS_SESSION_NUMBER_CHANGED)
                         && (mTunerResourceManager != null)) {
@@ -599,7 +600,11 @@
 
             try {
                 if (mICas != null) {
-                    mICas.setSessionPrivateData(mSessionId, data);
+                    try {
+                        mICas.setSessionPrivateData(mSessionId, data);
+                    } catch (ServiceSpecificException se) {
+                        MediaCasException.throwExceptionIfNeeded(se.errorCode);
+                    }
                 } else {
                     MediaCasException.throwExceptionIfNeeded(
                             mICasHidl.setSessionPrivateData(
@@ -628,7 +633,12 @@
 
             try {
                 if (mICas != null) {
-                    mICas.processEcm(mSessionId, data);
+                    try {
+                        mICas.processEcm(
+                                mSessionId, Arrays.copyOfRange(data, offset, length + offset));
+                    } catch (ServiceSpecificException se) {
+                        MediaCasException.throwExceptionIfNeeded(se.errorCode);
+                    }
                 } else {
                     MediaCasException.throwExceptionIfNeeded(
                             mICasHidl.processEcm(
@@ -671,23 +681,26 @@
             validateSessionInternalStates();
             if (mICas != null) {
                 try {
+                    if (data == null) {
+                        data = new byte[0];
+                    }
                     mICas.sendSessionEvent(mSessionId, event, arg, data);
                 } catch (RemoteException e) {
                     cleanupAndRethrowIllegalState();
                 }
-            }
+            } else {
+                if (mICasHidl11 == null) {
+                    Log.d(TAG, "Send Session Event isn't supported by cas@1.0 interface");
+                    throw new UnsupportedCasException("Send Session Event is not supported");
+                }
 
-            if (mICasHidl11 == null) {
-                Log.d(TAG, "Send Session Event isn't supported by cas@1.0 interface");
-                throw new UnsupportedCasException("Send Session Event is not supported");
-            }
-
-            try {
-                MediaCasException.throwExceptionIfNeeded(
-                        mICasHidl11.sendSessionEvent(
-                                toByteArray(mSessionId), event, arg, toByteArray(data)));
-            } catch (RemoteException e) {
-                cleanupAndRethrowIllegalState();
+                try {
+                    MediaCasException.throwExceptionIfNeeded(
+                            mICasHidl11.sendSessionEvent(
+                                    toByteArray(mSessionId), event, arg, toByteArray(data)));
+                } catch (RemoteException e) {
+                    cleanupAndRethrowIllegalState();
+                }
             }
         }
 
@@ -931,10 +944,11 @@
     }
 
     /**
-     * Check if the HAL is an AIDL implementation
+     * Check if the HAL is an AIDL implementation. For CTS testing purpose.
      *
      * @hide
      */
+    @TestApi
     public boolean isAidlHal() {
         return mICas != null;
     }
@@ -1038,7 +1052,11 @@
 
         try {
             if (mICas != null) {
-                mICas.setPrivateData(data);
+                try {
+                    mICas.setPrivateData(data);
+                } catch (ServiceSpecificException se) {
+                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
+                }
             } else {
                 MediaCasException.throwExceptionIfNeeded(
                         mICasHidl.setPrivateData(toByteArray(data, 0, data.length)));
@@ -1126,7 +1144,21 @@
         int sessionResourceHandle = getSessionResourceHandle();
 
         try {
-            if (mICasHidl != null) {
+            if (mICas != null) {
+                try {
+                    byte[] sessionId = mICas.openSessionDefault();
+                    Session session = createFromSessionId(sessionId);
+                    Log.d(TAG, "Write Stats Log for succeed to Open Session.");
+                    FrameworkStatsLog.write(
+                            FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS,
+                            mUserId,
+                            mCasSystemId,
+                            FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS__STATE__SUCCEEDED);
+                    return session;
+                } catch (ServiceSpecificException se) {
+                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
+                }
+            } else if (mICasHidl != null) {
                 OpenSessionCallback cb = new OpenSessionCallback();
                 mICasHidl.openSession(cb);
                 MediaCasException.throwExceptionIfNeeded(cb.mStatus);
@@ -1183,7 +1215,7 @@
                         mCasSystemId,
                         FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS__STATE__SUCCEEDED);
                 return session;
-            } catch (RemoteException e) {
+            } catch (ServiceSpecificException | RemoteException e) {
                 cleanupAndRethrowIllegalState();
             }
         }
@@ -1229,7 +1261,11 @@
 
         try {
             if (mICas != null) {
-                mICas.processEmm(Arrays.copyOfRange(data, offset, length));
+                try {
+                    mICas.processEmm(Arrays.copyOfRange(data, offset, length));
+                } catch (ServiceSpecificException se) {
+                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
+                }
             } else {
                 MediaCasException.throwExceptionIfNeeded(
                         mICasHidl.processEmm(toByteArray(data, offset, length)));
@@ -1272,7 +1308,14 @@
 
         try {
             if (mICas != null) {
-                mICas.sendEvent(event, arg, data);
+                try {
+                    if (data == null) {
+                        data = new byte[0];
+                    }
+                    mICas.sendEvent(event, arg, data);
+                } catch (ServiceSpecificException se) {
+                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
+                }
             } else {
                 MediaCasException.throwExceptionIfNeeded(
                         mICasHidl.sendEvent(event, arg, toByteArray(data)));
@@ -1298,7 +1341,11 @@
 
         try {
             if (mICas != null) {
-                mICas.provision(provisionString);
+                try {
+                    mICas.provision(provisionString);
+                } catch (ServiceSpecificException se) {
+                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
+                }
             } else {
                 MediaCasException.throwExceptionIfNeeded(mICasHidl.provision(provisionString));
             }
@@ -1323,7 +1370,14 @@
 
         try {
             if (mICas != null) {
-                mICas.refreshEntitlements(refreshType, refreshData);
+                try {
+                    if (refreshData == null) {
+                        refreshData = new byte[0];
+                    }
+                    mICas.refreshEntitlements(refreshType, refreshData);
+                } catch (ServiceSpecificException se) {
+                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
+                }
             } else {
                 MediaCasException.throwExceptionIfNeeded(
                         mICasHidl.refreshEntitlements(refreshType, toByteArray(refreshData)));
diff --git a/media/java/android/media/MediaDescrambler.java b/media/java/android/media/MediaDescrambler.java
index b4bdf93d..3c276d6 100644
--- a/media/java/android/media/MediaDescrambler.java
+++ b/media/java/android/media/MediaDescrambler.java
@@ -17,24 +17,16 @@
 package android.media;
 
 import android.annotation.NonNull;
-import android.hardware.cas.DestinationBuffer;
+import android.annotation.TestApi;
 import android.hardware.cas.IDescrambler;
 import android.hardware.cas.ScramblingControl;
-import android.hardware.cas.SharedBuffer;
-import android.hardware.cas.SubSample;
 import android.hardware.cas.V1_0.IDescramblerBase;
-import android.hardware.common.Ashmem;
-import android.hardware.common.NativeHandle;
 import android.media.MediaCasException.UnsupportedCasException;
 import android.os.IHwBinder;
-import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
-import android.os.SharedMemory;
-import android.system.ErrnoException;
 import android.util.Log;
 
-import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 
@@ -52,6 +44,7 @@
 public final class MediaDescrambler implements AutoCloseable {
     private static final String TAG = "MediaDescrambler";
     private DescramblerWrapper mIDescrambler;
+    private boolean mIsAidlHal;
 
     private interface DescramblerWrapper {
 
@@ -68,50 +61,18 @@
         void setMediaCasSession(byte[] sessionId) throws RemoteException;
 
         void release() throws RemoteException;
-    }
-    ;
-
-    private long getSubsampleInfo(
-            int numSubSamples,
-            int[] numBytesOfClearData,
-            int[] numBytesOfEncryptedData,
-            SubSample[] subSamples) {
-        long totalSize = 0;
-
-        for (int i = 0; i < numSubSamples; i++) {
-            totalSize += numBytesOfClearData[i];
-            subSamples[i].numBytesOfClearData = numBytesOfClearData[i];
-            totalSize += numBytesOfEncryptedData[i];
-            subSamples[i].numBytesOfEncryptedData = numBytesOfEncryptedData[i];
-        }
-        return totalSize;
-    }
-
-    private ParcelFileDescriptor createSharedMemory(ByteBuffer buffer, String name)
-            throws RemoteException {
-        byte[] source = buffer.array();
-        if (source.length == 0) {
-            return null;
-        }
-        ParcelFileDescriptor fd = null;
-        try {
-            SharedMemory ashmem = SharedMemory.create(name == null ? "" : name, source.length);
-            ByteBuffer ptr = ashmem.mapReadWrite();
-            ptr.put(buffer);
-            ashmem.unmap(ptr);
-            fd = ashmem.getFdDup();
-            return fd;
-        } catch (ErrnoException | IOException e) {
-            throw new RemoteException(e);
-        }
-    }
+    };
 
     private class AidlDescrambler implements DescramblerWrapper {
 
         IDescrambler mAidlDescrambler;
 
-        AidlDescrambler(IDescrambler aidlDescrambler) {
-            mAidlDescrambler = aidlDescrambler;
+        AidlDescrambler(IDescrambler aidlDescrambler) throws Exception {
+            if (aidlDescrambler != null) {
+                mAidlDescrambler = aidlDescrambler;
+            } else {
+                throw new Exception("Descrambler could not be created");
+            }
         }
 
         @Override
@@ -125,47 +86,17 @@
                 @NonNull ByteBuffer dst,
                 @NonNull MediaCodec.CryptoInfo cryptoInfo)
                 throws RemoteException {
-            SubSample[] subSamples = new SubSample[cryptoInfo.numSubSamples];
-            long totalLength =
-                    getSubsampleInfo(
-                            cryptoInfo.numSubSamples,
-                            cryptoInfo.numBytesOfClearData,
-                            cryptoInfo.numBytesOfEncryptedData,
-                            subSamples);
-            SharedBuffer srcBuffer = new SharedBuffer();
-            DestinationBuffer dstBuffer;
-            srcBuffer.heapBase = new Ashmem();
-            srcBuffer.heapBase.fd = createSharedMemory(src, "Descrambler Source Buffer");
-            srcBuffer.heapBase.size = src.array().length;
-            if (dst == null) {
-                dstBuffer = DestinationBuffer.nonsecureMemory(srcBuffer);
-            } else {
-                ParcelFileDescriptor pfd =
-                        createSharedMemory(dst, "Descrambler Destination Buffer");
-                NativeHandle nh = new NativeHandle();
-                nh.fds = new ParcelFileDescriptor[] {pfd};
-                nh.ints = new int[] {1}; // Mark 1 since source buffer also uses it?
-                dstBuffer = DestinationBuffer.secureMemory(nh);
-            }
-            @ScramblingControl int control = cryptoInfo.key[0];
-
-            return mAidlDescrambler.descramble(
-                    (byte) control,
-                    subSamples,
-                    srcBuffer,
-                    src.position(),
-                    dstBuffer,
-                    dst.position());
+            throw new RemoteException("Not supported");
         }
 
         @Override
         public boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException {
-            return mAidlDescrambler.requiresSecureDecoderComponent(mime);
+            throw new RemoteException("Not supported");
         }
 
         @Override
         public void setMediaCasSession(byte[] sessionId) throws RemoteException {
-            mAidlDescrambler.setMediaCasSession(sessionId);
+            throw new RemoteException("Not supported");
         }
 
         @Override
@@ -178,9 +109,13 @@
 
         IDescramblerBase mHidlDescrambler;
 
-        HidlDescrambler(IDescramblerBase hidlDescrambler) {
-            mHidlDescrambler = hidlDescrambler;
-            native_setup(hidlDescrambler.asBinder());
+        HidlDescrambler(IDescramblerBase hidlDescrambler) throws Exception {
+            if (hidlDescrambler != null) {
+                mHidlDescrambler = hidlDescrambler;
+                native_setup(hidlDescrambler.asBinder());
+            } else {
+                throw new Exception("Descrambler could not be created");
+            }
         }
 
         @Override
@@ -267,10 +202,14 @@
             if (MediaCas.getService() != null) {
                 mIDescrambler =
                         new AidlDescrambler(MediaCas.getService().createDescrambler(CA_system_id));
+                mIsAidlHal = true;
             } else if (MediaCas.getServiceHidl() != null) {
                 mIDescrambler =
                         new HidlDescrambler(
                                 MediaCas.getServiceHidl().createDescrambler(CA_system_id));
+                mIsAidlHal = false;
+            } else {
+                throw new Exception("No CAS service found!");
             }
         } catch(Exception e) {
             Log.e(TAG, "Failed to create descrambler: " + e);
@@ -282,6 +221,16 @@
         }
     }
 
+    /**
+     * Check if the underlying HAL is AIDL. For CTS testing purpose.
+     *
+     * @hide
+     */
+    @TestApi
+    public boolean isAidlHal() {
+        return mIsAidlHal;
+    }
+
     IHwBinder getBinder() {
         validateInternalStates();
 
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 1022d93..c5202dc 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -108,133 +108,148 @@
     public static final int PLAYBACK_VOLUME_VARIABLE = 1;
 
     /** @hide */
-    @IntDef({
-            TYPE_UNKNOWN, TYPE_BUILTIN_SPEAKER, TYPE_WIRED_HEADSET,
-            TYPE_WIRED_HEADPHONES, TYPE_BLUETOOTH_A2DP, TYPE_HDMI, TYPE_USB_DEVICE,
-            TYPE_USB_ACCESSORY, TYPE_DOCK, TYPE_USB_HEADSET, TYPE_HEARING_AID, TYPE_BLE_HEADSET,
-            TYPE_REMOTE_TV, TYPE_REMOTE_SPEAKER, TYPE_GROUP})
+    @IntDef(
+            prefix = {"TYPE_"},
+            value = {
+                TYPE_UNKNOWN,
+                TYPE_BUILTIN_SPEAKER,
+                TYPE_WIRED_HEADSET,
+                TYPE_WIRED_HEADPHONES,
+                TYPE_BLUETOOTH_A2DP,
+                TYPE_HDMI,
+                TYPE_USB_DEVICE,
+                TYPE_USB_ACCESSORY,
+                TYPE_DOCK,
+                TYPE_USB_HEADSET,
+                TYPE_HEARING_AID,
+                TYPE_BLE_HEADSET,
+                TYPE_REMOTE_TV,
+                TYPE_REMOTE_SPEAKER,
+                TYPE_REMOTE_AUDIO_VIDEO_RECEIVER,
+                TYPE_GROUP
+            })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {}
 
     /**
-     * The default route type indicating the type is unknown.
+     * Indicates the route's type is unknown or undefined.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_UNKNOWN = 0;
 
     /**
-     * A route type describing the speaker system (i.e. a mono speaker or stereo speakers) built
-     * in a device.
+     * Indicates the route is the speaker system (i.e. a mono speaker or stereo speakers) built into
+     * the device.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_BUILTIN_SPEAKER = AudioDeviceInfo.TYPE_BUILTIN_SPEAKER;
 
     /**
-     * A route type describing a headset, which is the combination of a headphones and microphone.
+     * Indicates the route is a headset, which is the combination of a headphones and a microphone.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_WIRED_HEADSET = AudioDeviceInfo.TYPE_WIRED_HEADSET;
 
     /**
-     * A route type describing a pair of wired headphones.
+     * Indicates the route is a pair of wired headphones.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_WIRED_HEADPHONES = AudioDeviceInfo.TYPE_WIRED_HEADPHONES;
 
     /**
-     * A route type indicating the presentation of the media is happening
-     * on a bluetooth device such as a bluetooth speaker.
+     * Indicates the route is a bluetooth device, such as a bluetooth speaker or headphones.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_BLUETOOTH_A2DP = AudioDeviceInfo.TYPE_BLUETOOTH_A2DP;
 
     /**
-     * A route type describing an HDMI connection.
+     * Indicates the route is an HDMI connection.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_HDMI = AudioDeviceInfo.TYPE_HDMI;
 
     /**
-     * A route type describing a USB audio device.
+     * Indicates the route is a USB audio device.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_USB_DEVICE = AudioDeviceInfo.TYPE_USB_DEVICE;
 
     /**
-     * A route type describing a USB audio device in accessory mode.
+     * Indicates the route is a USB audio device in accessory mode.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_USB_ACCESSORY = AudioDeviceInfo.TYPE_USB_ACCESSORY;
 
     /**
-     * A route type describing the audio device associated with a dock.
+     * Indicates the route is the audio device associated with a dock.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_DOCK = AudioDeviceInfo.TYPE_DOCK;
 
     /**
-     * A device type describing a USB audio headset.
+     * Indicates the route is a USB audio headset.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_USB_HEADSET = AudioDeviceInfo.TYPE_USB_HEADSET;
 
     /**
-     * A route type describing a Hearing Aid.
+     * Indicates the route is a hearing aid.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_HEARING_AID = AudioDeviceInfo.TYPE_HEARING_AID;
 
     /**
-     * A route type describing a BLE HEADSET.
+     * Indicates the route is a Bluetooth Low Energy (BLE) HEADSET.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_BLE_HEADSET = AudioDeviceInfo.TYPE_BLE_HEADSET;
 
     /**
-     * A route type indicating the presentation of the media is happening on a TV.
+     * Indicates the route is a remote TV.
+     *
+     * <p>A remote device uses a routing protocol managed by the application, as opposed to the
+     * routing being done by the system.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_REMOTE_TV = 1001;
 
     /**
-     * A route type indicating the presentation of the media is happening on a speaker.
+     * Indicates the route is a remote speaker.
+     *
+     * <p>A remote device uses a routing protocol managed by the application, as opposed to the
+     * routing being done by the system.
      *
      * @see #getType
-     * @hide
      */
     public static final int TYPE_REMOTE_SPEAKER = 1002;
 
     /**
-     * A route type indicating the presentation of the media is happening on multiple devices.
+     * Indicates the route is a remote Audio/Video Receiver (AVR).
+     *
+     * <p>A remote device uses a routing protocol managed by the application, as opposed to the
+     * routing being done by the system.
      *
      * @see #getType
-     * @hide
+     */
+    public static final int TYPE_REMOTE_AUDIO_VIDEO_RECEIVER = 1003;
+
+    /**
+     * Indicates the route is a group of devices.
+     *
+     * @see #getType
      */
     public static final int TYPE_GROUP = 2000;
 
@@ -436,16 +451,23 @@
     }
 
     /**
-     * Gets the type of this route.
+     * Returns the type of this route.
      *
-     * @return The type of this route:
-     * {@link #TYPE_UNKNOWN},
-     * {@link #TYPE_BUILTIN_SPEAKER}, {@link #TYPE_WIRED_HEADSET}, {@link #TYPE_WIRED_HEADPHONES},
-     * {@link #TYPE_BLUETOOTH_A2DP}, {@link #TYPE_HDMI}, {@link #TYPE_DOCK},
-     * {@Link #TYPE_USB_DEVICE}, {@link #TYPE_USB_ACCESSORY}, {@link #TYPE_USB_HEADSET}
-     * {@link #TYPE_HEARING_AID},
-     * {@link #TYPE_REMOTE_TV}, {@link #TYPE_REMOTE_SPEAKER}, {@link #TYPE_GROUP}.
-     * @hide
+     * @see #TYPE_UNKNOWN
+     * @see #TYPE_BUILTIN_SPEAKER
+     * @see #TYPE_WIRED_HEADSET
+     * @see #TYPE_WIRED_HEADPHONES
+     * @see #TYPE_BLUETOOTH_A2DP
+     * @see #TYPE_HDMI
+     * @see #TYPE_DOCK
+     * @see #TYPE_USB_DEVICE
+     * @see #TYPE_USB_ACCESSORY
+     * @see #TYPE_USB_HEADSET
+     * @see #TYPE_HEARING_AID
+     * @see #TYPE_REMOTE_TV
+     * @see #TYPE_REMOTE_SPEAKER
+     * @see #TYPE_REMOTE_AUDIO_VIDEO_RECEIVER
+     * @see #TYPE_GROUP
      */
     @Type
     public int getType() {
@@ -657,6 +679,7 @@
         pw.println(indent + "mId=" + mId);
         pw.println(indent + "mName=" + mName);
         pw.println(indent + "mFeatures=" + mFeatures);
+        pw.println(indent + "mType=" + getDeviceTypeString(mType));
         pw.println(indent + "mIsSystem=" + mIsSystem);
         pw.println(indent + "mIconUri=" + mIconUri);
         pw.println(indent + "mDescription=" + mDescription);
@@ -787,6 +810,42 @@
         dest.writeString8Array(mAllowedPackages.toArray(new String[0]));
     }
 
+    private static String getDeviceTypeString(@Type int deviceType) {
+        switch (deviceType) {
+            case TYPE_BUILTIN_SPEAKER:
+                return "BUILTIN_SPEAKER";
+            case TYPE_WIRED_HEADSET:
+                return "WIRED_HEADSET";
+            case TYPE_WIRED_HEADPHONES:
+                return "WIRED_HEADPHONES";
+            case TYPE_BLUETOOTH_A2DP:
+                return "BLUETOOTH_A2DP";
+            case TYPE_HDMI:
+                return "HDMI";
+            case TYPE_DOCK:
+                return "DOCK";
+            case TYPE_USB_DEVICE:
+                return "USB_DEVICE";
+            case TYPE_USB_ACCESSORY:
+                return "USB_ACCESSORY";
+            case TYPE_USB_HEADSET:
+                return "USB_HEADSET";
+            case TYPE_HEARING_AID:
+                return "HEARING_AID";
+            case TYPE_REMOTE_TV:
+                return "REMOTE_TV";
+            case TYPE_REMOTE_SPEAKER:
+                return "REMOTE_SPEAKER";
+            case TYPE_REMOTE_AUDIO_VIDEO_RECEIVER:
+                return "REMOTE_AUDIO_VIDEO_RECEIVER";
+            case TYPE_GROUP:
+                return "GROUP";
+            case TYPE_UNKNOWN:
+            default:
+                return TextUtils.formatSimple("UNKNOWN(%d)", deviceType);
+        }
+    }
+
     /**
      * Builder for {@link MediaRoute2Info media route info}.
      */
@@ -932,7 +991,8 @@
 
         /**
          * Sets the route's type.
-         * @hide
+         *
+         * @see MediaRoute2Info#getType()
          */
         @NonNull
         public Builder setType(@Type int type) {
@@ -1086,8 +1146,16 @@
         }
 
         /**
-         * Sets the visibility of this route to public. This is the default
-         * visibility for routes that are public to all other apps.
+         * Sets the visibility of this route to public.
+         *
+         * <p>By default, unless you call {@link #setVisibilityRestricted}, the new route will be
+         * public.
+         *
+         * <p>Public routes are visible to any application with a matching {@link
+         * RouteDiscoveryPreference#getPreferredFeatures feature}.
+         *
+         * <p>Calls to this method override previous calls to {@link #setVisibilityPublic} and
+         * {@link #setVisibilityRestricted}.
          */
         @NonNull
         public Builder setVisibilityPublic() {
@@ -1097,8 +1165,16 @@
         }
 
         /**
-         * Sets the visibility of this route to restricted. This means that the
-         * route is only visible to a set of package name.
+         * Sets the visibility of this route to restricted.
+         *
+         * <p>Routes with restricted visibility are only visible to its publisher application and
+         * applications whose package name is included in the provided {@code allowedPackages} set
+         * with a matching {@link RouteDiscoveryPreference#getPreferredFeatures feature}.
+         *
+         * <p>Calls to this method override previous calls to {@link #setVisibilityPublic} and
+         * {@link #setVisibilityRestricted}.
+         *
+         * @see #setVisibilityPublic
          * @param allowedPackages set of package names which are allowed to see this route.
          */
         @NonNull
diff --git a/media/java/android/media/RouteListingPreference.java b/media/java/android/media/RouteListingPreference.java
index ff0a492..ee1f203 100644
--- a/media/java/android/media/RouteListingPreference.java
+++ b/media/java/android/media/RouteListingPreference.java
@@ -17,7 +17,6 @@
 package android.media;
 
 import android.annotation.IntDef;
-import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
@@ -45,14 +44,24 @@
 public final class RouteListingPreference implements Parcelable {
 
     /**
-     * {@link Intent} action for apps to take the user to a screen for transferring media playback
-     * to the route with the id provided by the extra with key {@link #EXTRA_ROUTE_ID}.
+     * {@link Intent} action that the system uses to take the user the app when the user selects an
+     * {@link Item} whose {@link Item#getSelectionBehavior() selection behavior} is {@link
+     * Item#SELECTION_BEHAVIOR_GO_TO_APP}.
+     *
+     * <p>The launched intent will identify the selected item using the extra identified by {@link
+     * #EXTRA_ROUTE_ID}.
+     *
+     * @see #getLinkedItemComponentName()
+     * @see Item#SELECTION_BEHAVIOR_GO_TO_APP
      */
     public static final String ACTION_TRANSFER_MEDIA = "android.media.action.TRANSFER_MEDIA";
 
     /**
      * {@link Intent} string extra key that contains the {@link Item#getRouteId() id} of the route
      * to transfer to, as part of an {@link #ACTION_TRANSFER_MEDIA} intent.
+     *
+     * @see #getLinkedItemComponentName()
+     * @see Item#SELECTION_BEHAVIOR_GO_TO_APP
      */
     public static final String EXTRA_ROUTE_ID = "android.media.extra.ROUTE_ID";
 
@@ -72,12 +81,12 @@
 
     @NonNull private final List<Item> mItems;
     private final boolean mUseSystemOrdering;
-    @Nullable private final ComponentName mInAppOnlyItemRoutingReceiver;
+    @Nullable private final ComponentName mLinkedItemComponentName;
 
     private RouteListingPreference(Builder builder) {
         mItems = builder.mItems;
         mUseSystemOrdering = builder.mUseSystemOrdering;
-        mInAppOnlyItemRoutingReceiver = builder.mInAppOnlyItemRoutingReceiver;
+        mLinkedItemComponentName = builder.mLinkedItemComponentName;
     }
 
     private RouteListingPreference(Parcel in) {
@@ -85,7 +94,7 @@
                 in.readParcelableList(new ArrayList<>(), Item.class.getClassLoader(), Item.class);
         mItems = List.copyOf(items);
         mUseSystemOrdering = in.readBoolean();
-        mInAppOnlyItemRoutingReceiver = ComponentName.readFromParcel(in);
+        mLinkedItemComponentName = ComponentName.readFromParcel(in);
     }
 
     /**
@@ -110,18 +119,20 @@
     }
 
     /**
-     * Returns a {@link ComponentName} for handling routes disabled via {@link
-     * Item#DISABLE_REASON_IN_APP_ONLY}, or null if the user needs to manually navigate to the app
-     * in order to route to select the corresponding routes.
+     * Returns a {@link ComponentName} for navigating to the application.
      *
-     * <p>If the user selects an {@link Item} disabled via {@link Item#DISABLE_REASON_IN_APP_ONLY},
-     * and this method returns a non-null {@link ComponentName}, the system takes the user back to
-     * the app by launching an intent to the returned {@link ComponentName}, using action {@link
-     * #ACTION_TRANSFER_MEDIA}, with the extra {@link #EXTRA_ROUTE_ID}.
+     * <p>Must not be null if any of the {@link #getItems() items} of this route listing preference
+     * has {@link Item#getSelectionBehavior() selection behavior} {@link
+     * Item#SELECTION_BEHAVIOR_GO_TO_APP}.
+     *
+     * <p>The system navigates to the application when the user selects {@link Item} with {@link
+     * Item#SELECTION_BEHAVIOR_GO_TO_APP} by launching an intent to the returned {@link
+     * ComponentName}, using action {@link #ACTION_TRANSFER_MEDIA}, with the extra {@link
+     * #EXTRA_ROUTE_ID}.
      */
     @Nullable
-    public ComponentName getInAppOnlyItemRoutingReceiver() {
-        return mInAppOnlyItemRoutingReceiver;
+    public ComponentName getLinkedItemComponentName() {
+        return mLinkedItemComponentName;
     }
 
     // RouteListingPreference Parcelable implementation.
@@ -135,7 +146,7 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeParcelableList(mItems, flags);
         dest.writeBoolean(mUseSystemOrdering);
-        ComponentName.writeToParcel(mInAppOnlyItemRoutingReceiver, dest);
+        ComponentName.writeToParcel(mLinkedItemComponentName, dest);
     }
 
     // Equals and hashCode.
@@ -151,13 +162,12 @@
         RouteListingPreference that = (RouteListingPreference) other;
         return mItems.equals(that.mItems)
                 && mUseSystemOrdering == that.mUseSystemOrdering
-                && Objects.equals(
-                        mInAppOnlyItemRoutingReceiver, that.mInAppOnlyItemRoutingReceiver);
+                && Objects.equals(mLinkedItemComponentName, that.mLinkedItemComponentName);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mItems, mUseSystemOrdering, mInAppOnlyItemRoutingReceiver);
+        return Objects.hash(mItems, mUseSystemOrdering, mLinkedItemComponentName);
     }
 
     /** Builder for {@link RouteListingPreference}. */
@@ -165,11 +175,12 @@
 
         private List<Item> mItems;
         private boolean mUseSystemOrdering;
-        private ComponentName mInAppOnlyItemRoutingReceiver;
+        private ComponentName mLinkedItemComponentName;
 
         /** Creates a new instance with default values (documented in the setters). */
         public Builder() {
             mItems = List.of();
+            mUseSystemOrdering = true;
         }
 
         /**
@@ -180,7 +191,6 @@
         @NonNull
         public Builder setItems(@NonNull List<Item> items) {
             mItems = List.copyOf(Objects.requireNonNull(items));
-            mUseSystemOrdering = true;
             return this;
         }
 
@@ -198,14 +208,13 @@
         }
 
         /**
-         * See {@link #getInAppOnlyItemRoutingReceiver()}.
+         * See {@link #getLinkedItemComponentName()}.
          *
          * <p>The default value is {@code null}.
          */
         @NonNull
-        public Builder setInAppOnlyItemRoutingReceiver(
-                @Nullable ComponentName inAppOnlyItemRoutingReceiver) {
-            mInAppOnlyItemRoutingReceiver = inAppOnlyItemRoutingReceiver;
+        public Builder setLinkedItemComponentName(@Nullable ComponentName linkedItemComponentName) {
+            mLinkedItemComponentName = linkedItemComponentName;
             return this;
         }
 
@@ -225,9 +234,32 @@
         /** @hide */
         @Retention(RetentionPolicy.SOURCE)
         @IntDef(
+                prefix = {"SELECTION_BEHAVIOR_"},
+                value = {
+                    SELECTION_BEHAVIOR_NONE,
+                    SELECTION_BEHAVIOR_TRANSFER,
+                    SELECTION_BEHAVIOR_GO_TO_APP
+                })
+        public @interface SelectionBehavior {}
+
+        /** The corresponding route is not selectable by the user. */
+        public static final int SELECTION_BEHAVIOR_NONE = 0;
+        /** If the user selects the corresponding route, the media transfers to the said route. */
+        public static final int SELECTION_BEHAVIOR_TRANSFER = 1;
+        /**
+         * If the user selects the corresponding route, the system takes the user to the
+         * application.
+         *
+         * <p>The system uses {@link #getLinkedItemComponentName()} in order to navigate to the app.
+         */
+        public static final int SELECTION_BEHAVIOR_GO_TO_APP = 2;
+
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(
                 flag = true,
                 prefix = {"FLAG_"},
-                value = {FLAG_ONGOING_SESSION, FLAG_SUGGESTED_ROUTE})
+                value = {FLAG_ONGOING_SESSION, FLAG_ONGOING_SESSION_MANAGED, FLAG_SUGGESTED})
         public @interface Flags {}
 
         /**
@@ -237,6 +269,22 @@
         public static final int FLAG_ONGOING_SESSION = 1;
 
         /**
+         * Signals that the ongoing session on the corresponding route is managed by the current
+         * user of the app.
+         *
+         * <p>The system can use this flag to provide visual indication that the route is not only
+         * hosting a session, but also that the user has ownership over said session.
+         *
+         * <p>This flag is ignored if {@link #FLAG_ONGOING_SESSION} is not set, or if the
+         * corresponding route is not currently selected.
+         *
+         * <p>This flag does not affect volume adjustment (see {@link VolumeProvider}, and {@link
+         * MediaRoute2Info#getVolumeHandling()}), or any aspect other than the visual representation
+         * of the corresponding item.
+         */
+        public static final int FLAG_ONGOING_SESSION_MANAGED = 1 << 1;
+
+        /**
          * The corresponding route is specially likely to be selected by the user.
          *
          * <p>A UI reflecting this preference may reserve a specific space for suggested routes,
@@ -244,53 +292,71 @@
          * number supported by the UI, the routes listed first in {@link
          * RouteListingPreference#getItems()} will take priority.
          */
-        public static final int FLAG_SUGGESTED_ROUTE = 1 << 1;
+        public static final int FLAG_SUGGESTED = 1 << 2;
 
         /** @hide */
         @Retention(RetentionPolicy.SOURCE)
         @IntDef(
-                prefix = {"DISABLE_REASON_"},
+                prefix = {"SUBTEXT_"},
                 value = {
-                    DISABLE_REASON_NONE,
-                    DISABLE_REASON_SUBSCRIPTION_REQUIRED,
-                    DISABLE_REASON_DOWNLOADED_CONTENT,
-                    DISABLE_REASON_AD,
-                    DISABLE_REASON_IN_APP_ONLY,
-                    DISABLE_REASON_CUSTOM
+                    SUBTEXT_NONE,
+                    SUBTEXT_ERROR_UNKNOWN,
+                    SUBTEXT_SUBSCRIPTION_REQUIRED,
+                    SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED,
+                    SUBTEXT_AD_ROUTING_DISALLOWED,
+                    SUBTEXT_DEVICE_LOW_POWER,
+                    SUBTEXT_UNAUTHORIZED,
+                    SUBTEXT_TRACK_UNSUPPORTED,
+                    SUBTEXT_CUSTOM
                 })
-        public @interface DisableReason {}
+        public @interface SubText {}
 
-        /** The corresponding route is available for routing. */
-        public static final int DISABLE_REASON_NONE = 0;
+        /** The corresponding route has no associated subtext. */
+        public static final int SUBTEXT_NONE = 0;
         /**
-         * The corresponding route requires a special subscription in order to be available for
-         * routing.
+         * The corresponding route's subtext must indicate that it is not available because of an
+         * unknown error.
          */
-        public static final int DISABLE_REASON_SUBSCRIPTION_REQUIRED = 1;
+        public static final int SUBTEXT_ERROR_UNKNOWN = 1;
         /**
-         * The corresponding route is not available because downloaded content cannot be routed to
-         * it.
+         * The corresponding route's subtext must indicate that it requires a special subscription
+         * in order to be available for routing.
          */
-        public static final int DISABLE_REASON_DOWNLOADED_CONTENT = 2;
-        /** The corresponding route is not available because an ad is in progress. */
-        public static final int DISABLE_REASON_AD = 3;
+        public static final int SUBTEXT_SUBSCRIPTION_REQUIRED = 2;
         /**
-         * The corresponding route is only available for routing from within the app.
-         *
-         * <p>The user may still select the corresponding route if the app provides an {@link
-         * #getInAppOnlyItemRoutingReceiver() in-app routing receiver}, in which case the system
-         * will take the user to the app.
+         * The corresponding route's subtext must indicate that downloaded content cannot be routed
+         * to it.
          */
-        public static final int DISABLE_REASON_IN_APP_ONLY = 4;
+        public static final int SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED = 3;
         /**
-         * The corresponding route is not available because of the reason described by {@link
-         * #getCustomDisableReasonMessage()}.
+         * The corresponding route's subtext must indicate that it is not available because an ad is
+         * in progress.
+         */
+        public static final int SUBTEXT_AD_ROUTING_DISALLOWED = 4;
+        /**
+         * The corresponding route's subtext must indicate that it is not available because the
+         * device is in low-power mode.
+         */
+        public static final int SUBTEXT_DEVICE_LOW_POWER = 5;
+        /**
+         * The corresponding route's subtext must indicate that it is not available because the user
+         * is not authorized to route to it.
+         */
+        public static final int SUBTEXT_UNAUTHORIZED = 6;
+        /**
+         * The corresponding route's subtext must indicate that it is not available because the
+         * device does not support the current media track.
+         */
+        public static final int SUBTEXT_TRACK_UNSUPPORTED = 7;
+        /**
+         * The corresponding route's subtext must be obtained from {@link
+         * #getCustomSubtextMessage()}.
          *
          * <p>Applications should strongly prefer one of the other disable reasons (for the full
-         * list, see {@link #getDisableReason()}) in order to guarantee correct localization and
-         * rendering across all form factors.
+         * list, see {@link #getSubText()}) in order to guarantee correct localization and rendering
+         * across all form factors.
          */
-        public static final int DISABLE_REASON_CUSTOM = 5;
+        public static final int SUBTEXT_CUSTOM = 10000;
 
         @NonNull
         public static final Creator<Item> CREATOR =
@@ -307,29 +373,29 @@
                 };
 
         @NonNull private final String mRouteId;
+        @SelectionBehavior private final int mSelectionBehavior;
         @Flags private final int mFlags;
-        @DisableReason private final int mDisableReason;
-        private final int mSessionParticipantCount;
-        @Nullable private final CharSequence mCustomDisableReasonMessage;
+        @SubText private final int mSubText;
+
+        @Nullable private final CharSequence mCustomSubtextMessage;
 
         private Item(@NonNull Builder builder) {
             mRouteId = builder.mRouteId;
+            mSelectionBehavior = builder.mSelectionBehavior;
             mFlags = builder.mFlags;
-            mDisableReason = builder.mDisableReason;
-            mSessionParticipantCount = builder.mSessionParticipantCount;
-            mCustomDisableReasonMessage = builder.mCustomDisableReasonMessage;
-            validateCustomDisableReasonMessage();
+            mSubText = builder.mSubText;
+            mCustomSubtextMessage = builder.mCustomSubtextMessage;
+            validateCustomMessageSubtext();
         }
 
         private Item(Parcel in) {
             mRouteId = in.readString();
             Preconditions.checkArgument(!TextUtils.isEmpty(mRouteId));
+            mSelectionBehavior = in.readInt();
             mFlags = in.readInt();
-            mDisableReason = in.readInt();
-            mSessionParticipantCount = in.readInt();
-            Preconditions.checkArgument(mSessionParticipantCount >= 0);
-            mCustomDisableReasonMessage = in.readCharSequence();
-            validateCustomDisableReasonMessage();
+            mSubText = in.readInt();
+            mCustomSubtextMessage = in.readCharSequence();
+            validateCustomMessageSubtext();
         }
 
         /**
@@ -343,10 +409,22 @@
         }
 
         /**
+         * Returns the behavior that the corresponding route has if the user selects it.
+         *
+         * @see #SELECTION_BEHAVIOR_NONE
+         * @see #SELECTION_BEHAVIOR_TRANSFER
+         * @see #SELECTION_BEHAVIOR_GO_TO_APP
+         */
+        public int getSelectionBehavior() {
+            return mSelectionBehavior;
+        }
+
+        /**
          * Returns the flags associated to the route that corresponds to this item.
          *
          * @see #FLAG_ONGOING_SESSION
-         * @see #FLAG_SUGGESTED_ROUTE
+         * @see #FLAG_ONGOING_SESSION_MANAGED
+         * @see #FLAG_SUGGESTED
          */
         @Flags
         public int getFlags() {
@@ -354,49 +432,46 @@
         }
 
         /**
-         * Returns the reason for the corresponding route to be disabled, or {@link
-         * #DISABLE_REASON_NONE} if the route is not disabled.
+         * Returns the type of subtext associated to this route.
          *
-         * @see #DISABLE_REASON_NONE
-         * @see #DISABLE_REASON_SUBSCRIPTION_REQUIRED
-         * @see #DISABLE_REASON_DOWNLOADED_CONTENT
-         * @see #DISABLE_REASON_AD
-         * @see #DISABLE_REASON_IN_APP_ONLY
-         * @see #DISABLE_REASON_CUSTOM
+         * <p>Subtext types other than {@link #SUBTEXT_NONE} and {@link #SUBTEXT_CUSTOM} must not
+         * have {@link #SELECTION_BEHAVIOR_TRANSFER}.
+         *
+         * <p>If this method returns {@link #SUBTEXT_CUSTOM}, then the subtext is obtained form
+         * {@link #getCustomSubtextMessage()}.
+         *
+         * @see #SUBTEXT_NONE,
+         * @see #SUBTEXT_ERROR_UNKNOWN,
+         * @see #SUBTEXT_SUBSCRIPTION_REQUIRED,
+         * @see #SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED,
+         * @see #SUBTEXT_AD_ROUTING_DISALLOWED,
+         * @see #SUBTEXT_DEVICE_LOW_POWER,
+         * @see #SUBTEXT_UNAUTHORIZED ,
+         * @see #SUBTEXT_TRACK_UNSUPPORTED,
+         * @see #SUBTEXT_CUSTOM
          */
-        @DisableReason
-        public int getDisableReason() {
-            return mDisableReason;
+        @SubText
+        public int getSubText() {
+            return mSubText;
         }
 
         /**
-         * Returns a non-negative number of participants in the ongoing session (if any) on the
-         * corresponding route.
+         * Returns a human-readable {@link CharSequence} providing the subtext for the corresponding
+         * route.
          *
-         * <p>The system ignores this value if zero, or if {@link #getFlags()} does not include
-         * {@link #FLAG_ONGOING_SESSION}.
-         */
-        public int getSessionParticipantCount() {
-            return mSessionParticipantCount;
-        }
-
-        /**
-         * Returns a human-readable {@link CharSequence} describing the reason for this route to be
-         * disabled. May be null if {@link #getDisableReason()} is not {@link
-         * #DISABLE_REASON_CUSTOM}.
-         *
-         * <p>This value is ignored if the {@link #getDisableReason() disable reason} for this item
-         * is not {@link #DISABLE_REASON_CUSTOM}.
+         * <p>This value is ignored if the {@link #getSubText() subtext} for this item is not {@link
+         * #SUBTEXT_CUSTOM}..
          *
          * <p>Applications must provide a localized message that matches the system's locale. See
          * {@link Locale#getDefault()}.
          *
-         * <p>This message is a hint for the system. Applications should strongly prefer one of the
-         * other disable reasons listed in {@link #getDisableReason()}.
+         * <p>Applications should avoid using custom messages (and instead use one of non-custom
+         * subtexts listed in {@link #getSubText()} in order to guarantee correct visual
+         * representation and localization on all form factors.
          */
         @Nullable
-        public CharSequence getCustomDisableReasonMessage() {
-            return mCustomDisableReasonMessage;
+        public CharSequence getCustomSubtextMessage() {
+            return mCustomSubtextMessage;
         }
 
         // Item Parcelable implementation.
@@ -409,10 +484,10 @@
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
             dest.writeString(mRouteId);
+            dest.writeInt(mSelectionBehavior);
             dest.writeInt(mFlags);
-            dest.writeInt(mDisableReason);
-            dest.writeInt(mSessionParticipantCount);
-            dest.writeCharSequence(mCustomDisableReasonMessage);
+            dest.writeInt(mSubText);
+            dest.writeCharSequence(mCustomSubtextMessage);
         }
 
         // Equals and hashCode.
@@ -427,40 +502,36 @@
             }
             Item item = (Item) other;
             return mRouteId.equals(item.mRouteId)
+                    && mSelectionBehavior == item.mSelectionBehavior
                     && mFlags == item.mFlags
-                    && mDisableReason == item.mDisableReason
-                    && mSessionParticipantCount == item.mSessionParticipantCount
-                    && TextUtils.equals(
-                            mCustomDisableReasonMessage, item.mCustomDisableReasonMessage);
+                    && mSubText == item.mSubText
+                    && TextUtils.equals(mCustomSubtextMessage, item.mCustomSubtextMessage);
         }
 
         @Override
         public int hashCode() {
             return Objects.hash(
-                    mRouteId,
-                    mFlags,
-                    mDisableReason,
-                    mSessionParticipantCount,
-                    mCustomDisableReasonMessage);
+                    mRouteId, mSelectionBehavior, mFlags, mSubText, mCustomSubtextMessage);
         }
 
-        private void validateCustomDisableReasonMessage() {
-            if (mDisableReason == DISABLE_REASON_CUSTOM) {
-                Preconditions.checkArgument(
-                        !TextUtils.isEmpty(mCustomDisableReasonMessage),
-                        "customDisableReasonMessage must not be null or empty if disable reason is"
-                                + " DISABLE_REASON_CUSTOM.");
-            }
+        // Internal methods.
+
+        private void validateCustomMessageSubtext() {
+            Preconditions.checkArgument(
+                    mSubText != SUBTEXT_CUSTOM || mCustomSubtextMessage != null,
+                    "The custom subtext message cannot be null if subtext is SUBTEXT_CUSTOM.");
         }
 
+        // Internal classes.
+
         /** Builder for {@link Item}. */
         public static final class Builder {
 
             private final String mRouteId;
+            private int mSelectionBehavior;
             private int mFlags;
-            private int mDisableReason;
-            private int mSessionParticipantCount;
-            private CharSequence mCustomDisableReasonMessage;
+            private int mSubText;
+            private CharSequence mCustomSubtextMessage;
 
             /**
              * Constructor.
@@ -470,39 +541,51 @@
             public Builder(@NonNull String routeId) {
                 Preconditions.checkArgument(!TextUtils.isEmpty(routeId));
                 mRouteId = routeId;
-                mDisableReason = DISABLE_REASON_NONE;
+                mSelectionBehavior = SELECTION_BEHAVIOR_TRANSFER;
+                mSubText = SUBTEXT_NONE;
             }
 
-            /** See {@link Item#getFlags()}. */
+            /**
+             * See {@link Item#getSelectionBehavior()}.
+             *
+             * <p>The default value is {@link #ACTION_TRANSFER_MEDIA}.
+             */
+            @NonNull
+            public Builder setSelectionBehavior(int selectionBehavior) {
+                mSelectionBehavior = selectionBehavior;
+                return this;
+            }
+
+            /**
+             * See {@link Item#getFlags()}.
+             *
+             * <p>The default value is zero (no flags).
+             */
             @NonNull
             public Builder setFlags(int flags) {
                 mFlags = flags;
                 return this;
             }
 
-            /** See {@link Item#getDisableReason()}. */
+            /**
+             * See {@link Item#getSubText()}.
+             *
+             * <p>The default value is {@link #SUBTEXT_NONE}.
+             */
             @NonNull
-            public Builder setDisableReason(int disableReason) {
-                mDisableReason = disableReason;
+            public Builder setSubText(int subText) {
+                mSubText = subText;
                 return this;
             }
 
-            /** See {@link Item#getSessionParticipantCount()}. */
+            /**
+             * See {@link Item#getCustomSubtextMessage()}.
+             *
+             * <p>The default value is {@code null}.
+             */
             @NonNull
-            public Builder setSessionParticipantCount(
-                    @IntRange(from = 0) int sessionParticipantCount) {
-                Preconditions.checkArgument(
-                        sessionParticipantCount >= 0,
-                        "sessionParticipantCount must be non-negative.");
-                mSessionParticipantCount = sessionParticipantCount;
-                return this;
-            }
-
-            /** See {@link Item#getCustomDisableReasonMessage()}. */
-            @NonNull
-            public Builder setCustomDisableReasonMessage(
-                    @Nullable CharSequence customDisableReasonMessage) {
-                mCustomDisableReasonMessage = customDisableReasonMessage;
+            public Builder setCustomSubtextMessage(@Nullable CharSequence customSubtextMessage) {
+                mCustomSubtextMessage = customSubtextMessage;
                 return this;
             }
 
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 985ac3c..9e9012e 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -253,23 +253,19 @@
         public void onStop() { }
 
         /**
-         * Indicates the width and height of the captured region in pixels. Called immediately after
-         * capture begins to provide the app with accurate sizing for the stream. Also called
-         * when the region captured in this MediaProjection session is resized.
+         * Invoked immediately after capture begins or when the size of the captured region changes,
+         * providing the accurate sizing for the streamed capture.
          * <p>
          * The given width and height, in pixels, corresponds to the same width and height that
-         * would be returned from {@link android.view.WindowMetrics#getBounds()}
+         * would be returned from {@link android.view.WindowMetrics#getBounds()} of the captured
+         * region.
          * </p>
          * <p>
-         * Without the application resizing the {@link VirtualDisplay} (returned from
-         * {@code MediaProjection#createVirtualDisplay}) and output {@link Surface} (provided
-         * to {@code MediaProjection#createVirtualDisplay}), the captured stream will have
-         * letterboxing (black bars) around the recorded content to make up for the
-         * difference in aspect ratio.
-         * </p>
-         * <p>
-         * The application can prevent the letterboxing by overriding this method, and
-         * updating the size of both the {@link VirtualDisplay} and output {@link Surface}:
+         * If the recorded content has a different aspect ratio from either the
+         * {@link VirtualDisplay} or output {@link Surface}, the captured stream has letterboxing
+         * (black bars) around the recorded content. The application can avoid the letterboxing
+         * around the recorded content by updating the size of both the {@link VirtualDisplay} and
+         * output {@link Surface}:
          * </p>
          *
          * <pre>
@@ -293,27 +289,29 @@
         public void onCapturedContentResize(int width, int height) { }
 
         /**
-         * Indicates the visibility of the captured region has changed. Called immediately after
-         * capture begins with the initial visibility state, and when visibility changes. Provides
-         * the app with accurate state for presenting its own UI. The application can take advantage
-         * of this by showing or hiding the captured content, based on if the captured region is
-         * currently visible to the user.
+         * Invoked immediately after capture begins or when the visibility of the captured region
+         * changes, providing the current visibility of the captured region.
+         * <p>
+         * Applications can take advantage of this callback by showing or hiding the captured
+         * content from the output {@link Surface}, based on if the captured region is currently
+         * visible to the user.
+         * </p>
          * <p>
          * For example, if the user elected to capture a single app (from the activity shown from
-         * {@link MediaProjectionManager#createScreenCaptureIntent()}), the callback may be
-         * triggered for the following reasons:
+         * {@link MediaProjectionManager#createScreenCaptureIntent()}), the following scenarios
+         * trigger the callback:
          * <ul>
          *     <li>
-         *         The captured region may become visible ({@code isVisible} with value
-         *         {@code true}), because the captured app is at least partially visible. This may
-         *         happen if the captured app was previously covered by another app. The other app
-         *         moves to show at least some portion of the captured app.
+         *         The captured region is visible ({@code isVisible} with value {@code true}),
+         *         because the captured app is at least partially visible. This may happen if the
+         *         user moves the covering app to show at least some portion of the captured app
+         *         (e.g. the user has multiple apps visible in a multi-window mode such as split
+         *         screen).
          *     </li>
          *     <li>
-         *         The captured region may become invisible ({@code isVisible} with value
-         *         {@code false}) if it is entirely hidden. This may happen if the captured app is
-         *         entirely covered by another app, or the user navigates away from the captured
-         *         app.
+         *         The captured region is invisible ({@code isVisible} with value {@code false}) if
+         *         it is entirely hidden. This may happen if another app entirely covers the
+         *         captured app, or the user navigates away from the captured app.
          *     </li>
          * </ul>
          * </p>
diff --git a/media/java/android/media/projection/TEST_MAPPING b/media/java/android/media/projection/TEST_MAPPING
index a792498..4324930 100644
--- a/media/java/android/media/projection/TEST_MAPPING
+++ b/media/java/android/media/projection/TEST_MAPPING
@@ -13,6 +13,20 @@
           "exclude-annotation": "org.junit.Ignore"
         }
       ]
+    },
+    {
+      "name": "CtsMediaProjectionTestCases",
+      "options": [
+        {
+          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
     }
   ]
 }
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index d9c8a24..1a3e54d 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -25,6 +25,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
 import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
 import android.media.AudioFormat;
@@ -49,9 +50,11 @@
  * not voice-based. The voice-based recognition models should utilize the {@link
  * VoiceInteractionService} instead. Access to this class is protected by a permission
  * granted only to system or privileged apps.
+ * @deprecated use {@link SoundTriggerManager} directly
  *
  * @hide
  */
+@Deprecated
 @SystemApi
 public final class SoundTriggerDetector {
     private static final boolean DBG = false;
@@ -66,7 +69,7 @@
     private final Object mLock = new Object();
 
     private final ISoundTriggerSession mSoundTriggerSession;
-    private final UUID mSoundModelId;
+    private final GenericSoundModel mSoundModel;
     private final Callback mCallback;
     private final Handler mHandler;
     private final RecognitionCallback mRecognitionCallback;
@@ -276,10 +279,11 @@
      * This class should be constructed by the {@link SoundTriggerManager}.
      * @hide
      */
-    SoundTriggerDetector(ISoundTriggerSession soundTriggerSession, UUID soundModelId,
+    SoundTriggerDetector(ISoundTriggerSession soundTriggerSession,
+            @NonNull GenericSoundModel soundModel,
             @NonNull Callback callback, @Nullable Handler handler) {
         mSoundTriggerSession = soundTriggerSession;
-        mSoundModelId = soundModelId;
+        mSoundModel = soundModel;
         mCallback = callback;
         if (handler == null) {
             mHandler = new MyHandler();
@@ -292,8 +296,10 @@
     /**
      * Starts recognition on the associated sound model. Result is indicated via the
      * {@link Callback}.
+     * @deprecated use {@link SoundTriggerManager} directly
      * @return Indicates whether the call succeeded or not.
      */
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
         if (DBG) {
@@ -317,7 +323,7 @@
 
         int status;
         try {
-            status = mSoundTriggerSession.startRecognition(new ParcelUuid(mSoundModelId),
+            status = mSoundTriggerSession.startRecognition(mSoundModel,
                     mRecognitionCallback, new RecognitionConfig(captureTriggerAudio,
                             allowMultipleTriggers, null, null, audioCapabilities),
                     runInBatterySaver);
@@ -329,12 +335,14 @@
 
     /**
      * Stops recognition for the associated model.
+     * @deprecated use {@link SoundTriggerManager} directly
      */
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public boolean stopRecognition() {
         int status = STATUS_OK;
         try {
-            status = mSoundTriggerSession.stopRecognition(new ParcelUuid(mSoundModelId),
+            status = mSoundTriggerSession.stopRecognition(new ParcelUuid(mSoundModel.getUuid()),
                     mRecognitionCallback);
         } catch (RemoteException e) {
             return false;
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index f60c708..c473a01 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -104,8 +104,11 @@
 
     /**
      * Updates the given sound trigger model.
+     * @deprecated replace with {@link #loadSoundModel}
+     * SoundTriggerService model database will be removed
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @Deprecated
     public void updateModel(Model model) {
         try {
             mSoundTriggerSession.updateSoundModel(model.getGenericSoundModel());
@@ -119,9 +122,11 @@
      *
      * @param soundModelId UUID associated with a loaded model
      * @return {@link SoundTriggerManager.Model} associated with UUID soundModelId
+     * @deprecated SoundTriggerService model database will be removed
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     @Nullable
+    @Deprecated
     public Model getModel(UUID soundModelId) {
         try {
             GenericSoundModel model =
@@ -138,8 +143,11 @@
 
     /**
      * Deletes the sound model represented by the provided UUID.
+     * @deprecated replace with {@link #unloadSoundModel}
+     * SoundTriggerService model database will be removed
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @Deprecated
     public void deleteModel(UUID soundModelId) {
         try {
             mSoundTriggerSession.deleteSoundModel(new ParcelUuid(soundModelId));
@@ -159,8 +167,12 @@
      * @param handler The Handler to use for the callback operations. A null value will use the
      * current thread's Looper.
      * @return Instance of {@link SoundTriggerDetector} or null on error.
+     * @deprecated Use {@link SoundTriggerManager} directly. SoundTriggerDetector does not
+     * ensure callbacks are delivered, and its model state is prone to mismatch.
+     * It will be removed in a subsequent release.
      */
     @Nullable
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId,
             @NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) {
@@ -172,11 +184,16 @@
         if (oldInstance != null) {
             // Shutdown old instance.
         }
-        SoundTriggerDetector newInstance = new SoundTriggerDetector(mSoundTriggerSession,
-                soundModelId, callback, handler);
-        mReceiverInstanceMap.put(soundModelId, newInstance);
-        return newInstance;
-    }
+        try {
+            SoundTriggerDetector newInstance = new SoundTriggerDetector(mSoundTriggerSession,
+                    mSoundTriggerSession.getSoundModel(new ParcelUuid(soundModelId)),
+                    callback, handler);
+            mReceiverInstanceMap.put(soundModelId, newInstance);
+            return newInstance;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+   }
 
     /**
      * Class captures the data and fields that represent a non-keyphrase sound model. Use the
diff --git a/media/java/android/media/tv/AdBuffer.java b/media/java/android/media/tv/AdBuffer.java
index ed44508..230d763 100644
--- a/media/java/android/media/tv/AdBuffer.java
+++ b/media/java/android/media/tv/AdBuffer.java
@@ -24,9 +24,8 @@
 
 /**
  * Buffer for advertisement data.
- * @hide
  */
-public class AdBuffer implements Parcelable {
+public final class AdBuffer implements Parcelable {
     private final int mId;
     @NonNull
     private final String mMimeType;
@@ -60,6 +59,8 @@
 
     /**
      * Gets corresponding AD request ID.
+     *
+     * @return The ID of the ad request
      */
     public int getId() {
         return mId;
@@ -67,6 +68,8 @@
 
     /**
      * Gets the mime type of the data.
+     *
+     * @return The mime type of the data.
      */
     @NonNull
     public String getMimeType() {
@@ -74,7 +77,17 @@
     }
 
     /**
-     * Gets the shared memory which stores the data.
+     * Gets the {@link SharedMemory} which stores the data.
+     *
+     * <p> Information on how the data in this buffer is formatted can be found using
+     * {@link AdRequest#getMetadata()}
+     * <p> This data lives in a {@link SharedMemory} instance because of the
+     * potentially large amount of data needed to store the ad. This optimizes the
+     * data communication between the ad data source and the service responsible for
+     * its display.
+     *
+     * @see SharedMemory#create(String, int)
+     * @return The {@link SharedMemory} that stores the data for this ad buffer.
      */
     @NonNull
     public SharedMemory getSharedMemory() {
@@ -82,28 +95,38 @@
     }
 
     /**
-     * Gets the offset of the buffer.
+     * Gets the offset into the shared memory to begin mapping.
+     *
+     * @see SharedMemory#map(int, int, int)
+     * @return The offset of this ad buffer in the shared memory in bytes.
      */
     public int getOffset() {
         return mOffset;
     }
 
     /**
-     * Gets the data length.
+     * Gets the data length of this ad buffer.
+     *
+     * @return The data length of this ad buffer in bytes.
      */
     public int getLength() {
         return mLength;
     }
 
     /**
-     * Gets the presentation time in microseconds.
+     * Gets the presentation time.
+     *
+     * @return The presentation time in microseconds.
      */
     public long getPresentationTimeUs() {
         return mPresentationTimeUs;
     }
 
     /**
-     * Gets the flags.
+     * Gets the buffer flags for this ad buffer.
+     *
+     * @see android.media.MediaCodec
+     * @return The buffer flags for this ad buffer.
      */
     @BufferFlag
     public int getFlags() {
diff --git a/media/java/android/media/tv/AdRequest.java b/media/java/android/media/tv/AdRequest.java
index 60dfc5e..d8cddfc 100644
--- a/media/java/android/media/tv/AdRequest.java
+++ b/media/java/android/media/tv/AdRequest.java
@@ -79,7 +79,6 @@
                 mediaFileType, metadata);
     }
 
-    /** @hide */
     public AdRequest(int id, @RequestType int requestType, @Nullable Uri uri, long startTime,
             long stopTime, long echoInterval, @NonNull Bundle metadata) {
         this(id, requestType, null, uri, startTime, stopTime, echoInterval, null, metadata);
@@ -153,7 +152,6 @@
      *
      * @return The URI of the AD media. Can be {@code null} for {@link #REQUEST_TYPE_STOP} or a file
      *         descriptor is used.
-     * @hide
      */
     @Nullable
     public Uri getUri() {
diff --git a/media/java/android/media/tv/AdResponse.java b/media/java/android/media/tv/AdResponse.java
index a15e8c1..7ec4eb2 100644
--- a/media/java/android/media/tv/AdResponse.java
+++ b/media/java/android/media/tv/AdResponse.java
@@ -43,7 +43,6 @@
     public static final int RESPONSE_TYPE_FINISHED = 2;
     public static final int RESPONSE_TYPE_STOPPED = 3;
     public static final int RESPONSE_TYPE_ERROR = 4;
-    /** @hide */
     public static final int RESPONSE_TYPE_BUFFERING = 5;
 
     public static final @NonNull Parcelable.Creator<AdResponse> CREATOR =
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index c4f60c3..c52cd59 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -52,6 +52,9 @@
     void onTimeShiftCurrentPositionChanged(long timeMs, int seq);
     void onAitInfoUpdated(in AitInfo aitInfo, int seq);
     void onSignalStrength(int stength, int seq);
+    void onCueingMessageAvailability(boolean available, int seq);
+    void onTimeShiftMode(int mode, int seq);
+    void onAvailableSpeeds(in float[] speeds, int seq);
     void onTvMessage(in String type, in Bundle data, int seq);
 
     void onTuned(in Uri channelUri, int seq);
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 746cfa2..e9aa321 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -99,6 +99,7 @@
     void timeShiftResume(in IBinder sessionToken, int userId);
     void timeShiftSeekTo(in IBinder sessionToken, long timeMs, int userId);
     void timeShiftSetPlaybackParams(in IBinder sessionToken, in PlaybackParams params, int userId);
+    void timeShiftSetMode(in IBinder sessionToken, int mode, int userId);
     void timeShiftEnablePositionTracking(in IBinder sessionToken, boolean enable, int userId);
 
     List<TunedInfo> getCurrentTunedInfos(int userId);
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index e6c09a9..82875e5 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -60,6 +60,7 @@
     void timeShiftResume();
     void timeShiftSeekTo(long timeMs);
     void timeShiftSetPlaybackParams(in PlaybackParams params);
+    void timeShiftSetMode(int mode);
     void timeShiftEnablePositionTracking(boolean enable);
 
     // For the recording session
diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index 0111f09..449c2d6 100644
--- a/media/java/android/media/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -49,6 +49,9 @@
     void onTimeShiftCurrentPositionChanged(long timeMs);
     void onAitInfoUpdated(in AitInfo aitInfo);
     void onSignalStrength(int strength);
+    void onCueingMessageAvailability(boolean available);
+    void onTimeShiftMode(int mode);
+    void onAvailableSpeeds(in float[] speeds);
 
     // For the recording session
     void onTuned(in Uri channelUri);
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 847762f..465b617 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -30,6 +30,7 @@
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
 import android.view.Surface;
+
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 
@@ -75,6 +76,8 @@
     private static final int DO_REQUEST_AD = 27;
     private static final int DO_NOTIFY_AD_BUFFER = 28;
     private static final int DO_SELECT_AUDIO_PRESENTATION = 29;
+    private static final int DO_TIME_SHIFT_SET_MODE = 30;
+    private static final int DO_SET_TV_MESSAGE_ENABLED = 31;
 
     private final boolean mIsRecordingSession;
     private final HandlerCaller mCaller;
@@ -218,6 +221,9 @@
                 mTvInputSessionImpl.timeShiftSetPlaybackParams((PlaybackParams) msg.obj);
                 break;
             }
+            case DO_TIME_SHIFT_SET_MODE: {
+                mTvInputSessionImpl.timeShiftSetMode((Integer) msg.obj);
+            }
             case DO_TIME_SHIFT_ENABLE_POSITION_TRACKING: {
                 mTvInputSessionImpl.timeShiftEnablePositionTracking((Boolean) msg.obj);
                 break;
@@ -258,6 +264,11 @@
                 mTvInputSessionImpl.setInteractiveAppNotificationEnabled((Boolean) msg.obj);
                 break;
             }
+            case DO_SET_TV_MESSAGE_ENABLED: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mTvInputSessionImpl.setTvMessageEnabled((String) args.arg1, (Boolean) args.arg2);
+                break;
+            }
             case DO_REQUEST_AD: {
                 mTvInputSessionImpl.requestAd((AdRequest) msg.obj);
                 break;
@@ -401,6 +412,11 @@
     }
 
     @Override
+    public void timeShiftSetMode(int mode) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_TIME_SHIFT_SET_MODE, mode));
+    }
+
+    @Override
     public void timeShiftEnablePositionTracking(boolean enable) {
         mCaller.executeOrSendMessage(mCaller.obtainMessageO(
                 DO_TIME_SHIFT_ENABLE_POSITION_TRACKING, enable));
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index a4e2212..de1b164 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -56,7 +56,9 @@
 import android.view.KeyEvent;
 import android.view.Surface;
 import android.view.View;
+
 import com.android.internal.util.Preconditions;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -131,18 +133,15 @@
             VIDEO_UNAVAILABLE_REASON_CAS_REBOOTING, VIDEO_UNAVAILABLE_REASON_CAS_UNKNOWN})
     public @interface VideoUnavailableReason {}
 
-    /**
-     * @hide
-     */
+    /** Indicates that this TV message contains watermarking data */
     public static final String TV_MESSAGE_TYPE_WATERMARK = "Watermark";
-    /**
-     * @hide
-     */
-    public static final String TV_MESSAGE_TYPE_ATSC_CC = "ATSC_CC";
+
+    /** Indicates that this TV message contains Closed Captioning data */
+    public static final String TV_MESSAGE_TYPE_CLOSED_CAPTION = "CC";
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @StringDef({TV_MESSAGE_TYPE_WATERMARK, TV_MESSAGE_TYPE_ATSC_CC})
+    @StringDef({TV_MESSAGE_TYPE_WATERMARK, TV_MESSAGE_TYPE_CLOSED_CAPTION})
     public @interface TvMessageType {}
 
     static final int VIDEO_UNAVAILABLE_REASON_START = 0;
@@ -309,6 +308,39 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = false, prefix = "TIME_SHIFT_MODE_", value = {
+            TIME_SHIFT_MODE_OFF,
+            TIME_SHIFT_MODE_LOCAL,
+            TIME_SHIFT_MODE_NETWORK,
+            TIME_SHIFT_MODE_AUTO})
+    public @interface TimeShiftMode {}
+    /**
+     * Time shift mode: off.
+     * <p>Time shift is disabled.
+     * @hide
+     */
+    public static final int TIME_SHIFT_MODE_OFF = 1;
+    /**
+     * Time shift mode: local.
+     * <p>Time shift is handle locally, using on-device data. E.g. playing a local file.
+     * @hide
+     */
+    public static final int TIME_SHIFT_MODE_LOCAL = 2;
+    /**
+     * Time shift mode: network.
+     * <p>Time shift is handle remotely via network. E.g. online streaming.
+     * @hide
+     */
+    public static final int TIME_SHIFT_MODE_NETWORK = 3;
+    /**
+     * Time shift mode: auto.
+     * <p>Time shift mode is handled automatically.
+     * @hide
+     */
+    public static final int TIME_SHIFT_MODE_AUTO = 4;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
     @IntDef({RECORDING_ERROR_UNKNOWN, RECORDING_ERROR_INSUFFICIENT_SPACE,
             RECORDING_ERROR_RESOURCE_BUSY})
     public @interface RecordingError {}
@@ -719,6 +751,36 @@
         }
 
         /**
+         * This is called when cueing message becomes available or unavailable.
+         * @param session A {@link TvInputManager.Session} associated with this callback.
+         * @param available The current availability of cueing message. {@code true} if cueing
+         *                  message is available; {@code false} if it becomes unavailable.
+         */
+        public void onCueingMessageAvailability(Session session, boolean available) {
+        }
+
+        /**
+         * This is called when time shift mode is set or updated.
+         * @param session A {@link TvInputManager.Session} associated with this callback.
+         * @param mode The current time shift mode. The value is one of the following:
+         * {@link TvInputManager#TIME_SHIFT_MODE_OFF}, {@link TvInputManager#TIME_SHIFT_MODE_LOCAL},
+         * {@link TvInputManager#TIME_SHIFT_MODE_NETWORK},
+         * {@link TvInputManager#TIME_SHIFT_MODE_AUTO}.
+         */
+        public void onTimeShiftMode(Session session, @TimeShiftMode int mode) {
+        }
+
+        /**
+         * Informs the app available speeds for time-shifting.
+         * @param session A {@link TvInputManager.Session} associated with this callback.
+         * @param speeds An ordered array of playback speeds, expressed as values relative to the
+         *               normal playback speed 1.0.
+         * @see PlaybackParams#getSpeed()
+         */
+        public void onAvailableSpeeds(Session session, float[] speeds) {
+        }
+
+        /**
          * This is called when the session has been tuned to the given channel.
          *
          * @param channelUri The URI of a channel.
@@ -727,11 +789,11 @@
         }
 
         /**
-         * This is called when the session receives a new Tv Message
+         * This is called when the session receives a new TV Message
          *
-         * @param type the type of {@link TvMessageType}
-         * @param data the raw data of the message
-         * @hide
+         * @param session A {@link TvInputManager.Session} associated with this callback.
+         * @param type The type of message received, such as {@link #TV_MESSAGE_TYPE_WATERMARK}
+         * @param data The raw data of the message
          */
         public void onTvMessage(Session session, @TvInputManager.TvMessageType String type,
                 Bundle data) {
@@ -972,6 +1034,33 @@
             });
         }
 
+        void postCueingMessageAvailability(final boolean available) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onCueingMessageAvailability(mSession, available);
+                }
+            });
+        }
+
+        void postTimeShiftMode(final int mode) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onTimeShiftMode(mSession, mode);
+                }
+            });
+        }
+
+        void postAvailableSpeeds(float[] speeds) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onAvailableSpeeds(mSession, speeds);
+                }
+            });
+        }
+
         void postTuned(final Uri channelUri) {
             mHandler.post(new Runnable() {
                 @Override
@@ -1475,6 +1564,42 @@
             }
 
             @Override
+            public void onCueingMessageAvailability(boolean available, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postCueingMessageAvailability(available);
+                }
+            }
+
+            @Override
+            public void onTimeShiftMode(int mode, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postTimeShiftMode(mode);
+                }
+            }
+
+            @Override
+            public void onAvailableSpeeds(float[] speeds, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postAvailableSpeeds(speeds);
+                }
+            }
+
+            @Override
             public void onTuned(Uri channelUri, int seq) {
                 synchronized (mSessionCallbackRecordMap) {
                     SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
@@ -3058,6 +3183,27 @@
         }
 
         /**
+         * Sets time shift mode.
+         *
+         * @param mode The time shift mode. The value is one of the following:
+         * {@link TvInputManager#TIME_SHIFT_MODE_OFF}, {@link TvInputManager#TIME_SHIFT_MODE_LOCAL},
+         * {@link TvInputManager#TIME_SHIFT_MODE_NETWORK},
+         * {@link TvInputManager#TIME_SHIFT_MODE_AUTO}.
+         * @hide
+         */
+        void timeShiftSetMode(@TimeShiftMode int mode) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.timeShiftSetMode(mToken, mode, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
          * Enable/disable position tracking.
          *
          * @param enable {@code true} to enable tracking, {@code false} otherwise.
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index b769757..000ed3b 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -59,11 +59,14 @@
 import android.view.WindowManager;
 import android.view.accessibility.CaptioningManager;
 import android.widget.FrameLayout;
+
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.Preconditions;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -1002,9 +1005,10 @@
 
         /**
          * Notifies the advertisement buffer is consumed.
-         * @hide
+         *
+         * @param buffer the {@link AdBuffer} that was consumed.
          */
-        public void notifyAdBufferConsumed(AdBuffer buffer) {
+        public void notifyAdBufferConsumed(@NonNull AdBuffer buffer) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
                 @Override
@@ -1021,6 +1025,31 @@
             });
         }
 
+        /**
+         * Sends the raw data from the received TV message as well as the type of message received.
+         *
+         * @param type The of message that was sent, such as
+         * {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
+         * @param data The data sent with the message.
+         */
+        public void notifyTvMessage(@NonNull @TvInputManager.TvMessageType String type,
+                @NonNull Bundle data) {
+            executeOrPostRunnableOnMainThread(new Runnable() {
+                @MainThread
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) Log.d(TAG, "notifyTvMessage");
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onTvMessage(type, data);
+                        }
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in notifyTvMessage", e);
+                    }
+                }
+            });
+        }
+
         private void notifyTimeShiftStartPositionChanged(final long timeMs) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -1082,6 +1111,59 @@
         }
 
         /**
+         * Informs the app that the time shift mode is set or updated.
+         *
+         * @param mode The current time shift mode. The value is one of the following:
+         * {@link TvInputManager#TIME_SHIFT_MODE_OFF}, {@link TvInputManager#TIME_SHIFT_MODE_LOCAL},
+         * {@link TvInputManager#TIME_SHIFT_MODE_NETWORK},
+         * {@link TvInputManager#TIME_SHIFT_MODE_AUTO}.
+         * @hide
+         */
+        public void notifyTimeShiftMode(@android.media.tv.TvInputManager.TimeShiftMode int mode) {
+            executeOrPostRunnableOnMainThread(new Runnable() {
+                @MainThread
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) Log.d(TAG, "notifyTimeShiftMode");
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onTimeShiftMode(mode);
+                        }
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in notifyTimeShiftMode", e);
+                    }
+                }
+            });
+        }
+
+        /**
+         * Informs the app available speeds for time-shifting.
+         * <p>This should be called when time-shifting is enabled.
+         *
+         * @param speeds An ordered array of playback speeds, expressed as values relative to the
+         *               normal playback speed 1.0.
+         * @see PlaybackParams#getSpeed()
+         * @hide
+         */
+        public void notifyAvailableSpeeds(@NonNull float[] speeds) {
+            executeOrPostRunnableOnMainThread(new Runnable() {
+                @MainThread
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) Log.d(TAG, "notifyAvailableSpeeds");
+                        if (mSessionCallback != null) {
+                            Arrays.sort(speeds);
+                            mSessionCallback.onAvailableSpeeds(speeds);
+                        }
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in notifyAvailableSpeeds", e);
+                    }
+                }
+            });
+        }
+
+        /**
          * Notifies signal strength.
          */
         public void notifySignalStrength(@TvInputManager.SignalStrength final int strength) {
@@ -1102,6 +1184,33 @@
         }
 
         /**
+         * Informs the application that cueing message is available or unavailable.
+         *
+         * <p>The cueing message is used for digital program insertion, based on the standard
+         * ANSI/SCTE 35 2019r1.
+         *
+         * @param available {@code true} if cueing message is available; {@code false} if it becomes
+         *                  unavailable.
+         * @hide
+         */
+        public void notifyCueingMessageAvailability(boolean available) {
+            executeOrPostRunnableOnMainThread(new Runnable() {
+                @MainThread
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) Log.d(TAG, "notifyCueingMessageAvailability");
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onCueingMessageAvailability(available);
+                        }
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in notifyCueingMessageAvailability", e);
+                    }
+                }
+            });
+        }
+
+        /**
          * Assigns a size and position to the surface passed in {@link #onSetSurface}. The position
          * is relative to the overlay view that sits on top of this surface.
          *
@@ -1237,10 +1346,11 @@
         }
 
         /**
-         * Called when advertisement buffer is ready.
-         * @hide
+         * Called when an advertisement buffer is ready for playback.
+         *
+         * @param buffer The {@link AdBuffer} that became ready for playback.
          */
-        public void onAdBuffer(AdBuffer buffer) {
+        public void onAdBuffer(@NonNull AdBuffer buffer) {
         }
 
         /**
@@ -1373,6 +1483,17 @@
         }
 
         /**
+         * Called when the application enables or disables the detection of the specified message
+         * type.
+         * @param type The {@link TvInputManager.TvMessageType} of message that was sent.
+         * @param enabled {@code true} if TV message detection is enabled,
+         *                {@code false} otherwise.
+         */
+        public void onSetTvMessageEnabled(@NonNull @TvInputManager.TvMessageType String type,
+                boolean enabled){
+        }
+
+        /**
          * Called when the application requests to play a given recorded TV program.
          *
          * @param recordedProgramUri The URI of a recorded TV program.
@@ -1448,6 +1569,18 @@
         }
 
         /**
+         * Called when the application sets time shift mode.
+         *
+         * @param mode The time shift mode. The value is one of the following:
+         * {@link TvInputManager#TIME_SHIFT_MODE_OFF}, {@link TvInputManager#TIME_SHIFT_MODE_LOCAL},
+         * {@link TvInputManager#TIME_SHIFT_MODE_NETWORK},
+         * {@link TvInputManager#TIME_SHIFT_MODE_AUTO}.
+         * @hide
+         */
+        public void onTimeShiftSetMode(@android.media.tv.TvInputManager.TimeShiftMode int mode) {
+        }
+
+        /**
          * Returns the start position for time shifting, in milliseconds since the epoch.
          * Returns {@link TvInputManager#TIME_SHIFT_INVALID_TIME} if the position is unknown at the
          * moment.
@@ -1712,6 +1845,13 @@
         }
 
         /**
+         * Calls {@link #onSetTvMessageEnabled(String, boolean)}.
+         */
+        void setTvMessageEnabled(String type, boolean enabled) {
+            onSetTvMessageEnabled(type, enabled);
+        }
+
+        /**
          * Calls {@link #onAppPrivateCommand}.
          */
         void appPrivateCommand(String action, Bundle data) {
@@ -1853,6 +1993,13 @@
         }
 
         /**
+         * Calls {@link #onTimeShiftSetMode}.
+         */
+        void timeShiftSetMode(int mode) {
+            onTimeShiftSetMode(mode);
+        }
+
+        /**
          * Enable/disable position tracking.
          *
          * @param enable {@code true} to enable tracking, {@code false} otherwise.
@@ -2174,27 +2321,6 @@
         }
 
         /**
-         * Informs the application of the raw data from the TV message.
-         * @param type The {@link TvInputManager.TvMessageType} of message that was sent.
-         * @param data The data sent with the message.
-         * @hide
-         */
-        public void notifyTvMessage(@TvInputManager.TvMessageType String type, Bundle data) {
-        }
-
-        /**
-         * Called when the application enables or disables the detection of the specified message
-         * type.
-         * @param type The {@link TvInputManager.TvMessageType} of message that was sent.
-         * @param enabled {@code true} if you want to enable TV message detecting
-         *                {@code false} otherwise.
-         * @hide
-         */
-        public void onSetTvMessageEnabled(@TvInputManager.TvMessageType String type,
-                boolean enabled) {
-        }
-
-        /**
          * Called when the application requests to tune to a given channel for TV program recording.
          *
          * <p>The application may call this method before starting or after stopping recording, but
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 87d7a0b..cdeef2b 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -21,6 +21,7 @@
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.media.tv.TvInputManager;
+import android.media.tv.interactive.TvInteractiveAppView;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -53,6 +54,8 @@
     private boolean mIsPaused;
     private boolean mIsRecordingStopping;
     private final Queue<Pair<String, Bundle>> mPendingAppPrivateCommands = new ArrayDeque<>();
+    private TvInteractiveAppView mTvIAppView;
+    private String mRecordingId;
 
     /**
      * Creates a new TvRecordingClient object.
@@ -70,6 +73,26 @@
     }
 
     /**
+     * Sets the related {@link TvInteractiveAppView} instance so the interactive app service can be
+     * notified for recording events.
+     *
+     * @param view The related {@link TvInteractiveAppView} instance that is linked to this TV
+     *             recording client. {@code null} to unlink the view.
+     * @param recordingId The ID of the recording which is assigned by applications. {@code null} is
+     *                    valid only when the TvInteractiveAppView parameter is null.
+     * @hide
+     */
+    public void setTvInteractiveAppView(
+            @Nullable TvInteractiveAppView view, @Nullable String recordingId) {
+        if (view != null && recordingId == null) {
+            throw new IllegalArgumentException(
+                    "null recordingId is allowed only when the view is null");
+        }
+        mTvIAppView = view;
+        mRecordingId = view == null ? null : recordingId;
+    }
+
+    /**
      * Tunes to a given channel for TV program recording. The first tune request will create a new
      * recording session for the corresponding TV input and establish a connection between the
      * application and the session. If recording has already started in the current recording
@@ -468,6 +491,9 @@
                 if (mCallback != null) {
                     mCallback.onConnectionFailed(mInputId);
                 }
+                if (mTvIAppView != null) {
+                    mTvIAppView.notifyRecordingConnectionFailed(mRecordingId, mInputId);
+                }
             }
         }
 
@@ -485,7 +511,12 @@
                 return;
             }
             mIsTuned = true;
-            mCallback.onTuned(channelUri);
+            if (mCallback != null) {
+                mCallback.onTuned(channelUri);
+            }
+            if (mTvIAppView != null) {
+                mTvIAppView.notifyRecordingTuned(mRecordingId, channelUri);
+            }
         }
 
         @Override
@@ -506,6 +537,9 @@
             if (mCallback != null) {
                 mCallback.onDisconnected(mInputId);
             }
+            if (mTvIAppView != null) {
+                mTvIAppView.notifyRecordingDisconnected(mRecordingId, mInputId);
+            }
         }
 
         @Override
@@ -524,7 +558,12 @@
             mIsRecordingStarted = false;
             mIsPaused = false;
             mIsRecordingStopping = false;
-            mCallback.onRecordingStopped(recordedProgramUri);
+            if (mCallback != null) {
+                mCallback.onRecordingStopped(recordedProgramUri);
+            }
+            if (mTvIAppView != null) {
+                mTvIAppView.notifyRecordingStopped(mRecordingId);
+            }
         }
 
         @Override
@@ -536,7 +575,12 @@
                 Log.w(TAG, "onError - session not created");
                 return;
             }
-            mCallback.onError(error);
+            if (mCallback != null) {
+                mCallback.onError(error);
+            }
+            if (mTvIAppView != null) {
+                mTvIAppView.notifyRecordingError(mRecordingId, error);
+            }
         }
 
         @Override
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index c7a63ac..372fa6d 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -53,9 +53,11 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewRootImpl;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Queue;
 
@@ -625,6 +627,21 @@
     }
 
     /**
+     * Sets time shift mode.
+     *
+     * @param mode The time shift mode. The value is one of the following:
+     * {@link TvInputManager#TIME_SHIFT_MODE_OFF}, {@link TvInputManager#TIME_SHIFT_MODE_LOCAL},
+     * {@link TvInputManager#TIME_SHIFT_MODE_NETWORK},
+     * {@link TvInputManager#TIME_SHIFT_MODE_AUTO}.
+     * @hide
+     */
+    public void timeShiftSetMode(@android.media.tv.TvInputManager.TimeShiftMode int mode) {
+        if (mSession != null) {
+            mSession.timeShiftSetMode(mode);
+        }
+    }
+
+    /**
      * Sets the callback to be invoked when the time shift position is changed.
      *
      * @param callback The callback to receive time shift position changes. A value of {@code null}
@@ -705,14 +722,14 @@
     }
 
     /**
-     * Enables or disables TV message detecting in the streams of bound TV input.
+     * Enables or disables TV message detection in the stream of the bound TV input.
      *
      * @param type The type of {@link android.media.tv.TvInputManager.TvMessageType}
-     * @param enabled {@code true} if you want to enable TV message detecting
+     * @param enabled {@code true} if you want to enable TV message detection
      *                {@code false} otherwise.
-     * @hide
      */
-    public void setTvMessageEnabled(@TvInputManager.TvMessageType String type, boolean enabled) {
+    public void setTvMessageEnabled(@NonNull @TvInputManager.TvMessageType String type,
+            boolean enabled) {
     }
 
     @Override
@@ -1171,6 +1188,43 @@
         }
 
         /**
+         * This is called when cueing message becomes available or unavailable.
+         *
+         * @param inputId The ID of the TV input bound to this view.
+         * @param available The current availability of cueing message. {@code true} if cueing
+         *                  message is available; {@code false} if it becomes unavailable.
+         * @hide
+         */
+        public void onCueingMessageAvailability(@NonNull String inputId, boolean available) {
+        }
+
+        /**
+         * This is called when time shift mode is set or updated.
+         *
+         * @param inputId The ID of the TV input bound to this view.
+         * @param mode The current time shift mode. The value is one of the following:
+         * {@link TvInputManager#TIME_SHIFT_MODE_OFF}, {@link TvInputManager#TIME_SHIFT_MODE_LOCAL},
+         * {@link TvInputManager#TIME_SHIFT_MODE_NETWORK},
+         * {@link TvInputManager#TIME_SHIFT_MODE_AUTO}.
+         * @hide
+         */
+        public void onTimeShiftMode(
+                @NonNull String inputId, @TvInputManager.TimeShiftMode int mode) {
+        }
+
+        /**
+         * This is called when time-shifting is enabled to inform the available speeds.
+         *
+         * @param inputId The ID of the TV input bound to this view.
+         * @param speeds An ordered array of playback speeds, expressed as values relative to the
+         *               normal playback speed 1.0.
+         * @see PlaybackParams#getSpeed()
+         * @hide
+         */
+        public void onAvailableSpeeds(@NonNull String inputId, float[] speeds) {
+        }
+
+        /**
          * This is called when the session has been tuned to the given channel.
          *
          * @param channelUri The URI of a channel.
@@ -1179,14 +1233,14 @@
         }
 
         /**
-         * This is called when the session has been tuned to the given channel.
+         * This is called when a new TV Message has been received.
          *
+         * @param inputId The ID of the TV input bound to this view.
          * @param type The type of {@link android.media.tv.TvInputManager.TvMessageType}
          * @param data The raw data of the message
-         * @hide
          */
-        public void onTvMessage(@NonNull String inputId, @TvInputManager.TvMessageType String type,
-                Bundle data) {
+        public void onTvMessage(@NonNull String inputId,
+                @NonNull @TvInputManager.TvMessageType String type, @NonNull Bundle data) {
         }
     }
 
@@ -1545,6 +1599,48 @@
         }
 
         @Override
+        public void onCueingMessageAvailability(Session session, boolean available) {
+            if (DEBUG) {
+                Log.d(TAG, "onCueingMessageAvailability(available=" + available + ")");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onCueingMessageAvailability - session not created");
+                return;
+            }
+            if (mCallback != null) {
+                mCallback.onCueingMessageAvailability(mInputId, available);
+            }
+        }
+
+        @Override
+        public void onTimeShiftMode(Session session, int mode) {
+            if (DEBUG) {
+                Log.d(TAG, "onTimeShiftMode(mode=" + mode + ")");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onTimeShiftMode - session not created");
+                return;
+            }
+            if (mCallback != null) {
+                mCallback.onTimeShiftMode(mInputId, mode);
+            }
+        }
+
+        @Override
+        public void onAvailableSpeeds(Session session, float[] speeds) {
+            if (DEBUG) {
+                Log.d(TAG, "onAvailableSpeeds(speeds=" + Arrays.toString(speeds) + ")");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onAvailableSpeeds - session not created");
+                return;
+            }
+            if (mCallback != null) {
+                mCallback.onAvailableSpeeds(mInputId, speeds);
+            }
+        }
+
+        @Override
         public void onTuned(Session session, Uri channelUri) {
             if (DEBUG) {
                 Log.d(TAG, "onTuned(channelUri=" + channelUri + ")");
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
index ad9312f..aac2d61 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
@@ -49,8 +49,14 @@
     void onRequestStreamVolume(int seq);
     void onRequestTrackInfoList(int seq);
     void onRequestCurrentTvInputId(int seq);
+    void onRequestTimeShiftMode(int seq);
+    void onRequestAvailableSpeeds(int seq);
     void onRequestStartRecording(in Uri programUri, int seq);
     void onRequestStopRecording(in String recordingId, int seq);
+    void onRequestScheduleRecording(in String inputId, in Uri channelUri, in Uri programUri,
+            in Bundle params, int seq);
+    void onRequestScheduleRecording2(in String inputId, in Uri channelUri, long start,
+            long duration, int repeat, in Bundle params, int seq);
     void onSetTvRecordingInfo(in String recordingId, in TvRecordingInfo recordingInfo, int seq);
     void onRequestTvRecordingInfo(in String recordingId, int seq);
     void onRequestTvRecordingInfoList(in int type, int seq);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
index c0723f7..e362af2 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
@@ -54,6 +54,8 @@
     void sendStreamVolume(in IBinder sessionToken, float volume, int userId);
     void sendTrackInfoList(in IBinder sessionToken, in List<TvTrackInfo> tracks, int userId);
     void sendCurrentTvInputId(in IBinder sessionToken, in String inputId, int userId);
+    void sendTimeShiftMode(in IBinder sessionToken, int mode, int userId);
+    void sendAvailableSpeeds(in IBinder sessionToken, in float[] speeds, int userId);
     void sendSigningResult(in IBinder sessionToken, in String signingId, in byte[] result,
             int userId);
     void sendTvRecordingInfo(in IBinder sessionToken, in TvRecordingInfo recordingInfo, int userId);
@@ -68,6 +70,16 @@
             in IBinder sessionToken, in String inputId, long timeMs, int userId);
     void notifyTimeShiftCurrentPositionChanged(
             in IBinder sessionToken, in String inputId, long timeMs, int userId);
+    void notifyRecordingConnectionFailed(
+            in IBinder sessionToken, in String recordingId, in String inputId, int userId);
+    void notifyRecordingDisconnected(
+            in IBinder sessionToken, in String recordingId, in String inputId, int userId);
+    void notifyRecordingTuned(
+            in IBinder sessionToken, in String recordingId, in Uri channelUri, int userId);
+    void notifyRecordingError(
+            in IBinder sessionToken, in String recordingId, int err, int userId);
+    void notifyRecordingScheduled(
+            in IBinder sessionToken, in String recordingId, in String requestId, int userId);
     void createSession(in ITvInteractiveAppClient client, in String iAppServiceId, int type,
             int seq, int userId);
     void releaseSession(in IBinder sessionToken, int userId);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
index 9ae9ca7..8d77141 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
@@ -46,6 +46,8 @@
     void sendStreamVolume(float volume);
     void sendTrackInfoList(in List<TvTrackInfo> tracks);
     void sendCurrentTvInputId(in String inputId);
+    void sendTimeShiftMode(int mode);
+    void sendAvailableSpeeds(in float[] speeds);
     void sendSigningResult(in String signingId, in byte[] result);
     void sendTvRecordingInfo(in TvRecordingInfo recordingInfo);
     void sendTvRecordingInfoList(in List<TvRecordingInfo> recordingInfoList);
@@ -54,6 +56,11 @@
     void notifyTimeShiftStatusChanged(in String inputId, int status);
     void notifyTimeShiftStartPositionChanged(in String inputId, long timeMs);
     void notifyTimeShiftCurrentPositionChanged(in String inputId, long timeMs);
+    void notifyRecordingConnectionFailed(in String recordingId, in String inputId);
+    void notifyRecordingDisconnected(in String recordingId, in String inputId);
+    void notifyRecordingTuned(in String recordingId, in Uri channelUri);
+    void notifyRecordingError(in String recordingId, int err);
+    void notifyRecordingScheduled(in String recordingId, in String requestId);
     void release();
     void notifyTuned(in Uri channelUri);
     void notifyTrackSelected(int type, in String trackId);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
index d84affd..b71f23c 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
@@ -48,8 +48,14 @@
     void onRequestStreamVolume();
     void onRequestTrackInfoList();
     void onRequestCurrentTvInputId();
+    void onRequestTimeShiftMode();
+    void onRequestAvailableSpeeds();
     void onRequestStartRecording(in Uri programUri);
     void onRequestStopRecording(in String recordingId);
+    void onRequestScheduleRecording(in String inputId, in Uri channelUri, in Uri programUri,
+            in Bundle params);
+    void onRequestScheduleRecording2(in String inputId, in Uri channelUri, long start,
+            long duration, int repeat, in Bundle params);
     void onSetTvRecordingInfo(in String recordingId, in TvRecordingInfo recordingInfo);
     void onRequestTvRecordingInfo(in String recordingId);
     void onRequestTvRecordingInfoList(in int type);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
index 8a23e65..f009cea 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
@@ -95,6 +95,13 @@
     private static final int DO_NOTIFY_TIME_SHIFT_START_POSITION_CHANGED = 38;
     private static final int DO_NOTIFY_TIME_SHIFT_CURRENT_POSITION_CHANGED = 39;
     private static final int DO_SEND_CURRENT_VIDEO_BOUNDS = 40;
+    private static final int DO_NOTIFY_RECORDING_CONNECTION_FAILED = 41;
+    private static final int DO_NOTIFY_RECORDING_DISCONNECTED = 42;
+    private static final int DO_NOTIFY_RECORDING_TUNED = 43;
+    private static final int DO_NOTIFY_RECORDING_ERROR = 44;
+    private static final int DO_NOTIFY_RECORDING_SCHEDULED = 45;
+    private static final int DO_SEND_TIME_SHIFT_MODE = 46;
+    private static final int DO_SEND_AVAILABLE_SPEEDS = 47;
 
     private final HandlerCaller mCaller;
     private Session mSessionImpl;
@@ -182,6 +189,14 @@
                 mSessionImpl.sendCurrentTvInputId((String) msg.obj);
                 break;
             }
+            case DO_SEND_TIME_SHIFT_MODE: {
+                mSessionImpl.sendTimeShiftMode((Integer) msg.obj);
+                break;
+            }
+            case DO_SEND_AVAILABLE_SPEEDS: {
+                mSessionImpl.sendAvailableSpeeds((float[]) msg.obj);
+                break;
+            }
             case DO_SEND_RECORDING_INFO: {
                 mSessionImpl.sendTvRecordingInfo((TvRecordingInfo) msg.obj);
                 break;
@@ -311,6 +326,37 @@
                 args.recycle();
                 break;
             }
+            case DO_NOTIFY_RECORDING_CONNECTION_FAILED: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.notifyRecordingConnectionFailed(
+                        (String) args.arg1, (String) args.arg2);
+                args.recycle();
+                break;
+            }
+            case DO_NOTIFY_RECORDING_DISCONNECTED: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.notifyRecordingDisconnected((String) args.arg1, (String) args.arg2);
+                args.recycle();
+                break;
+            }
+            case DO_NOTIFY_RECORDING_TUNED: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.notifyRecordingTuned((String) args.arg1, (Uri) args.arg2);
+                args.recycle();
+                break;
+            }
+            case DO_NOTIFY_RECORDING_ERROR: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.notifyRecordingError((String) args.arg1, (Integer) args.arg2);
+                args.recycle();
+                break;
+            }
+            case DO_NOTIFY_RECORDING_SCHEDULED: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.notifyRecordingScheduled((String) args.arg1, (String) args.arg2);
+                args.recycle();
+                break;
+            }
             default: {
                 Log.w(TAG, "Unhandled message code: " + msg.what);
                 break;
@@ -396,6 +442,18 @@
     }
 
     @Override
+    public void sendTimeShiftMode(int mode) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageI(DO_SEND_TIME_SHIFT_MODE, mode));
+    }
+
+    @Override
+    public void sendAvailableSpeeds(float[] speeds) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_SEND_AVAILABLE_SPEEDS, speeds));
+    }
+
+    @Override
     public void sendTvRecordingInfo(@Nullable TvRecordingInfo recordingInfo) {
         mCaller.executeOrSendMessage(
                 mCaller.obtainMessageO(DO_SEND_RECORDING_INFO, recordingInfo));
@@ -463,7 +521,7 @@
     @Override
     public void notifyTvMessage(String type, Bundle data) {
         mCaller.executeOrSendMessage(
-                mCaller.obtainMessageOO(DO_NOTIFY_TRACK_SELECTED, type, data));
+                mCaller.obtainMessageOO(DO_NOTIFY_TV_MESSAGE, type, data));
     }
 
     @Override
@@ -509,6 +567,36 @@
     }
 
     @Override
+    public void notifyRecordingConnectionFailed(String recordingId, String inputId) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOO(
+                DO_NOTIFY_RECORDING_CONNECTION_FAILED, recordingId, inputId));
+    }
+
+    @Override
+    public void notifyRecordingDisconnected(String recordingId, String inputId) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOO(
+                DO_NOTIFY_RECORDING_DISCONNECTED, recordingId, inputId));
+    }
+
+    @Override
+    public void notifyRecordingTuned(String recordingId, Uri channelUri) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOO(
+                DO_NOTIFY_RECORDING_TUNED, recordingId, channelUri));
+    }
+
+    @Override
+    public void notifyRecordingError(String recordingId, int err) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOO(
+                DO_NOTIFY_RECORDING_ERROR, recordingId, err));
+    }
+
+    @Override
+    public void notifyRecordingScheduled(String recordingId, String requestId) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOO(
+                DO_NOTIFY_RECORDING_SCHEDULED, recordingId, recordingId));
+    }
+
+    @Override
     public void setSurface(Surface surface) {
         mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_SURFACE, surface));
     }
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
index fd3c29b..c88c8d4 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
@@ -33,6 +33,7 @@
 import android.media.tv.TvInputManager;
 import android.media.tv.TvRecordingInfo;
 import android.media.tv.TvTrackInfo;
+import android.media.tv.interactive.TvInteractiveAppService.Session;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -517,6 +518,30 @@
             }
 
             @Override
+            public void onRequestTimeShiftMode(int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postRequestTimeShiftMode();
+                }
+            }
+
+            @Override
+            public void onRequestAvailableSpeeds(int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postRequestAvailableSpeeds();
+                }
+            }
+
+            @Override
             public void onRequestStartRecording(Uri programUri, int seq) {
                 synchronized (mSessionCallbackRecordMap) {
                     SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
@@ -541,6 +566,33 @@
             }
 
             @Override
+            public void onRequestScheduleRecording(String inputId, Uri channelUri, Uri programUri,
+                    Bundle params, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postRequestScheduleRecording(inputId, channelUri, programUri, params);
+                }
+            }
+
+            @Override
+            public void onRequestScheduleRecording2(String inputId, Uri channelUri, long startTime,
+                    long duration, int repeatDays, Bundle params, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postRequestScheduleRecording(
+                            inputId, channelUri, startTime, duration, repeatDays, params);
+                }
+            }
+
+            @Override
             public void onSetTvRecordingInfo(String recordingId, TvRecordingInfo recordingInfo,
                     int seq) {
                 synchronized (mSessionCallbackRecordMap) {
@@ -1168,6 +1220,30 @@
             }
         }
 
+        void sendTimeShiftMode(int mode) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.sendTimeShiftMode(mToken, mode, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        void sendAvailableSpeeds(float[] speeds) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.sendAvailableSpeeds(mToken, speeds, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
         void sendTvRecordingInfo(@Nullable TvRecordingInfo recordingInfo) {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
@@ -1289,6 +1365,66 @@
             }
         }
 
+        void notifyRecordingConnectionFailed(@NonNull String recordingId, @NonNull String inputId) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.notifyRecordingConnectionFailed(mToken, recordingId, inputId, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        void notifyRecordingDisconnected(@NonNull String recordingId, @NonNull String inputId) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.notifyRecordingDisconnected(mToken, recordingId, inputId, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        void notifyRecordingTuned(@NonNull String recordingId, @NonNull Uri channelUri) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.notifyRecordingTuned(mToken, recordingId, channelUri, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        void notifyRecordingError(@NonNull String recordingId, int err) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.notifyRecordingError(mToken, recordingId, err, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        void notifyRecordingScheduled(@NonNull String recordingId, @Nullable String requestId) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.notifyRecordingScheduled(mToken, recordingId, recordingId, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
         /**
          * Sets the {@link android.view.Surface} for this session.
          *
@@ -1976,6 +2112,24 @@
             });
         }
 
+        void postRequestTimeShiftMode() {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onRequestTimeShiftMode(mSession);
+                }
+            });
+        }
+
+        void postRequestAvailableSpeeds() {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onRequestAvailableSpeeds(mSession);
+                }
+            });
+        }
+
         void postRequestStartRecording(Uri programUri) {
             mHandler.post(new Runnable() {
                 @Override
@@ -1994,6 +2148,28 @@
             });
         }
 
+        void postRequestScheduleRecording(String inputId, Uri channelUri, Uri programUri,
+                Bundle params) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onRequestScheduleRecording(
+                            mSession, inputId, channelUri, programUri, params);
+                }
+            });
+        }
+
+        void postRequestScheduleRecording(String inputId, Uri channelUri, long startTime,
+                long duration, int repeatDays, Bundle params) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onRequestScheduleRecording(
+                            mSession, inputId, channelUri, startTime, duration, repeatDays, params);
+                }
+            });
+        }
+
         void postRequestSigning(String id, String algorithm, String alias, byte[] data) {
             mHandler.post(new Runnable() {
                 @Override
@@ -2144,7 +2320,7 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#SetVideoBounds} is called.
+         * This is called when {@link TvInteractiveAppService.Session#setVideoBounds} is called.
          *
          * @param session A {@link TvInteractiveAppManager.Session} associated with this callback.
          */
@@ -2152,7 +2328,7 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestCurrentVideoBounds} is
+         * This is called when {@link TvInteractiveAppService.Session#requestCurrentVideoBounds} is
          * called.
          *
          * @param session A {@link TvInteractiveAppManager.Session} associated with this callback.
@@ -2161,7 +2337,7 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestCurrentChannelUri} is
+         * This is called when {@link TvInteractiveAppService.Session#requestCurrentChannelUri} is
          * called.
          *
          * @param session A {@link TvInteractiveAppManager.Session} associated with this callback.
@@ -2170,7 +2346,7 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestCurrentChannelLcn} is
+         * This is called when {@link TvInteractiveAppService.Session#requestCurrentChannelLcn} is
          * called.
          *
          * @param session A {@link TvInteractiveAppManager.Session} associated with this callback.
@@ -2179,7 +2355,7 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestStreamVolume} is
+         * This is called when {@link TvInteractiveAppService.Session#requestStreamVolume} is
          * called.
          *
          * @param session A {@link TvInteractiveAppManager.Session} associated with this callback.
@@ -2188,7 +2364,7 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestTrackInfoList} is
+         * This is called when {@link TvInteractiveAppService.Session#requestTrackInfoList} is
          * called.
          *
          * @param session A {@link TvInteractiveAppManager.Session} associated with this callback.
@@ -2197,7 +2373,7 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestCurrentTvInputId} is
+         * This is called when {@link TvInteractiveAppService.Session#requestCurrentTvInputId} is
          * called.
          *
          * @param session A {@link TvInteractiveAppService.Session} associated with this callback.
@@ -2206,7 +2382,25 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestStartRecording} is
+         * This is called when {@link TvInteractiveAppService.Session#requestTimeShiftMode()} is
+         * called.
+         *
+         * @param session A {@link TvInteractiveAppService.Session} associated with this callback.
+         */
+        public void onRequestTimeShiftMode(Session session) {
+        }
+
+        /**
+         * This is called when {@link TvInteractiveAppService.Session#requestAvailableSpeeds()} is
+         * called.
+         *
+         * @param session A {@link TvInteractiveAppService.Session} associated with this callback.
+         */
+        public void onRequestAvailableSpeeds(Session session) {
+        }
+
+        /**
+         * This is called when {@link TvInteractiveAppService.Session#requestStartRecording} is
          * called.
          *
          * @param session A {@link TvInteractiveAppService.Session} associated with this callback.
@@ -2216,8 +2410,8 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestStopRecording} is
-         * called.
+         * This is called when {@link TvInteractiveAppService.Session#requestStopRecording(String)}
+         * is called.
          *
          * @param session A {@link TvInteractiveAppService.Session} associated with this callback.
          * @param recordingId The recordingId of the recording to be stopped.
@@ -2227,6 +2421,47 @@
 
         /**
          * This is called when
+         * {@link TvInteractiveAppService.Session#requestScheduleRecording(String, Uri, Uri, Bundle)}
+         * is called.
+         *
+         * @param session A {@link TvInteractiveAppService.Session} associated with this callback.
+         * @param inputId The ID of the TV input for the given channel.
+         * @param channelUri The URI of a channel to be recorded.
+         * @param programUri The URI of the TV program to be recorded.
+         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
+         * @see android.media.tv.TvRecordingClient#tune(String, Uri, Bundle)
+         * @see android.media.tv.TvRecordingClient#startRecording(Uri)
+         */
+        public void onRequestScheduleRecording(Session session, @NonNull String inputId,
+                @NonNull Uri channelUri, @NonNull Uri programUri, @NonNull Bundle params) {
+        }
+
+        /**
+         * This is called when
+         * {@link TvInteractiveAppService.Session#requestScheduleRecording(String, Uri, long, long, int, Bundle)}
+         * is called.
+         *
+         * @param session A {@link TvInteractiveAppService.Session} associated with this callback.
+         * @param inputId The ID of the TV input for the given channel.
+         * @param channelUri The URI of a channel to be recorded.
+         * @param startTime The start time of the recording in milliseconds since epoch.
+         * @param duration The duration of the recording in milliseconds.
+         * @param repeatDays The repeated days. 0 if not repeated.
+         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
+         * @see android.media.tv.TvRecordingClient#tune(String, Uri, Bundle)
+         * @see android.media.tv.TvRecordingClient#startRecording(Uri)
+         */
+        public void onRequestScheduleRecording(Session session, @NonNull String inputId,
+                @NonNull Uri channelUri, long startTime, long duration, int repeatDays,
+                @NonNull Bundle params) {
+        }
+
+        /**
+         * This is called when
          * {@link TvInteractiveAppService.Session#setTvRecordingInfo(String, TvRecordingInfo)} is
          * called.
          *
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index d1777cc..999ff0d 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -224,6 +224,7 @@
             TIME_SHIFT_COMMAND_TYPE_RESUME,
             TIME_SHIFT_COMMAND_TYPE_SEEK_TO,
             TIME_SHIFT_COMMAND_TYPE_SET_PLAYBACK_PARAMS,
+            TIME_SHIFT_COMMAND_TYPE_SET_MODE,
     })
     public @interface TimeShiftCommandType {}
 
@@ -262,6 +263,12 @@
      * @hide
      */
     public static final String TIME_SHIFT_COMMAND_TYPE_SET_PLAYBACK_PARAMS = "set_playback_params";
+    /**
+     * Time shift command type: set time shift mode.
+     *
+     * @hide
+     */
+    public static final String TIME_SHIFT_COMMAND_TYPE_SET_MODE = "set_mode";
 
     /**
      * Time shift command parameter: program URI.
@@ -287,6 +294,17 @@
      * @hide
      */
     public static final String COMMAND_PARAMETER_KEY_PLAYBACK_PARAMS = "command_playback_params";
+    /**
+     * Time shift command parameter: playback params.
+     * <p>Type: Integer. One of {@link TvInputManager#TIME_SHIFT_MODE_OFF},
+     * {@link TvInputManager#TIME_SHIFT_MODE_LOCAL},
+     * {@link TvInputManager#TIME_SHIFT_MODE_NETWORK},
+     * {@link TvInputManager#TIME_SHIFT_MODE_AUTO}.
+     *
+     * @see #TIME_SHIFT_COMMAND_TYPE_SET_MODE
+     * @hide
+     */
+    public static final String COMMAND_PARAMETER_KEY_TIME_SHIFT_MODE = "command_time_shift_mode";
 
     private final Handler mServiceHandler = new ServiceHandler();
     private final RemoteCallbackList<ITvInteractiveAppServiceCallback> mCallbacks =
@@ -570,22 +588,40 @@
         }
 
         /**
-         * Receives requested recording info.
-         *
-         * @param recordingInfo The requested recording info. Null if recording not found.
+         * Receives current time shift mode.
+         * @param mode The current time shift mode. The value is one of the following:
+         * {@link TvInputManager#TIME_SHIFT_MODE_OFF}, {@link TvInputManager#TIME_SHIFT_MODE_LOCAL},
+         * {@link TvInputManager#TIME_SHIFT_MODE_NETWORK},
+         * {@link TvInputManager#TIME_SHIFT_MODE_AUTO}.
          * @hide
          */
+        public void onTimeShiftMode(@android.media.tv.TvInputManager.TimeShiftMode int mode) {
+        }
+
+        /**
+         * Receives available speeds.
+         * @hide
+         */
+        public void onAvailableSpeeds(@NonNull float[] speeds) {
+        }
+
+        /**
+         * Receives the requested {@link android.media.tv.TvRecordingInfo}.
+         *
+         * @see #requestTvRecordingInfo(String)
+         * @param recordingInfo The requested recording info. {@code null} if no recording found.
+         */
         public void onTvRecordingInfo(@Nullable TvRecordingInfo recordingInfo) {
         }
 
         /**
-         * Receives requested recording info.
+         * Receives requested recording info list.
          *
-         * @param recordingInfoList The requested recording info list. Null if recording not found.
-         * @hide
+         * @see #requestTvRecordingInfoList(int)
+         * @param recordingInfoList The list of recording info requested. Returns an empty list if
+         *                          no matching recording info found.
          */
-        public void onTvRecordingInfoList(@Nullable List<TvRecordingInfo> recordingInfoList) {
-        }
+        public void onTvRecordingInfoList(@NonNull List<TvRecordingInfo> recordingInfoList) {}
 
         /**
          * Receives started recording's ID.
@@ -608,6 +644,77 @@
         }
 
         /**
+         * This is called when an error occurred while establishing a connection to the recording
+         * session for the corresponding TV input.
+         *
+         * @param recordingId The ID of the related recording which is sent via
+         *                    {@link #notifyRecordingStarted(String)}
+         * @param inputId The ID of the TV input bound to the current TvRecordingClient.
+         * @see android.media.tv.TvRecordingClient.RecordingCallback#onConnectionFailed(String)
+         * @hide
+         */
+        public void onRecordingConnectionFailed(
+                @NonNull String recordingId, @NonNull String inputId) {
+        }
+
+        /**
+         * This is called when the connection to the current recording session is lost.
+         *
+         * @param recordingId The ID of the related recording which is sent via
+         *                    {@link #notifyRecordingStarted(String)}
+         * @param inputId The ID of the TV input bound to the current TvRecordingClient.
+         * @see android.media.tv.TvRecordingClient.RecordingCallback#onDisconnected(String)
+         * @hide
+         */
+        public void onRecordingDisconnected(@NonNull String recordingId, @NonNull String inputId) {
+        }
+
+        /**
+         * This is called when the recording session has been tuned to the given channel and is
+         * ready to start recording.
+         *
+         * @param recordingId The ID of the related recording which is sent via
+         *                    {@link #notifyRecordingStarted(String)}
+         * @param channelUri The URI of the tuned channel.
+         * @see android.media.tv.TvRecordingClient.RecordingCallback#onTuned(Uri)
+         * @hide
+         */
+        public void onRecordingTuned(@NonNull String recordingId, @NonNull Uri channelUri) {
+        }
+
+        /**
+         * This is called when an issue has occurred. It may be called at any time after the current
+         * recording session is created until it is released.
+         *
+         * @param recordingId The ID of the related recording which is sent via
+         *                    {@link #notifyRecordingStarted(String)}
+         * @param err The error code. Should be one of the following.
+         * <ul>
+         * <li>{@link TvInputManager#RECORDING_ERROR_UNKNOWN}
+         * <li>{@link TvInputManager#RECORDING_ERROR_INSUFFICIENT_SPACE}
+         * <li>{@link TvInputManager#RECORDING_ERROR_RESOURCE_BUSY}
+         * </ul>
+         * @see android.media.tv.TvRecordingClient.RecordingCallback#onError(int)
+         * @hide
+         */
+        public void onRecordingError(
+                @NonNull String recordingId, @TvInputManager.RecordingError int err) {
+        }
+
+        /**
+         * This is called when the recording has been scheduled.
+         *
+         * @param recordingId The ID assigned to this recording by the app. It can be used to send
+         *                    recording related requests such as
+         *                    {@link #requestStopRecording(String)}.
+         * @param requestId The ID of the request when requestScheduleRecording is called.
+         *                  {@code null} if the recording is not triggered by a request.
+         * @hide
+         */
+        public void onRecordingScheduled(@NonNull String recordingId, @Nullable String requestId) {
+        }
+
+        /**
          * Receives signing result.
          * @param signingId the ID to identify the request. It's the same as the corresponding ID in
          *        {@link Session#requestSigning(String, String, String, byte[])}
@@ -789,17 +896,21 @@
 
         /**
          * Called when an advertisement buffer is consumed.
-         * @hide
+         *
+         * @param buffer The {@link AdBuffer} that was consumed.
          */
-        public void onAdBufferConsumed(AdBuffer buffer) {
-
+        public void onAdBufferConsumed(@NonNull AdBuffer buffer) {
         }
 
         /**
-         * Called when a tv message is received
-         * @hide
+         * Called when a TV message is received
+         *
+         * @param type The type of message received, such as
+         * {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
+         * @param data The raw data of the message
          */
-        public void onTvMessage(@NonNull String type, @NonNull Bundle data) {
+        public void onTvMessage(@NonNull @TvInputManager.TvMessageType String type,
+                @NonNull Bundle data) {
         }
 
         @Override
@@ -1164,6 +1275,54 @@
         }
 
         /**
+         * Requests time shift mode.
+         * @hide
+         */
+        @CallSuper
+        public void requestTimeShiftMode() {
+            executeOrPostRunnableOnMainThread(new Runnable() {
+                @MainThread
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) {
+                            Log.d(TAG, "requestTimeShiftMode");
+                        }
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onRequestTimeShiftMode();
+                        }
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in requestTimeShiftMode", e);
+                    }
+                }
+            });
+        }
+
+        /**
+         * Requests available speeds for time shift.
+         * @hide
+         */
+        @CallSuper
+        public void requestAvailableSpeeds() {
+            executeOrPostRunnableOnMainThread(new Runnable() {
+                @MainThread
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) {
+                            Log.d(TAG, "requestAvailableSpeeds");
+                        }
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onRequestAvailableSpeeds();
+                        }
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in requestAvailableSpeeds", e);
+                    }
+                }
+            });
+        }
+
+        /**
          * Requests starting of recording
          *
          * <p> This is used to request the active {@link android.media.tv.TvRecordingClient} to
@@ -1219,7 +1378,71 @@
         }
 
         /**
-         * Sets the recording info for the specified recording.
+         * Requests scheduling of a recording.
+         *
+         * @param inputId The ID of the TV input for the given channel.
+         * @param channelUri The URI of a channel to be recorded.
+         * @param programUri The URI of the TV program to be recorded.
+         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
+         * @see android.media.tv.TvRecordingClient#tune(String, Uri, Bundle)
+         * @see android.media.tv.TvRecordingClient#startRecording(Uri)
+         * @hide
+         */
+        @CallSuper
+        public void requestScheduleRecording(@NonNull String inputId, @NonNull Uri channelUri,
+                @NonNull Uri programUri, @NonNull Bundle params) {
+            executeOrPostRunnableOnMainThread(() -> {
+                try {
+                    if (DEBUG) {
+                        Log.d(TAG, "requestScheduleRecording");
+                    }
+                    if (mSessionCallback != null) {
+                        mSessionCallback.onRequestScheduleRecording(
+                                inputId, channelUri, programUri, params);
+                    }
+                } catch (RemoteException e) {
+                    Log.w(TAG, "error in requestScheduleRecording", e);
+                }
+            });
+        }
+
+        /**
+         * Requests scheduling of a recording.
+         *
+         * @param inputId The ID of the TV input for the given channel.
+         * @param channelUri The URI of a channel to be recorded.
+         * @param startTime The start time of the recording in milliseconds since epoch.
+         * @param duration The duration of the recording in milliseconds.
+         * @param repeatDays The repeated days. 0 if not repeated.
+         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
+         * @see android.media.tv.TvRecordingClient#tune(String, Uri, Bundle)
+         * @see android.media.tv.TvRecordingClient#startRecording(Uri)
+         * @hide
+         */
+        @CallSuper
+        public void requestScheduleRecording(@NonNull String inputId, @NonNull Uri channelUri,
+                long startTime, long duration, int repeatDays, @NonNull Bundle params) {
+            executeOrPostRunnableOnMainThread(() -> {
+                try {
+                    if (DEBUG) {
+                        Log.d(TAG, "requestScheduleRecording");
+                    }
+                    if (mSessionCallback != null) {
+                        mSessionCallback.onRequestScheduleRecording2(
+                                inputId, channelUri, startTime, duration, repeatDays, params);
+                    }
+                } catch (RemoteException e) {
+                    Log.w(TAG, "error in requestScheduleRecording", e);
+                }
+            });
+        }
+
+        /**
+         * Sets the recording info for the specified recording
          *
          * @param recordingId The ID of the recording to set the info for. This is provided by the
          *     TV app in {@link TvInteractiveAppView#notifyRecordingStarted(String)}
@@ -1399,6 +1622,14 @@
             onCurrentTvInputId(inputId);
         }
 
+        void sendTimeShiftMode(int mode) {
+            onTimeShiftMode(mode);
+        }
+
+        void sendAvailableSpeeds(@NonNull float[] speeds) {
+            onAvailableSpeeds(speeds);
+        }
+
         void sendTvRecordingInfo(@Nullable TvRecordingInfo recordingInfo) {
             onTvRecordingInfo(recordingInfo);
         }
@@ -1540,6 +1771,41 @@
         }
 
         /**
+         * Calls {@link #onRecordingConnectionFailed(String, String)}.
+         */
+        void notifyRecordingConnectionFailed(String recordingId, String inputId) {
+            onRecordingConnectionFailed(recordingId, inputId);
+        }
+
+        /**
+         * Calls {@link #onRecordingDisconnected(String, String)}.
+         */
+        void notifyRecordingDisconnected(String recordingId, String inputId) {
+            onRecordingDisconnected(recordingId, inputId);
+        }
+
+        /**
+         * Calls {@link #onRecordingTuned(String, Uri)}.
+         */
+        void notifyRecordingTuned(String recordingId, Uri channelUri) {
+            onRecordingTuned(recordingId, channelUri);
+        }
+
+        /**
+         * Calls {@link #onRecordingError(String, int)}.
+         */
+        void notifyRecordingError(String recordingId, int err) {
+            onRecordingError(recordingId, err);
+        }
+
+        /**
+         * Calls {@link #onRecordingScheduled(String, String)}.
+         */
+        void notifyRecordingScheduled(String recordingId, String requestId) {
+            onRecordingScheduled(recordingId, requestId);
+        }
+
+        /**
          * Calls {@link #onTimeShiftPlaybackParams(PlaybackParams)}.
          */
         void notifyTimeShiftPlaybackParams(PlaybackParams params) {
@@ -1657,10 +1923,11 @@
 
         /**
          * Notifies when the advertisement buffer is filled and ready to be read.
-         * @hide
+         *
+         * @param buffer The {@link AdBuffer} to be received
          */
         @CallSuper
-        public void notifyAdBuffer(AdBuffer buffer) {
+        public void notifyAdBuffer(@NonNull AdBuffer buffer) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
                 @Override
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
index 4a01440..29a96f7 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
@@ -49,6 +49,7 @@
 import android.view.ViewRootImpl;
 
 import java.security.KeyStore;
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -596,10 +597,46 @@
     }
 
     /**
+     * Sends current time shift mode to related TV interactive app.
+     *
+     * @param mode The current time shift mode. The value is one of the following:
+     * {@link TvInputManager#TIME_SHIFT_MODE_OFF}, {@link TvInputManager#TIME_SHIFT_MODE_LOCAL},
+     * {@link TvInputManager#TIME_SHIFT_MODE_NETWORK},
+     * {@link TvInputManager#TIME_SHIFT_MODE_AUTO}.
+     * @hide
+     */
+    public void sendTimeShiftMode(@android.media.tv.TvInputManager.TimeShiftMode int mode) {
+        if (DEBUG) {
+            Log.d(TAG, "sendTimeShiftMode");
+        }
+        if (mSession != null) {
+            mSession.sendTimeShiftMode(mode);
+        }
+    }
+
+    /**
+     * Sends available supported speeds to related TV interactive app.
+     *
+     * @param speeds An ordered array of playback speeds, expressed as values relative to the normal
+     *               playback speed 1.0.
+     * @see PlaybackParams#getSpeed()
+     * @hide
+     */
+    public void sendAvailableSpeeds(@NonNull float[] speeds) {
+        if (DEBUG) {
+            Log.d(TAG, "sendAvailableSpeeds");
+        }
+        if (mSession != null) {
+            Arrays.sort(speeds);
+            mSession.sendAvailableSpeeds(speeds);
+        }
+    }
+
+    /**
      * Sends the requested {@link android.media.tv.TvRecordingInfo}.
      *
-     * @param recordingInfo The recording info requested {@code null} if no recording found.
-     * @hide
+     * @see TvInteractiveAppService.Session#requestTvRecordingInfo(String)
+     * @param recordingInfo The recording info requested. {@code null} if no recording found.
      */
     public void sendTvRecordingInfo(@Nullable TvRecordingInfo recordingInfo) {
         if (DEBUG) {
@@ -613,10 +650,11 @@
     /**
      * Sends the requested {@link android.media.tv.TvRecordingInfo}.
      *
-     * @param recordingInfoList The list of recording info requested.
-     * @hide
+     * @see TvInteractiveAppService.Session#requestTvRecordingInfoList(int)
+     * @param recordingInfoList The list of recording info requested. Returns an empty list if no
+     *                          matching recording info found.
      */
-    public void sendTvRecordingInfoList(@Nullable List<TvRecordingInfo> recordingInfoList) {
+    public void sendTvRecordingInfoList(@NonNull List<TvRecordingInfo> recordingInfoList) {
         if (DEBUG) {
             Log.d(TAG, "sendTvRecordingInfoList");
         }
@@ -633,6 +671,7 @@
      * @see TvInteractiveAppView#notifyRecordingStopped(String)
      */
     public void notifyRecordingStarted(@NonNull String recordingId) {
+        // TODO: add request ID to identify and map the corresponding request.
         if (DEBUG) {
             Log.d(TAG, "notifyRecordingStarted");
         }
@@ -767,6 +806,137 @@
         }
     }
 
+    /**
+     * This is called to notify the corresponding interactive app service when an error occurred
+     * while establishing a connection to the recording session for the corresponding TV input.
+     *
+     * @param recordingId The ID of the related recording which is sent via
+     *                    {@link #notifyRecordingStarted(String)}
+     * @param inputId The ID of the TV input bound to the current TvRecordingClient.
+     * @see android.media.tv.TvRecordingClient.RecordingCallback#onConnectionFailed(String)
+     * @hide
+     */
+    public void notifyRecordingConnectionFailed(
+            @NonNull String recordingId, @NonNull String inputId) {
+        if (DEBUG) {
+            Log.d(TAG, "notifyRecordingConnectionFailed recordingId=" + recordingId
+                    + "; inputId=" + inputId);
+        }
+        if (mSession != null) {
+            mSession.notifyRecordingConnectionFailed(recordingId, inputId);
+        }
+    }
+
+    /**
+     * This is called to notify the corresponding interactive app service when the connection to
+     * the current recording session is lost.
+     *
+     * @param recordingId The ID of the related recording which is sent via
+     *                    {@link #notifyRecordingStarted(String)}
+     * @param inputId The ID of the TV input bound to the current TvRecordingClient.
+     * @see android.media.tv.TvRecordingClient.RecordingCallback#onDisconnected(String)
+     * @hide
+     */
+    public void notifyRecordingDisconnected(
+            @NonNull String recordingId, @NonNull String inputId) {
+        if (DEBUG) {
+            Log.d(TAG, "notifyRecordingDisconnected recordingId=" + recordingId
+                    + "; inputId=" + inputId);
+        }
+        if (mSession != null) {
+            mSession.notifyRecordingDisconnected(recordingId, inputId);
+        }
+    }
+
+    /**
+     * This is called to notify the corresponding interactive app service when the recording session
+     * has been tuned to the given channel and is ready to start recording.
+     *
+     * @param recordingId The ID of the related recording which is sent via
+     *                    {@link #notifyRecordingStarted(String)}
+     * @param channelUri The URI of the tuned channel.
+     * @see android.media.tv.TvRecordingClient.RecordingCallback#onTuned(Uri)
+     * @hide
+     */
+    public void notifyRecordingTuned(
+            @NonNull String recordingId, @NonNull Uri channelUri) {
+        if (DEBUG) {
+            Log.d(TAG, "notifyRecordingTuned recordingId=" + recordingId
+                    + "; channelUri=" + channelUri);
+        }
+        if (mSession != null) {
+            mSession.notifyRecordingTuned(recordingId, channelUri);
+        }
+    }
+
+    /**
+     * This is called to notify the corresponding interactive app service when an issue has
+     * occurred. It may be called at any time after the current recording session is created until
+     * it is released.
+     *
+     * @param recordingId The ID of the related recording which is sent via
+     *                    {@link #notifyRecordingStarted(String)}
+     * @param err The error code. Should be one of the following.
+     * <ul>
+     * <li>{@link TvInputManager#RECORDING_ERROR_UNKNOWN}
+     * <li>{@link TvInputManager#RECORDING_ERROR_INSUFFICIENT_SPACE}
+     * <li>{@link TvInputManager#RECORDING_ERROR_RESOURCE_BUSY}
+     * </ul>
+     * @see android.media.tv.TvRecordingClient.RecordingCallback#onError(int)
+     * @hide
+     */
+    public void notifyRecordingError(
+            @NonNull String recordingId, @TvInputManager.RecordingError int err) {
+        if (DEBUG) {
+            Log.d(TAG, "notifyRecordingError recordingId=" + recordingId
+                    + "; err=" + err);
+        }
+        if (mSession != null) {
+            mSession.notifyRecordingError(recordingId, err);
+        }
+    }
+
+    /**
+     * This is called to notify the corresponding interactive app service when the recording has
+     * been scheduled.
+     *
+     * @param recordingId The ID assigned to this recording by the app. It can be used to send
+     *                    recording related requests such as
+     *                    {@link TvInteractiveAppService.Session#requestStopRecording(String)}.
+     * @param requestId The ID of the request when requestScheduleRecording is called.
+     *                  {@code null} if the recording is not triggered by a request.
+     * @hide
+     */
+    public void notifyRecordingScheduled(
+            @NonNull String recordingId, @Nullable String requestId) {
+        if (DEBUG) {
+            Log.d(TAG, "notifyRecordingScheduled recordingId=" + recordingId
+                    + "; requestId=" + requestId);
+        }
+        if (mSession != null) {
+            mSession.notifyRecordingScheduled(recordingId, requestId);
+        }
+    }
+
+    /**
+     * This is called to notify the corresponding interactive app service when a new TV message
+     * is received.
+     *
+     * @param type The type of message received, such as
+     * {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
+     * @param data The raw data of the message
+     */
+    public void notifyTvMessage(@NonNull @TvInputManager.TvMessageType String type,
+            @NonNull Bundle data) {
+        if (DEBUG) {
+            Log.d(TAG, "notifyTvMessage type=" + type
+                    + "; data=" + data);
+        }
+        if (mSession != null) {
+            mSession.notifyTvMessage(type, data);
+        }
+    }
+
     private void resetInternal() {
         mSessionCallback = null;
         if (mSession != null) {
@@ -1012,6 +1182,26 @@
         }
 
         /**
+         * This is called when {@link TvInteractiveAppService.Session#requestTimeShiftMode()} is
+         * called.
+         *
+         * @param iAppServiceId The ID of the TV interactive app service bound to this view.
+         * @hide
+         */
+        public void onRequestTimeShiftMode(@NonNull String iAppServiceId) {
+        }
+
+        /**
+         * This is called when {@link TvInteractiveAppService.Session#requestAvailableSpeeds()} is
+         * called.
+         *
+         * @param iAppServiceId The ID of the TV interactive app service bound to this view.
+         * @hide
+         */
+        public void onRequestAvailableSpeeds(@NonNull String iAppServiceId) {
+        }
+
+        /**
          * This is called when {@link TvInteractiveAppService.Session#requestStartRecording(Uri)}
          * is called.
          *
@@ -1041,6 +1231,50 @@
 
         /**
          * This is called when
+         * {@link TvInteractiveAppService.Session#requestScheduleRecording(String, Uri, Uri, Bundle)}
+         * is called.
+         *
+         * @param iAppServiceId The ID of the TV interactive app service bound to this view.
+         * @param inputId The ID of the TV input for the given channel.
+         * @param channelUri The URI of a channel to be recorded.
+         * @param programUri The URI of the TV program to be recorded.
+         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
+         * @see android.media.tv.TvRecordingClient#tune(String, Uri, Bundle)
+         * @see android.media.tv.TvRecordingClient#startRecording(Uri)
+         * @hide
+         */
+        public void onRequestScheduleRecording(@NonNull String iAppServiceId,
+                @NonNull String inputId, @NonNull Uri channelUri, @NonNull Uri programUri,
+                @NonNull Bundle params) {
+        }
+
+        /**
+         * This is called when
+         * {@link TvInteractiveAppService.Session#requestScheduleRecording(String, Uri, long, long, int, Bundle)}
+         * is called.
+         *
+         * @param iAppServiceId The ID of the TV interactive app service bound to this view.
+         * @param inputId The ID of the TV input for the given channel.
+         * @param channelUri The URI of a channel to be recorded.
+         * @param startTime The start time of the recording in milliseconds since epoch.
+         * @param duration The duration of the recording in milliseconds.
+         * @param repeatDays The repeated days. 0 if not repeated.
+         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
+         * @see android.media.tv.TvRecordingClient#tune(String, Uri, Bundle)
+         * @see android.media.tv.TvRecordingClient#startRecording(Uri)
+         * @hide
+         */
+        public void onRequestScheduleRecording(@NonNull String iAppServiceId,
+                @NonNull String inputId, @NonNull Uri channelUri, long startTime, long duration,
+                int repeatDays, @NonNull Bundle params) {
+        }
+
+        /**
+         * This is called when
          * {@link TvInteractiveAppService.Session#requestSigning(String, String, String, byte[])} is
          * called.
          *
@@ -1453,6 +1687,34 @@
         }
 
         @Override
+        public void onRequestTimeShiftMode(Session session) {
+            if (DEBUG) {
+                Log.d(TAG, "onRequestTimeShiftMode");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onRequestTimeShiftMode - session not created");
+                return;
+            }
+            if (mCallback != null) {
+                mCallback.onRequestTimeShiftMode(mIAppServiceId);
+            }
+        }
+
+        @Override
+        public void onRequestAvailableSpeeds(Session session) {
+            if (DEBUG) {
+                Log.d(TAG, "onRequestAvailableSpeeds");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onRequestAvailableSpeeds - session not created");
+                return;
+            }
+            if (mCallback != null) {
+                mCallback.onRequestAvailableSpeeds(mIAppServiceId);
+            }
+        }
+
+        @Override
         public void onRequestStartRecording(Session session, Uri programUri) {
             if (DEBUG) {
                 Log.d(TAG, "onRequestStartRecording");
@@ -1496,6 +1758,22 @@
         }
 
         @Override
+        public void onRequestScheduleRecording(Session session, @NonNull String inputId,
+                @NonNull Uri channelUri, Uri progarmUri, @NonNull Bundle params) {
+            if (DEBUG) {
+                Log.d(TAG, "onRequestScheduleRecording");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onRequestScheduleRecording - session not created");
+                return;
+            }
+            if (mCallback != null) {
+                mCallback.onRequestScheduleRecording(mIAppServiceId, inputId, channelUri,
+                        progarmUri, params);
+            }
+        }
+
+        @Override
         public void onRequestTvRecordingInfo(Session session,
                 String recordingId) {
             if (DEBUG) {
@@ -1525,6 +1803,22 @@
             }
         }
 
+        public void onRequestScheduleRecording(Session session, @NonNull String inputId,
+                @NonNull Uri channelUri, long startTime, long duration, int repeatDays,
+                @NonNull Bundle params) {
+            if (DEBUG) {
+                Log.d(TAG, "onRequestScheduleRecording");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onRequestScheduleRecording - session not created");
+                return;
+            }
+            if (mCallback != null) {
+                mCallback.onRequestScheduleRecording(mIAppServiceId, inputId, channelUri, startTime,
+                        duration, repeatDays, params);
+            }
+        }
+
         @Override
         public void onRequestSigning(
                 Session session, String id, String algorithm, String alias, byte[] data) {
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index d958db1..8f2e7b5 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -18,10 +18,15 @@
 
 import android.annotation.BytesLong;
 import android.annotation.IntRange;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.media.AudioPresentation;
 import android.media.MediaCodec.LinearBlock;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * Filter event sent from {@link Filter} objects with media type.
  *
@@ -51,12 +56,13 @@
     private final boolean mIsPrivateData;
     private final int mScIndexMask;
     private final AudioDescriptor mExtraMetaData;
+    private final List<AudioPresentation> mAudioPresentations;
 
     // This constructor is used by JNI code only
     private MediaEvent(int streamId, boolean isPtsPresent, long pts, boolean isDtsPresent, long dts,
             long dataLength, long offset, LinearBlock buffer, boolean isSecureMemory, long dataId,
             int mpuSequenceNumber, boolean isPrivateData, int scIndexMask,
-            AudioDescriptor extraMetaData) {
+            AudioDescriptor extraMetaData, List<AudioPresentation> audioPresentations) {
         mStreamId = streamId;
         mIsPtsPresent = isPtsPresent;
         mPts = pts;
@@ -71,6 +77,7 @@
         mIsPrivateData = isPrivateData;
         mScIndexMask = scIndexMask;
         mExtraMetaData = extraMetaData;
+        mAudioPresentations = audioPresentations;
     }
 
     /**
@@ -215,6 +222,13 @@
         return mExtraMetaData;
     }
 
+    /**
+     * Gets audio presentations.
+     */
+    @NonNull
+    public List<AudioPresentation> getAudioPresentations() {
+        return mAudioPresentations == null ? Collections.emptyList() : mAudioPresentations;
+    }
 
     /**
      * Finalize the MediaEvent object.
diff --git a/media/java/android/media/tv/tuner/frontend/IptvFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/IptvFrontendCapabilities.java
new file mode 100644
index 0000000..b04fe17
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/IptvFrontendCapabilities.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner.frontend;
+
+import android.annotation.SystemApi;
+
+/**
+ * IPTV Capabilities.
+ *
+ * @hide
+ */
+@SystemApi
+public class IptvFrontendCapabilities extends FrontendCapabilities {
+    private final int mProtocolCap;
+
+    // Used by native code
+    private IptvFrontendCapabilities(int protocolCap) {
+        mProtocolCap = protocolCap;
+    }
+
+    /**
+     * Gets the protocols of IPTV transmission (UDP/RTP) defined in
+     * {@link IptvFrontendSettings}.
+     */
+    public int getProtocolCapability() {
+        return mProtocolCap;
+    }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java
index fb11ea9..ba75102 100644
--- a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java
@@ -92,7 +92,7 @@
     private final long mBitrate;
     private final String mContentUrl;
 
-    public IptvFrontendSettings(@NonNull byte[] srcIpAddress, @NonNull byte[] dstIpAddress,
+    private IptvFrontendSettings(@NonNull byte[] srcIpAddress, @NonNull byte[] dstIpAddress,
             int srcPort, int dstPort, @NonNull IptvFrontendSettingsFec fec, int protocol, int igmp,
             long bitrate, @NonNull String contentUrl) {
         super(0);
diff --git a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java
index 699d615..a70af17 100644
--- a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java
+++ b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java
@@ -62,7 +62,7 @@
     private final int mFecRowNum;
     private final int mFecColNum;
 
-    public IptvFrontendSettingsFec(@FecType int fecType, int fecRowNum, int fecColNum) {
+    private IptvFrontendSettingsFec(@FecType int fecType, int fecRowNum, int fecColNum) {
         mFecType = fecType;
         mFecRowNum = fecRowNum;
         mFecColNum = fecColNum;
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index a0304bb..ed1072c 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -88,6 +88,7 @@
         "android.hidl.memory@1.0",
         "android.hidl.token@1.0-utils",
         "android.hardware.drm-V1-ndk",
+        "android.hardware.tv.tuner-V2-ndk",
     ],
 
     header_libs: [
diff --git a/media/jni/android_media_AudioPresentation.h b/media/jni/android_media_AudioPresentation.h
index a3adddd..0c83ddf 100644
--- a/media/jni/android_media_AudioPresentation.h
+++ b/media/jni/android_media_AudioPresentation.h
@@ -19,10 +19,14 @@
 
 #include "jni.h"
 
+#include <aidl/android/hardware/tv/tuner/AudioPresentation.h>
 #include <media/stagefright/foundation/ADebug.h>  // CHECK
 #include <media/stagefright/foundation/AudioPresentationInfo.h>
 #include <nativehelper/ScopedLocalRef.h>
 
+using ::aidl::android::hardware::tv::tuner::AudioPreselectionRenderingIndicationType;
+using TunerAudioPresentation = ::aidl::android::hardware::tv::tuner::AudioPresentation;
+
 namespace android {
 
 struct JAudioPresentationInfo {
@@ -97,6 +101,38 @@
     }
 
     static void addPresentations(JNIEnv *env, const fields_t& fields,
+            const std::vector<TunerAudioPresentation>& tunerAudioPresentations,
+            jobject presentationsJObj) {
+        AudioPresentationCollection apc = {};
+        static const std::map<AudioPreselectionRenderingIndicationType, MasteringIndication> mMap {
+            { AudioPreselectionRenderingIndicationType::NOT_INDICATED, MASTERING_NOT_INDICATED },
+            { AudioPreselectionRenderingIndicationType::STEREO, MASTERED_FOR_STEREO },
+            { AudioPreselectionRenderingIndicationType::TWO_DIMENSIONAL, MASTERED_FOR_SURROUND },
+            { AudioPreselectionRenderingIndicationType::THREE_DIMENSIONAL, MASTERED_FOR_3D },
+            { AudioPreselectionRenderingIndicationType::HEADPHONE, MASTERED_FOR_HEADPHONE },
+        };
+        for (const auto& tap : tunerAudioPresentations) {
+            AudioPresentationV1 ap;
+            ap.mPresentationId = tap.preselection.preselectionId;
+            ap.mProgramId = tap.ac4ShortProgramId;
+            for (const auto& md : tap.preselection.labels) {
+                ap.mLabels.insert(std::pair(md.language, md.text));
+            }
+            ap.mLanguage = tap.preselection.language;
+            ap.mMasteringIndication = MASTERING_NOT_INDICATED;
+            auto masteringSearch = mMap.find(tap.preselection.renderingIndication);
+            if (masteringSearch != mMap.end()) {
+                ap.mMasteringIndication = masteringSearch->second;
+            }
+            ap.mAudioDescriptionAvailable = tap.preselection.hasAudioDescription;
+            ap.mSpokenSubtitlesAvailable = tap.preselection.hasSpokenSubtitles;
+            ap.mDialogueEnhancementAvailable = tap.preselection.hasDialogueEnhancement;
+            apc.push_back(ap);
+        }
+        addPresentations(env, fields, apc, presentationsJObj);
+    }
+
+    static void addPresentations(JNIEnv *env, const fields_t& fields,
                     const AudioPresentationCollection& presentations, jobject presentationsJObj) {
         for (const auto& ap : presentations) {
             ScopedLocalRef<jobject> jLabelObject = convertLabelsToMap(env, fields, ap.mLabels);
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 625e842..7f4c03b 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -20,6 +20,7 @@
 #include "android_media_tv_Tuner.h"
 
 #include <aidl/android/hardware/tv/tuner/AudioExtraMetaData.h>
+#include <aidl/android/hardware/tv/tuner/AudioPresentation.h>
 #include <aidl/android/hardware/tv/tuner/AudioStreamType.h>
 #include <aidl/android/hardware/tv/tuner/AvStreamType.h>
 #include <aidl/android/hardware/tv/tuner/Constant.h>
@@ -161,12 +162,14 @@
 #include <nativehelper/ScopedLocalRef.h>
 #include <utils/Log.h>
 
+#include "android_media_AudioPresentation.h"
 #include "android_media_MediaCodecLinearBlock.h"
 #include "android_runtime/AndroidRuntime.h"
 
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 using ::aidl::android::hardware::tv::tuner::AudioExtraMetaData;
+using ::aidl::android::hardware::tv::tuner::AudioPreselection;
 using ::aidl::android::hardware::tv::tuner::AudioStreamType;
 using ::aidl::android::hardware::tv::tuner::AvStreamType;
 using ::aidl::android::hardware::tv::tuner::Constant;
@@ -362,6 +365,9 @@
 }
 
 namespace android {
+
+static JAudioPresentationInfo::fields_t gAudioPresentationFields;
+
 /////////////// LnbClientCallbackImpl ///////////////////////
 void LnbClientCallbackImpl::onEvent(const LnbEventType lnbEventType) {
     ALOGV("LnbClientCallbackImpl::onEvent, type=%d", lnbEventType);
@@ -634,27 +640,45 @@
             eventClazz,
             "<init>",
             "(IZJZJJJLandroid/media/MediaCodec$LinearBlock;"
-            "ZJIZILandroid/media/tv/tuner/filter/AudioDescriptor;)V");
+            "ZJIZILandroid/media/tv/tuner/filter/AudioDescriptor;"
+            "Ljava/util/List;)V");
     jfieldID eventContext = env->GetFieldID(eventClazz, "mNativeContext", "J");
 
     const DemuxFilterMediaEvent &mediaEvent = event.get<DemuxFilterEvent::Tag::media>();
     jobject audioDescriptor = nullptr;
-    if (mediaEvent.extraMetaData.getTag() == DemuxFilterMediaEventExtraMetaData::Tag::audio) {
-        jclass adClazz = env->FindClass("android/media/tv/tuner/filter/AudioDescriptor");
-        jmethodID adInit = env->GetMethodID(adClazz, "<init>", "(BBCBBB)V");
+    gAudioPresentationFields.init(env);
+    jobject presentationsJObj = JAudioPresentationInfo::asJobject(env, gAudioPresentationFields);
+    switch (mediaEvent.extraMetaData.getTag()) {
+        case DemuxFilterMediaEventExtraMetaData::Tag::audio: {
+            jclass adClazz = env->FindClass("android/media/tv/tuner/filter/AudioDescriptor");
+            jmethodID adInit = env->GetMethodID(adClazz, "<init>", "(BBCBBB)V");
 
-        const AudioExtraMetaData &ad =
-                mediaEvent.extraMetaData.get<DemuxFilterMediaEventExtraMetaData::Tag::audio>();
-        jbyte adFade = ad.adFade;
-        jbyte adPan = ad.adPan;
-        jchar versionTextTag = ad.versionTextTag;
-        jbyte adGainCenter = ad.adGainCenter;
-        jbyte adGainFront = ad.adGainFront;
-        jbyte adGainSurround = ad.adGainSurround;
+            const AudioExtraMetaData &ad =
+                    mediaEvent.extraMetaData.get<DemuxFilterMediaEventExtraMetaData::Tag::audio>();
+            jbyte adFade = ad.adFade;
+            jbyte adPan = ad.adPan;
+            jchar versionTextTag = ad.versionTextTag;
+            jbyte adGainCenter = ad.adGainCenter;
+            jbyte adGainFront = ad.adGainFront;
+            jbyte adGainSurround = ad.adGainSurround;
 
-        audioDescriptor = env->NewObject(adClazz, adInit, adFade, adPan, versionTextTag,
-                                         adGainCenter, adGainFront, adGainSurround);
-        env->DeleteLocalRef(adClazz);
+            audioDescriptor = env->NewObject(adClazz, adInit, adFade, adPan, versionTextTag,
+                                             adGainCenter, adGainFront, adGainSurround);
+            env->DeleteLocalRef(adClazz);
+            break;
+        }
+        case DemuxFilterMediaEventExtraMetaData::Tag::audioPresentations: {
+            JAudioPresentationInfo::addPresentations(
+                    env, gAudioPresentationFields,
+                    mediaEvent.extraMetaData
+                            .get<DemuxFilterMediaEventExtraMetaData::Tag::audioPresentations>(),
+                    presentationsJObj);
+            break;
+        }
+        default: {
+            ALOGE("FilterClientCallbackImpl::getMediaEvent: unknown extraMetaData");
+            break;
+        }
     }
 
     jlong dataLength = mediaEvent.dataLength;
@@ -683,7 +707,8 @@
 
     jobject obj = env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, isDtsPresent,
                                  dts, dataLength, offset, nullptr, isSecureMemory, avDataId,
-                                 mpuSequenceNumber, isPesPrivateData, sc, audioDescriptor);
+                                 mpuSequenceNumber, isPesPrivateData, sc, audioDescriptor,
+                                 presentationsJObj);
 
     uint64_t avSharedMemSize = mFilterClient->getAvSharedHandleInfo().size;
     if (mediaEvent.avMemory.fds.size() > 0 || mediaEvent.avDataId != 0 ||
@@ -702,6 +727,7 @@
     }
     env->DeleteLocalRef(obj);
     env->DeleteLocalRef(eventClazz);
+    env->DeleteLocalRef(presentationsJObj);
 }
 
 void FilterClientCallbackImpl::getPesEvent(jobjectArray &arr, const int size,
@@ -1591,6 +1617,15 @@
             interleaveModeCap, codeRateCap, bandwidthCap);
 }
 
+jobject JTuner::getIptvFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IptvFrontendCapabilities");
+    jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(I)V");
+
+    jint protocolCap = caps.get<FrontendCapabilities::Tag::iptvCaps>()->protocolCap;
+
+    return env->NewObject(clazz, capsInit, protocolCap);
+}
+
 jobject JTuner::getFrontendInfo(int id) {
     shared_ptr<FrontendInfo> feInfo;
     feInfo = sTunerClient->getFrontendInfo(id);
@@ -1669,6 +1704,11 @@
                 jcaps = getDtmbFrontendCaps(env, caps);
             }
             break;
+        case FrontendType::IPTV:
+            if (FrontendCapabilities::Tag::iptvCaps == caps.getTag()) {
+                jcaps = getIptvFrontendCaps(env, caps);
+            }
+            break;
         default:
             break;
     }
@@ -3492,17 +3532,18 @@
 
 static FrontendIptvSettingsFec getIptvFrontendSettingsFec(JNIEnv *env, const jobject &settings) {
     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IptvFrontendSettings");
-    jobject fec = env->GetObjectField(settings, env->GetFieldID(clazz, "mFec",
-            "[Landroid/media/tv/tuner/frontend/IptvFrontendSettingsFec;"));
     jclass fecClazz = env->FindClass("android/media/tv/tuner/frontend/IptvFrontendSettingsFec");
-    FrontendIptvSettingsFecType fecType =
+    jobject fec = env->GetObjectField(settings, env->GetFieldID(clazz, "mFec",
+            "Landroid/media/tv/tuner/frontend/IptvFrontendSettingsFec;"));
+
+    FrontendIptvSettingsFecType type =
             static_cast<FrontendIptvSettingsFecType>(
-                    env->GetIntField(fec, env->GetFieldID(fecClazz, "mFec", "I")));
+                    env->GetIntField(fec, env->GetFieldID(fecClazz, "mFecType", "I")));
     int32_t fecColNum = env->GetIntField(fec, env->GetFieldID(fecClazz, "mFecColNum", "I"));
     int32_t fecRowNum = env->GetIntField(fec, env->GetFieldID(fecClazz, "mFecRowNum", "I"));
 
-    FrontendIptvSettingsFec frontendIptvSettingsFec {
-        .type = fecType,
+    FrontendIptvSettingsFec frontendIptvSettingsFec = {
+        .type = type,
         .fecColNum = fecColNum,
         .fecRowNum = fecRowNum,
     };
@@ -3512,31 +3553,36 @@
 
 static FrontendSettings getIptvFrontendSettings(JNIEnv *env, const jobject &settings) {
     FrontendSettings frontendSettings;
-    const char *clazzName = "android/media/tv/tuner/frontend/IptvFrontendSettings";
-    jclass clazz = env->FindClass(clazzName);
+    const char *className = "android/media/tv/tuner/frontend/IptvFrontendSettings";
+    jclass clazz = env->FindClass(className);
     FrontendIptvSettingsProtocol protocol =
             static_cast<FrontendIptvSettingsProtocol>(
                     env->GetIntField(settings, env->GetFieldID(clazz, "mProtocol", "I")));
     FrontendIptvSettingsIgmp igmp =
             static_cast<FrontendIptvSettingsIgmp>(
                     env->GetIntField(settings, env->GetFieldID(clazz, "mIgmp", "I")));
-    FrontendIptvSettingsFec fec = getIptvFrontendSettingsFec(env, settings);
     int64_t bitrate = env->GetIntField(settings, env->GetFieldID(clazz, "mBitrate", "J"));
-    jstring contentUrlJString = (jstring) env->GetObjectField(settings, env->GetFieldID(
-                                clazz, "mContentUrl",
-                                "[Landroid/media/tv/tuner/frontend/IptvFrontendSettings;"));
-    const char *contentUrl = env->GetStringUTFChars(contentUrlJString, 0);
-    DemuxIpAddress ipAddr = getDemuxIpAddress(env, settings, clazzName);
+    jstring jContentUrl = (jstring) env->GetObjectField(settings, env->GetFieldID(
+                                clazz, "mContentUrl", "Ljava/lang/String;"));
+    const char *contentUrl = env->GetStringUTFChars(jContentUrl, 0);
+    DemuxIpAddress ipAddr = getDemuxIpAddress(env, settings, className);
 
     FrontendIptvSettings frontendIptvSettings{
             .protocol = protocol,
-            .fec = fec,
             .igmp = igmp,
             .bitrate = bitrate,
             .ipAddr = ipAddr,
             .contentUrl = contentUrl,
     };
+
+    jobject jFec = env->GetObjectField(settings, env->GetFieldID(clazz, "mFec",
+            "Landroid/media/tv/tuner/frontend/IptvFrontendSettingsFec;"));
+    if (jFec != nullptr) {
+        frontendIptvSettings.fec = getIptvFrontendSettingsFec(env, settings);
+    }
+
     frontendSettings.set<FrontendSettings::Tag::iptv>(frontendIptvSettings);
+    env->ReleaseStringUTFChars(jContentUrl, contentUrl);
     return frontendSettings;
 }
 
@@ -3853,7 +3899,6 @@
     return tuner->openLnbByName(name);
 }
 
-
 static jobject android_media_tv_Tuner_open_filter(
         JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) {
     sp<JTuner> tuner = getTuner(env, thiz);
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 4069aaf..2bb14f6 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -236,6 +236,7 @@
     static jobject getIsdbsFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
     static jobject getIsdbtFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
     static jobject getDtmbFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+    static jobject getIptvFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
 };
 
 class C2DataIdInfo : public C2Param {
diff --git a/omapi/OWNERS b/omapi/OWNERS
index 1dce1e0..39c5c5b 100644
--- a/omapi/OWNERS
+++ b/omapi/OWNERS
@@ -1,6 +1,2 @@
 # Bug component: 456592
-
-sattiraju@google.com
-henrichataing@google.com
-alisher@google.com
-jackcwyu@google.com
+include platform/packages/apps/Nfc:/OWNERS
diff --git a/omapi/java/android/se/OWNERS b/omapi/java/android/se/OWNERS
index 1dce1e0..39c5c5b 100644
--- a/omapi/java/android/se/OWNERS
+++ b/omapi/java/android/se/OWNERS
@@ -1,6 +1,2 @@
 # Bug component: 456592
-
-sattiraju@google.com
-henrichataing@google.com
-alisher@google.com
-jackcwyu@google.com
+include platform/packages/apps/Nfc:/OWNERS
diff --git a/omapi/java/android/se/omapi/OWNERS b/omapi/java/android/se/omapi/OWNERS
index 1dce1e0..39c5c5b 100644
--- a/omapi/java/android/se/omapi/OWNERS
+++ b/omapi/java/android/se/omapi/OWNERS
@@ -1,6 +1,2 @@
 # Bug component: 456592
-
-sattiraju@google.com
-henrichataing@google.com
-alisher@google.com
-jackcwyu@google.com
+include platform/packages/apps/Nfc:/OWNERS
diff --git a/packages/CompanionDeviceManager/res/layout/list_item_permission.xml b/packages/CompanionDeviceManager/res/layout/list_item_permission.xml
index ab2d815..6c463e1 100644
--- a/packages/CompanionDeviceManager/res/layout/list_item_permission.xml
+++ b/packages/CompanionDeviceManager/res/layout/list_item_permission.xml
@@ -22,7 +22,7 @@
               android:orientation="horizontal"
               android:paddingStart="32dp"
               android:paddingEnd="32dp"
-              android:paddingBottom="14dp">
+              android:paddingTop="12dp">
 
     <ImageView
         android:id="@+id/permission_icon"
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index a8e5143..4b64f97 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Metgeseltoestel-bestuurder"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Gee &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toegang tot jou &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"horlosie"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Kies \'n <xliff:g id="PROFILE_NAME">%1$s</xliff:g> om deur &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; bestuur te word"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Hierdie app is nodig om jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om interaksie met jou kennisgewings te hê, en sal toegang hê tot jou Foon-, SMS-, Kontakte-, Kalender-, Oproeprekords- en Toestelle in die Omtrek-toestemming."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Hierdie app is nodig om jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om interaksie met die volgende toestemmings te hê:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"bril"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Hierdie app is nodig om jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om interaksie met jou kennisgewings te hê en sal toegang tot jou Foon-, SMS-, Kontakte-, Mikrofoon, en Toestelle in die Omtrek-toestemmings hê."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Hierdie app is nodig om jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om interaksie met die volgende toestemmings te hê:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Gee &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toegang tot hierdie inligting op jou foon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Oorkruistoestel-dienste"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om programme tussen jou toestelle te stroom"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Oorkruistoesteldienste"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-toestemming om inhoud na toestelle in die omtrek te stroom"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"toestel"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Laat toe"</string>
     <string name="consent_no" msgid="2640796915611404382">"Moenie toelaat nie"</string>
     <string name="consent_back" msgid="2560683030046918882">"Terug"</string>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index f6abda8..86d8652 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"አጃቢ የመሣሪያ አስተዳዳሪ"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; የእርስዎን &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; መሣሪያ እንዲደርስ ይፍቀዱለት"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ሰዓት"</string>
     <string name="chooser_title" msgid="2262294130493605839">"በ&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; የሚተዳደር <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ይምረጡ"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"የእርስዎን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ለማስተዳደር መተግበሪያው ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ ዕውቂያዎች፣ የቀን መቁጠሪያ፣ የጥሪ ምዝገባ ማስታወሻዎች እና በአቅራቢያ ያሉ የመሣሪያዎች ፈቃዶች እንዲደርስ ይፈቀድለታል።"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"የእርስዎን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ለማስተዳደር መተግበሪያው ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> ከእነዚህ ፈቃዶች ጋር መስተጋብር እንዲፈጥር ይፈቀድለታል፦"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"መነጽሮች"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"የእርስዎን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ለማስተዳደር ይህ መተግበሪያ ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ ዕውቂያዎች፣ ማይክሮፎን እና በአቅራቢያ ያሉ መሣሪያዎች ፈቃዶችን እንዲደርስ ይፈቀድለታል።"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"የእርስዎን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ለማስተዳደር መተግበሪያው ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> ከእነዚህ ፈቃዶች ጋር መስተጋብር እንዲፈጥር ይፈቀድለታል፦"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ይህን መረጃ ከስልክዎ እንዲደርስበት ይፍቀዱለት"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"መሣሪያ ተሻጋሪ አገልግሎቶች"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> በእርስዎ መሣሪያዎች መካከል መተግበሪያዎችን በዥረት ለመልቀቅ የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"መሣሪያ ተሻጋሪ አገልግሎቶች"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> በአቅራቢያ ወዳሉ መሣሪያዎች ይዘትን በዥረት ለመልቀቅ የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"መሣሪያ"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"ፍቀድ"</string>
     <string name="consent_no" msgid="2640796915611404382">"አትፍቀድ"</string>
     <string name="consent_back" msgid="2560683030046918882">"ተመለስ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index 013e1ec..5864ec9 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"تطبيق \"مدير الجهاز المصاحب\""</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"‏السماح لتطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; بالوصول إلى &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"الساعة"</string>
     <string name="chooser_title" msgid="2262294130493605839">"‏اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديرها تطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"التطبيق مطلوب لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والتقويم وسجلّات المكالمات والأجهزة المجاورة."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"التطبيق مطلوب لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح للتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بالتفاعل مع هذه الأذونات."</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"النظارة"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"هذا التطبيق مطلوب لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والميكروفون والأجهزة المجاورة."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"التطبيق مطلوب لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح للتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بالتفاعل مع هذه الأذونات."</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"‏السماح لتطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; بالوصول إلى هذه المعلومات من هاتفك"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"الخدمات التي تعمل بين الأجهزة"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"يطلب تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> الحصول على إذن نيابةً عن <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> لمشاركة التطبيقات بين أجهزتك."</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"خدمات تعمل على عدة أجهزة"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" لبثّ محتوى إلى أجهزتك المجاورة."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"السماح"</string>
     <string name="consent_no" msgid="2640796915611404382">"عدم السماح"</string>
     <string name="consent_back" msgid="2560683030046918882">"رجوع"</string>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index f2f0b1e..38be80f 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"কম্পেনিয়ন ডিভাইচ মেনেজাৰ"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক আপোনাৰ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; এক্সেছ কৰিবলৈ দিয়ক"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ঘড়ী"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;এ পৰিচালনা কৰিব লগা এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক আপোনাৰ জাননী ব্যৱহাৰ কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক ,কেলেণ্ডাৰ, কল লগ আৰু নিকটৱৰ্তী ডিভাইচৰ অনুমতি এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক এই অনুমতিসমূহৰ সৈতে ভাব-বিনিময় কৰিবলৈ দিয়া হ’ব:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"চছ্‌মা"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এই এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক এই অনুমতিসমূহৰ সৈতে ভাব-বিনিময় কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক, মাইক্ৰ’ফ’ন আৰু নিকটৱৰ্তী ডিভাইচৰ অনুমতিসমূহ এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক এই অনুমতিসমূহৰ সৈতে ভাব-বিনিময় কৰিবলৈ দিয়া হ’ব:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক আপোনাৰ ফ’নৰ পৰা এই তথ্যখিনি এক্সেছ কৰাৰ অনুমতি দিয়ক"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্ৰছ-ডিভাইচ সেৱাসমূহ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ আপোনাৰ ডিভাইচসমূহৰ মাজত এপ্‌ ষ্ট্ৰীম কৰাৰ বাবে অনুৰোধ জনাইছে"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ক্ৰছ-ডিভাইচ সেৱাসমূহ"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ নিকটৱৰ্তী ডিভাইচত সমল ষ্ট্ৰীম কৰাৰ অনুমতি দিবলৈ অনুৰোধ জনাইছে"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইচ"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিয়ক"</string>
     <string name="consent_no" msgid="2640796915611404382">"অনুমতি নিদিব"</string>
     <string name="consent_back" msgid="2560683030046918882">"উভতি যাওক"</string>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index 454fa73..e333c51 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Kompanyon Cihaz Meneceri"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinin &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; cihazınıza girişinə icazə verin"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"izləyin"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; tərəfindən idarə ediləcək <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızı idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> bildirişlərinizə, Telefon, SMS, Kontaktlar, Təqvim, Zəng qeydləri və Yaxınlıqdakı cihaz icazələrinə giriş əldə edəcək."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızı idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> bu icazələrlə qarşılıqlı əlaqəyə icazə veriləcək:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"eynək"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Bu tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızı idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> bildirişlərinizə, Telefon, SMS, Kontaktlar, Mikrofon və Yaxınlıqdakı cihazlar icazələrinə giriş əldə edəcək."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızı idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> bu icazələrlə qarşılıqlı əlaqəyə icazə veriləcək:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinə telefonunuzdan bu məlumata giriş icazəsi verin"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlararası xidmətlər"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından cihazlarınız arasında tətbiqləri yayımlamaq üçün icazə istəyir"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cihazlararası xidmətlər"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından yaxınlıqdakı cihazlarda yayımlamaq üçün icazə istəyir"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"İcazə verin"</string>
     <string name="consent_no" msgid="2640796915611404382">"İcazə verməyin"</string>
     <string name="consent_back" msgid="2560683030046918882">"Geriyə"</string>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index 7734726..8564793 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Menadžer pridruženog uređaja"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Odaberite <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS, kontakte, kalendar, evidencije poziva i uređaje u blizini."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa ovim dozvolama:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"naočare"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS, kontakte, mikrofon i uređaje u blizini."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa ovim dozvolama:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa ovim informacijama sa telefona"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na više uređaja"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za strimovanje aplikacija između uređaja"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usluge na više uređaja"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> da strimuje sadržaj na uređaje u blizini"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ne dozvoli"</string>
     <string name="consent_back" msgid="2560683030046918882">"Nazad"</string>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index 0e60654..071dd6f 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Менеджар спадарожнай прылады"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Дазвольце праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ да вашай прылады &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"гадзіннік"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Выберыце прыладу (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа ўзаемадзейнічаць з вашымі апавяшчэннямі і атрымае доступ да тэлефона, SMS, кантактаў, календара, журналаў выклікаў і прылад паблізу."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа выкарыстоўваць наступныя дазволы:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"акуляры"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа ўзаемадзейнічаць з вашымі апавяшчэннямі і атрымае доступ да тэлефона, SMS, кантактаў, мікрафона і прылад паблізу."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа выкарыстоўваць наступныя дазволы:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Дазвольце праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; мець доступ да гэтай інфармацыі з вашага тэлефона"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сэрвісы для некалькіх прылад"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на трансляцыю праграм паміж вашымі прыладамі"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Сэрвісы для некалькіх прылад"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на перадачу змесціва плынню на прылады паблізу."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"прылада"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Дазволіць"</string>
     <string name="consent_no" msgid="2640796915611404382">"Не дазваляць"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index 1db64e4..780924a 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Разрешаване на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да осъществява достъп до устройството ви &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Изберете устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), което да се управлява от &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Това приложение е необходимо за управление на устройството ви (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи разрешение да взаимодейства с известията ви и да осъществява достъп до разрешенията за телефона, SMS съобщенията, контактите, календара, списъците с обажданията и разрешенията за устройства в близост."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Това приложение е необходимо за управление на устройството ви (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи разрешение да взаимодейства със следните разрешения:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"очилата"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи право да взаимодейства с известията ви, както и достъп до разрешенията за телефона, SMS съобщенията, контактите, микрофона и устройствата в близост."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ви. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи разрешение да взаимодейства със следните разрешения:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Разрешете на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да осъществява достъп до тази информация от телефона ви"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуги за различни устройства"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да предава поточно приложения между устройствата ви"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Услуги за различни устройства"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да предава поточно съдържание към устройства в близост"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Разрешаване"</string>
     <string name="consent_no" msgid="2640796915611404382">"Забраняване"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 3013457..88e334e 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"আপনার &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; অ্যাক্সেস করার জন্য &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-কে অনুমতি দিন"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ঘড়ি"</string>
     <string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন যেটি &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ম্যানেজ করবে"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে আপনার বিজ্ঞপ্তির সাথে ইন্টার‌্যাক্ট করার এবং ফোন, এসএমএস, পরিচিতি, ক্যালেন্ডার, কল লগ ও আশেপাশের ডিভাইস অ্যাক্সেস করার অনুমতি দেওয়া হবে।"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপকে এইসব অনুমতির সাথে ইন্টার‌্যাক্ট করার জন্য অনুমোদন দেওয়া হবে:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"চশমা"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করতে এই অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে আপনার বিজ্ঞপ্তির সাথে ইন্টার‌্যাক্ট করার জন্য অনুমতি দেওয়া হবে। এছাড়াও ফোন, এসএমএস, পরিচিতি, মাইক্রোফোন এবং আশেপাশের ডিভাইস ব্যবহার করার অনুমতি অ্যাক্সেস করতে দেওয়া হবে।"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপকে এইসব অনুমতির সাথে ইন্টার‌্যাক্ট করার জন্য অনুমোদন দেওয়া হবে:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"আপনার ফোন থেকে &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; অ্যাপকে এই তথ্য অ্যাক্সেস করার অনুমতি দিন"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্রস-ডিভাইস পরিষেবা"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"আপনার ডিভাইসগুলির মধ্যে অ্যাপ স্ট্রিম করার জন্য <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে অনুমতি চাইছে"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ক্রস-ডিভাইস পরিষেবা"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"আশেপাশের ডিভাইসে কন্টেন্ট স্ট্রিম করার জন্য আপনার <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে <xliff:g id="APP_NAME">%1$s</xliff:g> অনুমতি চাইছে"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিন"</string>
     <string name="consent_no" msgid="2640796915611404382">"অনুমতি দেবেন না"</string>
     <string name="consent_back" msgid="2560683030046918882">"ফিরুন"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index f3829b0..048e7739 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Prateći upravitelj uređaja"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Dozvolite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da pristupa uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Odaberite uređaj \"<xliff:g id="PROFILE_NAME">%1$s</xliff:g>\" kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će se dozvoliti da ostvaruje interakciju s vašim obavještenjima i da pristupa odobrenjima za telefon, SMS-ove, kontakte, kalendar, zapisnike poziva i uređaje u blizini."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljena interakcija s ovim odobrenjima:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"naočale"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljeno da stupi u interakciju s obavještenjima i pristupa odobrenjima telefona, SMS-a, kontakata, mikrofona i uređaja u blizini."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljena interakcija s ovim odobrenjima:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa ovim informacijama s telefona"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluga na više uređaja"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> zahtijeva odobrenje da prenosi aplikacije između vaših uređaja"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usluga na više uređaja"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva odobrenje u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> da prenosi sadržaj na uređajima u blizini"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nemoj dozvoliti"</string>
     <string name="consent_back" msgid="2560683030046918882">"Nazad"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index 0e0919c..c407a1c 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Gestor de dispositius complementaris"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Permet que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; accedeixi a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"rellotge"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> perquè el gestioni &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"L\'aplicació és necessària per gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes, al calendari, als registres de trucades i als dispositius propers."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"L\'aplicació és necessària per gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb aquests permisos:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ulleres"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Aquesta aplicació es necessita per gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes, al micròfon i als dispositius propers."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"L\'aplicació és necessària per gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb aquests permisos:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permet que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; accedeixi a aquesta informació del telèfon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serveis multidispositiu"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> per reproduir en continu aplicacions entre els dispositius"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Serveis multidispositiu"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu dispositiu (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) per reproduir contingut en continu en dispositius propers"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Permet"</string>
     <string name="consent_no" msgid="2640796915611404382">"No permetis"</string>
     <string name="consent_back" msgid="2560683030046918882">"Enrere"</string>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index 6f1bad7..6113d0b 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Správce doprovodných zařízení"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Povolit aplikaci &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; přístup k vašemu zařízení &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"hodinky"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Vyberte zařízení <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, které chcete spravovat pomocí aplikace &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikace <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci interagovat s vašimi oznámeními a získá přístup k telefonu, SMS, kontaktům, kalendáři, seznamům hovorů a zařízením v okolí."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikace <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci interagovat s těmito oprávněními:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"brýle"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Tato aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci interagovat s vašimi oznámeními a získat přístup k vašim oprávněním k telefonu, SMS, kontaktům, mikrofonu a zařízením v okolí."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikace <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci interagovat s těmito oprávněními:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Povolte aplikaci &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; přístup k těmto informacím z vašeho telefonu"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pro více zařízení"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> oprávnění ke streamování aplikací mezi zařízeními"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Služby pro více zařízení"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> oprávnění ke streamování obsahu do zařízení v okolí"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Povolit"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nepovolovat"</string>
     <string name="consent_back" msgid="2560683030046918882">"Zpět"</string>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index 2b6c42b..f1bf633 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Medfølgende enhedsadministrator"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Tillad, at &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; får adgang til dit &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ur"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Vælg det <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, som skal administreres af &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at interagere med dine notifikationer og får adgang til dine tilladelser for Opkald, Sms, Kalender, Opkaldshistorik og Enheder i nærheden."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får mulighed for at interagere med følgende tilladelser:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"briller"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at interagere med dine notifikationer og tilgå tilladelserne Telefon, Sms, Kontakter, Mikrofon og Enheder i nærheden."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får mulighed for at interagere med følgende tilladelser:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Giv &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; adgang til disse oplysninger fra din telefon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester, som kan tilsluttes en anden enhed"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at streame apps mellem dine enheder"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Tjenester til flere enheder"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at streame indhold til enheder i nærheden"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Tillad"</string>
     <string name="consent_no" msgid="2640796915611404382">"Tillad ikke"</string>
     <string name="consent_back" msgid="2560683030046918882">"Tilbage"</string>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index 32873c0..b914f2f 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Begleitgerät-Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; erlauben, auf dein Gerät (&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;) zuzugreifen"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"Smartwatch"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Gerät „<xliff:g id="PROFILE_NAME">%1$s</xliff:g>“ auswählen, das von &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; verwaltet werden soll"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“, „Kalender“, „Anrufliste“ und „Geräte in der Nähe“ zugreifen."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf mit diesen Berechtigungen interagieren:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Glass-Geräte"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Diese App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“, „Mikrofon“ und „Geräte in der Nähe“ zugreifen."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf mit diesen Berechtigungen interagieren:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; Zugriff auf diese Informationen von deinem Smartphone gewähren"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Geräteübergreifende Dienste"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> um die Berechtigung zum Streamen von Apps zwischen deinen Geräten"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Geräteübergreifende Dienste"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) um die Berechtigung zum Streamen von Inhalten auf Geräte in der Nähe"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Zulassen"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nicht zulassen"</string>
     <string name="consent_back" msgid="2560683030046918882">"Zurück"</string>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index 5567f3a..26fd793 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Διαχείριση συνοδευτικής εφαρμογής"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Επιτρέψτε στην εφαρμογή &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; να έχει πρόσβαση στη συσκευή &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ρολόι"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Επιλέξτε ένα προφίλ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> για διαχείριση από την εφαρμογή &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις ειδοποιήσεις και να έχει πρόσβαση στις άδειες Τηλέφωνο, SMS, Επαφές, Ημερολόγιο, Αρχεία καταγραφής κλήσεων και Συσκευές σε κοντινή απόσταση."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις εξής άδειες:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"γυαλιά"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Αυτή η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Θα επιτρέπεται στην εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> να αλληλεπιδρά με τις ειδοποιήσεις σας και να αποκτά πρόσβαση στις άδειες για το Τηλέφωνο, τα SMS, τις Επαφές, το Μικρόφωνο και τις Συσκευές σε κοντινή απόσταση."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις εξής άδειες:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Να επιτρέπεται στο &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; η πρόσβαση σε αυτές τις πληροφορίες από το τηλέφωνό σας."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Υπηρεσίες πολλών συσκευών"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά εκ μέρους της συσκευής σας <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> άδεια για ροή εφαρμογών μεταξύ των συσκευών σας"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Υπηρεσίες πολλών συσκευών"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά άδεια εκ μέρους της συσκευής <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> για ροή περιεχομένου σε συσκευές σε κοντινή απόσταση."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"συσκευή"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Να επιτρέπεται"</string>
     <string name="consent_no" msgid="2640796915611404382">"Να μην επιτρέπεται"</string>
     <string name="consent_back" msgid="2560683030046918882">"Πίσω"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index 897f343..ae65b88 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access your &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, calendar, call logs and Nearby devices permissions."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"This app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device services"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream content to nearby devices"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
     <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
     <string name="consent_back" msgid="2560683030046918882">"Back"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index 9905f28..9edc007 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access your &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"This app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device services"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream content to nearby devices"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
     <string name="consent_no" msgid="2640796915611404382">"Don’t allow"</string>
     <string name="consent_back" msgid="2560683030046918882">"Back"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index 897f343..ae65b88 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access your &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, calendar, call logs and Nearby devices permissions."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"This app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device services"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream content to nearby devices"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
     <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
     <string name="consent_back" msgid="2560683030046918882">"Back"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index 897f343..ae65b88 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access your &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, calendar, call logs and Nearby devices permissions."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"This app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device services"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream content to nearby devices"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
     <string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
     <string name="consent_back" msgid="2560683030046918882">"Back"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
index 073aeca..6dbd615 100644
--- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎Companion Device Manager‎‏‎‎‏‎"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to access your &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt;‎‏‎‎‏‎"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎watch‎‏‎‎‏‎"</string>
     <string name="chooser_title" msgid="2262294130493605839">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎Choose a ‎‏‎‎‏‏‎<xliff:g id="PROFILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to be managed by &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt;‎‏‎‎‏‎"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎The app is needed to manage your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions.‎‏‎‎‏‎"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎The app is needed to manage your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to interact with these permissions:‎‏‎‎‏‎"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎glasses‎‏‎‎‏‎"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎This app is needed to manage your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.‎‏‎‎‏‎"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎The app is needed to manage your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to interact with these permissions:‎‏‎‎‏‎"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to access this information from your phone‎‏‎‎‏‎"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎Cross-device services‎‏‎‎‏‎"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is requesting permission on behalf of your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to stream apps between your devices‎‏‎‎‏‎"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎Cross-device services‎‏‎‎‏‎"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is requesting permission on behalf of your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to stream content to nearby devices‎‏‎‎‏‎"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎device‎‏‎‎‏‎"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎Allow‎‏‎‎‏‎"</string>
     <string name="consent_no" msgid="2640796915611404382">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎Don’t allow‎‏‎‎‏‎"</string>
     <string name="consent_back" msgid="2560683030046918882">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎Back‎‏‎‎‏‎"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index 804c80b..85333a9 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Administrador de dispositivo complementario"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Permite que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a tu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que la app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; lo administre"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Calendario, Llamadas y Dispositivos cercanos."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con estos permisos:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Gafas"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Micrófono y Dispositivos cercanos."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con estos permisos:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permite que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información de tu teléfono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para transmitir apps entre dispositivos"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servicios multidispositivo"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para transmitir contenido a dispositivos cercanos"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index 5b25e15..c5127e8 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos complementario"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a tu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para gestionarlo con &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Se necesita la aplicación para gestionar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos, calendario, registros de llamadas y dispositivos cercanos."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Se necesita la aplicación para gestionar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Se permitirá que <xliff:g id="APP_NAME">%2$s</xliff:g> interaccione con los siguientes permisos:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"gafas"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Se necesita esta aplicación para gestionar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos, micrófono y dispositivos cercanos."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Se necesita la aplicación para gestionar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Se permitirá que <xliff:g id="APP_NAME">%2$s</xliff:g> interaccione con los siguientes permisos:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información de tu teléfono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para emitir aplicaciones en otros dispositivos tuyos"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servicios multidispositivo"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para reproducir contenido en dispositivos cercanos"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index ed7507b..cd362de 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Kaasseadme haldur"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Lubage rakendusel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; teie seadmele &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; juurde pääseda"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"käekell"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Valige <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mida haldab rakendus &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide, kalendri, kõnelogide ja läheduses olevate seadmete lubadele."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada järgmisi lube."</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"prillid"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide, mikrofoni ja läheduses olevate seadmete lubadele."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada järgmisi lube."</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Lubage rakendusel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pääseda teie telefonis juurde sellele teabele"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Seadmeülesed teenused"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi voogesitada"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Seadmeülesed teenused"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba voogesitada sisu läheduses olevates seadmetes"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"seade"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Luba"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ära luba"</string>
     <string name="consent_back" msgid="2560683030046918882">"Tagasi"</string>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index 4b71149..9b67fad 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Gailu osagarriaren kudeatzailea"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Eman &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; atzitzeko baimena &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"erlojua"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Aukeratu &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; aplikazioak kudeatu beharreko <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Jakinarazpenekin interakzioan aritzeko, eta telefonoa, SMSak, kontaktuak, egutegia, deien erregistroak eta inguruko gailuak erabiltzeko baimenak izango ditu <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Baimen hauek izango ditu <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"betaurrekoak"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Aplikazioa <xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da. Jakinarazpenekin interakzioan aritzeko, eta telefonoa, SMSak, kontaktuak, mikrofonoa eta inguruko gailuak erabiltzeko baimena izango du <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Baimen hauek izango ditu <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Eman informazioa telefonotik hartzeko baimena &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Gailu baterako baino gehiagotarako zerbitzuak"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Gailu batetik bestera aplikazioak igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuaren izenean"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Gailu baterako baino gehiagotarako zerbitzuak"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Inguruko gailuetara edukia igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuaren izenean"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Eman baimena"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ez eman baimenik"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atzera"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 101353e..1d283f0 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"مدیر دستگاه مرتبط"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"‏به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; اجازه دهید به &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; دسترسی داشته باشد"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ساعت"</string>
     <string name="chooser_title" msgid="2262294130493605839">"‏انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای مدیریت کردن با &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>‏&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. <xliff:g id="APP_NAME">%2$s</xliff:g> می‌تواند با اعلان‌های شما تعامل داشته باشد و به اجازه‌های «تلفن»، «پیامک»، «مخاطبین»، «تقویم»، «گزارش‌های تماس» و «دستگاه‌های اطراف» دسترسی خواهد داشت."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. <xliff:g id="APP_NAME">%2$s</xliff:g> مجاز است با این اجازه‌ها تعامل داشته باشد:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"عینک"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. به <xliff:g id="APP_NAME">%2$s</xliff:g> اجازه داده می‌شود با اعلان‌های شما تعامل داشته باشد و به اجازه‌های «تلفن»، «پیامک»، «مخاطبین»، «میکروفون»، و «دستگاه‌های اطراف» دسترسی داشته باشد."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. <xliff:g id="APP_NAME">%2$s</xliff:g> مجاز می‌شود با این اجازه‌ها تعامل داشته باشد:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"‏اجازه دادن به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; برای دسترسی به اطلاعات تلفن"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"سرویس‌های بین‌دستگاهی"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> اجازه می‌خواهد ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> برنامه‌ها را بین دستگاه‌های شما جاری‌سازی کند"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"سرویس‌های بین‌دستگاهی"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> اجازه می‌خواهد تا در دستگاه‌های اطراف محتوا جاری‌سازی کند."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"اجازه دادن"</string>
     <string name="consent_no" msgid="2640796915611404382">"اجازه ندادن"</string>
     <string name="consent_back" msgid="2560683030046918882">"برگشتن"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index e92cabb..f1acf5c 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Salli, että &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; saa pääsyn laitteeseesi: &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"kello"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Valitse <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, jota &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; hallinnoi"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Laitteen (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) ylläpitoon tarvitaan tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa luvan hallinnoida ilmoituksiasi sekä pääsyn puhelimeen, tekstiviesteihin, yhteystietoihin, kalenteriin, puhelulokeihin ja lähellä olevat laitteet ‑lupiin."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Laitteen (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) ylläpitoon tarvitaan tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa käyttää näitä lupia:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"lasit"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Ylläpitoon (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) tarvitaan tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa luvan hallinnoida ilmoituksiasi sekä pääsyn puhelimeen, tekstiviesteihin, yhteystietoihin, mikrofoniin ja lähellä olevat laitteet ‑lupiin."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Ylläpitoon (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) tarvitaan tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa käyttää näitä lupia:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Salli, että &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; saa pääsyn näihin puhelimesi tietoihin"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Laitteidenväliset palvelut"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) puolesta lupaa striimata sovelluksia laitteidesi välillä"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Laitteidenväliset palvelut"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) puolesta lupaa striimata sisältöä lähellä oleviin laitteisiin"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"laite"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Salli"</string>
     <string name="consent_no" msgid="2640796915611404382">"Älä salli"</string>
     <string name="consent_back" msgid="2560683030046918882">"Takaisin"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index 6e3df3e..3f9ec0b 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareil compagnon"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à votre &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Choisissez un(e) <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"L\'application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations suivantes : téléphone, messages texte, contacts, agenda, journaux d\'appels et appareils à proximité."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"L\'application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec ces autorisations :"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"lunettes"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Cette application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> sera autorisée à interagir avec vos notifications et à accéder à vos autorisations pour le téléphone, les messages texte, les contacts, le microphone et les appareils à proximité."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"L\'application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec ces autorisations :"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Autorisez &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à ces informations à partir de votre téléphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services multiappareils"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour diffuser des applications entre vos appareils"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Services multiappareils"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de diffuser du contenu aux appareils à proximité"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
     <string name="consent_back" msgid="2560683030046918882">"Retour"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index 5a93dc4..d05087d 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareils associés"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à votre &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Sélectionnez le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder au téléphone, aux SMS, aux contacts, à l\'agenda, aux journaux d\'appels et aux appareils à proximité."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> pourra interagir avec ces autorisations :"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"lunettes"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations du téléphone, des SMS, des contacts, du micro et des appareils à proximité."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> pourra interagir avec ces autorisations :"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à ces informations depuis votre téléphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services inter-appareils"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour caster des applis d\'un appareil à l\'autre"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Services inter-appareils"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de diffuser du contenu en streaming sur les appareils à proximité"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
     <string name="consent_back" msgid="2560683030046918882">"Retour"</string>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index 25ce2ba..f3e2d43 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Xestor de dispositivos complementarios"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda ao teu dispositivo (&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;)"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"reloxo"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Escolle un dispositivo (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) para que o xestione a aplicación &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"A aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das SMS, dos contactos, do calendario, dos rexistros de chamadas e dos dispositivos próximos."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"A aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar con estes permisos:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"lentes"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Esta aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teléfono, das SMS, dos contactos, do micrófono e dos dispositivos próximos."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"A aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar con estes permisos:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que a aplicación &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información desde o teu teléfono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizos multidispositivo"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para emitir contido de aplicacións entre os teus aparellos"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servizos multidispositivo"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para emitir contido aos dispositivos próximos"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"Non permitir"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index 4cfea49..5e21ccb 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"કમ્પેનિયન ડિવાઇસ મેનેજર"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"તમારા &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;ને ઍક્સેસ કરવાની &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને મંજૂરી આપો"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"સ્માર્ટવૉચ"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; દ્વારા મેનેજ કરવા માટે કોઈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> પસંદ કરો"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"તમારી <xliff:g id="DEVICE_NAME">%1$s</xliff:g> મેનેજ કરવા માટે ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની તેમજ તમારો ફોન, SMS, સંપર્કો, કૅલેન્ડર, કૉલ લૉગ અને નજીકના ડિવાઇસની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"તમારી <xliff:g id="DEVICE_NAME">%1$s</xliff:g> મેનેજ કરવા માટે ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને આ પરવાનગીઓ સાથે ક્રિયાપ્રતિક્રિયા કરવાની મંજૂરી આપવામાં આવશે:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ચશ્માં"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"તમારા <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે આ ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની અને તમારો ફોન, SMS, સંપર્કો, માઇક્રોફોન તથા નજીકના ડિવાઇસની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"તમારા <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને આ પરવાનગીઓ સાથે ક્રિયાપ્રતિક્રિયા કરવાની મંજૂરી આપવામાં આવશે:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"તમારા ફોનમાંથી આ માહિતી ઍક્સેસ કરવા માટે, &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને મંજૂરી આપો"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ક્રોસ-ડિવાઇસ સેવાઓ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> વતી તમારા ડિવાઇસ વચ્ચે ઍપ સ્ટ્રીમ કરવાની પરવાનગીની વિનંતી કરી રહી છે"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ક્રૉસ-ડિવાઇસ સેવાઓ"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> નજીકના ડિવાઇસ પર કન્ટેન્ટ સ્ટ્રીમ કરવા માટે તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> વતી પરવાનગીની વિનંતી કરી રહી છે"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ડિવાઇસ"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"મંજૂરી આપો"</string>
     <string name="consent_no" msgid="2640796915611404382">"મંજૂરી આપશો નહીં"</string>
     <string name="consent_back" msgid="2560683030046918882">"પાછળ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index b9492cc..4c52ad7 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"सहयोगी डिवाइस मैनेजर"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ऐक्सेस करने की अनुमति दें"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"स्मार्टवॉच"</string>
     <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; की मदद से मैनेज किया जा सके"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को अनुमति होगी कि यह आपकी सूचनाओं पर कार्रवाई कर सके और आपके फ़ोन, एसएमएस, संपर्कों, कैलेंडर, कॉल लॉग, और आस-पास मौजूद डिवाइसों को ऐक्सेस कर सके."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g>, इन अनुमतियों का इस्तेमाल कर पाएगा:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"चश्मा"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को अनुमति होगी कि यह आपकी सूचनाओं पर कार्रवाई कर सके. साथ ही, आपके फ़ोन, मैसेज, संपर्कों, माइक्रोफ़ोन, और आस-पास मौजूद डिवाइसों को ऐक्सेस कर सके."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g>, इन अनुमतियों का इस्तेमाल करके इंटरैक्ट कर पाएगा:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, आपके डिवाइसों के बीच ऐप्लिकेशन को स्ट्रीम करने की अनुमति मांग रहा है"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, कॉन्टेंट को आस-पास मौजूद डिवाइसों पर स्ट्रीम करने की अनुमति मांग रहा है"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"अनुमति दें"</string>
     <string name="consent_no" msgid="2640796915611404382">"अनुमति न दें"</string>
     <string name="consent_back" msgid="2560683030046918882">"वापस जाएं"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index 15e2b22..e7ed8cb 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Dopustite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da pristupa vašem uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"satom"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Odaberite <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Aplikacija je potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati dopuštenjima za telefon, SMS-ove, kontakte, kalendar, zapisnike poziva i uređaje u blizini."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacija je potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s ovim dopuštenjima:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"naočale"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Ta je aplikacija potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati vašim dopuštenjima za telefon, SMS-ove, kontakte, mikrofon i uređaje u blizini."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Aplikacija je potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s ovim dopuštenjima:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Omogućite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da pristupa informacijama s vašeg telefona"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na različitim uređajima"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za emitiranje aplikacija između vaših uređaja"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usluge na različitim uređajima"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za streamanje sadržaja na uređaje u blizini"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Dopusti"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nemoj dopustiti"</string>
     <string name="consent_back" msgid="2560683030046918882">"Natrag"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index 6a07011..cfd6ad4 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Társeszközök kezelője"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"A(z) &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; hozzáférésének engedélyezése a(z) &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; eszközhöz"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"óra"</string>
     <string name="chooser_title" msgid="2262294130493605839">"A(z) &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; alkalmazással kezelni kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiválasztása"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Szükség van az alkalmazásra a következő kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet a telefonra, az SMS-ekre, a névjegyekre, a naptárra, a hívásnaplókra és a közeli eszközökre vonatkozó engedélyekhez."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Szükség van az alkalmazásra a következő kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd ezekkel az engedélyekkel:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"szemüveg"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Szükség van erre az alkalmazásra a következő kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet majd a Telefon, az SMS, a Névjegyek, a Mikrofon és a Közeli eszközök engedélyekhez."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Szükség van az alkalmazásra a következő kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd ezekkel az engedélyekkel:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Engedélyezi a(z) „<xliff:g id="APP_NAME">%1$s</xliff:g>” alkalmazás számára az információhoz való hozzáférést a telefonról"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Többeszközös szolgáltatások"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében az alkalmazások eszközök közötti streameléséhez"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Többeszközös szolgáltatások"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében a közeli eszközökre való streameléséhez."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Engedélyezés"</string>
     <string name="consent_no" msgid="2640796915611404382">"Tiltás"</string>
     <string name="consent_back" msgid="2560683030046918882">"Vissza"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index 4ff57bc..0d88acb 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Թույլատրեք &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին կառավարել ձեր &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; սարքը"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ժամացույց"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Ընտրեք <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ը, որը պետք է կառավարվի &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; հավելվածի կողմից"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Այս հավելվածն անհրաժեշտ է ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g> պրոֆիլը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածը կկարողանա փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ», «Օրացույց», «Կանչերի ցուցակ» և «Մոտակա սարքեր» թույլտվությունները։"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Այս հավելվածն անհրաժեշտ է ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g> պրոֆիլը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածին կթույլատրվի օգտվել այս թույլտվություններից․"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ակնոց"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Այս հավելվածն անհրաժեշտ է ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածը կկարողանա փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ», «Խոսափող» և «Մոտակա սարքեր» թույլտվությունները։"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Հավելվածն անհրաժեշտ է ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածին կթույլատրվի օգտվել այս թույլտվություններից․"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Թույլատրեք &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին օգտագործել այս տեղեկությունները ձեր հեռախոսից"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Միջսարքային ծառայություններ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Միջսարքային ծառայություններ"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ մոտակա սարքերին բովանդակություն հեռարձակելու համար"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Թույլատրել"</string>
     <string name="consent_no" msgid="2640796915611404382">"Չթույլատրել"</string>
     <string name="consent_back" msgid="2560683030046918882">"Հետ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index 39e288a..5394808 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Pengelola Perangkat Pendamping"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengakses &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"smartwatch"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk dikelola oleh &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Telepon, SMS, Kontak, Kalender, Log panggilan, dan Perangkat di sekitar."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan izin ini:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Aplikasi ini diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Telepon, SMS, Kontak, Mikrofon, dan Perangkat di sekitar."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan izin ini:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; untuk mengakses informasi ini dari ponsel Anda"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Layanan lintas perangkat"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk menstreaming aplikasi di antara perangkat Anda"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Layanan lintas perangkat"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk menstreaming konten ke perangkat di sekitar"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Izinkan"</string>
     <string name="consent_no" msgid="2640796915611404382">"Jangan izinkan"</string>
     <string name="consent_back" msgid="2560683030046918882">"Kembali"</string>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index 655b843..81c7864 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Stjórnun fylgdartækja"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Veita &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aðgang að &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"úr"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Velja <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sem &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; á að stjórna"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Forritið er nauðsynlegt til að hafa umsjón með <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær aðgang að tilkynningum og heimildum síma, SMS, tengiliða, dagatals, símtalaskráa og nálægra tækja."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Forritið er nauðsynlegt til að hafa umsjón með <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær aðgang að eftirfarandi heimildum:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"gleraugu"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Þetta forrit er nauðsynlegt til að hafa umsjón með <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær heimild til að bregðast við tilkynningum og fær aðgang að heimildum fyrir síma, SMS, tengiliði, hljóðnema og nálæg tæki."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Forritið er nauðsynlegt til að stjórna <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær aðgang að eftirfarandi heimildum:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Veita &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aðgang að þessum upplýsingum úr símanum þínum"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Þjónustur á milli tækja"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> sendir beiðni um heimild til straumspilunar forrita á milli tækjanna þinna fyrir hönd <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Þjónustur á milli tækja"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til að streyma efni í nálægum tækjum"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Leyfa"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ekki leyfa"</string>
     <string name="consent_back" msgid="2560683030046918882">"Til baka"</string>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index 49b1fbd..8b5534d 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Gestione dispositivi companion"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Consenti all\'app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di accedere &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"orologio"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> da gestire con &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti, Calendario, Registri chiamate e Dispositivi nelle vicinanze."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le seguenti autorizzazioni:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"occhiali"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti, Microfono e Dispositivi nelle vicinanze."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le seguenti autorizzazioni:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Consenti a &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di accedere a queste informazioni dal tuo telefono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizi cross-device"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto del tuo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> l\'autorizzazione a trasmettere app in streaming tra i dispositivi"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servizi cross-device"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto di <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> l\'autorizzazione a trasmettere contenuti in streaming ai dispositivi nelle vicinanze"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Consenti"</string>
     <string name="consent_no" msgid="2640796915611404382">"Non consentire"</string>
     <string name="consent_back" msgid="2560683030046918882">"Indietro"</string>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index 167e216..f0be367 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"ניהול מכשיר מותאם"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"‏אישור לאפליקציה ‎&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&amp;g;‎‏ לגשת אל ‎&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;‎‏"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"שעון"</string>
     <string name="chooser_title" msgid="2262294130493605839">"‏בחירת <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"‏האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לבצע פעולות בהתראות ותקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר, ליומן, ליומני השיחות ולמכשירים בקרבת מקום."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לקיים אינטראקציה עם ההרשאות הבאות:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"משקפיים"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"‏האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לבצע פעולות בהתראות ותקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר, למיקרופון ולמכשירים בקרבת מקום."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לקיים אינטראקציה עם ההרשאות הבאות:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"‏מתן אישור לאפליקציה &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; לגשת למידע הזה מהטלפון שלך"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"שירותים למספר מכשירים"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור מכשיר <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> כדי לשדר אפליקציות בין המכשירים שלך"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"שירותים למספר מכשירים"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור מכשיר <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> כדי להעביר תוכן בסטרימינג למכשירים בקרבת מקום."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"מכשיר"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"יש אישור"</string>
     <string name="consent_no" msgid="2640796915611404382">"אין אישור"</string>
     <string name="consent_back" msgid="2560683030046918882">"חזרה"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index 599bffa..6eda60b 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"コンパニオン デバイス マネージャー"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; へのアクセスを許可"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ウォッチ"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; の管理対象となる<xliff:g id="PROFILE_NAME">%1$s</xliff:g>の選択"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"このアプリは<xliff:g id="DEVICE_NAME">%1$s</xliff:g>の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は、通知の使用と、電話、SMS、連絡先、カレンダー、通話履歴、付近のデバイスの権限へのアクセスが可能となります。"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"このアプリは<xliff:g id="DEVICE_NAME">%1$s</xliff:g>の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は、次の権限の使用が可能となります。"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"このアプリは<xliff:g id="DEVICE_NAME">%1$s</xliff:g>の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は、通知を操作し、電話、SMS、連絡先、マイク、付近のデバイスの権限を利用することができます。"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"このアプリは<xliff:g id="DEVICE_NAME">%1$s</xliff:g>の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は、次の権限の使用が可能となります。"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"スマートフォンのこの情報へのアクセスを &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に許可"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"クロスデバイス サービス"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わってデバイス間でアプリをストリーミングする権限をリクエストしています"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"クロスデバイス サービス"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わって付近のデバイスにコンテンツをストリーミングする権限をリクエストしています"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"デバイス"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"許可"</string>
     <string name="consent_no" msgid="2640796915611404382">"許可しない"</string>
     <string name="consent_back" msgid="2560683030046918882">"戻る"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index 0f578ea..4d7be34 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"კომპანიონი მოწყობილობების მენეჯერი"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"დაუშვით &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ის&lt;/strong&gt;, წვდომა თქვენს &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>-ზე&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"საათი"</string>
     <string name="chooser_title" msgid="2262294130493605839">"აირჩიეთ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, რომელიც უნდა მართოს &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;-მა"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"ეს აპი საჭიროა, რომ მართოთ თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> შეძლებს თქვენს შეტყობინებებთან ინტერაქციას და თქვენი ტელეფონის, SMS-ების, კონტაქტებისა, კალენდრის, ზარების ჟურნალისა და ახლომახლო მოწყობილობების ნებართვებზე წვდომას."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"ეს აპი საჭიროა, რომ მართოთ თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> შეძლებს ინტერაქციას შემდეგი ნებართვებით:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"სათვალე"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"ეს აპი საჭიროა თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ს სამართავად. <xliff:g id="APP_NAME">%2$s</xliff:g> შეძლებს თქვენს შეტყობინებებთან ინტერაქციას და თქვენს ტელეფონზე, SMS-ებზე, კონტაქტებზე, მიკროფონსა და ახლომახლო მოწყობილობების ნებართვებზე წვდომას."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"ეს აპი საჭიროა, რომ მართოთ თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> შეძლებს ინტერაქციას შემდეგი ნებართვებით:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"ნება დართეთ, რომ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; აპს ჰქონდეს ამ ინფორმაციაზე წვდომა თქვენი ტელეფონიდან"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"მოწყობილობათშორისი სერვისები"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს უფლებას თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის სახელით, რომ მოწყობილობებს შორის აპების სტრიმინგი შეძლოს"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"მოწყობილობათშორისი სერვისები"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს ნებართვას თქვენი სახელით<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> კონტენტის სტრიმინგისთვის ახლომდებარე მოწყობილობებზე"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"მოწყობილობა"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"დაშვება"</string>
     <string name="consent_no" msgid="2640796915611404382">"არ დაიშვას"</string>
     <string name="consent_back" msgid="2560683030046918882">"უკან"</string>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index 883269d..622834b 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; құрылғысын пайдалануға рұқсат беру"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"сағат"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; арқылы басқарылатын <xliff:g id="PROFILE_NAME">%1$s</xliff:g> құрылғысын таңдаңыз"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына хабарландыруларға қатысты әрекет жасау, телефон, SMS, контактілер, күнтізбе, қоңырау журналдары қолданбаларын және маңайдағы құрылғыларды пайдалану рұқсаттары беріледі."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына осы рұқсаттар беріледі:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"көзілдірік"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Бұл қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына хабарландыруларды оқуға, телефонды, хабарларды, контактілерді, микрофон мен маңайдағы құрылғыларды пайдалануға рұқсат беріледі."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына осы рұқсаттар беріледі:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына телефоныңыздағы осы ақпаратты пайдалануға рұқсат беріңіз."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Аралық құрылғы қызметтері"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан құрылғылар арасында қолданбалар трансляциялау үшін рұқсат сұрайды."</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Аралық құрылғы қызметтері"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы маңайдағы құрылғыларға <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан контент трансляциялау үшін рұқсат сұрайды."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"құрылғы"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Рұқсат беру"</string>
     <string name="consent_no" msgid="2640796915611404382">"Рұқсат бермеу"</string>
     <string name="consent_back" msgid="2560683030046918882">"Артқа"</string>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index e46c791..455f882 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"កម្មវិធី​គ្រប់​គ្រង​ឧបករណ៍ដៃគូ"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ចូលប្រើប្រាស់ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; របស់អ្នក"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"នាឡិកា"</string>
     <string name="chooser_title" msgid="2262294130493605839">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីឱ្យស្ថិតក្រោម​ការគ្រប់គ្រងរបស់ &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើអន្តរកម្មជាមួយ​ការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាតទូរសព្ទ, SMS, ទំនាក់ទំនង, ប្រតិទិន, កំណត់​ហេតុ​ហៅ​ទូរសព្ទ និងឧបករណ៍នៅជិតរបស់អ្នក។"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការអនុញ្ញាតទាំងនេះ៖"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"វ៉ែនតា"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើអន្តរកម្មជាមួយ​ការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាត​របស់ទូរសព្ទ, SMS, ទំនាក់ទំនង, មីក្រូហ្វូន និងឧបករណ៍នៅជិត​របស់អ្នក។"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការអនុញ្ញាតទាំងនេះ៖"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ចូលប្រើព័ត៌មាននេះពីទូរសព្ទរបស់អ្នក"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"សេវាកម្មឆ្លងកាត់ឧបករណ៍"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីបញ្ចាំងកម្មវិធីរវាងឧបករណ៍របស់អ្នក"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"សេវាកម្មឆ្លងកាត់ឧបករណ៍"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីផ្សាយខ្លឹមសារទៅឧបករណ៍នៅជិត"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ឧបករណ៍"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"អនុញ្ញាត"</string>
     <string name="consent_no" msgid="2640796915611404382">"មិនអនុញ្ញាត"</string>
     <string name="consent_back" msgid="2560683030046918882">"ថយក្រោយ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index c81a441..405167d 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"ಕಂಪ್ಯಾನಿಯನ್ ಸಾಧನ ನಿರ್ವಾಹಕರು"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"ನಿಮ್ಮ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ಅನ್ನು ಪ್ರವೇಶಿಸಲು &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ಗೆ ಅನುಮತಿಸಿ"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ವೀಕ್ಷಿಸಿ"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ಮೂಲಕ ನಿರ್ವಹಿಸಬೇಕಾದ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ನಿಮ್ಮ ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು, Calendar, ಕರೆಯ ಲಾಗ್‌ಗಳು ಹಾಗೂ ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳ ಅನುಮತಿಗಳನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಈ ಅನುಮತಿಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಅನುಮತಿಸಲಾಗುವುದು:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ಗ್ಲಾಸ್‌ಗಳು"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಈ ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. ನಿಮ್ಮ ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು, ಮೈಕ್ರೊಫೋನ್ ಮತ್ತು ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳ ಅನುಮತಿಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಹಾಗೂ ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಈ ಅನುಮತಿಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಅನುಮತಿಸಲಾಗುತ್ತದೆ:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ಈ ಮಾಹಿತಿಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ಗೆ ಅನುಮತಿಸಿ"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ಕ್ರಾಸ್-ಡಿವೈಸ್ ಸೇವೆಗಳು"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಿಕೊಳ್ಳುತ್ತಿದೆ"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ಕ್ರಾಸ್-ಡಿವೈಸ್ ಸೇವೆಗಳು"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"ಕಂಟೆಂಟ್ ಅನ್ನು ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳಿಗೆ ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಗಾಗಿ ವಿನಂತಿಸುತ್ತಿದೆ"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ಸಾಧನ"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"ಅನುಮತಿಸಿ"</string>
     <string name="consent_no" msgid="2640796915611404382">"ಅನುಮತಿಸಬೇಡಿ"</string>
     <string name="consent_back" msgid="2560683030046918882">"ಹಿಂದೆ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index 190ad22..38740f5 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"부속 기기 관리자"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;에서 내 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; 기기에 액세스하도록 허용"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"시계"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;에서 관리할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g>을(를) 선택"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 알림과 상호작용하고 내 전화, SMS, 연락처, Calendar, 통화 기록, 근처 기기에 대한 권한을 갖게 됩니다."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 다음 권한과 상호작용할 수 있습니다."</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"안경"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 알림과 상호작용하고 내 전화, SMS, 연락처, 마이크, 근처 기기에 대한 권한을 갖게 됩니다."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 다음 권한과 상호작용할 수 있습니다."</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;이 휴대전화의 이 정보에 액세스하도록 허용합니다."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"교차 기기 서비스"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 기기 간에 앱을 스트리밍할 수 있는 권한을 요청하고 있습니다."</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"교차 기기 서비스"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 근처 기기로 콘텐츠를 스트리밍할 수 있는 권한을 요청하고 있습니다."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"기기"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"허용"</string>
     <string name="consent_no" msgid="2640796915611404382">"허용 안함"</string>
     <string name="consent_back" msgid="2560683030046918882">"뒤로"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 8bd9a9c..705d984 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; түзмөгүңүзгө кирүүгө уруксат бериңиз"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"саат"</string>
     <string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; тарабынан башкарылсын"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздү тескөө үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> билдирмелериңизди көрүп, телефонуңуз, SMS билдирүүлөр, байланыштар, жылнаама, чалуулар тизмеси жана жакын жердеги түзмөктөргө болгон уруксаттарды пайдалана алат."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздү тескөө үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> төмөнкү уруксаттарды пайдалана алат:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"көз айнектер"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздү башкаруу үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> билдирмелериңизди көрүп, телефонуңуз, SMS билдирүүлөр, Байланыштар, Микрофон жана Жакын жердеги түзмөктөргө болгон уруксаттарды пайдалана алат."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздү тескөө үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> төмөнкү уруксаттарды пайдалана алат:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна телефонуңуздагы ушул маалыматты көрүүгө уруксат бериңиз"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Түзмөктөр аралык кызматтар"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрүңүздүн ортосунда колдонмолорду өткөрүүгө уруксат сурап жатат"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Түзмөктөр аралык кызматтар"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан жакын жердеги түзмөктөрдө контентти алып ойнотууга уруксат сурап жатат"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Ооба"</string>
     <string name="consent_no" msgid="2640796915611404382">"Уруксат берилбесин"</string>
     <string name="consent_back" msgid="2560683030046918882">"Артка"</string>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index f093aba..4ba1678 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"ຕົວຈັດການອຸປະກອນປະກອບ"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"ອະນຸຍາດ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ໃຫ້ເຂົ້າເຖິງ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ຂອງທ່ານໄດ້"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ໂມງ"</string>
     <string name="chooser_title" msgid="2262294130493605839">"ເລືອກ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ເພື່ອໃຫ້ຖືກຈັດການໂດຍ &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"ຕ້ອງໃຊ້ແອັບດັ່ງກ່າວເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ເຂົ້າເຖິງການອະນຸຍາດໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່, ປະຕິທິນ, ບັນທຶກການໂທ ແລະ ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງຂອງທ່ານ."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"ຕ້ອງໃຊ້ແອັບດັ່ງກ່າວເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການອະນຸຍາດເຫຼົ່ານີ້:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ແວ່ນຕາ"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"ຕ້ອງໃຊ້ແອັບນີ້ເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ການອະນຸຍາດສິດເຂົ້າເຖິງໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່, ໄມໂຄຣໂຟນ ແລະ ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງຂອງທ່ານ."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"ຕ້ອງໃຊ້ແອັບດັ່ງກ່າວເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການອະນຸຍາດເຫຼົ່ານີ້:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"ອະນຸຍາດ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນນີ້ຈາກໂທລະສັບຂອງທ່ານໄດ້"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ບໍລິການຂ້າມອຸປະກອນ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ເພື່ອສະຕຣີມແອັບລະຫວ່າງອຸປະກອນຂອງທ່ານ"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ບໍລິການຂ້າມອຸປະກອນ"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານເພື່ອສະຕຣີມເນື້ອຫາໄປຫາອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ອຸປະກອນ"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"ອະນຸຍາດ"</string>
     <string name="consent_no" msgid="2640796915611404382">"ບໍ່ອະນຸຍາດ"</string>
     <string name="consent_back" msgid="2560683030046918882">"ກັບຄືນ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index 7c74c69..843d54b 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Leisti &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pasiekti jūsų &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"laikrodį"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Jūsų <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, kurį valdys &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; (pasirinkite)"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Programa reikalinga norint tvarkyti jūsų <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sąveikauti su pranešimų funkcija ir pasiekti Telefono, SMS, Kontaktų, Kalendoriaus, Skambučių žurnalų ir Įrenginių netoliese leidimus."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Programa reikalinga norint tvarkyti jūsų <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sąveikauti su toliau nurodytais leidimais."</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"akiniai"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Ši programa reikalinga norint tvarkyti jūsų įrenginį „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“. Programai „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sąveikauti su jūsų pranešimais ir pasiekti jūsų leidimus „Telefonas“, „SMS“, „Kontaktai“, „Mikrofonas“ ir „Įrenginiai netoliese“."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Programa reikalinga norint tvarkyti jūsų įrenginį „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“. „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sąveikauti su toliau nurodytais leidimais."</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Leisti &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pasiekti šią informaciją iš jūsų telefono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Pasl. keliuose įrenginiuose"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti programas iš vieno įrenginio į kitą"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Keliais įreng. naud. paslaugos"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti turinį įrenginiams netoliese"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"įrenginys"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Leisti"</string>
     <string name="consent_no" msgid="2640796915611404382">"Neleisti"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atgal"</string>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index 15cce52..581c84a 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Palīgierīču pārzinis"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Atļauja lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; piekļūt jūsu ierīcei &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"pulkstenis"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Profila (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) izvēle, ko pārvaldīt lietotnē &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. Lietotnei <xliff:g id="APP_NAME">%2$s</xliff:g> tiks atļauts mijiedarboties ar jūsu paziņojumiem un piekļūt šādām atļaujām: Tālrunis, Īsziņas, Kontaktpersonas, Kalendārs, Zvanu žurnāli un Tuvumā esošas ierīces."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. Lietotnei <xliff:g id="APP_NAME">%2$s</xliff:g> tiks atļauts mijiedarboties ar šīm atļaujām:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"brilles"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. <xliff:g id="APP_NAME">%2$s</xliff:g> drīkstēs mijiedarboties ar jūsu paziņojumiem un piekļūt atļaujām Tālrunis, Īsziņas, Kontaktpersonas, Mikrofons un Tuvumā esošas ierīces."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. Lietotnei <xliff:g id="APP_NAME">%2$s</xliff:g> tiks atļauts mijiedarboties ar šīm atļaujām:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Atļaut lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; piekļūt šai informācijai no jūsu tālruņa"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Vairāku ierīču pakalpojumi"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt lietotnes starp jūsu ierīcēm šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Vairāku ierīču pakalpojumi"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt saturu tuvumā esošās ierīcēs šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Atļaut"</string>
     <string name="consent_no" msgid="2640796915611404382">"Neatļaut"</string>
     <string name="consent_back" msgid="2560683030046918882">"Atpakaļ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index 73afafac..2768d56 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Дозволете &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да пристапува до вашиот &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> со којшто ќе управува &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Апликацијата е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за „Телефон“, SMS, „Контакти“, „Календар“, „Евиденција на повици“ и „Уреди во близина“."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Апликацијата е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со следниве дозволи:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"очила"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Апликацијава е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за „Телефон“, SMS, „Контакти“, „Микрофон“ и „Уреди во близина“."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Апликацијата е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со следниве дозволи:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Овозможете &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да пристапува до овие податоци на телефонот"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Повеќенаменски услуги"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да стримува апликации помеѓу вашите уреди"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Услуги на повеќе уреди"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да стримува содржини на уредите во близина"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"уред"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
     <string name="consent_no" msgid="2640796915611404382">"Не дозволувај"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
index 0644dd9..e19947a 100644
--- a/packages/CompanionDeviceManager/res/values-ml/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"കമ്പാനിയൻ ഉപകരണ മാനേജർ"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"നിങ്ങളുടെ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ആക്‌സസ് ചെയ്യാൻ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; എന്നതിനെ അനുവദിക്കുക"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"വാച്ച്"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ഉപയോഗിച്ച് മാനേജ് ചെയ്യുന്നതിന് ഒരു <xliff:g id="PROFILE_NAME">%1$s</xliff:g> തിരഞ്ഞെടുക്കുക"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ആപ്പ് ആവശ്യമാണ്. നിങ്ങളുടെ അറിയിപ്പുകളുമായി സംവദിക്കാനും നിങ്ങളുടെ ഫോൺ, SMS, Contacts, Calendar, കോൾ ചരിത്രം, സമീപമുള്ള ഉപകരണങ്ങളുടെ അനുമതികൾ എന്നിവ ആക്‌സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%2$s</xliff:g> ആപ്പിനെ അനുവദിക്കും."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ആപ്പ് ആവശ്യമാണ്. ഇനിപ്പറയുന്ന അനുമതികളുമായി സംവദിക്കാൻ <xliff:g id="APP_NAME">%2$s</xliff:g> ആപ്പിനെ അനുവദിക്കും:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ഗ്ലാസുകൾ"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ഈ ആപ്പ് ആവശ്യമാണ്. നിങ്ങളുടെ അറിയിപ്പുകളുമായി സംവദിക്കാനും ഫോൺ, SMS, കോൺടാക്റ്റുകൾ, മൈക്രോഫോൺ, സമീപമുള്ള ഉപകരണങ്ങളുടെ അനുമതികൾ എന്നിവ ആക്‌സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%2$s</xliff:g> എന്നതിനെ അനുവദിക്കും."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ആപ്പ് ആവശ്യമാണ്. ഇനിപ്പറയുന്ന അനുമതികളുമായി സംവദിക്കാൻ <xliff:g id="APP_NAME">%2$s</xliff:g> ആപ്പിനെ അനുവദിക്കും:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഈ വിവരങ്ങൾ ആക്‌സസ് ചെയ്യാൻ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ആപ്പിനെ അനുവദിക്കുക"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ക്രോസ്-ഉപകരണ സേവനങ്ങൾ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"നിങ്ങളുടെ ഉപകരണങ്ങളിൽ ഒന്നിൽ നിന്ന് അടുത്തതിലേക്ക് ആപ്പുകൾ സ്ട്രീം ചെയ്യാൻ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ഉപകരണത്തിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ക്രോസ്-ഉപകരണ സേവനങ്ങൾ"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"സമീപമുള്ള ഉപകരണങ്ങളിൽ ഉള്ളടക്കം സ്ട്രീം ചെയ്യാൻ നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> എന്നതിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ഉപകരണം"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"അനുവദിക്കുക"</string>
     <string name="consent_no" msgid="2640796915611404382">"അനുവദിക്കരുത്"</string>
     <string name="consent_back" msgid="2560683030046918882">"മടങ്ങുക"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index d57b4d3..9ce4124 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;-д таны &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д хандахыг зөвшөөрнө үү"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"цаг"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;-н удирдах<xliff:g id="PROFILE_NAME">%1$s</xliff:g>-г сонгоно уу"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д таны мэдэгдэлтэй харилцан үйлдэл хийж, Утас, SMS, Харилцагчид, Календарь, Дуудлагын жагсаалт болон Ойролцоох төхөөрөмжүүдийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д эдгээр зөвшөөрөлтэй харилцан үйлдэл хийхийг зөвшөөрнө:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"нүдний шил"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-г таны мэдэгдлүүдтэй харилцаж, мөн таны утас, SMS, харилцагчид, микрофон болон ойролцоох төхөөрөмжүүдийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д эдгээр зөвшөөрөлтэй харилцан үйлдэл хийхийг зөвшөөрнө:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д таны утаснаас энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Төхөөрөмж хоорондын үйлчилгээ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Таны төхөөрөмжүүд хооронд апп дамжуулахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс зөвшөөрөл хүсэж байна"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Төхөөрөмж хоорондын үйлчилгээ"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс ойролцоох төхөөрөмжүүд рүү контент дамжуулах зөвшөөрөл хүсэж байна"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Зөвшөөрөх"</string>
     <string name="consent_no" msgid="2640796915611404382">"Бүү зөвшөөр"</string>
     <string name="consent_back" msgid="2560683030046918882">"Буцах"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index 70b0567..2c4d6f3 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"सहयोगी डिव्हाइस व्यवस्थापक"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"तुमचे &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; अ‍ॅक्सेस करण्यासाठी &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला अनुमती द्या"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"वॉच"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; द्वारे व्यवस्थापित करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला तुमच्या सूचनांशी संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क कॅलेंडर, कॉल लॉग व जवळपासच्या डिव्हाइसच्या परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला पुढील परवानग्यांशी संवाद साधण्याची अनुमती मिळेल:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Glasses"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"तुमची <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला तुमच्या सुचानांसोबत संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क, मायक्रोफोन व जवळपासच्या डिव्हाइसच्या परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला पुढील परवानग्यांशी संवाद साधण्याची अनुमती मिळेल:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला ही माहिती तुमच्या फोनवरून अ‍ॅक्सेस करण्यासाठी अनुमती द्या"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिव्हाइस सेवा"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"तुमच्या डिव्हाइसदरम्यान ॲप्स स्ट्रीम करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"क्रॉस-डिव्हाइस सेवा"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> हे जवळपासच्या डिव्हाइसवर आशय स्ट्रीम करण्यासाठी तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"डिव्हाइस"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"अनुमती द्या"</string>
     <string name="consent_no" msgid="2640796915611404382">"अनुमती देऊ नका"</string>
     <string name="consent_back" msgid="2560683030046918882">"मागे जा"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index 436ff9c..f353212 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Pengurus Peranti Rakan"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Benarkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengakses &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; anda"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"jam tangan"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk diurus oleh &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan, Kalendar, Log panggilan serta Peranti berdekatan anda."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan berinteraksi dengan kebenaran ini:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"cermin mata"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan untuk berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan, Mikrofon dan Peranti berdekatan anda."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan untuk berinteraksi dengan kebenaran ini:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Benarkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengakses maklumat ini daripada telefon anda"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Perkhidmatan silang peranti"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda untuk menstrim apl antara peranti anda"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Perkhidmatan silang peranti"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda untuk menstrim kandungan kepada peranti berdekatan"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"peranti"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Benarkan"</string>
     <string name="consent_no" msgid="2640796915611404382">"Jangan benarkan"</string>
     <string name="consent_back" msgid="2560683030046918882">"Kembali"</string>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
index eb03fb2..0d7380d 100644
--- a/packages/CompanionDeviceManager/res/values-my/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"တွဲဖက်ကိရိယာ မန်နေဂျာ"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"သင်၏ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ကို သုံးရန် &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ကို ခွင့်ပြုပါ"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"နာရီ"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; က စီမံခန့်ခွဲရန် <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ကို ရွေးချယ်ပါ"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"သင်၏ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် ဤအက်ပ်လိုအပ်သည်။ သင်၏ဖုန်း၊ SMS စာတိုစနစ်၊ အဆက်အသွယ်များ၊ ပြက္ခဒိန်၊ ခေါ်ဆိုမှတ်တမ်းနှင့် အနီးတစ်ဝိုက်ရှိ စက်များဆိုင်ရာ ခွင့်ပြုချက်များသုံးရန်၊ အကြောင်းကြားချက်များနှင့် ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%2$s</xliff:g> ကို ခွင့်ပြုမည်။"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"သင်၏ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် ဤအက်ပ်လိုအပ်သည်။ ဤခွင့်ပြုချက်များနှင့် ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%2$s</xliff:g> ကို ခွင့်ပြုမည်-"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"မျက်မှန်"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"သင်၏ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် ဤအက်ပ်လိုအပ်သည်။ သင့်အကြောင်းကြားချက်များနှင့် ပြန်လှန်တုံ့ပြန်ရန်နှင့် သင့်ဖုန်း၊ SMS စာတိုစနစ်၊ အဆက်အသွယ်၊ မိုက်ခရိုဖုန်းနှင့် အနီးတစ်ဝိုက်ရှိ စက်များ၏ ခွင့်ပြုချက်များအား <xliff:g id="APP_NAME">%2$s</xliff:g> ကို သုံးခွင့်ပြုပါမည်။"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"သင်၏ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် အက်ပ်လိုအပ်သည်။ ဤခွင့်ပြုချက်များနှင့် ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%2$s</xliff:g> ကို ခွင့်ပြုမည်-"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ကို သင့်ဖုန်းမှ ဤအချက်အလက် သုံးခွင့်ပြုမည်"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"စက်များကြားသုံး ဝန်ဆောင်မှုများ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင်၏စက်များအကြား အက်ပ်များတိုက်ရိုက်လွှင့်ရန် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"စက်များကြားသုံး ဝန်ဆောင်မှု"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အနီးတစ်ဝိုက်ရှိ စက်များတွင် အကြောင်းအရာတိုက်ရိုက်ဖွင့်ရန် သင့် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"စက်"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"ခွင့်ပြုရန်"</string>
     <string name="consent_no" msgid="2640796915611404382">"ခွင့်မပြုပါ"</string>
     <string name="consent_back" msgid="2560683030046918882">"နောက်သို့"</string>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index 76c75617..8833591 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Tillat at &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; bruker &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"klokke"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal administreres av &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med varslene dine og har tilgang til tillatelsene for telefon, SMS, kontakter, kalender, samtalelogger og enheter i nærheten."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med disse tillatelsene:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"briller"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Denne appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med varslene dine og har tilgang til tillatelsene for telefon, SMS, kontakter, mikrofon og enheter i nærheten."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med disse tillatelsene:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Gi &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tilgang til denne informasjonen fra telefonen din"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester på flere enheter"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å strømme apper mellom enhetene dine, på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Tjenester på flere enheter"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til å strømme innhold til enheter i nærheten"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Tillat"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ikke tillat"</string>
     <string name="consent_back" msgid="2560683030046918882">"Tilbake"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
index 149cbce..58b9ed0 100644
--- a/packages/CompanionDeviceManager/res/values-ne/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"सहयोगी डिभाइसको प्रबन्धक"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"आफ्नो &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; लाई &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; प्रयोग गर्ने अनुमति दिनुहोस्"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"घडी"</string>
     <string name="chooser_title" msgid="2262294130493605839">"आफूले &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; प्रयोग गरी व्यवस्थापन गर्न चाहेको <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चयन गर्नुहोस्"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"तपाईंको <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एपलाई अनुमति दिनु पर्ने हुन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट, पात्रो, कल लग तथा नजिकैका डिभाइससम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"तपाईंको <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एपलाई अनुमति दिनु पर्ने हुन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई निम्न अनुमतिहरू फेरबदल गर्न दिइने छः"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"चस्मा"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"तपाईंको <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एप चाहिन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट, माइक्रोफोन तथा नजिकैका डिभाइससम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"तपाईंको <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एपलाई अनुमति दिनु पर्ने हुन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई निम्न अनुमतिहरू फेरबदल गर्न दिइने छ:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; लाई तपाईंको फोनमा भएको यो जानकारी हेर्ने तथा प्रयोग गर्ने अनुमति दिनुहोस्"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रस-डिभाइस सेवाहरू"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको डिभाइस <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> को तर्फबाट तपाईंका कुनै एउटा डिभाइसबाट अर्को डिभाइसमा एप स्ट्रिम गर्ने अनुमति माग्दै छ"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"क्रस-डिभाइस सेवाहरू"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> को तर्फबाट नजिकैका डिभाइसहरूमा सामग्री स्ट्रिम गर्ने अनुमति माग्दै छ"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"यन्त्र"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"अनुमति दिनुहोस्"</string>
     <string name="consent_no" msgid="2640796915611404382">"अनुमति नदिनुहोस्"</string>
     <string name="consent_back" msgid="2560683030046918882">"पछाडि"</string>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index 97db70a..15c5b1d 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toegang geven tot je &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"smartwatch"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Een <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiezen om te beheren met &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"De app is vereist om je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> kan interactie hebben met je meldingen en toegang krijgen tot rechten voor Telefoon, Sms, Contacten, Agenda, Gesprekslijsten en Apparaten in de buurt."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"De app is vereist om je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> heeft toestemming om interactie te hebben met de volgende rechten:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"brillen"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Deze app is vereist om je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> mag interactie hebben met je meldingen en krijgt toegang tot de rechten Telefoon, Sms, Contacten, Microfoon en Apparaten in de buurt."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"De app is vereist om je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> heeft toestemming om interactie te hebben met de volgende rechten:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toegang geven tot deze informatie op je telefoon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device-services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om apps te streamen tussen je apparaten"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device-services"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens je <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om content te streamen naar apparaten in de buurt"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"apparaat"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Toestaan"</string>
     <string name="consent_no" msgid="2640796915611404382">"Niet toestaan"</string>
     <string name="consent_back" msgid="2560683030046918882">"Terug"</string>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index 519e711..b9794c4 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"ସହଯୋଗୀ ଡିଭାଇସ୍ ପରିଚାଳକ"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"ଆପଣଙ୍କ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;କୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ୱାଚ୍"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>କୁ ବାଛନ୍ତୁ"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କର ଫୋନ, SMS, କଣ୍ଟାକ୍ଟ, କେଲେଣ୍ଡର, କଲ ଲଗ ଓ ଆଖପାଖର ଡିଭାଇସ ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। ଏହି ଅନୁମତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ଚଷମା"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଏହି ଆପ ଆବଶ୍ୟକ। ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କର ଫୋନ, SMS, କଣ୍ଟାକ୍ଟ, ମାଇକ୍ରୋଫୋନ ଓ ଆଖପାଖର ଡିଭାଇସ ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। ଏହି ଅନୁମତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"ଆପଣଙ୍କ ଫୋନରୁ ଏହି ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"କ୍ରସ-ଡିଭାଇସ ସେବାଗୁଡ଼ିକ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"ଆପଣଙ୍କ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"କ୍ରସ-ଡିଭାଇସ ସେବାଗୁଡ଼ିକ"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକରେ ବିଷୟବସ୍ତୁକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ଡିଭାଇସ୍"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="consent_no" msgid="2640796915611404382">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
     <string name="consent_back" msgid="2560683030046918882">"ପଛକୁ ଫେରନ୍ତୁ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 8bc9e94..f933c9a 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"ਸੰਬੰਧੀ ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਕ"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਤੁਹਾਡੇ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ਸਮਾਰਟ-ਵਾਚ"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕਾਂ, ਕੈਲੰਡਰ, ਕਾਲ ਲੌਗਾਂ ਅਤੇ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ।"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ਐਨਕਾਂ"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕਾਂ, ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ।"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਲਈ ਸਮੱਗਰੀ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"ਆਗਿਆ ਦਿਓ"</string>
     <string name="consent_no" msgid="2640796915611404382">"ਆਗਿਆ ਨਾ ਦਿਓ"</string>
     <string name="consent_back" msgid="2560683030046918882">"ਪਿੱਛੇ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index 2fc8a47..6b71592 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Menedżer urządzeń towarzyszących"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Zezwól na dostęp aplikacji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; do urządzenia &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"zegarek"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, którym ma zarządzać aplikacja &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Aplikacja jest niezbędna do zarządzania profilem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła korzystać z powiadomień oraz uprawnień dotyczących telefonu, SMS-ów, kontaktów, kalendarza, rejestrów połączeń i Urządzeń w pobliżu."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacja jest niezbędna do zarządzania profilem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła korzystać z tych powiadomień:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Okulary"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła wchodzić w interakcję z powiadomieniami i korzystać z uprawnień dotyczących telefonu, SMS-ów, kontaktów, mikrofonu oraz urządzeń w pobliżu."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła korzystać z tych uprawnień:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Zezwól urządzeniu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na dostęp do tych informacji na Twoim telefonie"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści z aplikacji na innym urządzeniu"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usługi na innym urządzeniu"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści na urządzeniach w pobliżu"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Zezwól"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nie zezwalaj"</string>
     <string name="consent_back" msgid="2560683030046918882">"Wstecz"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index aa054a8..9c91481 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"O app é necessário para gerenciar seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. O <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com suas notificações e acessar os apps Telefone, SMS, Contatos, Google Agenda, registros de chamadas e as permissões de dispositivos por perto."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"O app é necessário para gerenciar seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com estas permissões:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"óculos"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Esse app é necessário para gerenciar seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. O <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com suas notificações e acessar os apps Telefone, SMS, Contatos, microfone e as permissões de dispositivos por perto."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"O app é necessário para gerenciar seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com estas permissões:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse estas informações do smartphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Serviços entre dispositivos"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de conteúdo para dispositivos por perto"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
     <string name="consent_back" msgid="2560683030046918882">"Voltar"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index 852d994..6f72db3 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos associados"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Permita que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aceda ao seu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerido pela app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"A app é necessária para gerir o seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com as suas notificações e aceder às autorizações do Telemóvel, SMS, Contactos, Calendário, Registos de chamadas e Dispositivos próximos."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"A app é necessária para gerir o seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com estas autorizações:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"óculos"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Esta app é necessária para gerir o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com as suas notificações e aceder às autorizações do Telemóvel, SMS, Contactos, Microfone e Dispositivos próximos."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"A app é necessária para gerir o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com estas autorizações:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permita que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aceda a estas informações do seu telemóvel"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer stream de apps entre os seus dispositivos"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Serviços entre dispositivos"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do dispositivo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer stream de conteúdo para dispositivos próximos"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
     <string name="consent_back" msgid="2560683030046918882">"Voltar"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index aa054a8..9c91481 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"O app é necessário para gerenciar seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. O <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com suas notificações e acessar os apps Telefone, SMS, Contatos, Google Agenda, registros de chamadas e as permissões de dispositivos por perto."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"O app é necessário para gerenciar seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com estas permissões:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"óculos"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Esse app é necessário para gerenciar seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. O <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com suas notificações e acessar os apps Telefone, SMS, Contatos, microfone e as permissões de dispositivos por perto."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"O app é necessário para gerenciar seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com estas permissões:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse estas informações do smartphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Serviços entre dispositivos"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de conteúdo para dispositivos por perto"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
     <string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
     <string name="consent_back" msgid="2560683030046918882">"Voltar"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index be66dca..e3a86c1 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Manager de dispozitiv Companion"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Permite ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să acceseze dispozitivul &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ceas"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Alege un profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pe care să îl gestioneze &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu notificările tale și să îți acceseze permisiunile pentru Telefon, SMS, Agendă, Calendar, Jurnale de apeluri și Dispozitive din apropiere."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu următoarele permisiuni:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ochelari"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Această aplicație este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu notificările tale și să-ți acceseze permisiunile pentru telefon, SMS-uri, agendă, microfon și dispozitivele din apropiere."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu următoarele permisiuni:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permite ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să acceseze aceste informații de pe telefon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicii pe mai multe dispozitive"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a reda în stream aplicații între dispozitivele tale"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servicii pe mai multe dispozitive"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a reda în stream conținut pe dispozitivele din apropiere"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Permite"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nu permite"</string>
     <string name="consent_back" msgid="2560683030046918882">"Înapoi"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index 8e2aed1..258a3c67 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Управление подключенными устройствами"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Разрешите приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ к устройству &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"часы"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Выберите устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), которым будет управлять приложение &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" получит доступ к уведомлениям, а также следующие разрешения: телефон, SMS, контакты, календарь, список вызовов и устройства поблизости."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" получит следующие разрешения:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Очки"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" получит доступ к уведомлениям, а также разрешения \"Телефон\", SMS, \"Контакты\", \"Микрофон\" и \"Устройства поблизости\"."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" получит следующие разрешения:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Разрешите приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; получать эту информацию с вашего телефона"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервисы стриминга приложений"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, чтобы транслировать приложения между вашими устройствами."</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Сервисы взаимодействия устр-в"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение на трансляцию контента на устройства поблизости от имени вашего устройства \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\"."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Разрешить"</string>
     <string name="consent_no" msgid="2640796915611404382">"Запретить"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index 0b9248b..fbe4823 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"සහායක උපාංග කළමනාකරු"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට ඔබගේ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; කළමනාකරණය කිරීමට ඉඩ දෙන්න"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ඔරලෝසුව"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; මගින් කළමනාකරණය කරනු ලැබීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනා කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> ඔබේ දැනුම්දීම් සමග අන්තර්ක්‍රියා කිරීමට සහ ඔබේ දුරකථනය, කෙටිපණිවුඩය, සම්බන්‍ධතා, දිනදර්ශනය, ඇමතුම් ලොග සහ අවට උපාංග අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙයි."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනා කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට මෙම අවසර සමග අන්තර්ක්‍රියා කිරීමට අවසර දෙනු ලැබේ:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"කණ්ණාඩි"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"මෙම යෙදුමට ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට ඔබේ දැනුම්දීම් සමග අන්තර් ක්‍රියා කිරීමට සහ ඔබේ දුරකථනය, SMS, සම්බන්ධතා, මයික්‍රෆෝනය සහ අවට උපාංග අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙනු ඇත."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනා කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට මෙම අවසර සමග අන්තර්ක්‍රියා කිරීමට අවසර දෙනු ලැබේ:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට ඔබගේ දුරකථනයෙන් මෙම තොරතුරුවලට ප්‍රවේශ වීමට ඉඩ දෙන්න"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"හරස්-උපාංග සේවා"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් ඔබගේ උපාංග අතර යෙදුම් ප්‍රවාහ කිරීමට අවසරය ඉල්ලමින් සිටියි"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"හරස්-උපාංග සේවා"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> අවට උපාංග වෙත අන්තර්ගතය ප්‍රවාහ කිරීමට ඔබේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් අවසර ඉල්ලයි"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"උපාංගය"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"ඉඩ දෙන්න"</string>
     <string name="consent_no" msgid="2640796915611404382">"ඉඩ නොදෙන්න"</string>
     <string name="consent_back" msgid="2560683030046918882">"ආපසු"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index 6be4e2c..97253b9 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Správca sprievodných zariadení"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Povoľte aplikácii &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; prístup k zariadeniu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"hodinky"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Vyberte profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ktorý bude spravovať aplikácia &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť interagovať s vašimi upozorneniami a získa prístup k povoleniam telefónu, SMS, kontaktov, kalendára, zoznamu hovorov a zariadení v okolí."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť interagovať s týmito povoleniami:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"okuliare"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Táto aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť interagovať s vašimi upozorneniami a získa prístup k povoleniam pre telefón, SMS, kontakty, mikrofón a zariadenia v okolí."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť interagovať s týmito povoleniami:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Povoľte aplikácii &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; prístup k týmto informáciám z vášho telefónu"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pre viacero zariadení"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje povolenie na streamovanie aplikácií medzi vašimi zariadeniami v mene tohto zariadenia (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>)"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Služby pre viacero zariadení"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> povolenie streamovať obsah do zariadení v okolí"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Povoliť"</string>
     <string name="consent_no" msgid="2640796915611404382">"Nepovoliť"</string>
     <string name="consent_back" msgid="2560683030046918882">"Späť"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index 7d3d168..6234286 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Upravitelj spremljevalnih naprav"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dovolite dostop do naprave &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ura"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Izbira naprave »<xliff:g id="PROFILE_NAME">%1$s</xliff:g>«, ki jo bo upravljala aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bosta omogočeni interakcija z obvestili in uporaba dovoljenj Telefon, SMS, Stiki, Koledar, Dnevniki klicev in Naprave v bližini."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bo omogočena interakcija s temi dovoljenji:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"očala"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bosta omogočeni interakcija z obvestili in uporaba dovoljenj Telefon, SMS, Stiki, Mikrofon in Naprave v bližini."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bo omogočena interakcija s temi dovoljenji:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Dovolite, da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dostopa do teh podatkov v vašem telefonu"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve za zunanje naprave"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje aplikacij v vaših napravah."</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Storitve za zunanje naprave"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje vsebine v napravah v bližini."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Dovoli"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ne dovoli"</string>
     <string name="consent_back" msgid="2560683030046918882">"Nazaj"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index 6ff4ce8..9ff0a77 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Menaxheri i pajisjes shoqëruese"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Lejo që &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; të ketë qasje te &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"ora inteligjente"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Zgjidh \"<xliff:g id="PROFILE_NAME">%1$s</xliff:g>\" që do të menaxhohet nga &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Aplikacioni nevojitet për të menaxhuar profilin tënd të \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\", \"Kalendarit\", \"Evidencave të telefonatave\" dhe të \"Pajisjeve në afërsi\"."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacioni nevojitet për të menaxhuar profilin tënd të \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të ndërveprojë me këto leje:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"syzet"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Ky aplikacion nevojitet për të menaxhuar \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\", \"Mikrofonit\" dhe të \"Pajisjeve në afërsi\"."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Ky aplikacion nevojitet për të menaxhuar profilin tënd të \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" do të lejohet të ndërveprojë me këto leje:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Lejo që &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; të ketë qasje në këtë informacion nga telefoni yt"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Shërbimet mes pajisjeve"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> për të transmetuar aplikacione ndërmjet pajisjeve të tua"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Shërbimet mes pajisjeve"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> për të transmetuar përmbajtje te pajisjet në afërsi"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Lejo"</string>
     <string name="consent_no" msgid="2640796915611404382">"Mos lejo"</string>
     <string name="consent_back" msgid="2560683030046918882">"Pas"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index fe9e5f9a..30f83e9 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Менаџер придруженог уређаја"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; приступа уређају &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"сат"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Одаберите <xliff:g id="PROFILE_NAME">%1$s</xliff:g> којим ће управљати апликација &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS, контакте, календар, евиденције позива и уређаје у близини."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са овим дозволама:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"наочаре"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Ова апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS, контакте, микрофон и уређаје у близини."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са овим дозволама:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; приступа овим информацијама са телефона"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуге на више уређаја"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за стримовање апликација између уређаја"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Услуге на више уређаја"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да стримује садржај на уређаје у близини"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"уређај"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
     <string name="consent_no" msgid="2640796915611404382">"Не дозволи"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index 11f115d..c3c9721 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Tillåt att &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; får åtkomst till din &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"klocka"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för hantering av &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med dina aviseringar och får åtkomst till behörigheterna Telefon, Sms, Kontakter, Kalender, Samtalsloggar och Enheter i närheten."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med följande behörigheter:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasögon"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får interagera med dina aviseringar och får åtkomst till behörigheterna Telefon, Sms, Kontakter, Mikrofon och Enheter i närheten."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med följande behörigheter:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Ge &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; åtkomstbehörighet till denna information på telefonen"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjänster för flera enheter"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet att låta <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> streama appar mellan enheter"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Tjänster för flera enheter"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för att streama innehåll till enheter i närheten för din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Tillåt"</string>
     <string name="consent_no" msgid="2640796915611404382">"Tillåt inte"</string>
     <string name="consent_back" msgid="2560683030046918882">"Tillbaka"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index 2c6bc8f..873c857 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Kidhibiti cha Vifaa Visaidizi"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Ruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifikie &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; yako"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"saa"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Chagua <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ili idhibitiwe na &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kufikia arifa zako na kufikia ruhusa zako za Simu, SMS, Anwani, Kalenda, Rekodi za nambari za simu na Vifaa vilivyo karibu."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kufikia ruhusa hizi:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"miwani"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kutumia arifa zako na kufikia ruhusa zako za Simu, SMS, Anwani, Maikrofoni na Vifaa vilivyo Karibu."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kufikia ruhusa hizi:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Ruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifikie maelezo haya kutoka kwenye simu yako"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Huduma za kifaa kilichounganishwa kwingine"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako ili itiririshe programu kati ya vifaa vyako"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Huduma za kifaa kilichounganishwa kwingine"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ili itiririshe maudhui kwenye vifaa vilivyo karibu"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Ruhusu"</string>
     <string name="consent_no" msgid="2640796915611404382">"Usiruhusu"</string>
     <string name="consent_back" msgid="2560683030046918882">"Nyuma"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index ac454ba..fbfbc40 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"கம்பேனியன் சாதன நிர்வாகி"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"உங்கள் &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; சாதனத்தை அணுக &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸை அனுமதியுங்கள்"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"வாட்ச்"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ஆப்ஸ் நிர்வகிக்கக்கூடிய <xliff:g id="PROFILE_NAME">%1$s</xliff:g> தேர்ந்தெடுக்கப்பட வேண்டும்"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. உங்கள் மொபைல், மெசேஜ், தொடர்புகள், கேலெண்டர், அழைப்புப் பதிவுகள், அருகிலுள்ள சாதனங்கள் ஆகியவற்றுக்கான அணுகலையும், உங்கள் அறிவிப்புகளைப் பார்ப்பதற்கான அனுமதியையும் <xliff:g id="APP_NAME">%2$s</xliff:g> ஆப்ஸ் பெறும்."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. இந்த அனுமதிகளைப் பயன்படுத்த <xliff:g id="APP_NAME">%2$s</xliff:g> ஆப்ஸ் அனுமதிக்கப்படும்:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"கிளாஸஸ்"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவைப்படுகிறது. உங்கள் மொபைல், மெசேஜ், தொடர்புகள், மைக்ரோஃபோன், அருகிலுள்ள சாதனங்கள் ஆகியவற்றுக்கான அணுகலையும் உங்கள் அறிவிப்புகளைப் பார்ப்பதற்கான அனுமதியையும் <xliff:g id="APP_NAME">%2$s</xliff:g> பெறும்."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. இந்த அனுமதிகளைப் பயன்படுத்த <xliff:g id="APP_NAME">%2$s</xliff:g> ஆப்ஸ் அனுமதிக்கப்படும்:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"மொபைலில் உள்ள இந்தத் தகவல்களை அணுக, &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸை அனுமதிக்கவும்"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"பன்முக சாதன சேவைகள்"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"உங்கள் சாதனங்களுக்கு இடையே ஆப்ஸை ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் அனுமதியைக் கோருகிறது"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"பன்முக சாதன சேவைகள்"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"அருகிலுள்ள சாதனங்களுடன் உள்ளடக்கத்தை ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கோருகிறது"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"அனுமதி"</string>
     <string name="consent_no" msgid="2640796915611404382">"அனுமதிக்க வேண்டாம்"</string>
     <string name="consent_back" msgid="2560683030046918882">"பின்செல்"</string>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index cb0356c..7c077ce 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"సహచర పరికర మేనేజర్"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"మీ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;ను యాక్సెస్ చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ను అనుమతించండి"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"వాచ్"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ద్వారా మేనేజ్ చేయబడటానికి ఒక <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ను ఎంచుకోండి"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. మీ నోటిఫికేషన్‌లతో ఇంటరాక్ట్ అవ్వడానికి, అలాగే మీ ఫోన్, SMS, కాంటాక్ట్‌లు, క్యాలెండర్, కాల్ లాగ్‌లు, సమీపంలోని పరికరాల అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. ఈ అనుమతులతో ఇంటరాక్ట్ అవ్వడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"గ్లాసెస్"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. <xliff:g id="APP_NAME">%2$s</xliff:g> మీ నోటిఫికేషన్‌లతో ఇంటరాక్ట్ అవ్వడానికి, అలాగే మీ ఫోన్, SMS, కాంటాక్ట్‌లు, మైక్రోఫోన్, సమీపంలోని పరికరాల అనుమతులను యాక్సెస్ చేయడానికి అనుమతించబడుతుంది."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. ఈ అనుమతులతో ఇంటరాక్ట్ అవ్వడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"మీ ఫోన్ నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; యాప్‌ను అనుమతించండి"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"మీ పరికరాల మధ్య యాప్‌లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"క్రాస్-డివైజ్ సర్వీస్‌లు"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"సమీపంలోని పరికరాలకు కంటెంట్‌ను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"పరికరం"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"అనుమతించండి"</string>
     <string name="consent_no" msgid="2640796915611404382">"అనుమతించవద్దు"</string>
     <string name="consent_back" msgid="2560683030046918882">"వెనుకకు"</string>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index e42bec5..5ee6a25 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"อนุญาตให้ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; เข้าถึง &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ของคุณ"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"นาฬิกา"</string>
     <string name="chooser_title" msgid="2262294130493605839">"เลือก<xliff:g id="PROFILE_NAME">%1$s</xliff:g>ที่จะให้มีการจัดการโดย &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและได้รับสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ, ปฏิทิน, บันทึกการโทร และอุปกรณ์ที่อยู่ใกล้เคียง"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับสิทธิ์เหล่านี้"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"แว่นตา"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"ต้องใช้แอปนี้ในการจัดการ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและได้รับสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ, ไมโครโฟน และอุปกรณ์ที่อยู่ใกล้เคียง"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"ต้องใช้แอปนี้ในการจัดการ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับสิทธิ์เหล่านี้"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"อนุญาตให้ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; เข้าถึงข้อมูลนี้จากโทรศัพท์ของคุณ"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"บริการหลายอุปกรณ์"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> เพื่อสตรีมแอประหว่างอุปกรณ์ต่างๆ ของคุณ"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"บริการหลายอุปกรณ์"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> เพื่อสตรีมเนื้อหาไปยังอุปกรณ์ที่อยู่ใกล้เคียง"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"อุปกรณ์"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"อนุญาต"</string>
     <string name="consent_no" msgid="2640796915611404382">"ไม่อนุญาต"</string>
     <string name="consent_back" msgid="2560683030046918882">"กลับ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index 15b69a2..2fd2eda 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Kasamang Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na i-access ang iyong &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"relo"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para pamahalaan ng &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Kailangan ang app para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga notification mo at i-access ang iyong pahintulot sa Telepono, SMS, Mga Contact, Kalendaryo, Log ng mga tawag, at Mga kalapit na device."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Kailangan ang app para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga pahintulot na ito:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"salamin"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Kailangan ang app na ito para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga notification mo at i-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, Mikropono, at Mga kalapit na device."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Kailangan ang app para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga pahintulot na ito:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na i-access ang impormasyong ito sa iyong telepono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Mga cross-device na serbisyo"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay humihiling ng pahintulot sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para mag-stream ng mga app sa pagitan ng mga device mo"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Mga cross-device na serbisyo"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Humihiling ng pahintulot ang <xliff:g id="APP_NAME">%1$s</xliff:g> sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para mag-stream ng content sa mga kalapit na device"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Payagan"</string>
     <string name="consent_no" msgid="2640796915611404382">"Huwag payagan"</string>
     <string name="consent_back" msgid="2560683030046918882">"Bumalik"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 35b99a7..8a73c65 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; cihazınıza erişmesi için &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; uygulamasına izin verin"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"saat"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; tarafından yönetilecek bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler, Takvim, Arama kayıtları ve Yakındaki cihazlar izinlerinize erişmesine izin verilir."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> uygulamasının şu izinlerle etkileşime girmesine izin verilir:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler, Mikrofon ve Yakındaki cihazlar izinlerine erişmesine izin verilir."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> uygulamasının şu izinlerle etkileşime girmesine izin verilir:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; uygulamasının, telefonunuzdaki bu bilgilere erişmesine izin verin"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlar arası hizmetler"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>, cihazlarınız arasında uygulama akışı gerçekleştirmek için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cihazlar arası hizmetler"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g>, yakındaki cihazlarda içerikleri canlı oynatmak için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"İzin ver"</string>
     <string name="consent_no" msgid="2640796915611404382">"İzin verme"</string>
     <string name="consent_back" msgid="2560683030046918882">"Geri"</string>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index d1d0815..1ba997e 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Диспетчер супутніх пристроїв"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Надати додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ до пристрою &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"годинник"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Виберіть <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, яким керуватиме додаток &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе взаємодіяти з вашими сповіщеннями й отримає дозволи \"Телефон\", \"SMS\", \"Контакти\", \"Календар\", \"Журнали викликів\" і \"Пристрої поблизу\"."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе взаємодіяти з такими дозволами:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"окуляри"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе взаємодіяти з вашими сповіщеннями й отримає дозволи \"Телефон\", \"SMS\", \"Контакти\", \"Мікрофон\" і \"Пристрої поблизу\"."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе взаємодіяти з такими дозволами:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Надайте додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ до цієї інформації з телефона"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервіси для кількох пристроїв"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> запитує дозвіл на трансляцію додатків між вашими пристроями"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Сервіси для кількох пристроїв"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) запитує дозвіл на трансляцію контенту на пристрої поблизу"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"пристрій"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Дозволити"</string>
     <string name="consent_no" msgid="2640796915611404382">"Не дозволяти"</string>
     <string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index 7cd681c..f83e216d 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"ساتھی آلہ مینیجر"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"‏‎&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;‎ کو اپنے ‎&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;‎ تک رسائی کی اجازت دیں"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"دیکھیں"</string>
     <string name="chooser_title" msgid="2262294130493605839">"‏&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"‏آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لئے ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں، کیلنڈر، کال لاگز اور قریبی آلات کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لئے ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو ان اجازتوں کے ساتھ تعامل کرنے کی اجازت ہوگی:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"گلاسز"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"‏آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے اس ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں، مائیکروفون اور قریبی آلات کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو ان اجازتوں کے ساتھ تعامل کرنے کی اجازت ہوگی:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"‏اپنے فون سے ان معلومات تک رسائی حاصل کرنے کی &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; کو اجازت دیں"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"کراس ڈیوائس سروسز"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"کراس آلے کی سروسز"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے مواد کے قریبی آلات کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"اجازت دیں"</string>
     <string name="consent_no" msgid="2640796915611404382">"اجازت نہ دیں"</string>
     <string name="consent_back" msgid="2560683030046918882">"پیچھے"</string>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index 4a6de17..5fd194e 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; qurilmasiga kirish uchun &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ilovasiga ruxsat bering"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"soat"</string>
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; boshqaradigan <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qurilmasini tanlang"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> profilini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar, taqvim, chaqiruvlar jurnali va yaqin-atrofdagi qurilmalarga kirishga ruxsat beriladi."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> profilini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga quyidagi ruxsatlar bilan ishlashga ruxsat beriladi:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"koʻzoynak"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Bu ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> profilini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar, mikrofon va yaqin-atrofdagi qurilmalarga kirishga ruxsat beriladi."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> profilini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga quyidagi ruxsatlar bilan ishlashga ruxsat beriladi:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ilovasiga telefondagi ushbu maʼlumot uchun ruxsat bering"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Qurilmalararo xizmatlar"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Qurilamalararo ilovalar strimingi uchun <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nomidan ruxsat soʻramoqda"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Qurilmalararo xizmatlar"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> qurilmangizdan nomidan atrofdagi qurilmalarga kontent uzatish uchun ruxsat olmoqchi"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"qurilma"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Ruxsat"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ruxsat berilmasin"</string>
     <string name="consent_back" msgid="2560683030046918882">"Orqaga"</string>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index 62f613b..e5f50af 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truy cập &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; của bạn"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"đồng hồ"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; quản lý"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép tương tác với thông báo và truy cập vào Điện thoại, SMS, Danh bạ, Lịch, Nhật ký cuộc gọi và Thiết bị ở gần."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> được quyền tương tác với những chức năng sau:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"kính"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép tương tác với thông báo cũng như sử dụng các quyền đối với Điện thoại, SMS, Danh bạ, Micrô của bạn và Thiết bị ở gần bạn."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép tương tác bằng những quyền truy cập sau:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truy cập vào thông tin này trên điện thoại của bạn"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Dịch vụ trên nhiều thiết bị"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> để truyền trực tuyến ứng dụng giữa các thiết bị của bạn"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Dịch vụ trên nhiều thiết bị"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang thay mặt <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yêu cầu quyền để truyền nội dung đến các thiết bị ở gần"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Cho phép"</string>
     <string name="consent_no" msgid="2640796915611404382">"Không cho phép"</string>
     <string name="consent_back" msgid="2560683030046918882">"Quay lại"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index b6fa7fc..715fb71 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"配套设备管理器"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"允许&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;访问您的&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"手表"</string>
     <string name="chooser_title" msgid="2262294130493605839">"选择要由&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"需要使用此应用,才能管理您的<xliff:g id="DEVICE_NAME">%1$s</xliff:g>。<xliff:g id="APP_NAME">%2$s</xliff:g>将能与通知交互,并可获得电话、短信、通讯录、日历、通话记录和附近设备的访问权限。"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"需要使用此应用,才能管理您的<xliff:g id="DEVICE_NAME">%1$s</xliff:g>。<xliff:g id="APP_NAME">%2$s</xliff:g>可与以下权限交互:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"眼镜"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"需要使用此应用才能管理您的设备“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”。<xliff:g id="APP_NAME">%2$s</xliff:g>将能与您收到的通知交互,并可获权访问/使用您的电话、短信、通讯录、麦克风和附近的设备。"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"需要使用此应用,才能管理您的“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”。“<xliff:g id="APP_NAME">%2$s</xliff:g>”将可使用以下权限:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”&lt;strong&gt;&lt;/strong&gt;访问您手机中的这项信息"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨设备服务"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>请求在您的设备之间流式传输应用内容"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"跨设备服务"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>请求向您附近的设备流式传输内容"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"设备"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"允许"</string>
     <string name="consent_no" msgid="2640796915611404382">"不允许"</string>
     <string name="consent_back" msgid="2560683030046918882">"返回"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index 6f19a84..7620ce4 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"隨附裝置管理工具"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"允許&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; 存取您的 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
     <string name="chooser_title" msgid="2262294130493605839">"選擇由 &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; 管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"必須使用此應用程式管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取通知、電話、短訊、通訊錄和日曆、通話記錄和咫尺共享裝置權限。"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取以下權限:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可透過通知與您互動,並存取電話、短訊、通訊錄、麥克風和附近的裝置權限。"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取以下權限:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取您手機中的這項資料"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在為 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 要求權限,以在裝置之間串流應用程式內容"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"跨裝置服務"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」將內容串流至附近的裝置"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"允許"</string>
     <string name="consent_no" msgid="2640796915611404382">"不允許"</string>
     <string name="consent_back" msgid="2560683030046918882">"返回"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index 48c289c..a829961 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"隨附裝置管理工具"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
     <string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取通知、電話、簡訊、聯絡人和日曆、通話記錄和鄰近裝置的權限。"</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可與下列權限互動:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"這個應用程式是管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」的必備工具。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將能透過通知與你互動,並取得電話、簡訊、聯絡人、麥克風和鄰近裝置權限。"</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可使用以下權限:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取手機中的這項資訊"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」要求必要權限,以便在裝置之間串流傳輸應用程式內容"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"跨裝置服務"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」將內容串流傳輸到鄰近裝置"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"允許"</string>
     <string name="consent_no" msgid="2640796915611404382">"不允許"</string>
     <string name="consent_back" msgid="2560683030046918882">"返回"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index f81406e..c8171e6 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -17,14 +17,19 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4470785958457506021">"Isiphathi sedivayisi esihambisanayo"</string>
-    <string name="confirmation_title" msgid="3785000297483688997">"Vumela i-&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ukuthi ifinyelele i-&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; yakho"</string>
+    <!-- no translation found for confirmation_title (8024993972587946678) -->
+    <skip />
     <string name="profile_name_watch" msgid="576290739483672360">"buka"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Khetha i-<xliff:g id="PROFILE_NAME">%1$s</xliff:g> ezophathwa yi-&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="summary_watch" msgid="4085794790142204006">"I-app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukuthi ihlanganyele nezaziso zakho futhi ifinyelele Ifoni yakho, i-SMS, Oxhumana nabo, Ikhalenda, Amarekhodi wamakholi Nezimvume zamadivayisi aseduze."</string>
-    <string name="summary_watch_single_device" msgid="1523091550243476756">"I-app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho. <xliff:g id="APP_NAME">%2$s</xliff:g> uzovunyelwa ukusebenzisana nalezi zimvume:"</string>
+    <!-- no translation found for summary_watch (6566922405914995759) -->
+    <skip />
+    <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Izingilazi"</string>
-    <string name="summary_glasses" msgid="8987925853224595628">"Le app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukuthi ihlanganyele nezaziso zakho futhi ifinyelele kufoni yakho, i-SMS, Oxhumana nabo, Imakrofoni nezimvume zamadivayisi aseduze."</string>
-    <string name="summary_glasses_single_device" msgid="5725890636605211803">"I-app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukusebenzisana nalezi zimvume:"</string>
+    <!-- no translation found for summary_glasses (3808267780579061241) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Vumela i-&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifinyelele lolu lwazi kusukela efonini yakho"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Amasevisi amadivayisi amaningi"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho ukuze isakaze-bukhoma ama-app phakathi kwamadivayisi akho"</string>
@@ -38,7 +43,10 @@
     <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Amasevisi amadivayisi amaningi"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho ukuze isakaze okuqukethwe kumadivayisi aseduze"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"idivayisi"</string>
-    <string name="summary_generic" msgid="2346762210105903720"></string>
+    <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
+    <skip />
+    <!-- no translation found for summary_generic (4988130802522924650) -->
+    <skip />
     <string name="consent_yes" msgid="8344487259618762872">"Vumela"</string>
     <string name="consent_no" msgid="2640796915611404382">"Ungavumeli"</string>
     <string name="consent_back" msgid="2560683030046918882">"Emuva"</string>
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index 7397688..b842761 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_label">Companion Device Manager</string>
 
     <!-- Title of the device association confirmation dialog. -->
-    <string name="confirmation_title">Allow &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; to access your &lt;strong&gt;<xliff:g id="device_name" example="ASUS ZenWatch 2">%2$s</xliff:g>&lt;/strong&gt;</string>
+    <string name="confirmation_title">Allow &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; to access &lt;strong&gt;<xliff:g id="device_name" example="ASUS ZenWatch 2">%2$s</xliff:g>&lt;/strong&gt;</string>
 
     <!-- ================= DEVICE_PROFILE_WATCH and null profile ================= -->
 
@@ -31,10 +31,10 @@
     <string name="chooser_title">Choose a <xliff:g id="profile_name" example="watch">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%2$s</xliff:g>&lt;/strong&gt;</string>
 
     <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile (type) [CHAR LIMIT=NONE] -->
-    <string name="summary_watch">The app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions.</string>
+    <string name="summary_watch">The app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions.</string>
 
     <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile for singleDevice(type) [CHAR LIMIT=NONE] -->
-    <string name="summary_watch_single_device">The app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to interact with these permissions:</string>
+    <string name="summary_watch_single_device">The app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, and access these permissions:</string>
 
     <!-- TODO(b/256140614) To replace all glasses related strings with final versions -->
     <!-- ================= DEVICE_PROFILE_GLASSES ================= -->
@@ -43,10 +43,10 @@
     <string name="profile_name_glasses">glasses</string>
 
     <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile (type) [CHAR LIMIT=NONE] -->
-    <string name="summary_glasses">This app is needed to manage your <xliff:g id="device_name" example="My Glasses">%1$s</xliff:g>. <xliff:g id="app_name" example="Glasses">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.</string>
+    <string name="summary_glasses">This app is needed to manage <xliff:g id="device_name" example="My Glasses">%1$s</xliff:g>. <xliff:g id="app_name" example="Glasses">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.</string>
 
     <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile for singleDevice(type) [CHAR LIMIT=NONE] -->
-    <string name="summary_glasses_single_device">The app is needed to manage your <xliff:g id="device_name" example="My Glasses">%1$s</xliff:g>. <xliff:g id="app_name" example="Glasses">%2$s</xliff:g> will be allowed to interact with these permissions:</string>
+    <string name="summary_glasses_single_device">The app is needed to manage <xliff:g id="device_name" example="My Glasses">%1$s</xliff:g>. <xliff:g id="app_name" example="Glasses">%2$s</xliff:g> will be allowed to interact with these permissions:</string>
 
     <!-- ================= DEVICE_PROFILE_APP_STREAMING ================= -->
 
@@ -99,7 +99,10 @@
     <string name="profile_name_generic">device</string>
 
     <!-- Description of the privileges the application will get if associated with the companion device of unspecified profile (type) [CHAR LIMIT=NONE] -->
-    <string name="summary_generic"></string>
+    <string name="summary_generic_single_device">This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>.</string>
+
+    <!-- Description of the privileges the application will get if associated with the companion device of unspecified profile (type) [CHAR LIMIT=NONE] -->
+    <string name="summary_generic">This app will be able to sync info, like the name of someone calling, between your phone and the chosen device.</string>
 
     <!-- ================= Buttons ================= -->
 
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index c5ed5c9..918f9c6 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -546,17 +546,16 @@
         }
 
         if (deviceProfile == null) {
-            // Summary is not needed for null profile.
-            mSummary.setVisibility(View.GONE);
+            summary = getHtmlFromResources(this, SUMMARIES.get(null), deviceName);
             mConstraintList.setVisibility(View.GONE);
         } else {
+            summary = getHtmlFromResources(this, SUMMARIES.get(deviceProfile),
+                    getString(PROFILES_NAME.get(deviceProfile)), appLabel);
             mPermissionTypes.addAll(PERMISSION_TYPES.get(deviceProfile));
             setupPermissionList();
         }
 
         title = getHtmlFromResources(this, TITLES.get(deviceProfile), appLabel, deviceName);
-        summary = getHtmlFromResources(this, SUMMARIES.get(deviceProfile),
-                getString(PROFILES_NAME.get(deviceProfile)), appLabel);
         profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile));
 
         mTitle.setText(title);
@@ -586,7 +585,6 @@
 
         if (deviceProfile == null) {
             summary = getHtmlFromResources(this, summaryResourceId);
-            mSummary.setVisibility(View.GONE);
         } else {
             summary = getHtmlFromResources(this, summaryResourceId, profileName, appLabel);
         }
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
index 6f5f4fe..e3fd354 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
@@ -88,7 +88,7 @@
         final Map<String, Integer> map = new ArrayMap<>();
         map.put(DEVICE_PROFILE_WATCH, R.string.summary_watch_single_device);
         map.put(DEVICE_PROFILE_GLASSES, R.string.summary_glasses_single_device);
-        map.put(null, R.string.summary_generic);
+        map.put(null, R.string.summary_generic_single_device);
 
         SUMMARIES = unmodifiableMap(map);
     }
diff --git a/packages/CredentialManager/Android.bp b/packages/CredentialManager/Android.bp
index 2cb3468..00d42bd 100644
--- a/packages/CredentialManager/Android.bp
+++ b/packages/CredentialManager/Android.bp
@@ -31,6 +31,7 @@
         "androidx.compose.ui_ui",
         "androidx.compose.ui_ui-tooling",
         "androidx.core_core-ktx",
+        "androidx.credentials_credentials",
         "androidx.lifecycle_lifecycle-extensions",
         "androidx.lifecycle_lifecycle-livedata",
         "androidx.lifecycle_lifecycle-runtime-ktx",
diff --git a/packages/CredentialManager/AndroidManifest.xml b/packages/CredentialManager/AndroidManifest.xml
index 5a4d256..499d130 100644
--- a/packages/CredentialManager/AndroidManifest.xml
+++ b/packages/CredentialManager/AndroidManifest.xml
@@ -32,7 +32,6 @@
       android:supportsRtl="true"
       android:theme="@style/Theme.CredentialSelector">
 
-    <!--TODO: make sure implementing singleTop on NewIntent-->
     <activity
         android:name=".CredentialSelectorActivity"
         android:exported="true"
diff --git a/packages/CredentialManager/res/values-af/strings.xml b/packages/CredentialManager/res/values-af/strings.xml
index f62b72d..4b33826 100644
--- a/packages/CredentialManager/res/values-af/strings.xml
+++ b/packages/CredentialManager/res/values-af/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Gaan voort"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Meer opsies"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Kom meer te wete"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Veiliger met wagwoordsleutels"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Met wagwoordsleutels hoef jy nie komplekse wagwoorde te skep of te onthou nie"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Wagwoordsleutels is geënkripteerde digitale sleutels wat jy met jou vingerafdruk, gesig of skermslot skep"</string>
diff --git a/packages/CredentialManager/res/values-am/strings.xml b/packages/CredentialManager/res/values-am/strings.xml
index 5a35369..4af61d4 100644
--- a/packages/CredentialManager/res/values-am/strings.xml
+++ b/packages/CredentialManager/res/values-am/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ቀጥል"</string>
     <string name="string_more_options" msgid="7990658711962795124">"ተጨማሪ አማራጮች"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"የበለጠ ለመረዳት"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"በይለፍ ቃል ይበልጥ ደህንነቱ የተጠበቀ"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"በይለፍ ቁልፎች ውስብስብ የይለፍ ቁልፎችን መፍጠር ወይም ማስታወስ አያስፈልግዎትም"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"የይለፍ ቁልፎች የእርስዎን የጣት አሻራ፣ መልክ ወይም የማያ ገጽ መቆለፊያ በመጠቀም የሚፈጥሯቸው የተመሰጠሩ ዲጂታል ቆልፎች ናቸው"</string>
diff --git a/packages/CredentialManager/res/values-ar/strings.xml b/packages/CredentialManager/res/values-ar/strings.xml
index 7244489..91ec097 100644
--- a/packages/CredentialManager/res/values-ar/strings.xml
+++ b/packages/CredentialManager/res/values-ar/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"متابعة"</string>
     <string name="string_more_options" msgid="7990658711962795124">"خيارات إضافية"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"مزيد من المعلومات"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"توفير المزيد من الأمان باستخدام مفاتيح المرور"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"باستخدام مفاتيح المرور، لا حاجة لإنشاء كلمات مرور معقدة أو تذكّرها."</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"مفاتيح المرور هي مفاتيح رقمية مشفّرة يمكنك إنشاؤها باستخدام بصمة الإصبع أو التعرّف على الوجه أو قفل الشاشة."</string>
diff --git a/packages/CredentialManager/res/values-as/strings.xml b/packages/CredentialManager/res/values-as/strings.xml
index 6f68adb..ddacad8 100644
--- a/packages/CredentialManager/res/values-as/strings.xml
+++ b/packages/CredentialManager/res/values-as/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"অব্যাহত ৰাখক"</string>
     <string name="string_more_options" msgid="7990658711962795124">"অধিক বিকল্প"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"অধিক জানক"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"পাছকীৰ জৰিয়তে অধিক সুৰক্ষিত"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"পাছকী ব্যৱহাৰ কৰিলে আপুনি জটিল পাছৱৰ্ড সৃষ্টি কৰিব অথবা মনত ৰাখিব নালাগে"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"পাছকীসমূহ হৈছে আপুনি আপোনাৰ ফিংগাৰপ্ৰিণ্ট, মুখাৱয়ব অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰি সৃষ্টি কৰা এনক্ৰিপ্ট কৰা ডিজিটেল চাবি"</string>
diff --git a/packages/CredentialManager/res/values-az/strings.xml b/packages/CredentialManager/res/values-az/strings.xml
index bb35963..5ecfd93 100644
--- a/packages/CredentialManager/res/values-az/strings.xml
+++ b/packages/CredentialManager/res/values-az/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Davam edin"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Digər seçimlər"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Ətraflı məlumat"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Giriş açarları ilə daha təhlükəsiz"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Giriş açarları ilə mürəkkəb parollar yaratmağa və ya yadda saxlamağa ehtiyac yoxdur"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Giriş açarları barmaq izi, üz və ya ekran kilidindən istifadə edərək yaratdığınız şifrələnmiş rəqəmsal açarlardır"</string>
diff --git a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
index 3182c13..8fc1ee5 100644
--- a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Nastavi"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Još opcija"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Saznajte više"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Bezbednije uz pristupne kodove"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne kodove nema potrebe da pravite ili pamtite složene lozinke"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pristupni kodovi su šifrovani digitalni kodovi koje pravite pomoću otiska prsta, lica ili zaključavanja ekrana"</string>
diff --git a/packages/CredentialManager/res/values-be/strings.xml b/packages/CredentialManager/res/values-be/strings.xml
index 2979cff..d483d98 100644
--- a/packages/CredentialManager/res/values-be/strings.xml
+++ b/packages/CredentialManager/res/values-be/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Далей"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Дадатковыя параметры"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Даведацца больш"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"З ключамі доступу вам будзе бяспечней."</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Дзякуючы ключам доступу вам не трэба ствараць і запамінаць складаныя паролі."</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ключы доступу – гэта зашыфраваныя лючбавыя ключы, створаныя вамі з дапамогай адбітка пальца, твару ці блакіроўкі экрана."</string>
diff --git a/packages/CredentialManager/res/values-bg/strings.xml b/packages/CredentialManager/res/values-bg/strings.xml
index 759f2d46..15a1c74 100644
--- a/packages/CredentialManager/res/values-bg/strings.xml
+++ b/packages/CredentialManager/res/values-bg/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Напред"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Още опции"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Научете повече"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"По-сигурно с помощта на кодове за достъп"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Когато използвате кодове за достъп, не е необходимо да създавате, нито да помните сложни пароли"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Кодовете за достъп са шифровани дигитални ключове, които създавате посредством отпечатъка, лицето си или опцията си за заключване на екрана"</string>
diff --git a/packages/CredentialManager/res/values-bn/strings.xml b/packages/CredentialManager/res/values-bn/strings.xml
index 17905ee..8787fa9 100644
--- a/packages/CredentialManager/res/values-bn/strings.xml
+++ b/packages/CredentialManager/res/values-bn/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"চালিয়ে যান"</string>
     <string name="string_more_options" msgid="7990658711962795124">"আরও বিকল্প"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"আরও জানুন"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"\'পাসকী\'-এর সাথে সুরক্ষিত"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"\'পাসকী\' ব্যবহার করলে জটিল পাসওয়ার্ড তৈরি করার বা মনে রাখার কোনও প্রয়োজন নেই"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"আপনার ফিঙ্গারপ্রিন্ট, ফেস মডেল বা \'স্ক্রিন লক\' ব্যবহার করে আপনি যে এনক্রিপটেড ডিজিটাল \'কী\' তৈরি করেন সেগুলিই হল \'পাসকী\'"</string>
diff --git a/packages/CredentialManager/res/values-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml
index e8d8ecc..a81e619 100644
--- a/packages/CredentialManager/res/values-bs/strings.xml
+++ b/packages/CredentialManager/res/values-bs/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Nastavi"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Više opcija"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Saznajte više"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sigurniji ste uz pristupne ključeve"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne ključeve ne morate kreirati ili pamtiti složene lozinke"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pristupni ključevi su šifrirani digitalni ključevi koje kreirate pomoću otiska prsta, lica ili zaključavanja ekrana"</string>
diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml
index 300c95f..465f7c1 100644
--- a/packages/CredentialManager/res/values-ca/strings.xml
+++ b/packages/CredentialManager/res/values-ca/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continua"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Més opcions"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Més informació"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Més seguretat amb les claus d\'accés"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Amb les claus d\'accés, no cal que creïs ni recordis contrasenyes difícils"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les claus d\'accés són claus digitals encriptades que pots crear amb la teva cara, l\'empremta digital o el bloqueig de pantalla"</string>
diff --git a/packages/CredentialManager/res/values-cs/strings.xml b/packages/CredentialManager/res/values-cs/strings.xml
index de5c5b6..059b931 100644
--- a/packages/CredentialManager/res/values-cs/strings.xml
+++ b/packages/CredentialManager/res/values-cs/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Pokračovat"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Další možnosti"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Další informace"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Přístupové klíče zvyšují bezpečnost"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"S přístupovými klíči si nemusíte vytvářet ani pamatovat složitá hesla"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Přístupové klíče jsou šifrované digitální klíče, které vytvoříte pomocí otisku prstu, obličeje nebo zámku obrazovky"</string>
diff --git a/packages/CredentialManager/res/values-da/strings.xml b/packages/CredentialManager/res/values-da/strings.xml
index b214c04..49c7fd8 100644
--- a/packages/CredentialManager/res/values-da/strings.xml
+++ b/packages/CredentialManager/res/values-da/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Fortsæt"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Flere valgmuligheder"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Få flere oplysninger"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Øget beskyttelse med adgangsnøgler"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Når du bruger adgangsnøgler, behøver du ikke at oprette eller huske avancerede adgangskoder"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Adgangsnøgler er krypterede digitale nøgler, som du opretter ved hjælp af fingeraftryk, ansigtsgenkendelse eller skærmlås"</string>
diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml
index 91afe23..52a0fc89 100644
--- a/packages/CredentialManager/res/values-de/strings.xml
+++ b/packages/CredentialManager/res/values-de/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Weiter"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Weitere Optionen"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Weitere Informationen"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mehr Sicherheit mit Passkeys"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Mit Passkeys musst du keine komplizierten Passwörter erstellen oder dir merken"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys sind verschlüsselte digitale Schlüssel, die du mithilfe deines Fingerabdrucks, Gesichts oder deiner Displaysperre erstellst"</string>
diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml
index 2797b37..eb5f333 100644
--- a/packages/CredentialManager/res/values-el/strings.xml
+++ b/packages/CredentialManager/res/values-el/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Συνέχεια"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Περισσότερες επιλογές"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Μάθετε περισσότερα"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Μεγαλύτερη ασφάλεια με κλειδιά πρόσβασης"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Με τα κλειδιά πρόσβασης, δεν χρειάζεται να δημιουργείτε ή να θυμάστε σύνθετους κωδικούς πρόσβασης."</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Τα κλειδιά πρόσβασης είναι κρυπτογραφημένα ψηφιακά κλειδιά που δημιουργείτε χρησιμοποιώντας το δακτυλικό σας αποτύπωμα, το πρόσωπο ή το κλείδωμα οθόνης."</string>
diff --git a/packages/CredentialManager/res/values-en-rAU/strings.xml b/packages/CredentialManager/res/values-en-rAU/strings.xml
index 76b58c7..db14cf2 100644
--- a/packages/CredentialManager/res/values-en-rAU/strings.xml
+++ b/packages/CredentialManager/res/values-en-rAU/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continue"</string>
     <string name="string_more_options" msgid="7990658711962795124">"More options"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Learn more"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Safer with passkeys"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"With passkeys, you don’t need to create or remember complex passwords"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys are encrypted digital keys that you create using your fingerprint, face or screen lock"</string>
diff --git a/packages/CredentialManager/res/values-en-rCA/strings.xml b/packages/CredentialManager/res/values-en-rCA/strings.xml
index 5277f67..e8d68ce 100644
--- a/packages/CredentialManager/res/values-en-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-en-rCA/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continue"</string>
     <string name="string_more_options" msgid="7990658711962795124">"More options"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Learn more"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Safer with passkeys"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"With passkeys, you don’t need to create or remember complex passwords"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys are encrypted digital keys you create using your fingerprint, face, or screen lock"</string>
diff --git a/packages/CredentialManager/res/values-en-rGB/strings.xml b/packages/CredentialManager/res/values-en-rGB/strings.xml
index 76b58c7..db14cf2 100644
--- a/packages/CredentialManager/res/values-en-rGB/strings.xml
+++ b/packages/CredentialManager/res/values-en-rGB/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continue"</string>
     <string name="string_more_options" msgid="7990658711962795124">"More options"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Learn more"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Safer with passkeys"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"With passkeys, you don’t need to create or remember complex passwords"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys are encrypted digital keys that you create using your fingerprint, face or screen lock"</string>
diff --git a/packages/CredentialManager/res/values-en-rIN/strings.xml b/packages/CredentialManager/res/values-en-rIN/strings.xml
index 76b58c7..db14cf2 100644
--- a/packages/CredentialManager/res/values-en-rIN/strings.xml
+++ b/packages/CredentialManager/res/values-en-rIN/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continue"</string>
     <string name="string_more_options" msgid="7990658711962795124">"More options"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Learn more"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Safer with passkeys"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"With passkeys, you don’t need to create or remember complex passwords"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys are encrypted digital keys that you create using your fingerprint, face or screen lock"</string>
diff --git a/packages/CredentialManager/res/values-en-rXC/strings.xml b/packages/CredentialManager/res/values-en-rXC/strings.xml
index 9ea9cf5..8eb00a3 100644
--- a/packages/CredentialManager/res/values-en-rXC/strings.xml
+++ b/packages/CredentialManager/res/values-en-rXC/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎Continue‎‏‎‎‏‎"</string>
     <string name="string_more_options" msgid="7990658711962795124">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‎‎More options‎‏‎‎‏‎"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎Learn more‎‏‎‎‏‎"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎Safer with passkeys‎‏‎‎‏‎"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎With passkeys, you don’t need to create or remember complex passwords‎‏‎‎‏‎"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎Passkeys are encrypted digital keys you create using your fingerprint, face, or screen lock‎‏‎‎‏‎"</string>
diff --git a/packages/CredentialManager/res/values-es-rUS/strings.xml b/packages/CredentialManager/res/values-es-rUS/strings.xml
index c096d13..5c644b8 100644
--- a/packages/CredentialManager/res/values-es-rUS/strings.xml
+++ b/packages/CredentialManager/res/values-es-rUS/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Más opciones"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Más información"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Más seguridad con llaves de acceso"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Con las llaves de acceso, no es necesario crear ni recordar contraseñas complejas"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Las llaves de acceso son claves digitales encriptadas que puedes crear usando tu huella dactilar, rostro o bloqueo de pantalla"</string>
diff --git a/packages/CredentialManager/res/values-es/strings.xml b/packages/CredentialManager/res/values-es/strings.xml
index c6e67cf..59408b5 100644
--- a/packages/CredentialManager/res/values-es/strings.xml
+++ b/packages/CredentialManager/res/values-es/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Más opciones"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Más información"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Más seguridad con las llaves de acceso"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Con las llaves de acceso, no tienes que crear ni recordar contraseñas complicadas"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Las llaves de acceso son claves digitales cifradas que puedes crear con tu huella digital, cara o bloqueo de pantalla"</string>
diff --git a/packages/CredentialManager/res/values-et/strings.xml b/packages/CredentialManager/res/values-et/strings.xml
index 875460d..f2480f6 100644
--- a/packages/CredentialManager/res/values-et/strings.xml
+++ b/packages/CredentialManager/res/values-et/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Jätka"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Rohkem valikuid"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Lisateave"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Pääsuvõtmed suurendavad turvalisust"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Pääsuvõtmetega ei pea te looma ega meelde jätma keerukaid paroole"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pääsuvõtmed on digitaalsed krüpteeritud võtmed, mille loote sõrmejälje, näo või ekraanilukuga"</string>
diff --git a/packages/CredentialManager/res/values-eu/strings.xml b/packages/CredentialManager/res/values-eu/strings.xml
index a037d78..3a06cd4 100644
--- a/packages/CredentialManager/res/values-eu/strings.xml
+++ b/packages/CredentialManager/res/values-eu/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Egin aurrera"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Aukera gehiago"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Lortu informazio gehiago"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sarbide-gako seguruagoak"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Sarbide-gakoei esker, ez duzu pasahitz konplexurik sortu edo gogoratu beharrik"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Hatz-marka, aurpegia edo pantailaren blokeoa erabilita sortzen dituzun giltza digital enkriptatuak dira sarbide-gakoak"</string>
diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml
index c833024..06cb202 100644
--- a/packages/CredentialManager/res/values-fa/strings.xml
+++ b/packages/CredentialManager/res/values-fa/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ادامه"</string>
     <string name="string_more_options" msgid="7990658711962795124">"گزینه‌های بیشتر"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"بیشتر بدانید"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"فضایی ایمن‌تر با گذرکلید"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"با گذرکلیدها، لازم نیست گذرواژه پیچیده‌ای بسازید یا آن را به‌خاطر بسپارید"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"گذرکلیدها کلیدهای دیجیتالی رمزگذاری‌شده‌ای هستند که بااستفاده از اثر انگشت، چهره، یا قفل صفحه ایجاد می‌کنید"</string>
diff --git a/packages/CredentialManager/res/values-fi/strings.xml b/packages/CredentialManager/res/values-fi/strings.xml
index 08dd739..9f5cb14 100644
--- a/packages/CredentialManager/res/values-fi/strings.xml
+++ b/packages/CredentialManager/res/values-fi/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Jatka"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Lisäasetukset"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Lue lisää"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Turvallisuutta avainkoodeilla"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Kun käytät avainkoodeja, sinun ei tarvitse luoda tai muistaa monimutkaisia salasanoja"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Avainkoodit ovat salattuja digitaalisia avaimia, joita voit luoda sormenjäljen, kasvojen tai näytön lukituksen avulla"</string>
diff --git a/packages/CredentialManager/res/values-fr-rCA/strings.xml b/packages/CredentialManager/res/values-fr-rCA/strings.xml
index 445284d..4a1c47a 100644
--- a/packages/CredentialManager/res/values-fr-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-fr-rCA/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continuer"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Autres options"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"En savoir plus"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Une sécurité accrue grâce aux clés d\'accès"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Avec les clés d\'accès, nul besoin de créer ou de mémoriser des mots de passe complexes"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les clés d\'accès sont des clés numériques chiffrées que vous créez en utilisant votre empreinte digitale, votre visage ou le verrouillage de votre écran"</string>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index cc39214..9b979b6 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continuer"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Autres options"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"En savoir plus"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sécurité renforcée grâce aux clés d\'accès"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Avec les clés d\'accès, plus besoin de créer ni de mémoriser des mots de passe complexes"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les clés d\'accès sont des clés numériques chiffrées que vous créez à l\'aide de votre empreinte digitale, de votre visage ou du verrouillage de l\'écran"</string>
diff --git a/packages/CredentialManager/res/values-gl/strings.xml b/packages/CredentialManager/res/values-gl/strings.xml
index 4fb09cc..0cdda7f 100644
--- a/packages/CredentialManager/res/values-gl/strings.xml
+++ b/packages/CredentialManager/res/values-gl/strings.xml
@@ -5,30 +5,24 @@
     <string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
     <string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Máis opcións"</string>
-    <!-- no translation found for string_learn_more (4541600451688392447) -->
+    <string name="string_learn_more" msgid="4541600451688392447">"Máis información"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
     <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Máis protección coas claves de acceso"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Cunha clave de acceso, non é necesario que crees ou lembres contrasinais complexos"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As claves de acceso son claves dixitais encriptadas que creas usando a túa impresión dixital, a túa cara ou o teu bloqueo de pantalla"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"As claves de acceso gárdanse nun xestor de contrasinais para que poidas iniciar sesión noutros dispositivos"</string>
-    <!-- no translation found for more_about_passkeys_title (7797903098728837795) -->
-    <skip />
-    <!-- no translation found for passwordless_technology_title (2497513482056606668) -->
-    <skip />
-    <!-- no translation found for passwordless_technology_detail (6853928846532955882) -->
-    <skip />
-    <!-- no translation found for public_key_cryptography_title (6751970819265298039) -->
-    <skip />
-    <!-- no translation found for public_key_cryptography_detail (6937631710280562213) -->
-    <skip />
-    <!-- no translation found for improved_account_security_title (1069841917893513424) -->
-    <skip />
-    <!-- no translation found for improved_account_security_detail (9123750251551844860) -->
-    <skip />
-    <!-- no translation found for seamless_transition_title (5335622196351371961) -->
-    <skip />
-    <!-- no translation found for seamless_transition_detail (4475509237171739843) -->
-    <skip />
+    <string name="more_about_passkeys_title" msgid="7797903098728837795">"Máis información sobre as claves de acceso"</string>
+    <string name="passwordless_technology_title" msgid="2497513482056606668">"Tecnoloxía sen contrasinais"</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"As claves de acceso permítenche iniciar sesión sen depender de contrasinais. Tan só tes que usar a impresión dixital, o recoñecemento facial, o PIN ou o padrón de desbloqueo para verificar a túa identidade e crear unha clave de acceso."</string>
+    <string name="public_key_cryptography_title" msgid="6751970819265298039">"Criptografía das claves públicas"</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Segundo os estándares da Alianza FIDO (con Google, Apple, Microsoft…) e o W3C, as claves de acceso usan pares de claves criptográficas. A diferenza do nome de usuario e contrasinal, créase un par de claves público-privado para unha aplicación ou sitio web. A clave privada, que confirma a identidade, almacénase de xeito seguro no dispositivo ou xestor de contrasinais. A pública compártese co servidor da aplicación ou sitio web. Coas claves vinculadas, podes rexistrarte e conectarte ao momento."</string>
+    <string name="improved_account_security_title" msgid="1069841917893513424">"Mellora na seguranza das contas"</string>
+    <string name="improved_account_security_detail" msgid="9123750251551844860">"Cada clave está vinculada de xeito exclusivo coa aplicación ou o sitio web para o que foi creada, de tal forma que nunca poidas iniciar sesión nunha aplicación ou un sitio web fraudulentos por erro. Ademais, como os servidores só gardan as claves públicas, resulta moito máis difícil piratear."</string>
+    <string name="seamless_transition_title" msgid="5335622196351371961">"Transición fluída"</string>
+    <string name="seamless_transition_detail" msgid="4475509237171739843">"Durante este percorrido cara a un futuro sen contrasinais, estes seguirán estando dispoñibles a canda as claves de acceso."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Escolle onde queres gardar: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selecciona un xestor de contrasinais para gardar a túa información e iniciar sesión máis rápido a próxima vez"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Queres crear unha clave de acceso para <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
diff --git a/packages/CredentialManager/res/values-gu/strings.xml b/packages/CredentialManager/res/values-gu/strings.xml
index 6afc6e6..e2c80f1 100644
--- a/packages/CredentialManager/res/values-gu/strings.xml
+++ b/packages/CredentialManager/res/values-gu/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ચાલુ રાખો"</string>
     <string name="string_more_options" msgid="7990658711962795124">"વધુ વિકલ્પો"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"વધુ જાણો"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"પાસકી સાથે વધુ સલામત"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"પાસકી હોવાથી, તમારે જટિલ પાસવર્ડ બનાવવાની કે યાદ રાખવાની જરૂર રહેતી નથી"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"પાસકી એ એન્ક્રિપ્ટેડ ડિજિટલ કી છે, જેને તમે તમારી ફિંગરપ્રિન્ટ, ચહેરા અથવા સ્ક્રીન લૉકનો ઉપયોગ કરીને બનાવો છો"</string>
diff --git a/packages/CredentialManager/res/values-hi/strings.xml b/packages/CredentialManager/res/values-hi/strings.xml
index 71ee22b..aead7a5 100644
--- a/packages/CredentialManager/res/values-hi/strings.xml
+++ b/packages/CredentialManager/res/values-hi/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"जारी रखें"</string>
     <string name="string_more_options" msgid="7990658711962795124">"ज़्यादा विकल्प"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ज़्यादा जानें"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकी के साथ सुरक्षित रहें"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"पासकी होने पर, आपको जटिल पासवर्ड बनाने या याद रखने की ज़रूरत नहीं पड़ती"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी, एन्क्रिप्ट (सुरक्षित) की गई डिजिटल की होती हैं. इन्हें फ़िंगरप्रिंट, चेहरे या स्क्रीन लॉक का इस्तेमाल करके बनाया जाता है"</string>
diff --git a/packages/CredentialManager/res/values-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml
index aff78ff..26ed677 100644
--- a/packages/CredentialManager/res/values-hr/strings.xml
+++ b/packages/CredentialManager/res/values-hr/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Nastavi"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Više opcija"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Saznajte više"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sigurniji s pristupnim ključevima"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne ključeve ne trebate izrađivati ili pamtiti složene zaporke"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pristupni ključevi šifrirani su digitalni ključevi koje izrađujete pomoću svojeg otiska prsta, lica ili zaključavanja zaslona"</string>
diff --git a/packages/CredentialManager/res/values-hu/strings.xml b/packages/CredentialManager/res/values-hu/strings.xml
index 71e8cb3..1caea61 100644
--- a/packages/CredentialManager/res/values-hu/strings.xml
+++ b/packages/CredentialManager/res/values-hu/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Folytatás"</string>
     <string name="string_more_options" msgid="7990658711962795124">"További lehetőségek"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"További információ"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Fokozott biztonság – azonosítókulccsal"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Azonosítókulcs birtokában nincs szükség összetett jelszavak létrehozására vagy megjegyzésére"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Az azonosítókulcsok olyan digitális kulcsok, amelyeket ujjlenyomata, arca vagy képernyőzár használatával hoz létre"</string>
diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml
index 66aa664..644a7f6 100644
--- a/packages/CredentialManager/res/values-hy/strings.xml
+++ b/packages/CredentialManager/res/values-hy/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Շարունակել"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Այլ տարբերակներ"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Իմանալ ավելին"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Անցաբառերի հետ ավելի ապահով է"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Անցաբառերի շնորհիվ դուք բարդ գաղտնաբառեր ստեղծելու կամ հիշելու անհրաժեշտություն չեք ունենա"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Անցաբառերը գաղտնագրված թվային բանալիներ են, որոնք ստեղծվում են մատնահետքի, դեմքով ապակողպման կամ էկրանի կողպման օգտագործմամբ"</string>
diff --git a/packages/CredentialManager/res/values-in/strings.xml b/packages/CredentialManager/res/values-in/strings.xml
index 8171335..e9adbd5 100644
--- a/packages/CredentialManager/res/values-in/strings.xml
+++ b/packages/CredentialManager/res/values-in/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Lanjutkan"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Opsi lainnya"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Pelajari lebih lanjut"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Lebih aman dengan kunci sandi"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dengan kunci sandi, Anda tidak perlu membuat atau mengingat sandi yang rumit"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kunci sandi adalah kunci digital terenkripsi yang Anda buat menggunakan sidik jari, wajah, atau kunci layar"</string>
diff --git a/packages/CredentialManager/res/values-is/strings.xml b/packages/CredentialManager/res/values-is/strings.xml
index 2e5218c..7917a0d 100644
--- a/packages/CredentialManager/res/values-is/strings.xml
+++ b/packages/CredentialManager/res/values-is/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Áfram"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Fleiri valkostir"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Nánar"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Aukið öryggi með aðgangslyklum"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Með aðgangslyklum þarftu hvorki að búa til né muna flókin aðgangsorð"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Aðgangslyklar eru dulkóðaðir stafrænir lyklar sem þú býrð til með fingrafarinu þínu, andliti eða skjálás."</string>
diff --git a/packages/CredentialManager/res/values-it/strings.xml b/packages/CredentialManager/res/values-it/strings.xml
index c28659b..c35f705 100644
--- a/packages/CredentialManager/res/values-it/strings.xml
+++ b/packages/CredentialManager/res/values-it/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continua"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Altre opzioni"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Scopri di più"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Più al sicuro con le passkey"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Con le passkey non è necessario creare o ricordare password complesse"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Le passkey sono chiavi digitali criptate che crei usando la tua impronta, il tuo volto o il blocco schermo"</string>
diff --git a/packages/CredentialManager/res/values-iw/strings.xml b/packages/CredentialManager/res/values-iw/strings.xml
index 2082e7e..ab17e2f 100644
--- a/packages/CredentialManager/res/values-iw/strings.xml
+++ b/packages/CredentialManager/res/values-iw/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"המשך"</string>
     <string name="string_more_options" msgid="7990658711962795124">"אפשרויות נוספות"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"מידע נוסף"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"בטוח יותר להשתמש במפתחות גישה"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"עם מפתחות הגישה לא צריך יותר ליצור או לזכור סיסמאות מורכבות"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"מפתחות גישה הם מפתחות דיגיטליים מוצפנים שניתן ליצור באמצעות טביעת האצבע, זיהוי הפנים או נעילת המסך"</string>
diff --git a/packages/CredentialManager/res/values-ja/strings.xml b/packages/CredentialManager/res/values-ja/strings.xml
index 3aab2e9f..92da64c 100644
--- a/packages/CredentialManager/res/values-ja/strings.xml
+++ b/packages/CredentialManager/res/values-ja/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"続行"</string>
     <string name="string_more_options" msgid="7990658711962795124">"その他のオプション"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"詳細"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"パスキーでより安全に"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"パスキーがあれば、複雑なパスワードを作成したり覚えたりする必要はありません"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"パスキーは、指紋認証、顔認証、または画面ロックを使って作成される暗号化されたデジタルキーです"</string>
diff --git a/packages/CredentialManager/res/values-ka/strings.xml b/packages/CredentialManager/res/values-ka/strings.xml
index ee94b7e..00c62bc 100644
--- a/packages/CredentialManager/res/values-ka/strings.xml
+++ b/packages/CredentialManager/res/values-ka/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"გაგრძელება"</string>
     <string name="string_more_options" msgid="7990658711962795124">"სხვა ვარიანტები"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"შეიტყვეთ მეტი"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"უფრო უსაფრთხოა წვდომის გასაღების შემთხვევაში"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"წვდომის გასაღებების დახმარებით აღარ მოგიწევთ რთული პაროლების შექმნა და დამახსოვრება"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"წვდომის გასაღებები დაშიფრული ციფრული გასაღებებია, რომლებსაც თქვენი თითის ანაბეჭდით, სახით ან ეკრანის დაბლოკვით ქმნით"</string>
diff --git a/packages/CredentialManager/res/values-kk/strings.xml b/packages/CredentialManager/res/values-kk/strings.xml
index 7daf552..a59bcd5 100644
--- a/packages/CredentialManager/res/values-kk/strings.xml
+++ b/packages/CredentialManager/res/values-kk/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Жалғастыру"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Басқа опциялар"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Толық ақпарат"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Кіру кілттерімен қауіпсіздеу"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Кіру кілттері бар кезде күрделі құпия сөздер жасаудың немесе оларды есте сақтаудың қажеті жоқ."</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Кіру кілттері — саусақ ізі, бет не экран құлпы арқылы жасалатын шифрланған цифрлық кілттер."</string>
diff --git a/packages/CredentialManager/res/values-km/strings.xml b/packages/CredentialManager/res/values-km/strings.xml
index dce384d..c5db1db 100644
--- a/packages/CredentialManager/res/values-km/strings.xml
+++ b/packages/CredentialManager/res/values-km/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"បន្ត"</string>
     <string name="string_more_options" msgid="7990658711962795124">"ជម្រើសច្រើនទៀត"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ស្វែងយល់បន្ថែម"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"កាន់តែមានសុវត្ថិភាពដោយប្រើកូដសម្ងាត់"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"តាមរយៈ​កូដសម្ងាត់ អ្នកមិនចាំបាច់​បង្កើត ឬចងចាំពាក្យសម្ងាត់ស្មុគស្មាញ​នោះទេ"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"កូដសម្ងាត់​ត្រូវបានអ៊ីនគ្រីប​ឃីឌីជីថលដែលអ្នកបង្កើតដោយប្រើ​ស្នាមម្រាមដៃ មុខ ឬចាក់សោអេក្រង់​របស់អ្នក"</string>
diff --git a/packages/CredentialManager/res/values-kn/strings.xml b/packages/CredentialManager/res/values-kn/strings.xml
index cbc9a26..0bb1c03 100644
--- a/packages/CredentialManager/res/values-kn/strings.xml
+++ b/packages/CredentialManager/res/values-kn/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ಮುಂದುವರಿಸಿ"</string>
     <string name="string_more_options" msgid="7990658711962795124">"ಇನ್ನಷ್ಟು ಆಯ್ಕೆಗಳು"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"ಪಾಸ್‌ಕೀಗಳೊಂದಿಗೆ ಸುರಕ್ಷಿತವಾಗಿರುತ್ತವೆ"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ಪಾಸ್‌ಕೀಗಳ ಮೂಲಕ, ನೀವು ಕ್ಲಿಷ್ಟ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ರಚಿಸುವ ಅಥವಾ ನೆನಪಿಟ್ಟುಕೊಳ್ಳುವ ಅಗತ್ಯವಿಲ್ಲ"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ಪಾಸ್‌ಕೀಗಳು ನಿಮ್ಮ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್, ಫೇಸ್ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು ನೀವು ರಚಿಸುವ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಡಿಜಿಟಲ್ ಕೀಗಳಾಗಿವೆ"</string>
diff --git a/packages/CredentialManager/res/values-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml
index 4af16b3..04bc0fd 100644
--- a/packages/CredentialManager/res/values-ko/strings.xml
+++ b/packages/CredentialManager/res/values-ko/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"계속"</string>
     <string name="string_more_options" msgid="7990658711962795124">"옵션 더보기"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"자세히 알아보기"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"패스키로 더 안전하게"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"패스키를 사용하면 복잡한 비밀번호를 만들거나 기억하지 않아도 됩니다."</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"패스키는 지문, 얼굴 또는 화면 잠금으로 생성하는 암호화된 디지털 키입니다."</string>
diff --git a/packages/CredentialManager/res/values-ky/strings.xml b/packages/CredentialManager/res/values-ky/strings.xml
index ac15c5b..446c8f0 100644
--- a/packages/CredentialManager/res/values-ky/strings.xml
+++ b/packages/CredentialManager/res/values-ky/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Улантуу"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Башка варианттар"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Кеңири маалымат"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Мүмкүндүк алуу ачкычтары менен коопсузураак болот"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Мүмкүндүк алуу ачкычтары менен татаал сырсөздөрдү түзүп же эстеп калуунун кереги жок"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Мүмкүндүк алуу ачкычтары – манжаңыздын изи, жүзүңүз же экранды кулпулоо функциясы аркылуу түзгөн шифрленген санариптик ачкычтар"</string>
diff --git a/packages/CredentialManager/res/values-lo/strings.xml b/packages/CredentialManager/res/values-lo/strings.xml
index 30d9219..967f6be 100644
--- a/packages/CredentialManager/res/values-lo/strings.xml
+++ b/packages/CredentialManager/res/values-lo/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ສືບຕໍ່"</string>
     <string name="string_more_options" msgid="7990658711962795124">"ຕົວເລືອກເພີ່ມເຕີມ"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ສຶກສາເພີ່ມເຕີມ"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"ປອດໄພຂຶ້ນດ້ວຍກະແຈຜ່ານ"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ໂດຍການໃຊ້ກະແຈຜ່ານ, ທ່ານບໍ່ຈຳເປັນຕ້ອງສ້າງ ຫຼື ຈື່ລະຫັດຜ່ານທີ່ຊັບຊ້ອນ"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ກະແຈຜ່ານແມ່ນກະແຈດິຈິຕອນທີ່ໄດ້ຖືກເຂົ້າລະຫັດໄວ້ເຊິ່ງທ່ານສ້າງຂຶ້ນໂດຍໃຊ້ລາຍນິ້ວມື, ໃບໜ້າ ຫຼື ການລັອກໜ້າຈໍຂອງທ່ານ"</string>
diff --git a/packages/CredentialManager/res/values-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml
index 4197e14..9dd3e79 100644
--- a/packages/CredentialManager/res/values-lt/strings.xml
+++ b/packages/CredentialManager/res/values-lt/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Tęsti"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Daugiau parinkčių"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Sužinokite daugiau"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Saugiau naudojant slaptažodžius"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Naudojant „passkey“ nereikės kurti ir prisiminti sudėtingų slaptažodžių"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"„Passkey“ šifruojami skaitiniais raktais, kuriuos sukuriate naudodami piršto atspaudą, veidą ar ekrano užraktą"</string>
diff --git a/packages/CredentialManager/res/values-lv/strings.xml b/packages/CredentialManager/res/values-lv/strings.xml
index d18dd15..5741abd 100644
--- a/packages/CredentialManager/res/values-lv/strings.xml
+++ b/packages/CredentialManager/res/values-lv/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Turpināt"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Citas opcijas"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Uzzināt vairāk"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Lielāka drošība ar piekļuves atslēgām"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Izmantojot piekļuves atslēgas, nav jāveido vai jāatceras sarežģītas paroles."</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Piekļuves atslēgas ir šifrētas digitālas atslēgas, ko varat izveidot, izmantojot pirksta nospiedumu, seju vai ekrāna bloķēšanas informāciju."</string>
diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml
index a75dbc2..85257ad 100644
--- a/packages/CredentialManager/res/values-mk/strings.xml
+++ b/packages/CredentialManager/res/values-mk/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Продолжи"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Повеќе опции"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Дознајте повеќе"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Побезбедно со криптографски клучеви"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Со криптографските клучеви нема потреба да создавате или да помните сложени лозинки"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Криптографските клучеви се шифрирани дигитални клучеви што ги создавате со вашиот отпечаток, лик или заклучување екран"</string>
diff --git a/packages/CredentialManager/res/values-ml/strings.xml b/packages/CredentialManager/res/values-ml/strings.xml
index aeef052..2e5b9e0 100644
--- a/packages/CredentialManager/res/values-ml/strings.xml
+++ b/packages/CredentialManager/res/values-ml/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"തുടരുക"</string>
     <string name="string_more_options" msgid="7990658711962795124">"കൂടുതൽ ഓപ്‌ഷനുകൾ"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"കൂടുതലറിയുക"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"പാസ്‌കീകൾ ഉപയോഗിച്ച് സുരക്ഷിതരാകൂ"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"പാസ്‌കീകൾ ഉപയോഗിക്കുമ്പോൾ നിങ്ങൾ സങ്കീർണ്ണമായ പാസ്‌വേഡുകൾ സൃഷ്ടിക്കുകയോ ഓർമ്മിക്കുകയോ ചെയ്യേണ്ടതില്ല"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ഫിംഗർപ്രിന്റ്, മുഖം അല്ലെങ്കിൽ സ്‌ക്രീൻ ലോക്ക് ഉപയോഗിച്ച് നിങ്ങൾ സൃഷ്‌ടിക്കുന്ന എൻ‌ക്രിപ്റ്റ് ചെയ്ത ഡിജിറ്റൽ കീകളാണ് പാസ്‌കീകൾ"</string>
diff --git a/packages/CredentialManager/res/values-mn/strings.xml b/packages/CredentialManager/res/values-mn/strings.xml
index 2e4ed38..994b455 100644
--- a/packages/CredentialManager/res/values-mn/strings.xml
+++ b/packages/CredentialManager/res/values-mn/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Үргэлжлүүлэх"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Бусад сонголт"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Нэмэлт мэдээлэл авах"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Passkey-тэй байхад илүү аюулгүй"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Passkey-н тусламжтай та нарийн төвөгтэй нууц үг үүсгэх эсвэл санах шаардлагагүй"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkey нь таны хурууны хээ, царай эсвэл дэлгэцийн түгжээгээ ашиглан үүсгэсэн шифрлэгдсэн дижитал түлхүүр юм"</string>
diff --git a/packages/CredentialManager/res/values-mr/strings.xml b/packages/CredentialManager/res/values-mr/strings.xml
index 8626790..12429605 100644
--- a/packages/CredentialManager/res/values-mr/strings.xml
+++ b/packages/CredentialManager/res/values-mr/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"पुढे सुरू ठेवा"</string>
     <string name="string_more_options" msgid="7990658711962795124">"आणखी पर्याय"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"अधिक जाणून घ्या"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकीसह आणखी सुरक्षित"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"पासकीसोबत, तुम्हाला क्लिष्ट पासवर्ड तयार करण्याची किंवा लक्षात ठेवण्याची आवश्यकता नाही"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी या तुम्ही तुमचे फिंगरप्रिंट, फेस किंवा स्क्रीन लॉक वापरून तयार करता अशा एंक्रिप्ट केलेल्या डिजिटल की आहेत"</string>
diff --git a/packages/CredentialManager/res/values-ms/strings.xml b/packages/CredentialManager/res/values-ms/strings.xml
index dcc1987..06cd03c 100644
--- a/packages/CredentialManager/res/values-ms/strings.xml
+++ b/packages/CredentialManager/res/values-ms/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Teruskan"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Lagi pilihan"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Ketahui lebih lanjut"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Lebih selamat dengan kunci laluan"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Anda tidak perlu mencipta atau mengingati kata laluan yang rumit dengan kunci laluan"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kunci laluan ialah kunci digital disulitkan yang anda cipta menggunakan cap jari, wajah atau kunci skrin anda"</string>
diff --git a/packages/CredentialManager/res/values-my/strings.xml b/packages/CredentialManager/res/values-my/strings.xml
index 047f738..a7451e5 100644
--- a/packages/CredentialManager/res/values-my/strings.xml
+++ b/packages/CredentialManager/res/values-my/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ရှေ့ဆက်ရန်"</string>
     <string name="string_more_options" msgid="7990658711962795124">"နောက်ထပ်ရွေးစရာများ"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ပိုမိုလေ့လာရန်"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"လျှို့ဝှက်ကီးများဖြင့် ပိုလုံခြုံသည်"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"လျှို့ဝှက်ကီးများဖြင့် ရှုပ်ထွေးသောစကားဝှက်များကို ပြုလုပ်ရန် (သို့) မှတ်မိရန် မလိုပါ"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"လျှို့ဝှက်ကီးများမှာ သင်၏လက်ဗွေ၊ မျက်နှာ (သို့) ဖန်သားပြင်လော့ခ်သုံး၍ ပြုလုပ်ထားသော အသွင်ဝှက်ထားသည့် ဒစ်ဂျစ်တယ်ကီးများ ဖြစ်သည်"</string>
diff --git a/packages/CredentialManager/res/values-nb/strings.xml b/packages/CredentialManager/res/values-nb/strings.xml
index bee211e..7f386b95 100644
--- a/packages/CredentialManager/res/values-nb/strings.xml
+++ b/packages/CredentialManager/res/values-nb/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Fortsett"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Flere alternativer"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Finn ut mer"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Tryggere med tilgangsnøkler"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med tilgangsnøkler trenger du ikke å lage eller huske kompliserte passord"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Tilgangsnøkler er krypterte digitale nøkler du oppretter med fingeravtrykket, ansiktet eller skjermlåsen"</string>
diff --git a/packages/CredentialManager/res/values-ne/strings.xml b/packages/CredentialManager/res/values-ne/strings.xml
index ce33822..f0b0620 100644
--- a/packages/CredentialManager/res/values-ne/strings.xml
+++ b/packages/CredentialManager/res/values-ne/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"जारी राख्नुहोस्"</string>
     <string name="string_more_options" msgid="7990658711962795124">"थप विकल्पहरू"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"थप जान्नुहोस्"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकीका सहायताले सुरक्षित रहनुहोस्"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"तपाईंले पासकी बनाउनुभयो भने तपाईंले जटिल पासवर्ड बनाउनु वा तिनलाई याद गरिराख्नु पर्दैन"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी भनेको तपाईंले आफ्नो फिंगरप्रिन्ट, अनुहार वा स्क्रिन लक प्रयोग गरेर बनाएको इन्क्रिप्ट गरिएको डिजिटल की हो"</string>
diff --git a/packages/CredentialManager/res/values-nl/strings.xml b/packages/CredentialManager/res/values-nl/strings.xml
index adea5a3..17cd3dc 100644
--- a/packages/CredentialManager/res/values-nl/strings.xml
+++ b/packages/CredentialManager/res/values-nl/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Doorgaan"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Meer opties"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Meer informatie"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Veiliger met toegangssleutels"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Met toegangssleutels hoef je geen ingewikkelde wachtwoorden te maken of te onthouden"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Toegangssleutels zijn versleutelde digitale sleutels die je maakt met je vingerafdruk, gezicht of schermvergrendeling"</string>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 7e6d10a..60e8022 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ଜାରି ରଖନ୍ତୁ"</string>
     <string name="string_more_options" msgid="7990658711962795124">"ଅଧିକ ବିକଳ୍ପ"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"ପାସକୀ ସହ ଅଧିକ ସୁରକ୍ଷିତ"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ପାସକୀଗୁଡ଼ିକ ସହ ଆପଣଙ୍କୁ ଜଟିଳ ପାସୱାର୍ଡଗୁଡ଼ିକ ତିଆରି କରିବା କିମ୍ବା ମନେରଖିବାର ଆବଶ୍ୟକତା ନାହିଁ"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ପାସକୀଗୁଡ଼ିକ ହେଉଛି ଆପଣ ଆପଣଙ୍କ ଟିପଚିହ୍ନ, ଫେସ କିମ୍ବା ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରି ତିଆରି କରୁଥିବା ଏକକ୍ରିପ୍ଟ କରାଯାଇଥିବା ଡିଜିଟାଲ କୀ"</string>
diff --git a/packages/CredentialManager/res/values-pa/strings.xml b/packages/CredentialManager/res/values-pa/strings.xml
index cbf199e..9693245 100644
--- a/packages/CredentialManager/res/values-pa/strings.xml
+++ b/packages/CredentialManager/res/values-pa/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ਜਾਰੀ ਰੱਖੋ"</string>
     <string name="string_more_options" msgid="7990658711962795124">"ਹੋਰ ਵਿਕਲਪ"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ਹੋਰ ਜਾਣੋ"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"ਪਾਸਕੀਆਂ ਨਾਲ ਸੁਰੱਖਿਅਤ"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ਪਾਸਕੀਆਂ ਨਾਲ, ਤੁਹਾਨੂੰ ਜਟਿਲ ਪਾਸਵਰਡ ਬਣਾਉਣ ਜਾਂ ਯਾਦ ਰੱਖਣ ਦੀ ਲੋੜ ਨਹੀਂ ਹੁੰਦੀ"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ਪਾਸਕੀਆਂ ਇਨਕ੍ਰਿਪਟਡ ਡਿਜੀਟਲ ਕੁੰਜੀਆਂ ਹੁੰਦੀਆਂ ਹਨ ਜੋ ਤੁਹਾਡੇ ਵੱਲੋਂ ਤੁਹਾਡੇ ਫਿੰਗਰਪ੍ਰਿੰਟ, ਚਿਹਰੇ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਬਣਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ"</string>
diff --git a/packages/CredentialManager/res/values-pl/strings.xml b/packages/CredentialManager/res/values-pl/strings.xml
index bf7a09e..812d424 100644
--- a/packages/CredentialManager/res/values-pl/strings.xml
+++ b/packages/CredentialManager/res/values-pl/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Dalej"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Więcej opcji"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Więcej informacji"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Klucze zwiększają Twoje bezpieczeństwo"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dzięki kluczom nie musisz tworzyć ani zapamiętywać skomplikowanych haseł"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Klucze są szyfrowanymi kluczami cyfrowymi, które tworzysz za pomocą funkcji rozpoznawania odcisku palca lub twarzy bądź blokady ekranu"</string>
diff --git a/packages/CredentialManager/res/values-pt-rBR/strings.xml b/packages/CredentialManager/res/values-pt-rBR/strings.xml
index 7a8e50a..8ecbc30 100644
--- a/packages/CredentialManager/res/values-pt-rBR/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rBR/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Mais opções"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Saiba mais"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mais segurança com as chaves de acesso"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Com as chaves de acesso, você não precisa criar nem se lembrar de senhas complexas"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais criptografadas que você cria usando a impressão digital, o rosto ou o bloqueio de tela"</string>
diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml
index 6ad17e0..910f24b 100644
--- a/packages/CredentialManager/res/values-pt-rPT/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Mais opções"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Saber mais"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mais segurança com chaves de acesso"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Com as chaves de acesso, não precisa de criar nem memorizar palavras-passe complexas"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais encriptadas que cria através da sua impressão digital, rosto ou bloqueio de ecrã"</string>
diff --git a/packages/CredentialManager/res/values-pt/strings.xml b/packages/CredentialManager/res/values-pt/strings.xml
index 7a8e50a..8ecbc30 100644
--- a/packages/CredentialManager/res/values-pt/strings.xml
+++ b/packages/CredentialManager/res/values-pt/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Mais opções"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Saiba mais"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mais segurança com as chaves de acesso"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Com as chaves de acesso, você não precisa criar nem se lembrar de senhas complexas"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais criptografadas que você cria usando a impressão digital, o rosto ou o bloqueio de tela"</string>
diff --git a/packages/CredentialManager/res/values-ro/strings.xml b/packages/CredentialManager/res/values-ro/strings.xml
index b0a008f..917f443 100644
--- a/packages/CredentialManager/res/values-ro/strings.xml
+++ b/packages/CredentialManager/res/values-ro/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Continuă"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Mai multe opțiuni"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Află mai multe"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mai în siguranță cu chei de acces"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dacă folosești chei de acces, nu este nevoie să creezi sau să reții parole complexe"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Cheile de acces sunt chei digitale criptate pe care le creezi folosindu-ți amprenta, fața sau blocarea ecranului"</string>
diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml
index 3f12657..4d306ac 100644
--- a/packages/CredentialManager/res/values-ru/strings.xml
+++ b/packages/CredentialManager/res/values-ru/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Продолжить"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Ещё"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Подробнее"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Ключи доступа безопаснее"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Благодаря ключам доступа вам не придется создавать или запоминать сложные пароли."</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ключ доступа – это зашифрованное цифровое удостоверение, которое создается с использованием отпечатка пальца, функции фейсконтроля или блокировки экрана."</string>
diff --git a/packages/CredentialManager/res/values-si/strings.xml b/packages/CredentialManager/res/values-si/strings.xml
index 64038ca..1fb99c2 100644
--- a/packages/CredentialManager/res/values-si/strings.xml
+++ b/packages/CredentialManager/res/values-si/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ඉදිරියට යන්න"</string>
     <string name="string_more_options" msgid="7990658711962795124">"තවත් විකල්ප"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"තව දැන ගන්න"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"මුරයතුරු සමග සුරක්ෂිතයි"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"මුරයතුරු සමග, ඔබට සංකීර්ණ මුරපද තැනීමට හෝ මතක තබා ගැනීමට අවශ්‍ය නොවේ"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"මුරයතුරු යනු ඔබේ ඇඟිලි සලකුණ, මුහුණ, හෝ තිර අගුල භාවිතයෙන් ඔබ තනන සංකේතාත්මක ඩිජිටල් යතුරු වේ"</string>
diff --git a/packages/CredentialManager/res/values-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml
index 635f0047..280bfa1 100644
--- a/packages/CredentialManager/res/values-sk/strings.xml
+++ b/packages/CredentialManager/res/values-sk/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Pokračovať"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Ďalšie možnosti"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Ďalšie informácie"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Bezpečnejšie s prístupovými kľúčmi"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Ak máte prístupové kľúče, nemusíte vytvárať ani si pamätať zložité heslá"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Prístupové kľúče sú šifrované digitálne kľúče, ktoré môžete vytvoriť odtlačkom prsta, tvárou alebo zámkou obrazovky."</string>
diff --git a/packages/CredentialManager/res/values-sl/strings.xml b/packages/CredentialManager/res/values-sl/strings.xml
index eeb4a96..2b1a6e2 100644
--- a/packages/CredentialManager/res/values-sl/strings.xml
+++ b/packages/CredentialManager/res/values-sl/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Naprej"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Več možnosti"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Več o tem"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Večja varnost s ključi za dostop"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Po zaslugi ključev za dostop vam ni treba ustvarjati ali si zapomniti zapletenih gesel."</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ključi za dostop so šifrirani digitalni ključi, ki jih ustvarite s prstnim odtisom, obrazom ali načinom zaklepanja zaslona."</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index 28e8716..4b6d721 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Vazhdo"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Opsione të tjera"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Mëso më shumë"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Më e sigurt me çelësat e kalimit"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Me çelësat e kalimit, nuk ka nevojë të krijosh ose të mbash mend fjalëkalime të ndërlikuara"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Çelësat e kalimit kanë çelësa dixhitalë të enkriptuar që ti i krijon duke përdorur gjurmën e gishtit, fytyrën ose kyçjen e ekranit"</string>
diff --git a/packages/CredentialManager/res/values-sr/strings.xml b/packages/CredentialManager/res/values-sr/strings.xml
index 0474277..8bd9ab2 100644
--- a/packages/CredentialManager/res/values-sr/strings.xml
+++ b/packages/CredentialManager/res/values-sr/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Настави"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Још опција"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Сазнајте више"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Безбедније уз приступне кодове"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Уз приступне кодове нема потребе да правите или памтите сложене лозинке"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Приступни кодови су шифровани дигитални кодови које правите помоћу отиска прста, лица или закључавања екрана"</string>
diff --git a/packages/CredentialManager/res/values-sv/strings.xml b/packages/CredentialManager/res/values-sv/strings.xml
index fe13124..30d7123 100644
--- a/packages/CredentialManager/res/values-sv/strings.xml
+++ b/packages/CredentialManager/res/values-sv/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Fortsätt"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Fler alternativ"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Läs mer"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Säkrare med nycklar"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med nycklar behöver du inte skapa eller komma ihop invecklade lösenord"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Nycklar är krypterade digitala nycklar som du skapar med ditt fingeravtryck, ansikte eller skärmlås"</string>
diff --git a/packages/CredentialManager/res/values-sw/strings.xml b/packages/CredentialManager/res/values-sw/strings.xml
index 3c50151..4626ff4 100644
--- a/packages/CredentialManager/res/values-sw/strings.xml
+++ b/packages/CredentialManager/res/values-sw/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Endelea"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Chaguo zaidi"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Pata maelezo zaidi"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Ni salama ukitumia funguo za siri"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Kwa kutumia funguo za siri, huhitaji kuunda au kukumbuka manenosiri changamano"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Funguo za siri ni funguo dijitali zilizosimbwa kwa njia fiche unazounda kwa kutumia alama yako ya kidole, uso au mbinu ya kufunga skrini"</string>
diff --git a/packages/CredentialManager/res/values-ta/strings.xml b/packages/CredentialManager/res/values-ta/strings.xml
index 77beb85..5c6d955 100644
--- a/packages/CredentialManager/res/values-ta/strings.xml
+++ b/packages/CredentialManager/res/values-ta/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"தொடர்க"</string>
     <string name="string_more_options" msgid="7990658711962795124">"கூடுதல் விருப்பங்கள்"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"மேலும் அறிக"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"கடவுச்சாவிகள் மூலம் பாதுகாப்பாக வைத்திருங்கள்"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"கடவுச்சாவிகளைப் பயன்படுத்துவதன் மூலம் கடினமான கடவுச்சொற்களை உருவாக்கவோ நினைவில்கொள்ளவோ தேவையில்லை"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"கடவுச்சாவிகள் என்பவை உங்கள் கைரேகை, முகம் அல்லது திரைப் பூட்டு மூலம் உருவாக்கப்படும் என்க்ரிப்ஷன் செய்யப்பட்ட டிஜிட்டல் சாவிகள் ஆகும்"</string>
diff --git a/packages/CredentialManager/res/values-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml
index e62bac9..a15b5d2 100644
--- a/packages/CredentialManager/res/values-te/strings.xml
+++ b/packages/CredentialManager/res/values-te/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"కొనసాగించండి"</string>
     <string name="string_more_options" msgid="7990658711962795124">"మరిన్ని ఆప్షన్‌లు"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"మరింత తెలుసుకోండి"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"పాస్-కీలతో సురక్షితంగా చెల్లించవచ్చు"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"పాస్-కీలతో, మీరు క్లిష్టమైన పాస్‌వర్డ్‌లను క్రియేట్ చేయనవసరం లేదు లేదా గుర్తుంచుకోనవసరం లేదు"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"పాస్-కీలు అనేవి మీ వేలిముద్రను, ముఖాన్ని లేదా స్క్రీన్ లాక్‌ను ఉపయోగించి మీరు క్రియేట్ చేసే ఎన్‌క్రిప్ట్ చేసిన డిజిటల్ కీలు"</string>
diff --git a/packages/CredentialManager/res/values-th/strings.xml b/packages/CredentialManager/res/values-th/strings.xml
index 61144f9..6f27653 100644
--- a/packages/CredentialManager/res/values-th/strings.xml
+++ b/packages/CredentialManager/res/values-th/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"ต่อไป"</string>
     <string name="string_more_options" msgid="7990658711962795124">"ตัวเลือกเพิ่มเติม"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ดูข้อมูลเพิ่มเติม"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"ปลอดภัยขึ้นด้วยพาสคีย์"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"พาสคีย์ช่วยให้คุณไม่ต้องสร้างหรือจำรหัสผ่านที่ซับซ้อน"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"พาสคีย์คือกุญแจดิจิทัลที่เข้ารหัสซึ่งคุณสร้างโดยใช้ลายนิ้วมือ ใบหน้า หรือการล็อกหน้าจอ"</string>
diff --git a/packages/CredentialManager/res/values-tl/strings.xml b/packages/CredentialManager/res/values-tl/strings.xml
index d75ac57..5a2bd3d 100644
--- a/packages/CredentialManager/res/values-tl/strings.xml
+++ b/packages/CredentialManager/res/values-tl/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Magpatuloy"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Higit pang opsyon"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Matuto pa"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mas ligtas gamit ang mga passkey"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Gamit ang mga passkey, hindi mo na kailangang gumawa o tumanda ng mga komplikadong password"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ang mga passkey ay mga naka-encrypt na digital na susi na ginagawa mo gamit ang iyong fingerprint, mukha, o lock ng screen"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index 4ee0b51..3737308 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Devam"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Diğer seçenekler"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Daha fazla bilgi"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Şifre anahtarlarıyla daha yüksek güvenlik"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Şifre anahtarı kullandığınızda karmaşık şifreler oluşturmanız veya bunları hatırlamanız gerekmez"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Şifre anahtarları; parmak iziniz, yüzünüz veya ekran kilidinizi kullanarak oluşturduğunuz şifrelenmiş dijital anahtarlardır"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index bd10f42..8733ed0 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Продовжити"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Інші опції"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Докладніше"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Ключі доступу покращують безпеку"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Маючи ключі доступу, не потрібно створювати чи запам’ятовувати складні паролі"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ключі доступу – це зашифровані цифрові ключі, які ви створюєте за допомогою відбитка пальця, фейс-контролю чи засобу розблокування екрана"</string>
diff --git a/packages/CredentialManager/res/values-ur/strings.xml b/packages/CredentialManager/res/values-ur/strings.xml
index 103ea38..d7e7c62 100644
--- a/packages/CredentialManager/res/values-ur/strings.xml
+++ b/packages/CredentialManager/res/values-ur/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"جاری رکھیں"</string>
     <string name="string_more_options" msgid="7990658711962795124">"مزید اختیارات"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"مزید جانیں"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"پاس کیز کے ساتھ زیادہ محفوظ"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"پاس کیز کے ساتھ آپ کو پیچیدہ پاس ورڈز تخلیق کرنے یا انہیں یاد رکھنے کی ضرورت نہیں ہے"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"پاس کیز مرموز کردہ ڈیجیٹل کلیدیں ہیں جنہیں آپ اپنا فنگر پرنٹ، چہرہ یا اسکرین لاک استعمال کرتے ہوئے تخلیق کرتے ہیں"</string>
diff --git a/packages/CredentialManager/res/values-uz/strings.xml b/packages/CredentialManager/res/values-uz/strings.xml
index 43ece9a..557944a 100644
--- a/packages/CredentialManager/res/values-uz/strings.xml
+++ b/packages/CredentialManager/res/values-uz/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Davom etish"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Boshqa parametrlar"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Batafsil"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Kalitlar orqali qulay"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Kodlar yordami tufayli murakkab parollarni yaratish va eslab qolish shart emas"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kodlar – bu barmoq izi, yuz yoki ekran qulfi yordamida yaratilgan shifrlangan raqamli identifikator."</string>
diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml
index f2b9476..0756139 100644
--- a/packages/CredentialManager/res/values-vi/strings.xml
+++ b/packages/CredentialManager/res/values-vi/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Tiếp tục"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Tuỳ chọn khác"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Tìm hiểu thêm"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"An toàn hơn nhờ mã xác thực"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Mã xác thực giúp bạn tránh được việc phải tạo và ghi nhớ mật khẩu phức tạp"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Mã xác thực là các khoá kỹ thuật số được mã hoá mà bạn tạo bằng cách dùng vân tay, khuôn mặt hoặc phương thức khoá màn hình của mình"</string>
diff --git a/packages/CredentialManager/res/values-zh-rCN/strings.xml b/packages/CredentialManager/res/values-zh-rCN/strings.xml
index daffaca..600e584 100644
--- a/packages/CredentialManager/res/values-zh-rCN/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rCN/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"继续"</string>
     <string name="string_more_options" msgid="7990658711962795124">"更多选项"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"了解详情"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"通行密钥可提高安全性"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"借助通行密钥,您无需创建或记住复杂的密码"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"通行密钥是指您使用您的指纹、面孔或屏锁方式创建的加密数字钥匙"</string>
diff --git a/packages/CredentialManager/res/values-zh-rHK/strings.xml b/packages/CredentialManager/res/values-zh-rHK/strings.xml
index 5255b92..6125e5d 100644
--- a/packages/CredentialManager/res/values-zh-rHK/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rHK/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"繼續"</string>
     <string name="string_more_options" msgid="7990658711962795124">"更多選項"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"瞭解詳情"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"使用密鑰確保帳戶安全"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"有了密鑰,您便無需建立或記住複雜的密碼"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"密鑰是您使用指紋、面孔或螢幕鎖定時建立的加密數碼鑰匙"</string>
diff --git a/packages/CredentialManager/res/values-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml
index 274ed21..1a37878 100644
--- a/packages/CredentialManager/res/values-zh-rTW/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"繼續"</string>
     <string name="string_more_options" msgid="7990658711962795124">"更多選項"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"瞭解詳情"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"使用密碼金鑰確保帳戶安全"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"有了密碼金鑰,就不必建立或記住複雜的密碼"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"密碼金鑰是你利用指紋、臉孔或螢幕鎖定功能建立的加密數位金鑰"</string>
diff --git a/packages/CredentialManager/res/values-zu/strings.xml b/packages/CredentialManager/res/values-zu/strings.xml
index d6624f0..2d7e00d 100644
--- a/packages/CredentialManager/res/values-zu/strings.xml
+++ b/packages/CredentialManager/res/values-zu/strings.xml
@@ -6,6 +6,10 @@
     <string name="string_continue" msgid="1346732695941131882">"Qhubeka"</string>
     <string name="string_more_options" msgid="7990658711962795124">"Okunye okungakukhethwa kukho"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Funda kabanzi"</string>
+    <!-- no translation found for content_description_show_password (3283502010388521607) -->
+    <skip />
+    <!-- no translation found for content_description_hide_password (6841375971631767996) -->
+    <skip />
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Iphephe ngokhiye bokudlula"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Ngokhiye wokudlula, awudingi ukusungula noma ukukhumbula amaphasiwedi ayinkimbinkimbi"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Okhiye bokungena bangokhiye bedijithali ababethelwe obasungula usebenzisa isigxivizo somunwe sakho, ubuso, noma ukukhiya isikrini"</string>
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index d6909719..49ac482 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -13,6 +13,10 @@
   <string name="string_more_options">More options</string>
   <!-- This is a label for a button that links to additional information about passkeys. [CHAR LIMIT=20] -->
   <string name="string_learn_more">Learn more</string>
+  <!-- This is a label for content description for show password icon button. -->
+  <string name="content_description_show_password">Show password</string>
+  <!-- This is a label for content description for hide password icon button. -->
+  <string name="content_description_hide_password">Hide password</string>
   <!-- This string introduces passkeys to the users for the first time they use this method. Tip: to avoid gendered language patterns, this header could be translated as if the original string were "More safety with passkeys". [CHAR LIMIT=200] -->
   <string name="passkey_creation_intro_title">Safer with passkeys</string>
   <!-- This string highlight passkey benefits related with the password. [CHAR LIMIT=200] -->
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index a48cd2b..51dc233 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -16,15 +16,13 @@
 
 package com.android.credentialmanager
 
-import android.app.PendingIntent
 import android.app.slice.Slice
 import android.app.slice.SliceSpec
 import android.content.Context
 import android.content.Intent
-import android.content.pm.SigningInfo
 import android.credentials.CreateCredentialRequest
 import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL
-import android.credentials.GetCredentialOption
+import android.credentials.CredentialOption
 import android.credentials.GetCredentialRequest
 import android.credentials.ui.Constants
 import android.credentials.ui.Entry
@@ -37,39 +35,44 @@
 import android.credentials.ui.ProviderPendingIntentResponse
 import android.credentials.ui.UserSelectionDialogResult
 import android.net.Uri
+import android.os.IBinder
 import android.os.Binder
 import android.os.Bundle
 import android.os.ResultReceiver
-import android.service.credentials.CredentialProviderService
 import com.android.credentialmanager.createflow.DisabledProviderInfo
 import com.android.credentialmanager.createflow.EnabledProviderInfo
 import com.android.credentialmanager.createflow.RequestDisplayInfo
 import com.android.credentialmanager.getflow.GetCredentialUiState
-import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest.Companion.toCredentialDataBundle
-import com.android.credentialmanager.jetpack.developer.CreatePublicKeyCredentialRequest
-import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
-import com.android.credentialmanager.jetpack.provider.Action
-import com.android.credentialmanager.jetpack.provider.CreateEntry
-import com.android.credentialmanager.jetpack.provider.CredentialCountInformation
-import com.android.credentialmanager.jetpack.provider.CredentialEntry
+import androidx.credentials.CreateCredentialRequest.DisplayInfo
+import androidx.credentials.CreatePublicKeyCredentialRequest
+import androidx.credentials.CreatePasswordRequest
 
-// Consider repo per screen, similar to view model?
+import java.time.Instant
+
+/**
+ * Client for interacting with Credential Manager. Also holds data inputs from it.
+ *
+ * IMPORTANT: instantiation of the object can fail if the data inputs aren't valid. Callers need
+ * to be equipped to handle this gracefully.
+ */
 class CredentialManagerRepo(
     private val context: Context,
     intent: Intent,
+    userConfigRepo: UserConfigRepo,
 ) {
     val requestInfo: RequestInfo
     private val providerEnabledList: List<ProviderData>
     private val providerDisabledList: List<DisabledProviderData>?
-
     // TODO: require non-null.
     val resultReceiver: ResultReceiver?
 
+    var initialUiState: UiState
+
     init {
         requestInfo = intent.extras?.getParcelable(
             RequestInfo.EXTRA_REQUEST_INFO,
             RequestInfo::class.java
-        ) ?: testCreatePasskeyRequestInfo()
+        ) ?: testGetRequestInfo()
 
         providerEnabledList = when (requestInfo.type) {
             RequestInfo.TYPE_CREATE ->
@@ -83,7 +86,6 @@
                     GetCredentialProviderData::class.java
                 ) ?: testGetCredentialProviderList()
             else -> {
-                // TODO: fail gracefully
                 throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
             }
         }
@@ -98,6 +100,35 @@
             Constants.EXTRA_RESULT_RECEIVER,
             ResultReceiver::class.java
         )
+
+        initialUiState = when (requestInfo.type) {
+            RequestInfo.TYPE_CREATE -> {
+                val defaultProviderId = userConfigRepo.getDefaultProviderId()
+                val isPasskeyFirstUse = userConfigRepo.getIsPasskeyFirstUse()
+                val providerEnableListUiState = getCreateProviderEnableListInitialUiState()
+                val providerDisableListUiState = getCreateProviderDisableListInitialUiState()
+                val requestDisplayInfoUiState = getCreateRequestDisplayInfoInitialUiState()!!
+                UiState(
+                    createCredentialUiState = CreateFlowUtils.toCreateCredentialUiState(
+                        providerEnableListUiState,
+                        providerDisableListUiState,
+                        defaultProviderId,
+                        requestDisplayInfoUiState,
+                        /** isOnPasskeyIntroStateAlready = */ false,
+                        isPasskeyFirstUse)!!,
+                    getCredentialUiState = null,
+                )
+            }
+            RequestInfo.TYPE_GET -> UiState(
+                createCredentialUiState = null,
+                getCredentialUiState = getCredentialInitialUiState()!!,
+            )
+            else -> throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
+        }
+    }
+
+    fun initState(): UiState {
+        return initialUiState
     }
 
     // The dialog is canceled by the user.
@@ -115,9 +146,7 @@
     }
 
     fun onCancel(cancelCode: Int) {
-        val resultData = Bundle()
-        BaseDialogResult.addToBundle(BaseDialogResult(requestInfo.token), resultData)
-        resultReceiver?.send(cancelCode, resultData)
+        sendCancellationCode(cancelCode, requestInfo.token, resultReceiver)
     }
 
     fun onOptionSelected(
@@ -134,17 +163,17 @@
             entrySubkey,
             if (resultCode != null) ProviderPendingIntentResponse(resultCode, resultData) else null
         )
-        val resultData = Bundle()
-        UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultData)
+        val resultDataBundle = Bundle()
+        UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultDataBundle)
         resultReceiver?.send(
             BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION,
-            resultData
+            resultDataBundle
         )
     }
 
-    fun getCredentialInitialUiState(): GetCredentialUiState? {
+    // IMPORTANT: new invocation should be mindful that this method can throw.
+    private fun getCredentialInitialUiState(): GetCredentialUiState? {
         val providerEnabledList = GetFlowUtils.toProviderList(
-            // TODO: handle runtime cast error
             providerEnabledList as List<GetCredentialProviderData>, context
         )
         val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context)
@@ -154,25 +183,39 @@
         )
     }
 
-    fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> {
+    // IMPORTANT: new invocation should be mindful that this method can throw.
+    private fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> {
         val providerEnabledList = CreateFlowUtils.toEnabledProviderList(
-            // Handle runtime cast error
             providerEnabledList as List<CreateCredentialProviderData>, context
         )
         return providerEnabledList
     }
 
-    fun getCreateProviderDisableListInitialUiState(): List<DisabledProviderInfo> {
+    private fun getCreateProviderDisableListInitialUiState(): List<DisabledProviderInfo> {
         return CreateFlowUtils.toDisabledProviderList(
             // Handle runtime cast error
             providerDisabledList, context
         )
     }
 
-    fun getCreateRequestDisplayInfoInitialUiState(): RequestDisplayInfo? {
+    private fun getCreateRequestDisplayInfoInitialUiState(): RequestDisplayInfo? {
         return CreateFlowUtils.toRequestDisplayInfo(requestInfo, context)
     }
 
+    companion object {
+        fun sendCancellationCode(
+            cancelCode: Int,
+            requestToken: IBinder?,
+            resultReceiver: ResultReceiver?
+        ) {
+            if (requestToken != null && resultReceiver != null) {
+                val resultData = Bundle()
+                BaseDialogResult.addToBundle(BaseDialogResult(requestToken), resultData)
+                resultReceiver.send(cancelCode, resultData)
+            }
+        }
+    }
+
     // TODO: below are prototype functionalities. To be removed for productionization.
     private fun testCreateCredentialEnabledProviderList(): List<CreateCredentialProviderData> {
         return listOf(
@@ -180,14 +223,14 @@
                 .Builder("io.enpass.app")
                 .setSaveEntries(
                     listOf<Entry>(
-                        newCreateEntry(
+                        CreateTestUtils.newCreateEntry(context,
                             "key1", "subkey-1", "elisa.beckett@gmail.com",
-                            20, 7, 27, 10L,
-                            "Optional footer description"
+                            20, 7, 27, Instant.ofEpochSecond(10L),
+                            "Legal note"
                         ),
-                        newCreateEntry(
+                        CreateTestUtils.newCreateEntry(context,
                             "key1", "subkey-2", "elisa.work@google.com",
-                            20, 7, 27, 12L,
+                            20, 7, 27, Instant.ofEpochSecond(12L),
                             null
                         ),
                     )
@@ -200,14 +243,14 @@
                 .Builder("com.dashlane")
                 .setSaveEntries(
                     listOf<Entry>(
-                        newCreateEntry(
+                        CreateTestUtils.newCreateEntry(context,
                             "key1", "subkey-3", "elisa.beckett@dashlane.com",
-                            20, 7, 27, 11L,
+                            20, 7, 27, Instant.ofEpochSecond(11L),
                             null
                         ),
-                        newCreateEntry(
+                        CreateTestUtils.newCreateEntry(context,
                             "key1", "subkey-4", "elisa.work@dashlane.com",
-                            20, 7, 27, 14L,
+                            20, 7, 27, Instant.ofEpochSecond(14L),
                             null
                         ),
                     )
@@ -227,34 +270,39 @@
         return listOf(
             GetCredentialProviderData.Builder("io.enpass.app")
                 .setCredentialEntries(
-                    listOf<Entry>(
-                        newGetEntry(
-                            "key1", "subkey-1", TYPE_PASSWORD_CREDENTIAL, "Password",
-                            "elisa.family@outlook.com", null, 3L
+                    listOf(
+                        GetTestUtils.newPasswordEntry(
+                            context, "key1", "subkey-1", "elisa.family@outlook.com", null,
+                            Instant.ofEpochSecond(8000L)
                         ),
-                        newGetEntry(
-                            "key1", "subkey-1", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey",
-                            "elisa.bakery@gmail.com", "Elisa Beckett", 0L
+                        GetTestUtils.newPasskeyEntry(
+                            context, "key1", "subkey-1", "elisa.bakery@gmail.com", "Elisa Beckett",
+                            null
                         ),
-                        newGetEntry(
-                            "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password",
-                            "elisa.bakery@gmail.com", null, 10L
+                        GetTestUtils.newPasswordEntry(
+                            context, "key1", "subkey-2", "elisa.bakery@gmail.com", null,
+                            Instant.ofEpochSecond(10000L)
                         ),
-                        newGetEntry(
-                            "key1", "subkey-3", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey",
-                            "elisa.family@outlook.com", "Elisa Beckett", 1L
+                        GetTestUtils.newPasskeyEntry(
+                            context, "key1", "subkey-3", "elisa.family@outlook.com",
+                            "Elisa Beckett", Instant.ofEpochSecond(500L)
                         ),
                     )
-                ).setAuthenticationEntry(
-                    newAuthenticationEntry("key2", "subkey-1", TYPE_PASSWORD_CREDENTIAL)
+                ).setAuthenticationEntries(
+                    listOf(
+                        GetTestUtils.newAuthenticationEntry(
+                            context, "key2", "subkey-1", "locked-user1@gmail.com"),
+                        GetTestUtils.newAuthenticationEntry(
+                            context, "key2", "subkey-2", "locked-user2@gmail.com"),
+                    )
                 ).setActionChips(
                     listOf(
-                        newActionEntry(
-                            "key3", "subkey-1", TYPE_PASSWORD_CREDENTIAL,
+                        GetTestUtils.newActionEntry(
+                            context, "key3", "subkey-1",
                             "Open Google Password Manager", "elisa.beckett@gmail.com"
                         ),
-                        newActionEntry(
-                            "key3", "subkey-2", TYPE_PASSWORD_CREDENTIAL,
+                        GetTestUtils.newActionEntry(
+                            context, "key3", "subkey-2",
                             "Open Google Password Manager", "beckett-family@gmail.com"
                         ),
                     )
@@ -264,137 +312,30 @@
             GetCredentialProviderData.Builder("com.dashlane")
                 .setCredentialEntries(
                     listOf<Entry>(
-                        newGetEntry(
-                            "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password",
-                            "elisa.family@outlook.com", null, 4L
+                        GetTestUtils.newPasswordEntry(
+                            context, "key1", "subkey-2", "elisa.family@outlook.com", null,
+                            Instant.ofEpochSecond(9000L)
                         ),
-                        newGetEntry(
-                            "key1", "subkey-3", TYPE_PASSWORD_CREDENTIAL, "Password",
-                            "elisa.work@outlook.com", null, 11L
+                        GetTestUtils.newPasswordEntry(
+                            context, "key1", "subkey-3", "elisa.work@outlook.com", null,
+                            Instant.ofEpochSecond(11000L)
                         ),
                     )
-                ).setAuthenticationEntry(
-                    newAuthenticationEntry("key2", "subkey-1", TYPE_PASSWORD_CREDENTIAL)
+                ).setAuthenticationEntries(
+                     listOf(GetTestUtils.newAuthenticationEntry(
+                         context, "key2", "subkey-1", "foo@email.com"))
                 ).setActionChips(
                     listOf(
-                        newActionEntry(
-                            "key3", "subkey-1", TYPE_PASSWORD_CREDENTIAL,
-                            "Open Enpass"
+                        GetTestUtils.newActionEntry(
+                            context, "key3", "subkey-1", "Open Enpass",
+                            "Manage passwords"
                         ),
                     )
                 ).build(),
         )
     }
 
-    private fun newActionEntry(
-        key: String,
-        subkey: String,
-        credentialType: String,
-        text: String,
-        subtext: String? = null,
-    ): Entry {
-        val action = Action(text, subtext, null)
 
-        return Entry(
-            key,
-            subkey,
-            Action.toSlice(action)
-        )
-    }
-
-    private fun newAuthenticationEntry(
-        key: String,
-        subkey: String,
-        credentialType: String,
-    ): Entry {
-        val slice = Slice.Builder(
-            Uri.EMPTY, SliceSpec(credentialType, 1)
-        )
-        return Entry(
-            key,
-            subkey,
-            slice.build()
-        )
-    }
-
-    private fun newGetEntry(
-        key: String,
-        subkey: String,
-        credentialType: String,
-        credentialTypeDisplayName: String,
-        userName: String,
-        userDisplayName: String?,
-        lastUsedTimeMillis: Long?,
-    ): Entry {
-        val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
-            .setPackage("com.androidauth.androidvault")
-        intent.putExtra("provider_extra_sample", "testprovider")
-
-        val pendingIntent = PendingIntent.getActivity(
-            context, 1,
-            intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
-                or PendingIntent.FLAG_ONE_SHOT)
-        )
-
-        val credentialEntry = CredentialEntry(
-            credentialType, credentialTypeDisplayName, userName,
-            userDisplayName, pendingIntent, lastUsedTimeMillis
-                ?: 0L, null, false
-        )
-
-        return Entry(
-            key,
-            subkey,
-            CredentialEntry.toSlice(credentialEntry),
-            Intent()
-        )
-    }
-
-    private fun newCreateEntry(
-        key: String,
-        subkey: String,
-        providerDisplayName: String,
-        passwordCount: Int,
-        passkeyCount: Int,
-        totalCredentialCount: Int,
-        lastUsedTimeMillis: Long,
-        footerDescription: String?,
-    ): Entry {
-        val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
-            .setPackage("com.androidauth.androidvault")
-        intent.putExtra("provider_extra_sample", "testprovider")
-        val pendingIntent = PendingIntent.getActivity(
-            context, 1,
-            intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
-                or PendingIntent.FLAG_ONE_SHOT)
-        )
-        val createPasswordRequest = android.service.credentials.CreateCredentialRequest(
-            android.service.credentials.CallingAppInfo(
-                context.applicationInfo.packageName, SigningInfo()
-            ),
-            TYPE_PASSWORD_CREDENTIAL,
-            toCredentialDataBundle("beckett-bakert@gmail.com", "password123")
-        )
-        val fillInIntent = Intent().putExtra(
-            CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST,
-            createPasswordRequest
-        )
-
-        val createEntry = CreateEntry(
-            providerDisplayName, pendingIntent,
-            null, lastUsedTimeMillis,
-            listOf(
-                CredentialCountInformation.createPasswordCountInformation(passwordCount),
-                CredentialCountInformation.createPublicKeyCountInformation(passkeyCount),
-            ), footerDescription
-        )
-        return Entry(
-            key,
-            subkey,
-            CreateEntry.toSlice(createEntry),
-            fillInIntent
-        )
-    }
 
     private fun newRemoteEntry(
         key: String,
@@ -451,9 +392,8 @@
         return RequestInfo.newCreateRequestInfo(
             Binder(),
             CreateCredentialRequest(
-                TYPE_PUBLIC_KEY_CREDENTIAL,
+                "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
                 credentialData,
-                // TODO: populate with actual data
                 /*candidateQueryData=*/ Bundle(),
                 /*isSystemProviderRequired=*/ false
             ),
@@ -462,14 +402,13 @@
     }
 
     private fun testCreatePasswordRequestInfo(): RequestInfo {
-        val data = toCredentialDataBundle("beckett-bakert@gmail.com", "password123")
+        val request = CreatePasswordRequest("beckett-bakert@gmail.com", "password123")
         return RequestInfo.newCreateRequestInfo(
             Binder(),
             CreateCredentialRequest(
                 TYPE_PASSWORD_CREDENTIAL,
-                data,
-                // TODO: populate with actual data
-                /*candidateQueryData=*/ Bundle(),
+                request.credentialData,
+                request.candidateQueryData,
                 /*isSystemProviderRequired=*/ false
             ),
             "com.google.android.youtube"
@@ -478,6 +417,10 @@
 
     private fun testCreateOtherCredentialRequestInfo(): RequestInfo {
         val data = Bundle()
+        val displayInfo = DisplayInfo("my-username00", "Joe")
+        data.putBundle(
+            "androidx.credentials.BUNDLE_KEY_REQUEST_DISPLAY_INFO",
+            displayInfo.toBundle())
         return RequestInfo.newCreateRequestInfo(
             Binder(),
             CreateCredentialRequest(
@@ -496,9 +439,9 @@
             GetCredentialRequest.Builder(
                 Bundle()
             )
-                .addGetCredentialOption(
-                    GetCredentialOption(
-                        TYPE_PUBLIC_KEY_CREDENTIAL,
+                .addCredentialOption(
+                    CredentialOption(
+                        "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
                         Bundle(),
                         Bundle(), /*isSystemProviderRequired=*/
                         false
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index 3b9c02a..bf69ef4 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -17,112 +17,98 @@
 package com.android.credentialmanager
 
 import android.content.Intent
+import android.credentials.ui.BaseDialogResult
 import android.credentials.ui.RequestInfo
 import android.os.Bundle
+import android.os.ResultReceiver
 import android.provider.Settings
 import android.util.Log
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.rememberLauncherForActivityResult
 import androidx.activity.compose.setContent
 import androidx.activity.result.contract.ActivityResultContracts
+import androidx.activity.viewModels
 import androidx.compose.material.ExperimentalMaterialApi
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
 import androidx.lifecycle.viewmodel.compose.viewModel
 import com.android.credentialmanager.common.Constants
 import com.android.credentialmanager.common.DialogState
 import com.android.credentialmanager.common.ProviderActivityResult
 import com.android.credentialmanager.createflow.CreateCredentialScreen
-import com.android.credentialmanager.createflow.CreateCredentialViewModel
 import com.android.credentialmanager.getflow.GetCredentialScreen
-import com.android.credentialmanager.getflow.GetCredentialViewModel
 import com.android.credentialmanager.ui.theme.CredentialSelectorTheme
 
 @ExperimentalMaterialApi
 class CredentialSelectorActivity : ComponentActivity() {
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        val credManRepo = CredentialManagerRepo(this, intent)
-        UserConfigRepo.setup(this)
+        Log.d(Constants.LOG_TAG, "Creating new CredentialSelectorActivity")
         try {
+            val userConfigRepo = UserConfigRepo(this)
+            val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
             setContent {
                 CredentialSelectorTheme {
-                    CredentialManagerBottomSheet(credManRepo.requestInfo.type, credManRepo)
+                    CredentialManagerBottomSheet(
+                        credManRepo,
+                        userConfigRepo
+                    )
                 }
             }
         } catch (e: Exception) {
-            Log.e(Constants.LOG_TAG, "Failed to show the credential selector", e)
-            reportInstantiationErrorAndFinishActivity(credManRepo)
+            onInitializationError(e, intent)
+        }
+    }
+
+    override fun onNewIntent(intent: Intent) {
+        super.onNewIntent(intent)
+        setIntent(intent)
+        Log.d(Constants.LOG_TAG, "Existing activity received new intent")
+        try {
+            val userConfigRepo = UserConfigRepo(this)
+            val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
+            val viewModel: CredentialSelectorViewModel by viewModels()
+            viewModel.onNewCredentialManagerRepo(credManRepo)
+        } catch (e: Exception) {
+            onInitializationError(e, intent)
         }
     }
 
     @ExperimentalMaterialApi
     @Composable
-    fun CredentialManagerBottomSheet(requestType: String, credManRepo: CredentialManagerRepo) {
-        val providerActivityResult = remember { mutableStateOf<ProviderActivityResult?>(null) }
+    fun CredentialManagerBottomSheet(
+        credManRepo: CredentialManagerRepo,
+        userConfigRepo: UserConfigRepo
+    ) {
+        val viewModel: CredentialSelectorViewModel = viewModel {
+            CredentialSelectorViewModel(credManRepo, userConfigRepo)
+        }
         val launcher = rememberLauncherForActivityResult(
             ActivityResultContracts.StartIntentSenderForResult()
         ) {
-            providerActivityResult.value = ProviderActivityResult(it.resultCode, it.data)
+            viewModel.onProviderActivityResult(ProviderActivityResult(it.resultCode, it.data))
         }
-        when (requestType) {
-            RequestInfo.TYPE_CREATE -> {
-                val viewModel: CreateCredentialViewModel = viewModel {
-                    val vm = CreateCredentialViewModel.newInstance(
-                        credManRepo = credManRepo,
-                        providerEnableListUiState =
-                        credManRepo.getCreateProviderEnableListInitialUiState(),
-                        providerDisableListUiState =
-                        credManRepo.getCreateProviderDisableListInitialUiState(),
-                        requestDisplayInfoUiState =
-                        credManRepo.getCreateRequestDisplayInfoInitialUiState()
-                    )
-                    if (vm == null) {
-                        // Input parsing failed. Close the activity.
-                        reportInstantiationErrorAndFinishActivity(credManRepo)
-                        throw IllegalStateException()
-                    } else {
-                        vm
-                    }
-                }
-                LaunchedEffect(viewModel.uiState.dialogState) {
-                    handleDialogState(viewModel.uiState.dialogState)
-                }
-                providerActivityResult.value?.let {
-                    viewModel.onProviderActivityResult(it)
-                    providerActivityResult.value = null
-                }
-                CreateCredentialScreen(
-                    viewModel = viewModel,
-                    providerActivityLauncher = launcher
-                )
-            }
-            RequestInfo.TYPE_GET -> {
-                val viewModel: GetCredentialViewModel = viewModel {
-                    val initialUiState = credManRepo.getCredentialInitialUiState()
-                    if (initialUiState == null) {
-                        // Input parsing failed. Close the activity.
-                        reportInstantiationErrorAndFinishActivity(credManRepo)
-                        throw IllegalStateException()
-                    } else {
-                        GetCredentialViewModel(credManRepo, initialUiState)
-                    }
-                }
-                LaunchedEffect(viewModel.uiState.dialogState) {
-                    handleDialogState(viewModel.uiState.dialogState)
-                }
-                providerActivityResult.value?.let {
-                    viewModel.onProviderActivityResult(it)
-                    providerActivityResult.value = null
-                }
-                GetCredentialScreen(viewModel = viewModel, providerActivityLauncher = launcher)
-            }
-            else -> {
-                Log.d(Constants.LOG_TAG, "Unknown type, not rendering any UI")
-                reportInstantiationErrorAndFinishActivity(credManRepo)
-            }
+        LaunchedEffect(viewModel.uiState.dialogState) {
+            handleDialogState(viewModel.uiState.dialogState)
+        }
+
+        val createCredentialUiState = viewModel.uiState.createCredentialUiState
+        val getCredentialUiState = viewModel.uiState.getCredentialUiState
+        if (createCredentialUiState != null) {
+            CreateCredentialScreen(
+                viewModel = viewModel,
+                createCredentialUiState = createCredentialUiState,
+                providerActivityLauncher = launcher
+            )
+        } else if (getCredentialUiState != null) {
+            GetCredentialScreen(
+                viewModel = viewModel,
+                getCredentialUiState = getCredentialUiState,
+                providerActivityLauncher = launcher
+            )
+        } else {
+            Log.d(Constants.LOG_TAG, "UI wasn't able to render neither get nor create flow")
+            reportInstantiationErrorAndFinishActivity(credManRepo)
         }
     }
 
@@ -142,4 +128,21 @@
             this@CredentialSelectorActivity.finish()
         }
     }
+
+    private fun onInitializationError(e: Exception, intent: Intent) {
+        Log.e(Constants.LOG_TAG, "Failed to show the credential selector", e)
+        val resultReceiver = intent.getParcelableExtra(
+            android.credentials.ui.Constants.EXTRA_RESULT_RECEIVER,
+            ResultReceiver::class.java
+        )
+        val requestInfo = intent.extras?.getParcelable(
+            RequestInfo.EXTRA_REQUEST_INFO,
+            RequestInfo::class.java
+        )
+        CredentialManagerRepo.sendCancellationCode(
+            BaseDialogResult.RESULT_CODE_DATA_PARSING_FAILURE,
+            requestInfo?.token, resultReceiver
+        )
+        this.finish()
+    }
 }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
new file mode 100644
index 0000000..30b4b86
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager
+
+import android.app.Activity
+import android.util.Log
+import androidx.activity.compose.ManagedActivityResultLauncher
+import androidx.activity.result.ActivityResult
+import androidx.activity.result.IntentSenderRequest
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.lifecycle.ViewModel
+import com.android.credentialmanager.common.BaseEntry
+import com.android.credentialmanager.common.Constants
+import com.android.credentialmanager.common.DialogState
+import com.android.credentialmanager.common.ProviderActivityResult
+import com.android.credentialmanager.common.ProviderActivityState
+import com.android.credentialmanager.createflow.ActiveEntry
+import com.android.credentialmanager.createflow.CreateCredentialUiState
+import com.android.credentialmanager.createflow.CreateScreenState
+import com.android.credentialmanager.getflow.GetCredentialUiState
+import com.android.credentialmanager.getflow.GetScreenState
+
+/** One and only one of create or get state can be active at any given time. */
+data class UiState(
+    val createCredentialUiState: CreateCredentialUiState?,
+    val getCredentialUiState: GetCredentialUiState?,
+    val selectedEntry: BaseEntry? = null,
+    val providerActivityState: ProviderActivityState = ProviderActivityState.NOT_APPLICABLE,
+    val dialogState: DialogState = DialogState.ACTIVE,
+)
+
+class CredentialSelectorViewModel(
+    private var credManRepo: CredentialManagerRepo,
+    private val userConfigRepo: UserConfigRepo,
+) : ViewModel() {
+    var uiState by mutableStateOf(credManRepo.initState())
+        private set
+
+    /**************************************************************************/
+    /*****                       Shared Callbacks                         *****/
+    /**************************************************************************/
+    fun onCancel() {
+        credManRepo.onUserCancel()
+        uiState = uiState.copy(dialogState = DialogState.COMPLETE)
+    }
+
+    fun onNewCredentialManagerRepo(credManRepo: CredentialManagerRepo) {
+        this.credManRepo = credManRepo
+        uiState = credManRepo.initState()
+    }
+
+    fun launchProviderUi(
+        launcher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
+    ) {
+        val entry = uiState.selectedEntry
+        if (entry != null && entry.pendingIntent != null) {
+            Log.d(Constants.LOG_TAG, "Launching provider activity")
+            uiState = uiState.copy(providerActivityState = ProviderActivityState.PENDING)
+            val intentSenderRequest = IntentSenderRequest.Builder(entry.pendingIntent)
+                .setFillInIntent(entry.fillInIntent).build()
+            launcher.launch(intentSenderRequest)
+        } else {
+            Log.d(Constants.LOG_TAG, "No provider UI to launch")
+            onInternalError()
+        }
+    }
+
+    fun onProviderActivityResult(providerActivityResult: ProviderActivityResult) {
+        val entry = uiState.selectedEntry
+        val resultCode = providerActivityResult.resultCode
+        val resultData = providerActivityResult.data
+        if (resultCode == Activity.RESULT_CANCELED) {
+            // Re-display the CredMan UI if the user canceled from the provider UI.
+            Log.d(Constants.LOG_TAG, "The provider activity was cancelled," +
+                " re-displaying our UI.")
+            uiState = uiState.copy(
+                selectedEntry = null,
+                providerActivityState = ProviderActivityState.NOT_APPLICABLE,
+            )
+        } else {
+            if (entry != null) {
+                Log.d(
+                    Constants.LOG_TAG, "Got provider activity result: {provider=" +
+                    "${entry.providerId}, key=${entry.entryKey}, subkey=${entry.entrySubkey}" +
+                    ", resultCode=$resultCode, resultData=$resultData}"
+                )
+                credManRepo.onOptionSelected(
+                    entry.providerId, entry.entryKey, entry.entrySubkey,
+                    resultCode, resultData,
+                )
+                if (entry.shouldTerminateUiUponSuccessfulProviderResult) {
+                    uiState = uiState.copy(dialogState = DialogState.COMPLETE)
+                }
+            } else {
+                Log.w(Constants.LOG_TAG,
+                    "Illegal state: received a provider result but found no matching entry.")
+                onInternalError()
+            }
+        }
+    }
+
+    private fun onInternalError() {
+        Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state")
+        credManRepo.onParsingFailureCancel()
+        uiState = uiState.copy(dialogState = DialogState.COMPLETE)
+    }
+
+    /**************************************************************************/
+    /*****                      Get Flow Callbacks                        *****/
+    /**************************************************************************/
+    fun getFlowOnEntrySelected(entry: BaseEntry) {
+        Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" +
+            ", key=${entry.entryKey}, subkey=${entry.entrySubkey}}")
+        uiState = if (entry.pendingIntent != null) {
+            uiState.copy(
+                selectedEntry = entry,
+                providerActivityState = ProviderActivityState.READY_TO_LAUNCH,
+            )
+        } else {
+            credManRepo.onOptionSelected(entry.providerId, entry.entryKey, entry.entrySubkey)
+            uiState.copy(dialogState = DialogState.COMPLETE)
+        }
+    }
+
+    fun getFlowOnConfirmEntrySelected() {
+        val activeEntry = uiState.getCredentialUiState?.activeEntry
+        if (activeEntry != null) {
+            getFlowOnEntrySelected(activeEntry)
+        } else {
+            Log.d(Constants.LOG_TAG,
+                "Illegal state: confirm is pressed but activeEntry isn't set.")
+            onInternalError()
+        }
+    }
+
+    fun getFlowOnMoreOptionSelected() {
+        Log.d(Constants.LOG_TAG, "More Option selected")
+        uiState = uiState.copy(
+            getCredentialUiState = uiState.getCredentialUiState?.copy(
+                currentScreenState = GetScreenState.ALL_SIGN_IN_OPTIONS
+            )
+        )
+    }
+
+    fun getFlowOnMoreOptionOnSnackBarSelected(isNoAccount: Boolean) {
+        Log.d(Constants.LOG_TAG, "More Option on snackBar selected")
+        uiState = uiState.copy(
+            getCredentialUiState = uiState.getCredentialUiState?.copy(
+                currentScreenState = GetScreenState.ALL_SIGN_IN_OPTIONS,
+                isNoAccount = isNoAccount,
+            )
+        )
+    }
+
+    fun getFlowOnBackToPrimarySelectionScreen() {
+        uiState = uiState.copy(
+            getCredentialUiState = uiState.getCredentialUiState?.copy(
+                currentScreenState = GetScreenState.PRIMARY_SELECTION
+            )
+        )
+    }
+
+    /**************************************************************************/
+    /*****                     Create Flow Callbacks                      *****/
+    /**************************************************************************/
+    fun createFlowOnConfirmIntro() {
+        val prevUiState = uiState.createCredentialUiState
+        if (prevUiState == null) {
+            Log.d(Constants.LOG_TAG, "Encountered unexpected null create ui state")
+            onInternalError()
+            return
+        }
+        val newUiState = CreateFlowUtils.toCreateCredentialUiState(
+            prevUiState.enabledProviders, prevUiState.disabledProviders,
+            userConfigRepo.getDefaultProviderId(), prevUiState.requestDisplayInfo, true,
+            userConfigRepo.getIsPasskeyFirstUse())
+        if (newUiState == null) {
+            Log.d(Constants.LOG_TAG, "Unable to update create ui state")
+            onInternalError()
+            return
+        }
+        uiState = uiState.copy(createCredentialUiState = newUiState)
+        userConfigRepo.setIsPasskeyFirstUse(false)
+    }
+
+    fun createFlowOnMoreOptionsSelectedOnProviderSelection() {
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState = CreateScreenState.MORE_OPTIONS_SELECTION,
+                isFromProviderSelection = true
+            )
+        )
+    }
+
+    fun createFlowOnMoreOptionsSelectedOnCreationSelection() {
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState = CreateScreenState.MORE_OPTIONS_SELECTION,
+                isFromProviderSelection = false
+            )
+        )
+    }
+
+    fun createFlowOnBackProviderSelectionButtonSelected() {
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState = CreateScreenState.PROVIDER_SELECTION,
+            )
+        )
+    }
+
+    fun createFlowOnBackCreationSelectionButtonSelected() {
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
+            )
+        )
+    }
+
+    fun createFlowOnBackPasskeyIntroButtonSelected() {
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState = CreateScreenState.PASSKEY_INTRO,
+            )
+        )
+    }
+
+    fun createFlowOnEntrySelectedFromMoreOptionScreen(activeEntry: ActiveEntry) {
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState =
+                if (activeEntry.activeProvider.id ==
+                    userConfigRepo.getDefaultProviderId())
+                    CreateScreenState.CREATION_OPTION_SELECTION
+                else CreateScreenState.MORE_OPTIONS_ROW_INTRO,
+                activeEntry = activeEntry
+            )
+        )
+    }
+
+    fun createFlowOnEntrySelectedFromFirstUseScreen(activeEntry: ActiveEntry) {
+        val providerId = activeEntry.activeProvider.id
+        createFlowOnDefaultChanged(providerId)
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
+                activeEntry = activeEntry
+            )
+        )
+    }
+
+    fun createFlowOnDisabledProvidersSelected() {
+        credManRepo.onSettingLaunchCancel()
+        uiState = uiState.copy(dialogState = DialogState.CANCELED_FOR_SETTINGS)
+    }
+
+    fun createFlowOnLearnMore() {
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState = CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO,
+            )
+        )
+    }
+
+    fun createFlowOnChangeDefaultSelected() {
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
+            )
+        )
+        val providerId = uiState.createCredentialUiState?.activeEntry?.activeProvider?.id
+        createFlowOnDefaultChanged(providerId)
+    }
+
+    fun createFlowOnUseOnceSelected() {
+        uiState = uiState.copy(
+            createCredentialUiState = uiState.createCredentialUiState?.copy(
+                currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
+            )
+        )
+    }
+
+    fun createFlowOnDefaultChanged(providerId: String?) {
+        if (providerId != null) {
+            Log.d(
+                Constants.LOG_TAG, "Default provider changed to: " +
+                " {provider=$providerId")
+            userConfigRepo.setDefaultProvider(providerId)
+        } else {
+            Log.w(Constants.LOG_TAG, "Null provider is being changed")
+        }
+    }
+
+    fun createFlowOnEntrySelected(selectedEntry: BaseEntry) {
+        val providerId = selectedEntry.providerId
+        val entryKey = selectedEntry.entryKey
+        val entrySubkey = selectedEntry.entrySubkey
+        Log.d(
+            Constants.LOG_TAG, "Option selected for entry: " +
+            " {provider=$providerId, key=$entryKey, subkey=$entrySubkey")
+        if (selectedEntry.pendingIntent != null) {
+            uiState = uiState.copy(
+                selectedEntry = selectedEntry,
+                providerActivityState = ProviderActivityState.READY_TO_LAUNCH,
+            )
+        } else {
+            credManRepo.onOptionSelected(
+                providerId,
+                entryKey,
+                entrySubkey
+            )
+            uiState = uiState.copy(dialogState = DialogState.COMPLETE)
+        }
+    }
+
+    fun createFlowOnConfirmEntrySelected() {
+        val selectedEntry = uiState.createCredentialUiState?.activeEntry?.activeEntryInfo
+        if (selectedEntry != null) {
+            createFlowOnEntrySelected(selectedEntry)
+        } else {
+            Log.d(Constants.LOG_TAG,
+                "Unexpected: confirm is pressed but no active entry exists.")
+            onInternalError()
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index 3f705d6..ae87d95 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -16,18 +16,23 @@
 
 package com.android.credentialmanager
 
+import android.app.slice.Slice
+import android.app.slice.SliceItem
 import android.content.ComponentName
 import android.content.Context
 import android.content.pm.PackageManager
+import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL
 import android.credentials.ui.CreateCredentialProviderData
 import android.credentials.ui.DisabledProviderData
 import android.credentials.ui.Entry
 import android.credentials.ui.GetCredentialProviderData
 import android.credentials.ui.RequestInfo
 import android.graphics.drawable.Drawable
+import android.service.credentials.CredentialEntry
 import android.text.TextUtils
 import android.util.Log
 import com.android.credentialmanager.common.Constants
+import com.android.credentialmanager.common.CredentialType
 import com.android.credentialmanager.createflow.ActiveEntry
 import com.android.credentialmanager.createflow.CreateCredentialUiState
 import com.android.credentialmanager.createflow.CreateOptionInfo
@@ -41,17 +46,22 @@
 import com.android.credentialmanager.getflow.CredentialEntryInfo
 import com.android.credentialmanager.getflow.ProviderInfo
 import com.android.credentialmanager.getflow.RemoteEntryInfo
-import com.android.credentialmanager.jetpack.developer.CreateCredentialRequest
-import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest
-import com.android.credentialmanager.jetpack.developer.CreatePublicKeyCredentialRequest
-import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
-import com.android.credentialmanager.jetpack.provider.Action
-import com.android.credentialmanager.jetpack.provider.AuthenticationAction
-import com.android.credentialmanager.jetpack.provider.CreateEntry
-import com.android.credentialmanager.jetpack.provider.CredentialCountInformation
-import com.android.credentialmanager.jetpack.provider.CredentialEntry
+import androidx.credentials.CreateCredentialRequest
+import androidx.credentials.CreateCustomCredentialRequest
+import androidx.credentials.CreatePasswordRequest
+import androidx.credentials.CreatePublicKeyCredentialRequest
+import androidx.credentials.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
+import androidx.credentials.provider.Action
+import androidx.credentials.provider.AuthenticationAction
+import androidx.credentials.provider.CreateEntry
+import androidx.credentials.provider.CustomCredentialEntry
+import androidx.credentials.provider.PasswordCredentialEntry
+import androidx.credentials.provider.PublicKeyCredentialEntry
+import androidx.credentials.provider.RemoteCreateEntry
+import androidx.credentials.provider.RemoteCredentialEntry
 import org.json.JSONObject
 
+// TODO: remove all !! checks
 private fun getAppLabel(
     pm: PackageManager,
     appPackageName: String
@@ -138,12 +148,11 @@
                         credentialEntryList = getCredentialOptionInfoList(
                             it.providerFlattenedComponentName, it.credentialEntries, context
                         ),
-                        authenticationEntry = getAuthenticationEntry(
+                        authenticationEntryList = getAuthenticationEntryList(
                             it.providerFlattenedComponentName,
                             providerLabel,
                             providerIcon,
-                            it.authenticationEntry
-                        ),
+                            it.authenticationEntries),
                         remoteEntry = getRemoteEntry(
                             it.providerFlattenedComponentName,
                             it.remoteEntry
@@ -168,103 +177,169 @@
         }
 
 
-        /* From service data structure to UI credential entry list representation. */
+        /**
+         * Note: caller required handle empty list due to parsing error.
+         */
         private fun getCredentialOptionInfoList(
             providerId: String,
             credentialEntries: List<Entry>,
             context: Context,
         ): List<CredentialEntryInfo> {
-            return credentialEntries.map {
-                // TODO: handle NPE gracefully
-                val credentialEntry = CredentialEntry.fromSlice(it.slice)!!
+            val result: MutableList<CredentialEntryInfo> = mutableListOf()
+            credentialEntries.forEach {
+                val credentialEntry = parseCredentialEntryFromSlice(it.slice)
+                when (credentialEntry) {
+                    is PasswordCredentialEntry -> {
+                        result.add(CredentialEntryInfo(
+                            providerId = providerId,
+                            entryKey = it.key,
+                            entrySubkey = it.subkey,
+                            pendingIntent = credentialEntry.pendingIntent,
+                            fillInIntent = it.frameworkExtrasIntent,
+                            credentialType = CredentialType.PASSWORD,
+                            credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
+                            userName = credentialEntry.username.toString(),
+                            displayName = credentialEntry.displayName?.toString(),
+                            icon = credentialEntry.icon?.loadDrawable(context),
+                            lastUsedTimeMillis = credentialEntry.lastUsedTime,
+                        ))
+                    }
+                    is PublicKeyCredentialEntry -> {
+                        result.add(CredentialEntryInfo(
+                            providerId = providerId,
+                            entryKey = it.key,
+                            entrySubkey = it.subkey,
+                            pendingIntent = credentialEntry.pendingIntent,
+                            fillInIntent = it.frameworkExtrasIntent,
+                            credentialType = CredentialType.PASSKEY,
+                            credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
+                            userName = credentialEntry.username.toString(),
+                            displayName = credentialEntry.displayName?.toString(),
+                            icon = credentialEntry.icon?.loadDrawable(context),
+                            lastUsedTimeMillis = credentialEntry.lastUsedTime,
+                        ))
+                    }
+                    is CustomCredentialEntry -> {
+                        result.add(CredentialEntryInfo(
+                            providerId = providerId,
+                            entryKey = it.key,
+                            entrySubkey = it.subkey,
+                            pendingIntent = credentialEntry.pendingIntent,
+                            fillInIntent = it.frameworkExtrasIntent,
+                            credentialType = CredentialType.UNKNOWN,
+                            credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
+                            userName = credentialEntry.title.toString(),
+                            displayName = credentialEntry.subtitle?.toString(),
+                            icon = credentialEntry.icon?.loadDrawable(context),
+                            lastUsedTimeMillis = credentialEntry.lastUsedTime,
+                        ))
+                    }
+                    else -> Log.d(
+                        Constants.LOG_TAG,
+                        "Encountered unrecognized credential entry ${it.slice.spec?.type}"
+                    )
+                }
+            }
+            // TODO: handle empty list due to parsing error.
+            return result
+        }
 
-                // Consider directly move the UI object into the class.
-                return@map CredentialEntryInfo(
-                    providerId = providerId,
-                    entryKey = it.key,
-                    entrySubkey = it.subkey,
-                    pendingIntent = credentialEntry.pendingIntent,
-                    fillInIntent = it.frameworkExtrasIntent,
-                    credentialType = credentialEntry.type,
-                    credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
-                    userName = credentialEntry.username.toString(),
-                    displayName = credentialEntry.displayName?.toString(),
-                    // TODO: proper fallback
-                    icon = credentialEntry.icon?.loadDrawable(context),
-                    lastUsedTimeMillis = credentialEntry.lastUsedTimeMillis,
-                )
+        private fun parseCredentialEntryFromSlice(slice: Slice): CredentialEntry? {
+            try {
+                when (slice.spec?.type) {
+                    TYPE_PASSWORD_CREDENTIAL -> return PasswordCredentialEntry.fromSlice(slice)!!
+                    TYPE_PUBLIC_KEY_CREDENTIAL -> return PublicKeyCredentialEntry.fromSlice(slice)!!
+                    else -> return CustomCredentialEntry.fromSlice(slice)!!
+                }
+            } catch (e: Exception) {
+                // Try CustomCredentialEntry.fromSlice one last time in case the cause was a failed
+                // password / passkey parsing attempt.
+                return CustomCredentialEntry.fromSlice(slice)
             }
         }
 
-        private fun getAuthenticationEntry(
+        /**
+         * Note: caller required handle empty list due to parsing error.
+         */
+        private fun getAuthenticationEntryList(
             providerId: String,
             providerDisplayName: String,
             providerIcon: Drawable,
-            authEntry: Entry?,
-        ): AuthenticationEntryInfo? {
-            if (authEntry == null) {
-                return null
-            }
-            val authStructuredEntry = AuthenticationAction.fromSlice(
-                authEntry!!.slice
-            )
-            if (authStructuredEntry == null) {
-                return null
-            }
+            authEntryList: List<Entry>,
+        ): List<AuthenticationEntryInfo> {
+            val result: MutableList<AuthenticationEntryInfo> = mutableListOf()
+            authEntryList.forEach { entry ->
+                val structuredAuthEntry =
+                    AuthenticationAction.fromSlice(entry.slice) ?: return@forEach
 
-            return AuthenticationEntryInfo(
-                providerId = providerId,
-                entryKey = authEntry.key,
-                entrySubkey = authEntry.subkey,
-                pendingIntent = authStructuredEntry.pendingIntent,
-                fillInIntent = authEntry.frameworkExtrasIntent,
-                title = providerDisplayName,
-                icon = providerIcon,
-            )
+                // TODO: replace with official jetpack code.
+                val titleItem: SliceItem? = entry.slice.items.firstOrNull {
+                    it.hasHint(
+                        "androidx.credentials.provider.authenticationAction.SLICE_HINT_TITLE")
+                }
+                val title: String = titleItem?.text?.toString() ?: providerDisplayName
+
+                result.add(AuthenticationEntryInfo(
+                    providerId = providerId,
+                    entryKey = entry.key,
+                    entrySubkey = entry.subkey,
+                    pendingIntent = structuredAuthEntry.pendingIntent,
+                    fillInIntent = entry.frameworkExtrasIntent,
+                    title = title,
+                    icon = providerIcon,
+                ))
+            }
+            return result
         }
 
         private fun getRemoteEntry(providerId: String, remoteEntry: Entry?): RemoteEntryInfo? {
-            // TODO: should also call fromSlice after getting the official jetpack code.
             if (remoteEntry == null) {
                 return null
             }
+            val structuredRemoteEntry = RemoteCredentialEntry.fromSlice(remoteEntry.slice)
+                ?: return null
             return RemoteEntryInfo(
                 providerId = providerId,
                 entryKey = remoteEntry.key,
                 entrySubkey = remoteEntry.subkey,
-                pendingIntent = remoteEntry.pendingIntent,
+                pendingIntent = structuredRemoteEntry.pendingIntent,
                 fillInIntent = remoteEntry.frameworkExtrasIntent,
             )
         }
 
+        /**
+         * Note: caller required handle empty list due to parsing error.
+         */
         private fun getActionEntryList(
             providerId: String,
             actionEntries: List<Entry>,
             providerIcon: Drawable,
         ): List<ActionEntryInfo> {
-            return actionEntries.map {
-                // TODO: handle NPE gracefully
-                val actionEntryUi = Action.fromSlice(it.slice)!!
-
-                return@map ActionEntryInfo(
+            val result: MutableList<ActionEntryInfo> = mutableListOf()
+            actionEntries.forEach {
+                val actionEntryUi = Action.fromSlice(it.slice) ?: return@forEach
+                result.add(ActionEntryInfo(
                     providerId = providerId,
                     entryKey = it.key,
                     entrySubkey = it.subkey,
                     pendingIntent = actionEntryUi.pendingIntent,
                     fillInIntent = it.frameworkExtrasIntent,
                     title = actionEntryUi.title.toString(),
-                    // TODO: gracefully fail
                     icon = providerIcon,
-                    subTitle = actionEntryUi.subTitle?.toString(),
-                )
+                    subTitle = actionEntryUi.subtitle?.toString(),
+                ))
             }
+            // TODO: handle empty list
+            return result
         }
     }
 }
 
 class CreateFlowUtils {
     companion object {
-        // Returns the list (potentially empty) of enabled provider.
+        /**
+         * Note: caller required handle empty list due to parsing error.
+         */
         fun toEnabledProviderList(
             providerDataList: List<CreateCredentialProviderData>,
             context: Context,
@@ -289,7 +364,9 @@
             return providerList
         }
 
-        // Returns the list (potentially empty) of disabled provider.
+        /**
+         * Note: caller required handle empty list due to parsing error.
+         */
         fun toDisabledProviderList(
             providerDataList: List<DisabledProviderData>?,
             context: Context,
@@ -316,22 +393,21 @@
         ): RequestDisplayInfo? {
             val appLabel = getAppLabel(context.packageManager, requestInfo.appPackageName)
                 ?: return null
-            val createCredentialRequest = requestInfo.createCredentialRequest
-            val createCredentialRequestJetpack = createCredentialRequest?.let {
-                CreateCredentialRequest.createFrom(
-                    it.type, it.credentialData, it.candidateQueryData, it.isSystemProviderRequired
+            val createCredentialRequest = requestInfo.createCredentialRequest ?: return null
+            val createCredentialRequestJetpack = CreateCredentialRequest.createFrom(
+                createCredentialRequest.type,
+                createCredentialRequest.credentialData,
+                createCredentialRequest.candidateQueryData,
+                createCredentialRequest.isSystemProviderRequired
+            )
+            return when (createCredentialRequestJetpack) {
+                is CreatePasswordRequest -> RequestDisplayInfo(
+                    createCredentialRequestJetpack.id,
+                    createCredentialRequestJetpack.password,
+                    CredentialType.PASSWORD,
+                    appLabel,
+                    context.getDrawable(R.drawable.ic_password)!!
                 )
-            }
-            when (createCredentialRequestJetpack) {
-                is CreatePasswordRequest -> {
-                    return RequestDisplayInfo(
-                        createCredentialRequestJetpack.id,
-                        createCredentialRequestJetpack.password,
-                        createCredentialRequestJetpack.type,
-                        appLabel,
-                        context.getDrawable(R.drawable.ic_password)!!
-                    )
-                }
                 is CreatePublicKeyCredentialRequest -> {
                     val requestJson = createCredentialRequestJetpack.requestJson
                     val json = JSONObject(requestJson)
@@ -342,24 +418,29 @@
                         name = user.getString("name")
                         displayName = user.getString("displayName")
                     }
-                    return RequestDisplayInfo(
+                    RequestDisplayInfo(
                         name,
                         displayName,
-                        createCredentialRequestJetpack.type,
+                        CredentialType.PASSKEY,
                         appLabel,
                         context.getDrawable(R.drawable.ic_passkey)!!
                     )
                 }
-                // TODO: correctly parsing for other sign-ins
-                else -> {
-                    return RequestDisplayInfo(
-                        "beckett-bakert@gmail.com",
-                        "Elisa Beckett",
-                        "other-sign-ins",
-                        appLabel.toString(),
-                        context.getDrawable(R.drawable.ic_other_sign_in)!!
+                is CreateCustomCredentialRequest -> {
+                    // TODO: directly use the display info once made public
+                    val displayInfo = CreateCredentialRequest.DisplayInfo
+                        .parseFromCredentialDataBundle(createCredentialRequest.credentialData)
+                        ?: return null
+                    RequestDisplayInfo(
+                        title = displayInfo.userId,
+                        subtitle = displayInfo.userDisplayName,
+                        type = CredentialType.UNKNOWN,
+                        appName = appLabel,
+                        typeIcon = displayInfo.credentialTypeIcon?.loadDrawable(context)
+                            ?: context.getDrawable(R.drawable.ic_other_sign_in)!!
                     )
                 }
+                else -> null
             }
         }
 
@@ -398,17 +479,14 @@
                 /*requestDisplayInfo=*/requestDisplayInfo,
                 /*defaultProvider=*/defaultProvider, /*remoteEntry=*/remoteEntry,
                 /*isPasskeyFirstUse=*/isPasskeyFirstUse
-            )
-            if (initialScreenState == null) {
-                return null
-            }
+            ) ?: return null
             return CreateCredentialUiState(
                 enabledProviders = enabledProviders,
                 disabledProviders = disabledProviders,
                 currentScreenState = initialScreenState,
                 requestDisplayInfo = requestDisplayInfo,
                 sortedCreateOptionsPairs = createOptionsPairs.sortedWith(
-                    compareByDescending { it.first.lastUsedTimeMillis }
+                    compareByDescending { it.first.lastUsedTime }
                 ),
                 hasDefaultProvider = defaultProvider != null,
                 activeEntry = toActiveEntry(
@@ -430,7 +508,7 @@
             isPasskeyFirstUse: Boolean,
         ): CreateScreenState? {
             return if (isPasskeyFirstUse && requestDisplayInfo.type ==
-                TYPE_PUBLIC_KEY_CREDENTIAL && !isOnPasskeyIntroStateAlready) {
+                CredentialType.PASSKEY && !isOnPasskeyIntroStateAlready) {
                 CreateScreenState.PASSKEY_INTRO
             } else if ((defaultProvider == null || defaultProvider.createOptions.isEmpty()) &&
                 createOptionSize > 1) {
@@ -474,17 +552,18 @@
             } else null
         }
 
+        /**
+         * Note: caller required handle empty list due to parsing error.
+         */
         private fun toCreationOptionInfoList(
             providerId: String,
             creationEntries: List<Entry>,
             context: Context,
         ): List<CreateOptionInfo> {
-            return creationEntries.map {
-                // TODO: handle NPE gracefully
-                val createEntry = CreateEntry.fromSlice(it.slice)!!
-
-                return@map CreateOptionInfo(
-                    // TODO: remove fallbacks
+            val result: MutableList<CreateOptionInfo> = mutableListOf()
+            creationEntries.forEach {
+                val createEntry = CreateEntry.fromSlice(it.slice) ?: return@forEach
+                result.add(CreateOptionInfo(
                     providerId = providerId,
                     entryKey = it.key,
                     entrySubkey = it.subkey,
@@ -492,32 +571,28 @@
                     fillInIntent = it.frameworkExtrasIntent,
                     userProviderDisplayName = createEntry.accountName.toString(),
                     profileIcon = createEntry.icon?.loadDrawable(context),
-                    passwordCount = CredentialCountInformation.getPasswordCount(
-                        createEntry.credentialCountInformationList
-                    ) ?: 0,
-                    passkeyCount = CredentialCountInformation.getPasskeyCount(
-                        createEntry.credentialCountInformationList
-                    ) ?: 0,
-                    totalCredentialCount = CredentialCountInformation.getTotalCount(
-                        createEntry.credentialCountInformationList
-                    ) ?: 0,
-                    lastUsedTimeMillis = createEntry.lastUsedTimeMillis ?: 0,
-                    footerDescription = createEntry.footerDescription?.toString()
-                )
+                    passwordCount = createEntry.getPasswordCredentialCount(),
+                    passkeyCount = createEntry.getPublicKeyCredentialCount(),
+                    totalCredentialCount = createEntry.getTotalCredentialCount(),
+                    lastUsedTime = createEntry.lastUsedTime,
+                    footerDescription = createEntry.description?.toString()
+                ))
             }
+            return result
         }
 
         private fun toRemoteInfo(
             providerId: String,
             remoteEntry: Entry?,
         ): RemoteInfo? {
-            // TODO: should also call fromSlice after getting the official jetpack code.
             return if (remoteEntry != null) {
+                val structuredRemoteEntry = RemoteCreateEntry.fromSlice(remoteEntry.slice)
+                    ?: return null
                 RemoteInfo(
                     providerId = providerId,
                     entryKey = remoteEntry.key,
                     entrySubkey = remoteEntry.subkey,
-                    pendingIntent = remoteEntry.pendingIntent,
+                    pendingIntent = structuredRemoteEntry.pendingIntent,
                     fillInIntent = remoteEntry.frameworkExtrasIntent,
                 )
             } else null
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
new file mode 100644
index 0000000..a580c6c
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
@@ -0,0 +1,204 @@
+/*
+ * 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.credentialmanager
+
+import android.app.PendingIntent
+import android.app.slice.Slice
+import android.app.slice.SliceSpec
+import android.content.Context
+import android.content.Intent
+import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL
+import android.credentials.ui.Entry
+import android.net.Uri
+import android.provider.Settings
+import androidx.credentials.provider.CreateEntry
+import androidx.credentials.provider.PasswordCredentialEntry
+import androidx.credentials.provider.PublicKeyCredentialEntry
+
+import java.time.Instant
+
+// TODO: remove once testing is complete
+class GetTestUtils {
+    companion object {
+        internal fun newAuthenticationEntry(
+            context: Context,
+            key: String,
+            subkey: String,
+            title: String,
+        ): Entry {
+            val slice = Slice.Builder(
+                Uri.EMPTY, SliceSpec("AuthenticationAction", 0)
+            )
+            val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
+            val pendingIntent =
+                PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
+            slice.addAction(
+                pendingIntent,
+                Slice.Builder(slice)
+                    .addHints(listOf("androidx.credentials.provider.authenticationAction" +
+                        ".SLICE_HINT_PENDING_INTENT"))
+                    .build(),
+                /*subType=*/null
+            )
+            slice.addText(
+                title,
+                null,
+                listOf("androidx.credentials.provider.authenticationAction.SLICE_HINT_TITLE")
+            )
+            return Entry(
+                key,
+                subkey,
+                slice.build()
+            )
+        }
+
+        internal fun newActionEntry(
+            context: Context,
+            key: String,
+            subkey: String,
+            text: String,
+            subtext: String? = null,
+        ): Entry {
+            val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
+            val pendingIntent =
+                PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
+            val sliceBuilder = Slice.Builder(Uri.EMPTY, SliceSpec("Action", 0))
+                .addText(
+                    text, /*subType=*/null,
+                    listOf("androidx.credentials.provider.action.HINT_ACTION_TITLE")
+                )
+                .addText(
+                    subtext, /*subType=*/null,
+                    listOf("androidx.credentials.provider.action.HINT_ACTION_SUBTEXT")
+                )
+            sliceBuilder.addAction(
+                pendingIntent,
+                Slice.Builder(sliceBuilder)
+                    .addHints(
+                        listOf("androidx.credentials.provider.action.SLICE_HINT_PENDING_INTENT")
+                    )
+                    .build(),
+                /*subType=*/null
+            )
+            return Entry(
+                key,
+                subkey,
+                sliceBuilder.build()
+            )
+        }
+
+        internal fun newPasswordEntry(
+            context: Context,
+            key: String,
+            subkey: String,
+            userName: String,
+            userDisplayName: String?,
+            lastUsedTime: Instant?,
+        ): Entry {
+            val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
+                .setPackage("com.androidauth.androidvault")
+            intent.putExtra("provider_extra_sample", "testprovider")
+            val pendingIntent = PendingIntent.getActivity(
+                context, 1,
+                intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+                or PendingIntent.FLAG_ONE_SHOT)
+            )
+            val passwordEntry = PasswordCredentialEntry.Builder(context, userName, pendingIntent)
+                .setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
+            return Entry(key, subkey, passwordEntry.slice, Intent())
+        }
+
+        internal fun newPasskeyEntry(
+            context: Context,
+            key: String,
+            subkey: String,
+            userName: String,
+            userDisplayName: String?,
+            lastUsedTime: Instant?,
+        ): Entry {
+            val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
+                .setPackage("com.androidauth.androidvault")
+            intent.putExtra("provider_extra_sample", "testprovider")
+            val pendingIntent = PendingIntent.getActivity(
+                context, 1,
+                intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+                or PendingIntent.FLAG_ONE_SHOT)
+            )
+            val passkeyEntry = PublicKeyCredentialEntry.Builder(context, userName, pendingIntent)
+                .setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
+            return Entry(key, subkey, passkeyEntry.slice, Intent())
+        }
+    }
+}
+
+class CreateTestUtils {
+    companion object {
+        private const val TYPE_TOTAL_CREDENTIAL = "TOTAL_CREDENTIAL_COUNT_TYPE"
+        private const val SLICE_HINT_ACCOUNT_NAME =
+            "androidx.credentials.provider.createEntry.SLICE_HINT_USER_PROVIDER_ACCOUNT_NAME"
+        private const val SLICE_HINT_NOTE =
+            "androidx.credentials.provider.createEntry.SLICE_HINT_NOTE"
+        private const val SLICE_HINT_ICON =
+            "androidx.credentials.provider.createEntry.SLICE_HINT_PROFILE_ICON"
+        private const val SLICE_HINT_CREDENTIAL_COUNT_INFORMATION =
+            "androidx.credentials.provider.createEntry.SLICE_HINT_CREDENTIAL_COUNT_INFORMATION"
+        private const val SLICE_HINT_LAST_USED_TIME_MILLIS =
+            "androidx.credentials.provider.createEntry.SLICE_HINT_LAST_USED_TIME_MILLIS"
+        private const val SLICE_HINT_PENDING_INTENT =
+            "androidx.credentials.provider.createEntry.SLICE_HINT_PENDING_INTENT"
+
+        internal fun newCreateEntry(
+            context: Context,
+            key: String,
+            subkey: String,
+            providerUserDisplayName: String,
+            passwordCount: Int?,
+            passkeyCount: Int?,
+            totalCredentialCount: Int?,
+            lastUsedTime: Instant?,
+            footerDescription: String?,
+        ): Entry {
+            val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
+                .setPackage("com.androidauth.androidvault")
+            intent.putExtra("provider_extra_sample", "testprovider")
+            val pendingIntent = PendingIntent.getActivity(
+                context, 1,
+                intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+                or PendingIntent.FLAG_ONE_SHOT)
+            )
+            val credCountMap = mutableMapOf<String, Int>()
+            passwordCount?.let { credCountMap.put(TYPE_PASSWORD_CREDENTIAL, it) }
+            passkeyCount?.let {
+                credCountMap.put("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL", it)
+            }
+            totalCredentialCount?.let { credCountMap.put(TYPE_TOTAL_CREDENTIAL, it) }
+            return Entry(
+                key,
+                subkey,
+                CreateEntry.toSlice(
+                    providerUserDisplayName,
+                    null,
+                    footerDescription,
+                    lastUsedTime,
+                    credCountMap,
+                    pendingIntent
+                ),
+                Intent()
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/UserConfigRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/UserConfigRepo.kt
index 021dcab..a17f2c8 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/UserConfigRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/UserConfigRepo.kt
@@ -50,21 +50,9 @@
     }
 
     companion object {
-        lateinit var repo: UserConfigRepo
-
         const val DEFAULT_PROVIDER = "default_provider"
         // This first use value only applies to passkeys, not related with if generally
         // credential manager is first use or not
         const val IS_PASSKEY_FIRST_USE = "is_passkey_first_use"
-
-        fun setup(
-            context: Context,
-        ) {
-            repo = UserConfigRepo(context)
-        }
-
-        fun getInstance(): UserConfigRepo {
-            return repo
-        }
     }
 }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BaseEntry.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BaseEntry.kt
new file mode 100644
index 0000000..ee36989
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BaseEntry.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.credentialmanager.common
+
+import android.app.PendingIntent
+import android.content.Intent
+
+open class BaseEntry (
+    val providerId: String,
+    val entryKey: String,
+    val entrySubkey: String,
+    val pendingIntent: PendingIntent?,
+    val fillInIntent: Intent?,
+    val shouldTerminateUiUponSuccessfulProviderResult: Boolean,
+)
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/CredentialType.kt
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to packages/CredentialManager/src/com/android/credentialmanager/common/CredentialType.kt
index 497c272..cc92f60 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/CredentialType.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package com.android.credentialmanager.common
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+enum class CredentialType {
+    UNKNOWN, PASSKEY, PASSWORD,
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
index f1f453d..58edb25 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
@@ -28,6 +28,7 @@
 import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.sizeIn
 import androidx.compose.foundation.layout.offset
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Surface
@@ -40,6 +41,7 @@
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.saveable.Saver
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
@@ -131,7 +133,7 @@
         if (isSkipHalfExpanded) {
             require(initialValue != HalfExpanded) {
                 "The initial value must not be set to HalfExpanded if skipHalfExpanded is set to" +
-                        " true."
+                    " true."
             }
         }
     }
@@ -209,10 +211,10 @@
             message = "Please specify the skipHalfExpanded parameter",
             replaceWith = ReplaceWith(
                 "ModalBottomSheetState.Saver(" +
-                        "animationSpec = animationSpec," +
-                        "skipHalfExpanded = ," +
-                        "confirmStateChange = confirmStateChange" +
-                        ")"
+                    "animationSpec = animationSpec," +
+                    "skipHalfExpanded = ," +
+                    "confirmStateChange = confirmStateChange" +
+                    ")"
             )
         )
         fun Saver(
@@ -339,55 +341,77 @@
                 visible = sheetState.targetValue != Hidden
             )
         }
-        Surface(
-            Modifier
-                .fillMaxWidth()
-                .nestedScroll(sheetState.nestedScrollConnection)
-                .offset {
-                    val y = if (sheetState.anchors.isEmpty()) {
-                        // if we don't know our anchors yet, render the sheet as hidden
-                        fullHeight.roundToInt()
-                    } else {
-                        // if we do know our anchors, respect them
-                        sheetState.offset.value.roundToInt()
-                    }
-                    IntOffset(0, y)
-                }
-                .bottomSheetSwipeable(sheetState, fullHeight, sheetHeightState)
-                .onGloballyPositioned {
-                    sheetHeightState.value = it.size.height.toFloat()
-                }
-                .semantics {
-                    if (sheetState.isVisible) {
-                        dismiss {
-                            if (sheetState.confirmStateChange(Hidden)) {
-                                scope.launch { sheetState.hide() }
-                            }
-                            true
-                        }
-                        if (sheetState.currentValue == HalfExpanded) {
-                            expand {
-                                if (sheetState.confirmStateChange(Expanded)) {
-                                    scope.launch { sheetState.expand() }
-                                }
-                                true
-                            }
-                        } else if (sheetState.hasHalfExpandedState) {
-                            collapse {
-                                if (sheetState.confirmStateChange(HalfExpanded)) {
-                                    scope.launch { sheetState.halfExpand() }
-                                }
-                                true
-                            }
-                        }
-                    }
-                },
-            shape = sheetShape,
-            shadowElevation = sheetElevation,
-            color = sheetBackgroundColor,
-            contentColor = sheetContentColor
+
+        // For large screen, allow enough horizontal scrim space.
+        // Manually calculate the > compact width due to lack of corresponding jetpack dependency.
+        val maxSheetContentWidth: Dp =
+            if (maxWidth >= ModalBottomSheetDefaults.MaxCompactWidth &&
+                maxWidth <= ModalBottomSheetDefaults.MaxCompactWidth +
+                ModalBottomSheetDefaults.StartPadding + ModalBottomSheetDefaults.EndPadding
+            )
+                (maxWidth - ModalBottomSheetDefaults.StartPadding -
+                    ModalBottomSheetDefaults.EndPadding)
+            else ModalBottomSheetDefaults.MaxSheetWidth
+        val maxSheetContentHeight = maxHeight - ModalBottomSheetDefaults.MinScrimHeight
+        Box(
+            Modifier.sizeIn(
+                maxWidth = maxSheetContentWidth,
+                // Allow enough vertical scrim space.
+                maxHeight = maxSheetContentHeight
+            ).align(Alignment.TopCenter)
         ) {
-            Column(content = sheetContent)
+            Surface(
+                Modifier
+                    .fillMaxWidth()
+                    .nestedScroll(sheetState.nestedScrollConnection)
+                    .offset {
+                        val y = if (sheetState.anchors.isEmpty()) {
+                            // if we don't know our anchors yet, render the sheet as hidden
+                            fullHeight.roundToInt()
+                        } else {
+                            // if we do know our anchors, respect them
+                            sheetState.offset.value.roundToInt()
+                        }
+                        IntOffset(0, y)
+                    }
+                    .bottomSheetSwipeable(sheetState, fullHeight, sheetHeightState)
+                    .onGloballyPositioned {
+                        sheetHeightState.value = it.size.height.toFloat()
+                    }
+                    .semantics {
+                        if (sheetState.isVisible) {
+                            dismiss {
+                                if (sheetState.confirmStateChange(Hidden)) {
+                                    scope.launch { sheetState.hide() }
+                                }
+                                true
+                            }
+                            if (sheetState.currentValue == HalfExpanded) {
+                                expand {
+                                    if (sheetState.confirmStateChange(Expanded)) {
+                                        scope.launch { sheetState.expand() }
+                                    }
+                                    true
+                                }
+                            } else if (sheetState.hasHalfExpandedState) {
+                                collapse {
+                                    if (sheetState.confirmStateChange(HalfExpanded)) {
+                                        scope.launch { sheetState.halfExpand() }
+                                    }
+                                    true
+                                }
+                            }
+                        }
+                    },
+                shape = sheetShape,
+                shadowElevation = sheetElevation,
+                color = sheetBackgroundColor,
+                contentColor = sheetContentColor
+            ) {
+                Column(
+                    content = sheetContent
+                )
+            }
         }
     }
 }
@@ -465,6 +489,11 @@
  * Contains useful Defaults for [ModalBottomSheetLayout].
  */
 object ModalBottomSheetDefaults {
+    val MaxCompactWidth = 600.dp
+    val MaxSheetWidth = 640.dp
+    val MinScrimHeight = 56.dp
+    val StartPadding = 56.dp
+    val EndPadding = 56.dp
 
     /**
      * The default elevation used by [ModalBottomSheetLayout].
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
index d0271ab..984057a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
@@ -16,11 +16,23 @@
 
 package com.android.credentialmanager.common.ui
 
+import com.android.credentialmanager.R
+import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.Visibility
+import androidx.compose.material.icons.outlined.VisibilityOff
 import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.material3.TextButton
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
 
 @Composable
 fun ActionButton(text: String, onClick: () -> Unit) {
@@ -32,4 +44,27 @@
     ) {
         Text(text = text)
     }
+}
+
+@Composable
+fun ToggleVisibilityButton(modifier: Modifier = Modifier, onToggle: (Boolean) -> Unit) {
+    // default state is visibility off
+    val toggleState: MutableState<Boolean> = remember { mutableStateOf(false) }
+
+    IconButton(
+        modifier = modifier,
+        onClick = {
+            toggleState.value = !toggleState.value
+            onToggle(toggleState.value)
+        }
+    ) {
+        Icon(
+            imageVector = if (toggleState.value)
+                Icons.Outlined.Visibility else Icons.Outlined.VisibilityOff,
+            contentDescription = if (toggleState.value)
+                stringResource(R.string.content_description_show_password) else
+                stringResource(R.string.content_description_hide_password),
+            tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant
+        )
+    }
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
new file mode 100644
index 0000000..c4d96cc
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
@@ -0,0 +1,54 @@
+/*
+ * 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.credentialmanager.common.ui
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import com.android.credentialmanager.common.material.ModalBottomSheetLayout
+import com.android.credentialmanager.common.material.ModalBottomSheetValue
+import com.android.credentialmanager.common.material.rememberModalBottomSheetState
+import com.android.credentialmanager.ui.theme.EntryShape
+
+/** Draws a modal bottom sheet with the same styles and effects shared by various flows. */
+@Composable
+fun ModalBottomSheet(
+    sheetContent: @Composable ColumnScope.() -> Unit,
+    onDismiss: () -> Unit
+) {
+    val state = rememberModalBottomSheetState(
+        initialValue = ModalBottomSheetValue.Expanded,
+        skipHalfExpanded = true
+    )
+    ModalBottomSheetLayout(
+        sheetBackgroundColor = MaterialTheme.colorScheme.surface,
+        modifier = Modifier.background(Color.Transparent),
+        sheetState = state,
+        sheetContent = sheetContent,
+        scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
+        sheetShape = EntryShape.TopRoundedCorner,
+    ) {}
+    LaunchedEffect(state.currentValue) {
+        if (state.currentValue == ModalBottomSheetValue.Hidden) {
+            onDismiss()
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
index aaabce3..85e5c1e 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
@@ -18,9 +18,9 @@
 
 import androidx.compose.foundation.BorderStroke
 import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.material3.Card
 import androidx.compose.material3.CardDefaults
-import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
@@ -30,7 +30,6 @@
  * By default the card is filled with surfaceVariant color. This container card instead fills the
  * background color with surface corlor.
  */
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun ContainerCard(
     modifier: Modifier = Modifier,
@@ -39,7 +38,7 @@
     content: @Composable ColumnScope.() -> Unit,
 ) {
     Card(
-        modifier = modifier,
+        modifier = modifier.fillMaxWidth(),
         shape = shape,
         border = border,
         colors = CardDefaults.cardColors(
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index 5e432b9..558c229 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -2,7 +2,6 @@
 
 package com.android.credentialmanager.createflow
 
-import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL
 import androidx.activity.compose.ManagedActivityResultLauncher
 import androidx.activity.result.ActivityResult
 import androidx.activity.result.IntentSenderRequest
@@ -11,6 +10,8 @@
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
@@ -27,117 +28,123 @@
 import androidx.compose.material.icons.filled.Add
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.asImageBitmap
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.input.PasswordVisualTransformation
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.core.graphics.drawable.toBitmap
+import com.android.credentialmanager.CredentialSelectorViewModel
 import com.android.credentialmanager.R
+import com.android.credentialmanager.common.BaseEntry
+import com.android.credentialmanager.common.CredentialType
 import com.android.credentialmanager.common.ProviderActivityState
-import com.android.credentialmanager.common.material.ModalBottomSheetLayout
-import com.android.credentialmanager.common.material.ModalBottomSheetValue
-import com.android.credentialmanager.common.material.rememberModalBottomSheetState
 import com.android.credentialmanager.common.ui.ActionButton
 import com.android.credentialmanager.common.ui.ConfirmButton
 import com.android.credentialmanager.common.ui.Entry
+import com.android.credentialmanager.common.ui.ModalBottomSheet
 import com.android.credentialmanager.common.ui.TextOnSurface
 import com.android.credentialmanager.common.ui.TextSecondary
 import com.android.credentialmanager.common.ui.TextOnSurfaceVariant
 import com.android.credentialmanager.common.ui.ContainerCard
-import com.android.credentialmanager.ui.theme.EntryShape
+import com.android.credentialmanager.common.ui.ToggleVisibilityButton
 import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
-import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun CreateCredentialScreen(
-    viewModel: CreateCredentialViewModel,
+    viewModel: CredentialSelectorViewModel,
+    createCredentialUiState: CreateCredentialUiState,
     providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
 ) {
-    val state = rememberModalBottomSheetState(
-        initialValue = ModalBottomSheetValue.Expanded,
-        skipHalfExpanded = true
-    )
-    ModalBottomSheetLayout(
-        sheetBackgroundColor = MaterialTheme.colorScheme.surface,
-        sheetState = state,
+    ModalBottomSheet(
         sheetContent = {
-            val uiState = viewModel.uiState
             // Hide the sheet content as opposed to the whole bottom sheet to maintain the scrim
             // background color even when the content should be hidden while waiting for
             // results from the provider app.
-            when (uiState.providerActivityState) {
+            when (viewModel.uiState.providerActivityState) {
                 ProviderActivityState.NOT_APPLICABLE -> {
-                    when (uiState.currentScreenState) {
+                    when (createCredentialUiState.currentScreenState) {
                         CreateScreenState.PASSKEY_INTRO -> ConfirmationCard(
-                            onConfirm = viewModel::onConfirmIntro,
-                            onLearnMore = viewModel::onLearnMore,
+                            onConfirm = viewModel::createFlowOnConfirmIntro,
+                            onLearnMore = viewModel::createFlowOnLearnMore,
                         )
                         CreateScreenState.PROVIDER_SELECTION -> ProviderSelectionCard(
-                            requestDisplayInfo = uiState.requestDisplayInfo,
-                            enabledProviderList = uiState.enabledProviders,
-                            disabledProviderList = uiState.disabledProviders,
-                            sortedCreateOptionsPairs = uiState.sortedCreateOptionsPairs,
-                            onOptionSelected = viewModel::onEntrySelectedFromFirstUseScreen,
+                            requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                            enabledProviderList = createCredentialUiState.enabledProviders,
+                            disabledProviderList = createCredentialUiState.disabledProviders,
+                            sortedCreateOptionsPairs =
+                            createCredentialUiState.sortedCreateOptionsPairs,
+                            onOptionSelected =
+                            viewModel::createFlowOnEntrySelectedFromFirstUseScreen,
                             onDisabledProvidersSelected =
-                            viewModel::onDisabledProvidersSelected,
+                            viewModel::createFlowOnDisabledProvidersSelected,
                             onMoreOptionsSelected =
-                            viewModel::onMoreOptionsSelectedOnProviderSelection,
+                            viewModel::createFlowOnMoreOptionsSelectedOnProviderSelection,
                         )
                         CreateScreenState.CREATION_OPTION_SELECTION -> CreationSelectionCard(
-                            requestDisplayInfo = uiState.requestDisplayInfo,
-                            enabledProviderList = uiState.enabledProviders,
-                            providerInfo = uiState.activeEntry?.activeProvider!!,
+                            requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                            enabledProviderList = createCredentialUiState.enabledProviders,
+                            providerInfo = createCredentialUiState.activeEntry?.activeProvider!!,
+                            hasDefaultProvider = createCredentialUiState.hasDefaultProvider,
                             createOptionInfo =
-                            uiState.activeEntry.activeEntryInfo as CreateOptionInfo,
-                            onOptionSelected = viewModel::onEntrySelected,
-                            onConfirm = viewModel::onConfirmEntrySelected,
+                            createCredentialUiState.activeEntry.activeEntryInfo
+                                as CreateOptionInfo,
+                            onOptionSelected = viewModel::createFlowOnEntrySelected,
+                            onConfirm = viewModel::createFlowOnConfirmEntrySelected,
                             onMoreOptionsSelected =
-                            viewModel::onMoreOptionsSelectedOnCreationSelection,
+                            viewModel::createFlowOnMoreOptionsSelectedOnCreationSelection,
                         )
                         CreateScreenState.MORE_OPTIONS_SELECTION -> MoreOptionsSelectionCard(
-                            requestDisplayInfo = uiState.requestDisplayInfo,
-                            enabledProviderList = uiState.enabledProviders,
-                            disabledProviderList = uiState.disabledProviders,
-                            sortedCreateOptionsPairs = uiState.sortedCreateOptionsPairs,
-                            hasDefaultProvider = uiState.hasDefaultProvider,
-                            isFromProviderSelection = uiState.isFromProviderSelection!!,
+                            requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                            enabledProviderList = createCredentialUiState.enabledProviders,
+                            disabledProviderList = createCredentialUiState.disabledProviders,
+                            sortedCreateOptionsPairs =
+                            createCredentialUiState.sortedCreateOptionsPairs,
+                            hasDefaultProvider = createCredentialUiState.hasDefaultProvider,
+                            isFromProviderSelection =
+                            createCredentialUiState.isFromProviderSelection!!,
                             onBackProviderSelectionButtonSelected =
-                            viewModel::onBackProviderSelectionButtonSelected,
+                            viewModel::createFlowOnBackProviderSelectionButtonSelected,
                             onBackCreationSelectionButtonSelected =
-                            viewModel::onBackCreationSelectionButtonSelected,
+                            viewModel::createFlowOnBackCreationSelectionButtonSelected,
                             onOptionSelected =
-                            viewModel::onEntrySelectedFromMoreOptionScreen,
+                            viewModel::createFlowOnEntrySelectedFromMoreOptionScreen,
                             onDisabledProvidersSelected =
-                            viewModel::onDisabledProvidersSelected,
-                            onRemoteEntrySelected = viewModel::onEntrySelected,
+                            viewModel::createFlowOnDisabledProvidersSelected,
+                            onRemoteEntrySelected = viewModel::createFlowOnEntrySelected,
                         )
                         CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard(
-                            providerInfo = uiState.activeEntry?.activeProvider!!,
-                            onChangeDefaultSelected = viewModel::onChangeDefaultSelected,
-                            onUseOnceSelected = viewModel::onUseOnceSelected,
+                            providerInfo = createCredentialUiState.activeEntry?.activeProvider!!,
+                            onChangeDefaultSelected = viewModel::createFlowOnChangeDefaultSelected,
+                            onUseOnceSelected = viewModel::createFlowOnUseOnceSelected,
                         )
                         CreateScreenState.EXTERNAL_ONLY_SELECTION -> ExternalOnlySelectionCard(
-                            requestDisplayInfo = uiState.requestDisplayInfo,
-                            activeRemoteEntry = uiState.activeEntry?.activeEntryInfo!!,
-                            onOptionSelected = viewModel::onEntrySelected,
-                            onConfirm = viewModel::onConfirmEntrySelected,
+                            requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                            activeRemoteEntry =
+                            createCredentialUiState.activeEntry?.activeEntryInfo!!,
+                            onOptionSelected = viewModel::createFlowOnEntrySelected,
+                            onConfirm = viewModel::createFlowOnConfirmEntrySelected,
                         )
                         CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO ->
                             MoreAboutPasskeysIntroCard(
                                 onBackPasskeyIntroButtonSelected =
-                                viewModel::onBackPasskeyIntroButtonSelected,
+                                viewModel::createFlowOnBackPasskeyIntroButtonSelected,
                             )
                     }
                 }
                 ProviderActivityState.READY_TO_LAUNCH -> {
                     // Launch only once per providerActivityState change so that the provider
                     // UI will not be accidentally launched twice.
-                    LaunchedEffect(uiState.providerActivityState) {
+                    LaunchedEffect(viewModel.uiState.providerActivityState) {
                         viewModel.launchProviderUi(providerActivityLauncher)
                     }
                 }
@@ -146,14 +153,8 @@
                 }
             }
         },
-        scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
-        sheetShape = EntryShape.TopRoundedCorner,
-    ) {}
-    LaunchedEffect(state.currentValue) {
-        if (state.currentValue == ModalBottomSheetValue.Hidden) {
-            viewModel.onCancel()
-        }
-    }
+        onDismiss = viewModel::onCancel
+    )
 }
 
 @OptIn(ExperimentalMaterial3Api::class)
@@ -264,7 +265,6 @@
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun ProviderSelectionCard(
     requestDisplayInfo: RequestDisplayInfo,
@@ -288,11 +288,11 @@
                 text = stringResource(
                     R.string.choose_provider_title,
                     when (requestDisplayInfo.type) {
-                        TYPE_PUBLIC_KEY_CREDENTIAL ->
+                        CredentialType.PASSKEY ->
                             stringResource(R.string.passkeys)
-                        TYPE_PASSWORD_CREDENTIAL ->
+                        CredentialType.PASSWORD ->
                             stringResource(R.string.passwords)
-                        else -> stringResource(R.string.sign_in_info)
+                        CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
                     }),
                 style = MaterialTheme.typography.titleMedium,
                 modifier = Modifier.padding(horizontal = 24.dp)
@@ -351,7 +351,6 @@
                 thickness = 24.dp,
                 color = Color.Transparent
             )
-            // TODO: handle the error situation that if multiple remoteInfos exists
             enabledProviderList.forEach { enabledProvider ->
                 if (enabledProvider.remoteEntry != null) {
                     Row(
@@ -363,6 +362,7 @@
                             onMoreOptionsSelected
                         )
                     }
+                    return@forEach
                 }
             }
             Divider(
@@ -387,7 +387,7 @@
     onBackCreationSelectionButtonSelected: () -> Unit,
     onOptionSelected: (ActiveEntry) -> Unit,
     onDisabledProvidersSelected: () -> Unit,
-    onRemoteEntrySelected: (EntryInfo) -> Unit,
+    onRemoteEntrySelected: (BaseEntry) -> Unit,
 ) {
     ContainerCard() {
         Column() {
@@ -398,11 +398,11 @@
                         stringResource(
                             R.string.save_credential_to_title,
                             when (requestDisplayInfo.type) {
-                                TYPE_PUBLIC_KEY_CREDENTIAL ->
+                                CredentialType.PASSKEY ->
                                     stringResource(R.string.passkey)
-                                TYPE_PASSWORD_CREDENTIAL ->
+                                CredentialType.PASSWORD ->
                                     stringResource(R.string.password)
-                                else -> stringResource(R.string.sign_in_info)
+                                CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
                             }),
                         style = MaterialTheme.typography.titleMedium,
                     )
@@ -463,7 +463,6 @@
                             )
                         }
                     }
-                    // TODO: handle the error situation that if multiple remoteInfos exists
                     enabledProviderList.forEach {
                         if (it.remoteEntry != null) {
                             item {
@@ -472,6 +471,7 @@
                                     onRemoteEntrySelected = onRemoteEntrySelected,
                                 )
                             }
+                            return@forEach
                         }
                     }
                 }
@@ -546,9 +546,10 @@
     enabledProviderList: List<EnabledProviderInfo>,
     providerInfo: EnabledProviderInfo,
     createOptionInfo: CreateOptionInfo,
-    onOptionSelected: (EntryInfo) -> Unit,
+    onOptionSelected: (BaseEntry) -> Unit,
     onConfirm: () -> Unit,
     onMoreOptionsSelected: () -> Unit,
+    hasDefaultProvider: Boolean,
 ) {
     ContainerCard() {
         Column() {
@@ -571,15 +572,15 @@
             )
             TextOnSurface(
                 text = when (requestDisplayInfo.type) {
-                    TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(
+                    CredentialType.PASSKEY -> stringResource(
                         R.string.choose_create_option_passkey_title,
                         requestDisplayInfo.appName
                     )
-                    TYPE_PASSWORD_CREDENTIAL -> stringResource(
+                    CredentialType.PASSWORD -> stringResource(
                         R.string.choose_create_option_password_title,
                         requestDisplayInfo.appName
                     )
-                    else -> stringResource(
+                    CredentialType.UNKNOWN -> stringResource(
                         R.string.choose_create_option_sign_in_title,
                         requestDisplayInfo.appName
                     )
@@ -601,7 +602,6 @@
                     onOptionSelected = onOptionSelected
                 )
             }
-            var shouldShowMoreOptionsButton = false
             var createOptionsSize = 0
             var remoteEntry: RemoteInfo? = null
             enabledProviderList.forEach { enabledProvider ->
@@ -610,8 +610,13 @@
                 }
                 createOptionsSize += enabledProvider.createOptions.size
             }
-            if (createOptionsSize > 1 || remoteEntry != null) {
-                shouldShowMoreOptionsButton = true
+            val shouldShowMoreOptionsButton = if (!hasDefaultProvider) {
+                // User has already been presented with all options on the default provider
+                // selection screen. Don't show them again. Therefore, only show the more option
+                // button if remote option is present.
+                remoteEntry != null
+            } else {
+                createOptionsSize > 1 || remoteEntry != null
             }
             Row(
                 horizontalArrangement =
@@ -655,8 +660,8 @@
 @Composable
 fun ExternalOnlySelectionCard(
     requestDisplayInfo: RequestDisplayInfo,
-    activeRemoteEntry: EntryInfo,
-    onOptionSelected: (EntryInfo) -> Unit,
+    activeRemoteEntry: BaseEntry,
+    onOptionSelected: (BaseEntry) -> Unit,
     onConfirm: () -> Unit,
 ) {
     ContainerCard() {
@@ -803,8 +808,8 @@
 @Composable
 fun PrimaryCreateOptionRow(
     requestDisplayInfo: RequestDisplayInfo,
-    entryInfo: EntryInfo,
-    onOptionSelected: (EntryInfo) -> Unit
+    entryInfo: BaseEntry,
+    onOptionSelected: (BaseEntry) -> Unit
 ) {
     Entry(
         onClick = { onOptionSelected(entryInfo) },
@@ -828,7 +833,7 @@
             Column() {
                 // TODO: Add the function to hide/view password when the type is create password
                 when (requestDisplayInfo.type) {
-                    TYPE_PUBLIC_KEY_CREDENTIAL -> {
+                    CredentialType.PASSKEY -> {
                         TextOnSurfaceVariant(
                             text = requestDisplayInfo.title,
                             style = MaterialTheme.typography.titleLarge,
@@ -846,20 +851,46 @@
                             modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
                         )
                     }
-                    TYPE_PASSWORD_CREDENTIAL -> {
+                    CredentialType.PASSWORD -> {
                         TextOnSurfaceVariant(
                             text = requestDisplayInfo.title,
                             style = MaterialTheme.typography.titleLarge,
                             modifier = Modifier.padding(top = 16.dp, start = 5.dp),
                         )
-                        TextSecondary(
+                        Row(modifier = Modifier.fillMaxWidth().padding(top = 4.dp, bottom = 16.dp,
+                                                                       start = 5.dp),
+                            verticalAlignment = Alignment.CenterVertically) {
+                            val visualTransformation = remember { PasswordVisualTransformation() }
                             // This subtitle would never be null for create password
-                            text = requestDisplayInfo.subtitle ?: "",
-                            style = MaterialTheme.typography.bodyMedium,
-                            modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
-                        )
+                            val originalPassword by remember {
+                                mutableStateOf(requestDisplayInfo.subtitle ?: "")
+                            }
+                            val displayedPassword = remember {
+                                mutableStateOf(
+                                    visualTransformation.filter(
+                                        AnnotatedString(originalPassword)
+                                    ).text.text
+                                )
+                            }
+                            TextSecondary(
+                                text = displayedPassword.value,
+                                style = MaterialTheme.typography.bodyMedium,
+                                modifier = Modifier.padding(top = 4.dp, bottom = 4.dp),
+                            )
+
+                            ToggleVisibilityButton(modifier = Modifier.padding(start = 4.dp)
+                                .height(24.dp).width(24.dp), onToggle = {
+                                if (it) {
+                                    displayedPassword.value = originalPassword
+                                } else {
+                                    displayedPassword.value = visualTransformation.filter(
+                                        AnnotatedString(originalPassword)
+                                    ).text.text
+                                }
+                            })
+                        }
                     }
-                    else -> {
+                    CredentialType.UNKNOWN -> {
                         if (requestDisplayInfo.subtitle != null) {
                             TextOnSurfaceVariant(
                                 text = requestDisplayInfo.title,
@@ -917,8 +948,8 @@
                         modifier = Modifier.padding(start = 5.dp),
                     )
                 }
-                if (requestDisplayInfo.type == TYPE_PUBLIC_KEY_CREDENTIAL ||
-                    requestDisplayInfo.type == TYPE_PASSWORD_CREDENTIAL) {
+                if (requestDisplayInfo.type == CredentialType.PASSKEY ||
+                    requestDisplayInfo.type == CredentialType.PASSWORD) {
                     if (createOptionInfo.passwordCount != null &&
                         createOptionInfo.passkeyCount != null
                     ) {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
deleted file mode 100644
index 01318b1..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.createflow
-
-import android.app.Activity
-import android.util.Log
-import androidx.activity.compose.ManagedActivityResultLauncher
-import androidx.activity.result.ActivityResult
-import androidx.activity.result.IntentSenderRequest
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.lifecycle.ViewModel
-import com.android.credentialmanager.common.Constants
-import com.android.credentialmanager.CreateFlowUtils
-import com.android.credentialmanager.CredentialManagerRepo
-import com.android.credentialmanager.UserConfigRepo
-import com.android.credentialmanager.common.DialogState
-import com.android.credentialmanager.common.ProviderActivityResult
-import com.android.credentialmanager.common.ProviderActivityState
-
-
-class CreateCredentialViewModel(
-    private val credManRepo: CredentialManagerRepo,
-    private val providerEnableListUiState: List<EnabledProviderInfo>,
-    private val providerDisableListUiState: List<DisabledProviderInfo>,
-    private val requestDisplayInfoUiState: RequestDisplayInfo,
-    userConfigRepo: UserConfigRepo = UserConfigRepo.getInstance(),
-) : ViewModel() {
-
-    val defaultProviderId = userConfigRepo.getDefaultProviderId()
-    val isPasskeyFirstUse = userConfigRepo.getIsPasskeyFirstUse()
-
-    var uiState by mutableStateOf(
-        CreateFlowUtils.toCreateCredentialUiState(
-            providerEnableListUiState,
-            providerDisableListUiState,
-            defaultProviderId,
-            requestDisplayInfoUiState,
-            false,
-            isPasskeyFirstUse)!!)
-        private set
-
-    fun onConfirmIntro() {
-        val newUiState = CreateFlowUtils.toCreateCredentialUiState(
-            providerEnableListUiState, providerDisableListUiState, defaultProviderId,
-            requestDisplayInfoUiState, true, isPasskeyFirstUse)
-        if (newUiState == null) {
-            onInternalError()
-            return
-        }
-        uiState = newUiState
-        UserConfigRepo.getInstance().setIsPasskeyFirstUse(false)
-    }
-
-    fun getProviderInfoByName(providerId: String): EnabledProviderInfo {
-        return uiState.enabledProviders.single {
-            it.id == providerId
-        }
-    }
-
-    fun onMoreOptionsSelectedOnProviderSelection() {
-        uiState = uiState.copy(
-            currentScreenState = CreateScreenState.MORE_OPTIONS_SELECTION,
-            isFromProviderSelection = true
-        )
-    }
-
-    fun onMoreOptionsSelectedOnCreationSelection() {
-        uiState = uiState.copy(
-            currentScreenState = CreateScreenState.MORE_OPTIONS_SELECTION,
-            isFromProviderSelection = false
-        )
-    }
-
-    fun onBackProviderSelectionButtonSelected() {
-        uiState = uiState.copy(
-            currentScreenState = CreateScreenState.PROVIDER_SELECTION,
-        )
-    }
-
-    fun onBackCreationSelectionButtonSelected() {
-        uiState = uiState.copy(
-            currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
-        )
-    }
-
-    fun onBackPasskeyIntroButtonSelected() {
-        uiState = uiState.copy(
-            currentScreenState = CreateScreenState.PASSKEY_INTRO,
-        )
-    }
-
-    fun onEntrySelectedFromMoreOptionScreen(activeEntry: ActiveEntry) {
-        uiState = uiState.copy(
-            currentScreenState =
-            if (activeEntry.activeProvider.id ==
-                UserConfigRepo.getInstance().getDefaultProviderId())
-                CreateScreenState.CREATION_OPTION_SELECTION
-            else CreateScreenState.MORE_OPTIONS_ROW_INTRO,
-            activeEntry = activeEntry
-        )
-    }
-
-    fun onEntrySelectedFromFirstUseScreen(activeEntry: ActiveEntry) {
-        uiState = uiState.copy(
-            currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
-            activeEntry = activeEntry
-        )
-        val providerId = uiState.activeEntry?.activeProvider?.id
-        onDefaultChanged(providerId)
-    }
-
-    fun onDisabledProvidersSelected() {
-        credManRepo.onSettingLaunchCancel()
-        uiState = uiState.copy(dialogState = DialogState.CANCELED_FOR_SETTINGS)
-    }
-
-    // When the view model runs into unexpected illegal state, reports the error back and close
-    // the activity gracefully.
-    private fun onInternalError() {
-        Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state")
-        credManRepo.onParsingFailureCancel()
-        uiState = uiState.copy(dialogState = DialogState.COMPLETE)
-    }
-
-    fun onCancel() {
-        credManRepo.onUserCancel()
-        uiState = uiState.copy(dialogState = DialogState.COMPLETE)
-    }
-
-    fun onLearnMore() {
-        uiState = uiState.copy(
-            currentScreenState = CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO,
-        )
-    }
-
-    fun onChangeDefaultSelected() {
-        uiState = uiState.copy(
-            currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
-        )
-        val providerId = uiState.activeEntry?.activeProvider?.id
-        onDefaultChanged(providerId)
-    }
-
-    fun onUseOnceSelected() {
-        uiState = uiState.copy(
-            currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
-        )
-    }
-
-    fun onDefaultChanged(providerId: String?) {
-        if (providerId != null) {
-            Log.d(
-                Constants.LOG_TAG, "Default provider changed to: " +
-                " {provider=$providerId")
-            UserConfigRepo.getInstance().setDefaultProvider(providerId)
-        } else {
-            Log.w(Constants.LOG_TAG, "Null provider is being changed")
-        }
-    }
-
-    fun onEntrySelected(selectedEntry: EntryInfo) {
-        val providerId = selectedEntry.providerId
-        val entryKey = selectedEntry.entryKey
-        val entrySubkey = selectedEntry.entrySubkey
-        Log.d(
-            Constants.LOG_TAG, "Option selected for entry: " +
-            " {provider=$providerId, key=$entryKey, subkey=$entrySubkey")
-        if (selectedEntry.pendingIntent != null) {
-            uiState = uiState.copy(
-                selectedEntry = selectedEntry,
-                providerActivityState = ProviderActivityState.READY_TO_LAUNCH,
-            )
-        } else {
-            credManRepo.onOptionSelected(
-                providerId,
-                entryKey,
-                entrySubkey
-            )
-            uiState = uiState.copy(dialogState = DialogState.COMPLETE)
-        }
-    }
-
-    fun launchProviderUi(
-        launcher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
-    ) {
-        val entry = uiState.selectedEntry
-        if (entry != null && entry.pendingIntent != null) {
-            uiState = uiState.copy(providerActivityState = ProviderActivityState.PENDING)
-            val intentSenderRequest = IntentSenderRequest.Builder(entry.pendingIntent)
-                .setFillInIntent(entry.fillInIntent).build()
-            launcher.launch(intentSenderRequest)
-        } else {
-            Log.d(Constants.LOG_TAG, "Unexpected: no provider UI to launch")
-            onInternalError()
-        }
-    }
-
-    fun onConfirmEntrySelected() {
-        val selectedEntry = uiState.activeEntry?.activeEntryInfo
-        if (selectedEntry != null) {
-            onEntrySelected(selectedEntry)
-        } else {
-            Log.d(Constants.LOG_TAG,
-                "Unexpected: confirm is pressed but no active entry exists.")
-            onInternalError()
-        }
-    }
-
-    fun onProviderActivityResult(providerActivityResult: ProviderActivityResult) {
-        val entry = uiState.selectedEntry
-        val resultCode = providerActivityResult.resultCode
-        val resultData = providerActivityResult.data
-        if (resultCode == Activity.RESULT_CANCELED) {
-            // Re-display the CredMan UI if the user canceled from the provider UI.
-            Log.d(Constants.LOG_TAG, "The provider activity was cancelled," +
-                " re-displaying our UI.")
-            uiState = uiState.copy(
-                selectedEntry = null,
-                providerActivityState = ProviderActivityState.NOT_APPLICABLE,
-            )
-        } else {
-            if (entry != null) {
-                val providerId = entry.providerId
-                Log.d(Constants.LOG_TAG, "Got provider activity result: {provider=" +
-                    "$providerId, key=${entry.entryKey}, subkey=${entry.entrySubkey}, " +
-                    "resultCode=$resultCode, resultData=$resultData}"
-                )
-                credManRepo.onOptionSelected(
-                    providerId, entry.entryKey, entry.entrySubkey, resultCode, resultData,
-                )
-                uiState = uiState.copy(dialogState = DialogState.COMPLETE)
-            } else {
-                Log.d(Constants.LOG_TAG,
-                    "Illegal state: received a provider result but found no matching entry.")
-                onInternalError()
-            }
-        }
-    }
-
-    companion object Factory {
-        // Validates the input and returns null if the input is invalid.
-        fun newInstance(
-            credManRepo: CredentialManagerRepo,
-            providerEnableListUiState: List<EnabledProviderInfo>,
-            providerDisableListUiState: List<DisabledProviderInfo>,
-            requestDisplayInfoUiState: RequestDisplayInfo?,
-        ): CreateCredentialViewModel? {
-            if (providerEnableListUiState.isEmpty() || requestDisplayInfoUiState == null) {
-                return null
-            }
-            return try {
-                val result = CreateCredentialViewModel(
-                    credManRepo = credManRepo,
-                    providerEnableListUiState = providerEnableListUiState,
-                    providerDisableListUiState = providerDisableListUiState,
-                    requestDisplayInfoUiState = requestDisplayInfoUiState
-                )
-                result
-            } catch (e: Exception) {
-                null
-            }
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index 12a5085..8d20564 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -19,8 +19,9 @@
 import android.app.PendingIntent
 import android.content.Intent
 import android.graphics.drawable.Drawable
-import com.android.credentialmanager.common.DialogState
-import com.android.credentialmanager.common.ProviderActivityState
+import com.android.credentialmanager.common.BaseEntry
+import com.android.credentialmanager.common.CredentialType
+import java.time.Instant
 
 data class CreateCredentialUiState(
   val enabledProviders: List<EnabledProviderInfo>,
@@ -32,11 +33,7 @@
   // we're showing provider selection page at the beginning
   val hasDefaultProvider: Boolean,
   val activeEntry: ActiveEntry? = null,
-  val selectedEntry: EntryInfo? = null,
-  val providerActivityState: ProviderActivityState =
-    ProviderActivityState.NOT_APPLICABLE,
   val isFromProviderSelection: Boolean? = null,
-  val dialogState: DialogState = DialogState.ACTIVE,
 )
 
 open class ProviderInfo(
@@ -59,28 +56,27 @@
   displayName: String,
 ) : ProviderInfo(icon, id, displayName)
 
-open class EntryInfo (
-  val providerId: String,
-  val entryKey: String,
-  val entrySubkey: String,
-  val pendingIntent: PendingIntent?,
-  val fillInIntent: Intent?,
-)
-
 class CreateOptionInfo(
-  providerId: String,
-  entryKey: String,
-  entrySubkey: String,
-  pendingIntent: PendingIntent?,
-  fillInIntent: Intent?,
-  val userProviderDisplayName: String?,
-  val profileIcon: Drawable?,
-  val passwordCount: Int?,
-  val passkeyCount: Int?,
-  val totalCredentialCount: Int?,
-  val lastUsedTimeMillis: Long?,
-  val footerDescription: String?,
-) : EntryInfo(providerId, entryKey, entrySubkey, pendingIntent, fillInIntent)
+    providerId: String,
+    entryKey: String,
+    entrySubkey: String,
+    pendingIntent: PendingIntent?,
+    fillInIntent: Intent?,
+    val userProviderDisplayName: String?,
+    val profileIcon: Drawable?,
+    val passwordCount: Int?,
+    val passkeyCount: Int?,
+    val totalCredentialCount: Int?,
+    val lastUsedTime: Instant?,
+    val footerDescription: String?,
+) : BaseEntry(
+    providerId,
+    entryKey,
+    entrySubkey,
+    pendingIntent,
+    fillInIntent,
+    shouldTerminateUiUponSuccessfulProviderResult = true,
+)
 
 class RemoteInfo(
   providerId: String,
@@ -88,12 +84,19 @@
   entrySubkey: String,
   pendingIntent: PendingIntent?,
   fillInIntent: Intent?,
-) : EntryInfo(providerId, entryKey, entrySubkey, pendingIntent, fillInIntent)
+) : BaseEntry(
+    providerId,
+    entryKey,
+    entrySubkey,
+    pendingIntent,
+    fillInIntent,
+    shouldTerminateUiUponSuccessfulProviderResult = true,
+)
 
 data class RequestDisplayInfo(
   val title: String,
   val subtitle: String?,
-  val type: String,
+  val type: CredentialType,
   val appName: String,
   val typeIcon: Drawable,
 )
@@ -104,7 +107,7 @@
  */
 data class ActiveEntry (
   val activeProvider: EnabledProviderInfo,
-  val activeEntryInfo: EntryInfo,
+  val activeEntryInfo: BaseEntry,
 )
 
 /** The name of the current screen. */
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index b30d1ec..48ee287 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -16,14 +16,12 @@
 
 package com.android.credentialmanager.getflow
 
-import android.credentials.Credential
 import android.text.TextUtils
 import androidx.activity.compose.ManagedActivityResultLauncher
 import androidx.activity.result.ActivityResult
 import androidx.activity.result.IntentSenderRequest
 
 import androidx.compose.foundation.Image
-import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
@@ -58,69 +56,64 @@
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.core.graphics.drawable.toBitmap
+import com.android.credentialmanager.CredentialSelectorViewModel
 import com.android.credentialmanager.R
+import com.android.credentialmanager.common.BaseEntry
+import com.android.credentialmanager.common.CredentialType
 import com.android.credentialmanager.common.ProviderActivityState
-import com.android.credentialmanager.common.material.ModalBottomSheetLayout
-import com.android.credentialmanager.common.material.ModalBottomSheetValue
-import com.android.credentialmanager.common.material.rememberModalBottomSheetState
 import com.android.credentialmanager.common.ui.ActionButton
 import com.android.credentialmanager.common.ui.ConfirmButton
 import com.android.credentialmanager.common.ui.Entry
+import com.android.credentialmanager.common.ui.ModalBottomSheet
 import com.android.credentialmanager.common.ui.TextOnSurface
 import com.android.credentialmanager.common.ui.TextSecondary
 import com.android.credentialmanager.common.ui.TextOnSurfaceVariant
 import com.android.credentialmanager.common.ui.ContainerCard
 import com.android.credentialmanager.common.ui.TransparentBackgroundEntry
-import com.android.credentialmanager.jetpack.developer.PublicKeyCredential
 import com.android.credentialmanager.ui.theme.EntryShape
 import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
 
 @Composable
 fun GetCredentialScreen(
-    viewModel: GetCredentialViewModel,
+    viewModel: CredentialSelectorViewModel,
+    getCredentialUiState: GetCredentialUiState,
     providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
 ) {
-    val state = rememberModalBottomSheetState(
-        initialValue = ModalBottomSheetValue.Expanded,
-        skipHalfExpanded = true
-    )
-    val uiState = viewModel.uiState
-    if (uiState.currentScreenState != GetScreenState.REMOTE_ONLY) {
-        ModalBottomSheetLayout(
-            sheetBackgroundColor = MaterialTheme.colorScheme.surface,
-            modifier = Modifier.background(Color.Transparent),
-            sheetState = state,
+    if (getCredentialUiState.currentScreenState != GetScreenState.REMOTE_ONLY) {
+        ModalBottomSheet(
             sheetContent = {
                 // Hide the sheet content as opposed to the whole bottom sheet to maintain the scrim
                 // background color even when the content should be hidden while waiting for
                 // results from the provider app.
-                when (uiState.providerActivityState) {
+                when (viewModel.uiState.providerActivityState) {
                     ProviderActivityState.NOT_APPLICABLE -> {
-                        if (uiState.currentScreenState == GetScreenState.PRIMARY_SELECTION) {
+                        if (getCredentialUiState.currentScreenState
+                            == GetScreenState.PRIMARY_SELECTION) {
                             PrimarySelectionCard(
-                                requestDisplayInfo = uiState.requestDisplayInfo,
-                                providerDisplayInfo = uiState.providerDisplayInfo,
-                                providerInfoList = uiState.providerInfoList,
-                                activeEntry = uiState.activeEntry,
-                                onEntrySelected = viewModel::onEntrySelected,
-                                onConfirm = viewModel::onConfirmEntrySelected,
-                                onMoreOptionSelected = viewModel::onMoreOptionSelected,
+                                requestDisplayInfo = getCredentialUiState.requestDisplayInfo,
+                                providerDisplayInfo = getCredentialUiState.providerDisplayInfo,
+                                providerInfoList = getCredentialUiState.providerInfoList,
+                                activeEntry = getCredentialUiState.activeEntry,
+                                onEntrySelected = viewModel::getFlowOnEntrySelected,
+                                onConfirm = viewModel::getFlowOnConfirmEntrySelected,
+                                onMoreOptionSelected = viewModel::getFlowOnMoreOptionSelected,
                             )
                         } else {
                             AllSignInOptionCard(
-                                providerInfoList = uiState.providerInfoList,
-                                providerDisplayInfo = uiState.providerDisplayInfo,
-                                onEntrySelected = viewModel::onEntrySelected,
-                                onBackButtonClicked = viewModel::onBackToPrimarySelectionScreen,
+                                providerInfoList = getCredentialUiState.providerInfoList,
+                                providerDisplayInfo = getCredentialUiState.providerDisplayInfo,
+                                onEntrySelected = viewModel::getFlowOnEntrySelected,
+                                onBackButtonClicked =
+                                viewModel::getFlowOnBackToPrimarySelectionScreen,
                                 onCancel = viewModel::onCancel,
-                                isNoAccount = uiState.isNoAccount,
+                                isNoAccount = getCredentialUiState.isNoAccount,
                             )
                         }
                     }
                     ProviderActivityState.READY_TO_LAUNCH -> {
                         // Launch only once per providerActivityState change so that the provider
                         // UI will not be accidentally launched twice.
-                        LaunchedEffect(uiState.providerActivityState) {
+                        LaunchedEffect(viewModel.uiState.providerActivityState) {
                             viewModel.launchProviderUi(providerActivityLauncher)
                         }
                     }
@@ -129,17 +122,11 @@
                     }
                 }
             },
-            scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
-            sheetShape = EntryShape.TopRoundedCorner,
-        ) {}
-        LaunchedEffect(state.currentValue) {
-            if (state.currentValue == ModalBottomSheetValue.Hidden) {
-                viewModel.onCancel()
-            }
-        }
+            onDismiss = viewModel::onCancel,
+        )
     } else {
         SnackBarScreen(
-            onClick = viewModel::onMoreOptionOnSnackBarSelected,
+            onClick = viewModel::getFlowOnMoreOptionOnSnackBarSelected,
             onCancel = viewModel::onCancel,
         )
     }
@@ -151,8 +138,8 @@
     requestDisplayInfo: RequestDisplayInfo,
     providerDisplayInfo: ProviderDisplayInfo,
     providerInfoList: List<ProviderInfo>,
-    activeEntry: EntryInfo?,
-    onEntrySelected: (EntryInfo) -> Unit,
+    activeEntry: BaseEntry?,
+    onEntrySelected: (BaseEntry) -> Unit,
     onConfirm: () -> Unit,
     onMoreOptionSelected: () -> Unit,
 ) {
@@ -171,7 +158,7 @@
                     ) {
                         if (sortedUserNameToCredentialEntryList.first()
                                 .sortedCredentialEntryList.first().credentialType
-                            == PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL
+                            == CredentialType.PASSKEY
                         ) R.string.get_dialog_title_use_passkey_for
                         else R.string.get_dialog_title_use_sign_in_for
                     } else if (
@@ -280,7 +267,7 @@
 fun AllSignInOptionCard(
     providerInfoList: List<ProviderInfo>,
     providerDisplayInfo: ProviderDisplayInfo,
-    onEntrySelected: (EntryInfo) -> Unit,
+    onEntrySelected: (BaseEntry) -> Unit,
     onBackButtonClicked: () -> Unit,
     onCancel: () -> Unit,
     isNoAccount: Boolean,
@@ -379,7 +366,7 @@
 @Composable
 fun ActionChips(
     providerInfoList: List<ProviderInfo>,
-    onEntrySelected: (EntryInfo) -> Unit,
+    onEntrySelected: (BaseEntry) -> Unit,
 ) {
     val actionChips = providerInfoList.flatMap { it.actionEntryList }
     if (actionChips.isEmpty()) {
@@ -407,7 +394,7 @@
 @Composable
 fun RemoteEntryCard(
     remoteEntry: RemoteEntryInfo,
-    onEntrySelected: (EntryInfo) -> Unit,
+    onEntrySelected: (BaseEntry) -> Unit,
 ) {
     TextSecondary(
         text = stringResource(R.string.get_dialog_heading_from_another_device),
@@ -449,7 +436,7 @@
 @Composable
 fun LockedCredentials(
     authenticationEntryList: List<AuthenticationEntryInfo>,
-    onEntrySelected: (EntryInfo) -> Unit,
+    onEntrySelected: (BaseEntry) -> Unit,
 ) {
     TextSecondary(
         text = stringResource(R.string.get_dialog_heading_locked_password_managers),
@@ -474,7 +461,7 @@
 @Composable
 fun PerUserNameCredentials(
     perUserNameCredentialEntryList: PerUserNameCredentialEntryList,
-    onEntrySelected: (EntryInfo) -> Unit,
+    onEntrySelected: (BaseEntry) -> Unit,
 ) {
     TextSecondary(
         text = stringResource(
@@ -502,7 +489,7 @@
 @Composable
 fun CredentialEntryRow(
     credentialEntryInfo: CredentialEntryInfo,
-    onEntrySelected: (EntryInfo) -> Unit,
+    onEntrySelected: (BaseEntry) -> Unit,
 ) {
     Entry(
         onClick = { onEntrySelected(credentialEntryInfo) },
@@ -534,7 +521,7 @@
                 )
                 TextSecondary(
                     text = if (
-                        credentialEntryInfo.credentialType == Credential.TYPE_PASSWORD_CREDENTIAL) {
+                        credentialEntryInfo.credentialType == CredentialType.PASSWORD) {
                         "••••••••••••"
                     } else {
                         if (TextUtils.isEmpty(credentialEntryInfo.displayName))
@@ -558,7 +545,7 @@
 @Composable
 fun AuthenticationEntryRow(
     authenticationEntryInfo: AuthenticationEntryInfo,
-    onEntrySelected: (EntryInfo) -> Unit,
+    onEntrySelected: (BaseEntry) -> Unit,
 ) {
     Entry(
         onClick = { onEntrySelected(authenticationEntryInfo) },
@@ -602,7 +589,7 @@
 @Composable
 fun ActionEntryRow(
     actionEntryInfo: ActionEntryInfo,
-    onEntrySelected: (EntryInfo) -> Unit,
+    onEntrySelected: (BaseEntry) -> Unit,
 ) {
     TransparentBackgroundEntry(
         icon = {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
deleted file mode 100644
index 7d2f0da..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.getflow
-
-import android.app.Activity
-import android.util.Log
-import androidx.activity.compose.ManagedActivityResultLauncher
-import androidx.activity.result.ActivityResult
-import androidx.activity.result.IntentSenderRequest
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.lifecycle.ViewModel
-import com.android.credentialmanager.CredentialManagerRepo
-import com.android.credentialmanager.common.Constants
-import com.android.credentialmanager.common.DialogState
-import com.android.credentialmanager.common.ProviderActivityResult
-import com.android.credentialmanager.common.ProviderActivityState
-import com.android.credentialmanager.jetpack.developer.PublicKeyCredential
-import com.android.internal.util.Preconditions
-
-data class GetCredentialUiState(
-    val providerInfoList: List<ProviderInfo>,
-    val requestDisplayInfo: RequestDisplayInfo,
-    val currentScreenState: GetScreenState = toGetScreenState(providerInfoList),
-    val providerDisplayInfo: ProviderDisplayInfo = toProviderDisplayInfo(providerInfoList),
-    val selectedEntry: EntryInfo? = null,
-    val activeEntry: EntryInfo? = toActiveEntry(providerDisplayInfo),
-    val providerActivityState: ProviderActivityState =
-        ProviderActivityState.NOT_APPLICABLE,
-    val isNoAccount: Boolean = false,
-    val dialogState: DialogState = DialogState.ACTIVE,
-)
-
-class GetCredentialViewModel(
-    private val credManRepo: CredentialManagerRepo,
-    initialUiState: GetCredentialUiState,
-) : ViewModel() {
-
-    var uiState by mutableStateOf(initialUiState)
-        private set
-
-    fun onEntrySelected(entry: EntryInfo) {
-        Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" +
-            ", key=${entry.entryKey}, subkey=${entry.entrySubkey}}")
-        if (entry.pendingIntent != null) {
-            uiState = uiState.copy(
-                selectedEntry = entry,
-                providerActivityState = ProviderActivityState.READY_TO_LAUNCH,
-            )
-        } else {
-            credManRepo.onOptionSelected(entry.providerId, entry.entryKey, entry.entrySubkey)
-            uiState = uiState.copy(dialogState = DialogState.COMPLETE)
-        }
-    }
-
-    fun onConfirmEntrySelected() {
-        val activeEntry = uiState.activeEntry
-        if (activeEntry != null) {
-            onEntrySelected(activeEntry)
-        } else {
-            Log.d(Constants.LOG_TAG,
-                "Illegal state: confirm is pressed but activeEntry isn't set.")
-            onInternalError()
-        }
-    }
-
-    fun launchProviderUi(
-        launcher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
-    ) {
-        val entry = uiState.selectedEntry
-        if (entry != null && entry.pendingIntent != null) {
-            Log.d(Constants.LOG_TAG, "Launching provider activity")
-            uiState = uiState.copy(providerActivityState = ProviderActivityState.PENDING)
-            val intentSenderRequest = IntentSenderRequest.Builder(entry.pendingIntent)
-                .setFillInIntent(entry.fillInIntent).build()
-            launcher.launch(intentSenderRequest)
-        } else {
-            Log.d(Constants.LOG_TAG, "No provider UI to launch")
-            onInternalError()
-        }
-    }
-
-    // When the view model runs into unexpected illegal state, reports the error back and close
-    // the activity gracefully.
-    private fun onInternalError() {
-        Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state")
-        credManRepo.onParsingFailureCancel()
-        uiState = uiState.copy(dialogState = DialogState.COMPLETE)
-    }
-
-    fun onProviderActivityResult(providerActivityResult: ProviderActivityResult) {
-        val entry = uiState.selectedEntry
-        val resultCode = providerActivityResult.resultCode
-        val resultData = providerActivityResult.data
-        if (resultCode == Activity.RESULT_CANCELED) {
-            // Re-display the CredMan UI if the user canceled from the provider UI.
-            Log.d(Constants.LOG_TAG, "The provider activity was cancelled," +
-                " re-displaying our UI.")
-            uiState = uiState.copy(
-                selectedEntry = null,
-                providerActivityState = ProviderActivityState.NOT_APPLICABLE,
-            )
-        } else {
-            if (entry != null) {
-                Log.d(
-                    Constants.LOG_TAG, "Got provider activity result: {provider=" +
-                    "${entry.providerId}, key=${entry.entryKey}, subkey=${entry.entrySubkey}" +
-                    ", resultCode=$resultCode, resultData=$resultData}"
-                )
-                credManRepo.onOptionSelected(
-                    entry.providerId, entry.entryKey, entry.entrySubkey,
-                    resultCode, resultData,
-                )
-                uiState = uiState.copy(dialogState = DialogState.COMPLETE)
-            } else {
-                Log.w(Constants.LOG_TAG,
-                    "Illegal state: received a provider result but found no matching entry.")
-                onInternalError()
-            }
-        }
-    }
-
-    fun onMoreOptionSelected() {
-        Log.d(Constants.LOG_TAG, "More Option selected")
-        uiState = uiState.copy(
-            currentScreenState = GetScreenState.ALL_SIGN_IN_OPTIONS
-        )
-    }
-
-    fun onMoreOptionOnSnackBarSelected(isNoAccount: Boolean) {
-        Log.d(Constants.LOG_TAG, "More Option on snackBar selected")
-        uiState = uiState.copy(
-            currentScreenState = GetScreenState.ALL_SIGN_IN_OPTIONS,
-            isNoAccount = isNoAccount,
-        )
-    }
-
-    fun onBackToPrimarySelectionScreen() {
-        uiState = uiState.copy(
-            currentScreenState = GetScreenState.PRIMARY_SELECTION
-        )
-    }
-
-    fun onCancel() {
-        credManRepo.onUserCancel()
-        uiState = uiState.copy(dialogState = DialogState.COMPLETE)
-    }
-}
-
-private fun toProviderDisplayInfo(
-    providerInfoList: List<ProviderInfo>
-): ProviderDisplayInfo {
-
-    val userNameToCredentialEntryMap = mutableMapOf<String, MutableList<CredentialEntryInfo>>()
-    val authenticationEntryList = mutableListOf<AuthenticationEntryInfo>()
-    val remoteEntryList = mutableListOf<RemoteEntryInfo>()
-    providerInfoList.forEach { providerInfo ->
-        if (providerInfo.authenticationEntry != null) {
-            authenticationEntryList.add(providerInfo.authenticationEntry)
-        }
-        if (providerInfo.remoteEntry != null) {
-            remoteEntryList.add(providerInfo.remoteEntry)
-        }
-
-        providerInfo.credentialEntryList.forEach {
-            userNameToCredentialEntryMap.compute(
-                it.userName
-            ) { _, v ->
-                if (v == null) {
-                    mutableListOf(it)
-                } else {
-                    v.add(it)
-                    v
-                }
-            }
-        }
-    }
-    // There can only be at most one remote entry
-    // TODO: fail elegantly
-    Preconditions.checkState(remoteEntryList.size <= 1)
-
-    // Compose sortedUserNameToCredentialEntryList
-    val comparator = CredentialEntryInfoComparatorByTypeThenTimestamp()
-    // Sort per username
-    userNameToCredentialEntryMap.values.forEach {
-        it.sortWith(comparator)
-    }
-    // Transform to list of PerUserNameCredentialEntryLists and then sort across usernames
-    val sortedUserNameToCredentialEntryList = userNameToCredentialEntryMap.map {
-        PerUserNameCredentialEntryList(it.key, it.value)
-    }.sortedWith(
-        compareByDescending { it.sortedCredentialEntryList.first().lastUsedTimeMillis }
-    )
-
-    return ProviderDisplayInfo(
-        sortedUserNameToCredentialEntryList = sortedUserNameToCredentialEntryList,
-        authenticationEntryList = authenticationEntryList,
-        remoteEntry = remoteEntryList.getOrNull(0),
-    )
-}
-
-private fun toActiveEntry(
-    providerDisplayInfo: ProviderDisplayInfo,
-): EntryInfo? {
-    val sortedUserNameToCredentialEntryList =
-        providerDisplayInfo.sortedUserNameToCredentialEntryList
-    val authenticationEntryList = providerDisplayInfo.authenticationEntryList
-    var activeEntry: EntryInfo? = null
-    if (sortedUserNameToCredentialEntryList
-            .size == 1 && authenticationEntryList.isEmpty()
-    ) {
-        activeEntry = sortedUserNameToCredentialEntryList.first().sortedCredentialEntryList.first()
-    } else if (
-        sortedUserNameToCredentialEntryList
-            .isEmpty() && authenticationEntryList.size == 1
-    ) {
-        activeEntry = authenticationEntryList.first()
-    }
-    return activeEntry
-}
-
-private fun toGetScreenState(
-    providerInfoList: List<ProviderInfo>
-): GetScreenState {
-    var noLocalAccount = true
-    var remoteInfo: RemoteEntryInfo? = null
-    providerInfoList.forEach { providerInfo ->
-        if (providerInfo.credentialEntryList.isNotEmpty() ||
-            providerInfo.authenticationEntry != null) {
-            noLocalAccount = false
-        }
-        // TODO: handle the error situation that if multiple remoteInfos exists
-        if (providerInfo.remoteEntry != null) {
-            remoteInfo = providerInfo.remoteEntry
-        }
-    }
-
-    return if (noLocalAccount && remoteInfo != null)
-        GetScreenState.REMOTE_ONLY else GetScreenState.PRIMARY_SELECTION
-}
-
-internal class CredentialEntryInfoComparatorByTypeThenTimestamp : Comparator<CredentialEntryInfo> {
-    override fun compare(p0: CredentialEntryInfo, p1: CredentialEntryInfo): Int {
-        // First prefer passkey type for its security benefits
-        if (p0.credentialType != p1.credentialType) {
-            if (PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL == p0.credentialType) {
-                return -1
-            } else if (PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL == p1.credentialType) {
-                return 1
-            }
-        }
-
-        // Then order by last used timestamp
-        if (p0.lastUsedTimeMillis != null && p1.lastUsedTimeMillis != null) {
-            if (p0.lastUsedTimeMillis < p1.lastUsedTimeMillis) {
-                return 1
-            } else if (p0.lastUsedTimeMillis > p1.lastUsedTimeMillis) {
-                return -1
-            }
-        } else if (p0.lastUsedTimeMillis != null && p0.lastUsedTimeMillis > 0) {
-            return -1
-        } else if (p1.lastUsedTimeMillis != null && p1.lastUsedTimeMillis > 0) {
-            return 1
-        }
-        return 0
-    }
-}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index 8ce31bd..bca06c7 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -19,89 +19,121 @@
 import android.app.PendingIntent
 import android.content.Intent
 import android.graphics.drawable.Drawable
+import com.android.credentialmanager.common.BaseEntry
+import com.android.credentialmanager.common.CredentialType
+import com.android.internal.util.Preconditions
+
+import java.time.Instant
+
+data class GetCredentialUiState(
+    val providerInfoList: List<ProviderInfo>,
+    val requestDisplayInfo: RequestDisplayInfo,
+    val currentScreenState: GetScreenState = toGetScreenState(providerInfoList),
+    val providerDisplayInfo: ProviderDisplayInfo = toProviderDisplayInfo(providerInfoList),
+    val activeEntry: BaseEntry? = toActiveEntry(providerDisplayInfo),
+    val isNoAccount: Boolean = false,
+)
 
 data class ProviderInfo(
-  /**
-   * Unique id (component name) of this provider.
-   * Not for display purpose - [displayName] should be used for ui rendering.
-   */
-  val id: String,
-  val icon: Drawable,
-  val displayName: String,
-  val credentialEntryList: List<CredentialEntryInfo>,
-  val authenticationEntry: AuthenticationEntryInfo?,
-  val remoteEntry: RemoteEntryInfo?,
-  val actionEntryList: List<ActionEntryInfo>,
+    /**
+     * Unique id (component name) of this provider.
+     * Not for display purpose - [displayName] should be used for ui rendering.
+     */
+    val id: String,
+    val icon: Drawable,
+    val displayName: String,
+    val credentialEntryList: List<CredentialEntryInfo>,
+    val authenticationEntryList: List<AuthenticationEntryInfo>,
+    val remoteEntry: RemoteEntryInfo?,
+    val actionEntryList: List<ActionEntryInfo>,
 )
 
 /** Display-centric data structure derived from the [ProviderInfo]. This abstraction is not grouping
  *  by the provider id but instead focuses on structures convenient for display purposes. */
 data class ProviderDisplayInfo(
-  /**
-   * The credential entries grouped by userName, derived from all entries of the [providerInfoList].
-   * Note that the list order matters to the display order.
-   */
-  val sortedUserNameToCredentialEntryList: List<PerUserNameCredentialEntryList>,
-  val authenticationEntryList: List<AuthenticationEntryInfo>,
-  val remoteEntry: RemoteEntryInfo?
-)
-
-abstract class EntryInfo (
-  /** Unique id combination of this entry. Not for display purpose. */
-  val providerId: String,
-  val entryKey: String,
-  val entrySubkey: String,
-  val pendingIntent: PendingIntent?,
-  val fillInIntent: Intent?,
+    /**
+     * The credential entries grouped by userName, derived from all entries of the [providerInfoList].
+     * Note that the list order matters to the display order.
+     */
+    val sortedUserNameToCredentialEntryList: List<PerUserNameCredentialEntryList>,
+    val authenticationEntryList: List<AuthenticationEntryInfo>,
+    val remoteEntry: RemoteEntryInfo?
 )
 
 class CredentialEntryInfo(
-  providerId: String,
-  entryKey: String,
-  entrySubkey: String,
-  pendingIntent: PendingIntent?,
-  fillInIntent: Intent?,
-  /** Type of this credential used for sorting. Not localized so must not be directly displayed. */
-  val credentialType: String,
-  /** Localized type value of this credential used for display purpose. */
-  val credentialTypeDisplayName: String,
-  val userName: String,
-  val displayName: String?,
-  val icon: Drawable?,
-  val lastUsedTimeMillis: Long?,
-) : EntryInfo(providerId, entryKey, entrySubkey, pendingIntent, fillInIntent)
+    providerId: String,
+    entryKey: String,
+    entrySubkey: String,
+    pendingIntent: PendingIntent?,
+    fillInIntent: Intent?,
+    /** Type of this credential used for sorting. Not localized so must not be directly displayed. */
+    val credentialType: CredentialType,
+    /** Localized type value of this credential used for display purpose. */
+    val credentialTypeDisplayName: String,
+    val userName: String,
+    val displayName: String?,
+    val icon: Drawable?,
+    val lastUsedTimeMillis: Instant?,
+) : BaseEntry(
+    providerId,
+    entryKey,
+    entrySubkey,
+    pendingIntent,
+    fillInIntent,
+    shouldTerminateUiUponSuccessfulProviderResult = true,
+)
 
 class AuthenticationEntryInfo(
-  providerId: String,
-  entryKey: String,
-  entrySubkey: String,
-  pendingIntent: PendingIntent?,
-  fillInIntent: Intent?,
-  val title: String,
-  val icon: Drawable,
-) : EntryInfo(providerId, entryKey, entrySubkey, pendingIntent, fillInIntent)
+    providerId: String,
+    entryKey: String,
+    entrySubkey: String,
+    pendingIntent: PendingIntent?,
+    fillInIntent: Intent?,
+    val title: String,
+    val icon: Drawable,
+) : BaseEntry(
+    providerId,
+    entryKey, entrySubkey,
+    pendingIntent,
+    fillInIntent,
+    shouldTerminateUiUponSuccessfulProviderResult = false,
+)
 
 class RemoteEntryInfo(
-  providerId: String,
-  entryKey: String,
-  entrySubkey: String,
-  pendingIntent: PendingIntent?,
-  fillInIntent: Intent?,
-) : EntryInfo(providerId, entryKey, entrySubkey, pendingIntent, fillInIntent)
+    providerId: String,
+    entryKey: String,
+    entrySubkey: String,
+    pendingIntent: PendingIntent?,
+    fillInIntent: Intent?,
+) : BaseEntry(
+    providerId,
+    entryKey,
+    entrySubkey,
+    pendingIntent,
+    fillInIntent,
+    shouldTerminateUiUponSuccessfulProviderResult = true,
+)
 
 class ActionEntryInfo(
-  providerId: String,
-  entryKey: String,
-  entrySubkey: String,
-  pendingIntent: PendingIntent?,
-  fillInIntent: Intent?,
-  val title: String,
-  val icon: Drawable,
-  val subTitle: String?,
-) : EntryInfo(providerId, entryKey, entrySubkey, pendingIntent, fillInIntent)
+    providerId: String,
+    entryKey: String,
+    entrySubkey: String,
+    pendingIntent: PendingIntent?,
+    fillInIntent: Intent?,
+    val title: String,
+    val icon: Drawable,
+    val subTitle: String?,
+) : BaseEntry(
+    providerId,
+    entryKey,
+    entrySubkey,
+    pendingIntent,
+    fillInIntent,
+    shouldTerminateUiUponSuccessfulProviderResult = false,
+)
 
 data class RequestDisplayInfo(
-  val appName: String,
+    val appName: String,
 )
 
 /**
@@ -110,16 +142,135 @@
  *                                     by last used timestamps and then by credential types
  */
 data class PerUserNameCredentialEntryList(
-  val userName: String,
-  val sortedCredentialEntryList: List<CredentialEntryInfo>,
+    val userName: String,
+    val sortedCredentialEntryList: List<CredentialEntryInfo>,
 )
 
 /** The name of the current screen. */
 enum class GetScreenState {
-  /** The primary credential selection page. */
-  PRIMARY_SELECTION,
-  /** The secondary credential selection page, where all sign-in options are listed. */
-  ALL_SIGN_IN_OPTIONS,
-  /** The snackbar only page when there's no account but only a remoteEntry. */
-  REMOTE_ONLY,
+    /** The primary credential selection page. */
+    PRIMARY_SELECTION,
+
+    /** The secondary credential selection page, where all sign-in options are listed. */
+    ALL_SIGN_IN_OPTIONS,
+
+    /** The snackbar only page when there's no account but only a remoteEntry. */
+    REMOTE_ONLY,
 }
+
+// IMPORTANT: new invocation should be mindful that this method will throw if more than 1 remote
+// entry exists
+private fun toProviderDisplayInfo(
+    providerInfoList: List<ProviderInfo>
+): ProviderDisplayInfo {
+
+    val userNameToCredentialEntryMap = mutableMapOf<String, MutableList<CredentialEntryInfo>>()
+    val authenticationEntryList = mutableListOf<AuthenticationEntryInfo>()
+    val remoteEntryList = mutableListOf<RemoteEntryInfo>()
+    providerInfoList.forEach { providerInfo ->
+        authenticationEntryList.addAll(providerInfo.authenticationEntryList)
+        if (providerInfo.remoteEntry != null) {
+            remoteEntryList.add(providerInfo.remoteEntry)
+        }
+        // There can only be at most one remote entry
+        Preconditions.checkState(remoteEntryList.size <= 1)
+
+        providerInfo.credentialEntryList.forEach {
+            userNameToCredentialEntryMap.compute(
+                it.userName
+            ) { _, v ->
+                if (v == null) {
+                    mutableListOf(it)
+                } else {
+                    v.add(it)
+                    v
+                }
+            }
+        }
+    }
+
+    // Compose sortedUserNameToCredentialEntryList
+    val comparator = CredentialEntryInfoComparatorByTypeThenTimestamp()
+    // Sort per username
+    userNameToCredentialEntryMap.values.forEach {
+        it.sortWith(comparator)
+    }
+    // Transform to list of PerUserNameCredentialEntryLists and then sort across usernames
+    val sortedUserNameToCredentialEntryList = userNameToCredentialEntryMap.map {
+        PerUserNameCredentialEntryList(it.key, it.value)
+    }.sortedWith(
+        compareByDescending { it.sortedCredentialEntryList.first().lastUsedTimeMillis }
+    )
+
+    return ProviderDisplayInfo(
+        sortedUserNameToCredentialEntryList = sortedUserNameToCredentialEntryList,
+        authenticationEntryList = authenticationEntryList,
+        remoteEntry = remoteEntryList.getOrNull(0),
+    )
+}
+
+private fun toActiveEntry(
+    providerDisplayInfo: ProviderDisplayInfo,
+): BaseEntry? {
+    val sortedUserNameToCredentialEntryList =
+        providerDisplayInfo.sortedUserNameToCredentialEntryList
+    val authenticationEntryList = providerDisplayInfo.authenticationEntryList
+    var activeEntry: BaseEntry? = null
+    if (sortedUserNameToCredentialEntryList
+            .size == 1 && authenticationEntryList.isEmpty()
+    ) {
+        activeEntry = sortedUserNameToCredentialEntryList.first().sortedCredentialEntryList.first()
+    } else if (
+        sortedUserNameToCredentialEntryList
+            .isEmpty() && authenticationEntryList.size == 1
+    ) {
+        activeEntry = authenticationEntryList.first()
+    }
+    return activeEntry
+}
+
+private fun toGetScreenState(
+    providerInfoList: List<ProviderInfo>
+): GetScreenState {
+    var noLocalAccount = true
+    var remoteInfo: RemoteEntryInfo? = null
+    providerInfoList.forEach { providerInfo ->
+        if (providerInfo.credentialEntryList.isNotEmpty() ||
+            providerInfo.authenticationEntryList.isNotEmpty()) {
+            noLocalAccount = false
+        }
+        if (providerInfo.remoteEntry != null) {
+            remoteInfo = providerInfo.remoteEntry
+        }
+    }
+
+    return if (noLocalAccount && remoteInfo != null)
+        GetScreenState.REMOTE_ONLY else GetScreenState.PRIMARY_SELECTION
+}
+
+internal class CredentialEntryInfoComparatorByTypeThenTimestamp : Comparator<CredentialEntryInfo> {
+    override fun compare(p0: CredentialEntryInfo, p1: CredentialEntryInfo): Int {
+        // First prefer passkey type for its security benefits
+        if (p0.credentialType != p1.credentialType) {
+            if (CredentialType.PASSKEY == p0.credentialType) {
+                return -1
+            } else if (CredentialType.PASSKEY == p1.credentialType) {
+                return 1
+            }
+        }
+
+        // Then order by last used timestamp
+        if (p0.lastUsedTimeMillis != null && p1.lastUsedTimeMillis != null) {
+            if (p0.lastUsedTimeMillis < p1.lastUsedTimeMillis) {
+                return 1
+            } else if (p0.lastUsedTimeMillis > p1.lastUsedTimeMillis) {
+                return -1
+            }
+        } else if (p0.lastUsedTimeMillis != null) {
+            return -1
+        } else if (p1.lastUsedTimeMillis != null) {
+            return 1
+        }
+        return 0
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreateCredentialRequest.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreateCredentialRequest.kt
deleted file mode 100644
index eaa2ad4..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreateCredentialRequest.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.credentials.Credential
-import android.os.Bundle
-import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.BUNDLE_KEY_SUBTYPE
-
-/**
- * Base request class for registering a credential.
- *
- * @property type the credential type
- * @property data the request data in the [Bundle] format
- * @property requireSystemProvider true if must only be fulfilled by a system provider and false
- *                              otherwise
- */
-open class CreateCredentialRequest(
-    open val type: String,
-    open val credentialData: Bundle,
-    open val candidateQueryData: Bundle,
-    open val requireSystemProvider: Boolean
-) {
-    companion object {
-        @JvmStatic
-        fun createFrom(
-            type: String,
-            credentialData: Bundle,
-            candidateQueryData: Bundle,
-            requireSystemProvider: Boolean
-        ): CreateCredentialRequest {
-            return try {
-                when (type) {
-                    Credential.TYPE_PASSWORD_CREDENTIAL ->
-                        CreatePasswordRequest.createFrom(credentialData)
-                    PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL ->
-                        when (credentialData.getString(BUNDLE_KEY_SUBTYPE)) {
-                            CreatePublicKeyCredentialRequest
-                                .BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST ->
-                                CreatePublicKeyCredentialRequest.createFrom(credentialData)
-                            CreatePublicKeyCredentialRequestPrivileged
-                                .BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST_PRIV ->
-                                CreatePublicKeyCredentialRequestPrivileged
-                                    .createFrom(credentialData)
-                            else -> throw FrameworkClassParsingException()
-                        }
-                    else -> throw FrameworkClassParsingException()
-                }
-            } catch (e: FrameworkClassParsingException) {
-                // Parsing failed but don't crash the process. Instead just output a request with
-                // the raw framework values.
-                CreateCustomCredentialRequest(
-                    type,
-                    credentialData,
-                    candidateQueryData,
-                    requireSystemProvider
-                )
-            }
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreateCustomCredentialRequest.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreateCustomCredentialRequest.kt
deleted file mode 100644
index 50da9a1..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreateCustomCredentialRequest.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.credentialmanager.jetpack.developer
-
-import android.os.Bundle
-
-/**
- * Base custom create request class for registering a credential.
- *
- * An application can construct a subtype custom request and call
- * [CredentialManager.executeCreateCredential] to launch framework UI flows to collect consent and
- * any other metadata needed from the user to register a new user credential.
- *
- * @property type the credential type determined by the credential-type-specific subclass for custom
- * use cases
- * @property credentialData the full credential creation request data in the [Bundle] format for
- * custom use cases
- * @property candidateQueryData the partial request data in the [Bundle] format that will be sent to
- * the provider during the initial candidate query stage, which should not contain sensitive user
- * credential information
- * @property requireSystemProvider true if must only be fulfilled by a system provider and false
- * otherwise
- * @throws IllegalArgumentException If [type] is empty
- * @throws NullPointerException If [type] or [credentialData] are null
- */
-open class CreateCustomCredentialRequest(
-    final override val type: String,
-    final override val credentialData: Bundle,
-    final override val candidateQueryData: Bundle,
-    @get:JvmName("requireSystemProvider")
-    final override val requireSystemProvider: Boolean
-) : CreateCredentialRequest(type, credentialData, candidateQueryData, requireSystemProvider) {
-    init {
-        require(type.isNotEmpty()) { "type should not be empty" }
-    }
-}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreatePasswordRequest.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreatePasswordRequest.kt
deleted file mode 100644
index bf0aa8a..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreatePasswordRequest.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.credentials.Credential
-import android.os.Bundle
-
-/**
- * A request to save the user password credential with their password provider.
- *
- * @property id the user id associated with the password
- * @property password the password
- * @throws NullPointerException If [id] is null
- * @throws NullPointerException If [password] is null
- * @throws IllegalArgumentException If [password] is empty
- */
-class CreatePasswordRequest constructor(
-        val id: String,
-        val password: String,
-) : CreateCredentialRequest(
-        type = Credential.TYPE_PASSWORD_CREDENTIAL,
-        credentialData = toCredentialDataBundle(id, password),
-        // No credential data should be sent during the query phase.
-        candidateQueryData = Bundle(),
-        requireSystemProvider = false,
-) {
-
-    init {
-        require(password.isNotEmpty()) { "password should not be empty" }
-    }
-
-    companion object {
-        const val BUNDLE_KEY_ID = "androidx.credentials.BUNDLE_KEY_ID"
-        const val BUNDLE_KEY_PASSWORD = "androidx.credentials.BUNDLE_KEY_PASSWORD"
-
-        @JvmStatic
-        internal fun toCredentialDataBundle(id: String, password: String): Bundle {
-            val bundle = Bundle()
-            bundle.putString(BUNDLE_KEY_ID, id)
-            bundle.putString(BUNDLE_KEY_PASSWORD, password)
-            return bundle
-        }
-
-        @JvmStatic
-        internal fun toCandidateDataBundle(id: String): Bundle {
-            val bundle = Bundle()
-            bundle.putString(BUNDLE_KEY_ID, id)
-            return bundle
-        }
-
-        @JvmStatic
-        internal fun createFrom(data: Bundle): CreatePasswordRequest {
-            try {
-                val id = data.getString(BUNDLE_KEY_ID)
-                val password = data.getString(BUNDLE_KEY_PASSWORD)
-                return CreatePasswordRequest(id!!, password!!)
-            } catch (e: Exception) {
-                throw FrameworkClassParsingException()
-            }
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreatePublicKeyCredentialRequest.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreatePublicKeyCredentialRequest.kt
deleted file mode 100644
index f3d402a..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreatePublicKeyCredentialRequest.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.os.Bundle
-import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.BUNDLE_KEY_SUBTYPE
-
-/**
-* A request to register a passkey from the user's public key credential provider.
-*
-* @property requestJson the privileged request in JSON format in the standard webauthn web json
-* shown [here](https://w3c.github.io/webauthn/#dictdef-publickeycredentialrequestoptionsjson).
-* @property preferImmediatelyAvailableCredentials true if you prefer the operation to return
-* immediately when there is no available passkey registration offering instead of falling back to
-* discovering remote options, and false (default) otherwise
-* @throws NullPointerException If [requestJson] is null
-* @throws IllegalArgumentException If [requestJson] is empty
-*/
-class CreatePublicKeyCredentialRequest @JvmOverloads constructor(
-    val requestJson: String,
-    @get:JvmName("preferImmediatelyAvailableCredentials")
-    val preferImmediatelyAvailableCredentials: Boolean = false
-) : CreateCredentialRequest(
-    type = PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL,
-    credentialData = toCredentialDataBundle(requestJson, preferImmediatelyAvailableCredentials),
-    // The whole request data should be passed during the query phase.
-    candidateQueryData = toCredentialDataBundle(requestJson, preferImmediatelyAvailableCredentials),
-    requireSystemProvider = false,
-) {
-
-    init {
-        require(requestJson.isNotEmpty()) { "requestJson must not be empty" }
-    }
-
-    /** @hide */
-    companion object {
-        const val BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS =
-            "androidx.credentials.BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS"
-        internal const val BUNDLE_KEY_REQUEST_JSON = "androidx.credentials.BUNDLE_KEY_REQUEST_JSON"
-        internal const val BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST =
-            "androidx.credentials.BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST"
-
-        @JvmStatic
-        internal fun toCredentialDataBundle(
-            requestJson: String,
-            preferImmediatelyAvailableCredentials: Boolean
-        ): Bundle {
-            val bundle = Bundle()
-            bundle.putString(BUNDLE_KEY_SUBTYPE,
-                BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST)
-            bundle.putString(BUNDLE_KEY_REQUEST_JSON, requestJson)
-            bundle.putBoolean(BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS,
-                preferImmediatelyAvailableCredentials)
-            return bundle
-        }
-
-        @JvmStatic
-        internal fun toCandidateDataBundle(
-            requestJson: String,
-            preferImmediatelyAvailableCredentials: Boolean
-        ): Bundle {
-            val bundle = Bundle()
-            bundle.putString(BUNDLE_KEY_SUBTYPE,
-                BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST)
-            bundle.putString(BUNDLE_KEY_REQUEST_JSON, requestJson)
-            bundle.putBoolean(BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS,
-                preferImmediatelyAvailableCredentials)
-            return bundle
-        }
-
-        @Suppress("deprecation") // bundle.get() used for boolean value to prevent default
-        // boolean value from being returned.
-        @JvmStatic
-        internal fun createFrom(data: Bundle): CreatePublicKeyCredentialRequest {
-            try {
-                val requestJson = data.getString(BUNDLE_KEY_REQUEST_JSON)
-                val preferImmediatelyAvailableCredentials =
-                    data.get(BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS)
-                return CreatePublicKeyCredentialRequest(requestJson!!,
-                    (preferImmediatelyAvailableCredentials!!) as Boolean)
-            } catch (e: Exception) {
-                throw FrameworkClassParsingException()
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreatePublicKeyCredentialRequestPrivileged.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreatePublicKeyCredentialRequestPrivileged.kt
deleted file mode 100644
index 85ab2d2..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/CreatePublicKeyCredentialRequestPrivileged.kt
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.os.Bundle
-import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.BUNDLE_KEY_SUBTYPE
-
-/**
- * A privileged request to register a passkey from the user’s public key credential provider, where
- * the caller can modify the rp. Only callers with privileged permission, e.g. user’s default
- * brower, caBLE, can use this. These permissions will be introduced in an upcoming release.
- * TODO("Add specific permission info/annotation")
- *
- * @property requestJson the privileged request in JSON format in the standard webauthn web json
- * shown [here](https://w3c.github.io/webauthn/#dictdef-publickeycredentialrequestoptionsjson).
- * @property preferImmediatelyAvailableCredentials true if you prefer the operation to return
- * immediately when there is no available passkey registration offering instead of falling back to
- * discovering remote options, and false (default) otherwise
- * @property relyingParty the expected true RP ID which will override the one in the [requestJson],
- * where rp is defined [here](https://w3c.github.io/webauthn/#rp-id)
- * @property clientDataHash a hash that is used to verify the [relyingParty] Identity
- * @throws NullPointerException If any of [requestJson], [relyingParty], or [clientDataHash] is
- * null
- * @throws IllegalArgumentException If any of [requestJson], [relyingParty], or [clientDataHash] is
- * empty
- */
-class CreatePublicKeyCredentialRequestPrivileged @JvmOverloads constructor(
-    val requestJson: String,
-    val relyingParty: String,
-    val clientDataHash: String,
-    @get:JvmName("preferImmediatelyAvailableCredentials")
-    val preferImmediatelyAvailableCredentials: Boolean = false
-) : CreateCredentialRequest(
-    type = PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL,
-    credentialData = toCredentialDataBundle(
-        requestJson,
-        relyingParty,
-        clientDataHash,
-        preferImmediatelyAvailableCredentials
-    ),
-    // The whole request data should be passed during the query phase.
-    candidateQueryData = toCredentialDataBundle(
-        requestJson, relyingParty, clientDataHash, preferImmediatelyAvailableCredentials
-    ),
-    requireSystemProvider = false,
-) {
-
-    init {
-        require(requestJson.isNotEmpty()) { "requestJson must not be empty" }
-        require(relyingParty.isNotEmpty()) { "rp must not be empty" }
-        require(clientDataHash.isNotEmpty()) { "clientDataHash must not be empty" }
-    }
-
-    /** A builder for [CreatePublicKeyCredentialRequestPrivileged]. */
-    class Builder(
-        private var requestJson: String,
-        private var relyingParty: String,
-        private var clientDataHash: String
-    ) {
-
-        private var preferImmediatelyAvailableCredentials: Boolean = false
-
-        /**
-         * Sets the privileged request in JSON format.
-         */
-        fun setRequestJson(requestJson: String): Builder {
-            this.requestJson = requestJson
-            return this
-        }
-
-        /**
-         * Sets to true if you prefer the operation to return immediately when there is no available
-         * passkey registration offering instead of falling back to discovering remote options, and
-         * false otherwise.
-         *
-         * The default value is false.
-         */
-        @Suppress("MissingGetterMatchingBuilder")
-        fun setPreferImmediatelyAvailableCredentials(
-            preferImmediatelyAvailableCredentials: Boolean
-        ): Builder {
-            this.preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials
-            return this
-        }
-
-        /**
-         * Sets the expected true RP ID which will override the one in the [requestJson].
-         */
-        fun setRelyingParty(relyingParty: String): Builder {
-            this.relyingParty = relyingParty
-            return this
-        }
-
-        /**
-         * Sets a hash that is used to verify the [relyingParty] Identity.
-         */
-        fun setClientDataHash(clientDataHash: String): Builder {
-            this.clientDataHash = clientDataHash
-            return this
-        }
-
-        /** Builds a [CreatePublicKeyCredentialRequestPrivileged]. */
-        fun build(): CreatePublicKeyCredentialRequestPrivileged {
-            return CreatePublicKeyCredentialRequestPrivileged(
-                this.requestJson,
-                this.relyingParty, this.clientDataHash, this.preferImmediatelyAvailableCredentials
-            )
-        }
-    }
-
-    /** @hide */
-    companion object {
-        internal const val BUNDLE_KEY_RELYING_PARTY =
-            "androidx.credentials.BUNDLE_KEY_RELYING_PARTY"
-        internal const val BUNDLE_KEY_CLIENT_DATA_HASH =
-            "androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH"
-        internal const val BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS =
-            "androidx.credentials.BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS"
-
-        internal const val BUNDLE_KEY_REQUEST_JSON = "androidx.credentials.BUNDLE_KEY_REQUEST_JSON"
-
-        internal const val BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST_PRIV =
-            "androidx.credentials.BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST_" +
-                    "PRIVILEGED"
-
-        @JvmStatic
-        internal fun toCredentialDataBundle(
-            requestJson: String,
-            relyingParty: String,
-            clientDataHash: String,
-            preferImmediatelyAvailableCredentials: Boolean
-        ): Bundle {
-            val bundle = Bundle()
-            bundle.putString(
-                PublicKeyCredential.BUNDLE_KEY_SUBTYPE,
-                BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST_PRIV
-            )
-            bundle.putString(BUNDLE_KEY_REQUEST_JSON, requestJson)
-            bundle.putString(BUNDLE_KEY_RELYING_PARTY, relyingParty)
-            bundle.putString(BUNDLE_KEY_CLIENT_DATA_HASH, clientDataHash)
-            bundle.putBoolean(
-                BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS,
-                preferImmediatelyAvailableCredentials
-            )
-            return bundle
-        }
-
-        @Suppress("deprecation") // bundle.get() used for boolean value to prevent default
-        // boolean value from being returned.
-        @JvmStatic
-        internal fun createFrom(data: Bundle): CreatePublicKeyCredentialRequestPrivileged {
-            try {
-                val requestJson = data.getString(BUNDLE_KEY_REQUEST_JSON)
-                val rp = data.getString(BUNDLE_KEY_RELYING_PARTY)
-                val clientDataHash = data.getString(BUNDLE_KEY_CLIENT_DATA_HASH)
-                val preferImmediatelyAvailableCredentials =
-                    data.get(BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS)
-                return CreatePublicKeyCredentialRequestPrivileged(
-                    requestJson!!,
-                    rp!!,
-                    clientDataHash!!,
-                    (preferImmediatelyAvailableCredentials!!) as Boolean,
-                )
-            } catch (e: Exception) {
-                throw FrameworkClassParsingException()
-            }
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/Credential.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/Credential.kt
deleted file mode 100644
index ee08e9e..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/Credential.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.os.Bundle
-
-/**
- * Base class for a credential with which the user consented to authenticate to the app.
- *
- * @property type the credential type
- * @property data the credential data in the [Bundle] format.
- */
-open class Credential(val type: String, val data: Bundle)
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialOption.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialOption.kt
deleted file mode 100644
index fc7b7de..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialOption.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.credentials.Credential
-import android.os.Bundle
-
-/**
- * Base request class for getting a registered credential.
- *
- * @property type the credential type
- * @property data the request data in the [Bundle] format
- * @property requireSystemProvider true if must only be fulfilled by a system provider and false
- *                              otherwise
- */
-open class GetCredentialOption(
-    open val type: String,
-    open val requestData: Bundle,
-    open val candidateQueryData: Bundle,
-    open val requireSystemProvider: Boolean,
-) {
-    companion object {
-        @JvmStatic
-        fun createFrom(
-            type: String,
-            requestData: Bundle,
-            candidateQueryData: Bundle,
-            requireSystemProvider: Boolean
-        ): GetCredentialOption {
-            return try {
-                when (type) {
-                    Credential.TYPE_PASSWORD_CREDENTIAL ->
-                        GetPasswordOption.createFrom(requestData)
-                    PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL ->
-                        when (requestData.getString(PublicKeyCredential.BUNDLE_KEY_SUBTYPE)) {
-                            GetPublicKeyCredentialOption
-                                .BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION ->
-                                GetPublicKeyCredentialOption.createFrom(requestData)
-                            GetPublicKeyCredentialOptionPrivileged
-                                .BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION_PRIVILEGED ->
-                                GetPublicKeyCredentialOptionPrivileged.createFrom(requestData)
-                            else -> throw FrameworkClassParsingException()
-                        }
-                    else -> throw FrameworkClassParsingException()
-                }
-            } catch (e: FrameworkClassParsingException) {
-                // Parsing failed but don't crash the process. Instead just output a request with
-                // the raw framework values.
-                GetCustomCredentialOption(
-                    type, requestData, candidateQueryData, requireSystemProvider)
-            }
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialRequest.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialRequest.kt
deleted file mode 100644
index 5cb8d3b..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialRequest.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-/**
- * Encapsulates a request to get a user credential.
- *
- * @property getCredentialOptions the list of [GetCredentialOption] from which the user can choose
- * one to authenticate to the app
- * @throws IllegalArgumentException If [getCredentialOptions] is empty
- */
-class GetCredentialRequest constructor(
-    val getCredentialOptions: List<GetCredentialOption>,
-) {
-
-    init {
-        require(getCredentialOptions.isNotEmpty()) { "credentialRequests should not be empty" }
-    }
-
-    /** A builder for [GetCredentialRequest]. */
-    class Builder {
-        private var getCredentialOptions: MutableList<GetCredentialOption> = mutableListOf()
-
-        /** Adds a specific type of [GetCredentialOption]. */
-        fun addGetCredentialOption(getCredentialOption: GetCredentialOption): Builder {
-            getCredentialOptions.add(getCredentialOption)
-            return this
-        }
-
-        /** Sets the list of [GetCredentialOption]. */
-        fun setGetCredentialOptions(getCredentialOptions: List<GetCredentialOption>): Builder {
-            this.getCredentialOptions = getCredentialOptions.toMutableList()
-            return this
-        }
-
-        /**
-         * Builds a [GetCredentialRequest].
-         *
-         * @throws IllegalArgumentException If [getCredentialOptions] is empty
-         */
-        fun build(): GetCredentialRequest {
-            return GetCredentialRequest(getCredentialOptions.toList())
-        }
-    }
-
-    companion object {
-        @JvmStatic
-        fun createFrom(from: android.credentials.GetCredentialRequest): GetCredentialRequest {
-            return GetCredentialRequest(
-                from.getCredentialOptions.map {
-                    GetCredentialOption.createFrom(
-                        it.type,
-                        it.credentialRetrievalData,
-                        it.candidateQueryData,
-                        it.isSystemProviderRequired()
-                    )
-                }
-            )
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCustomCredentialOption.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCustomCredentialOption.kt
deleted file mode 100644
index 803885c..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCustomCredentialOption.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.credentialmanager.jetpack.developer
-
-import android.os.Bundle
-
-/**
- * Allows extending custom versions of GetCredentialOptions for unique use cases.
- *
- * @property type the credential type determined by the credential-type-specific subclass
- * generated for custom use cases
- * @property requestData the request data in the [Bundle] format, generated for custom use cases
- * @property candidateQueryData the partial request data in the [Bundle] format that will be sent to
- * the provider during the initial candidate query stage, which should not contain sensitive user
- * information
- * @property requireSystemProvider true if must only be fulfilled by a system provider and false
- * otherwise
- * @throws IllegalArgumentException If [type] is empty
- * @throws NullPointerException If [requestData] or [type] is null
- */
-open class GetCustomCredentialOption(
-    final override val type: String,
-    final override val requestData: Bundle,
-    final override val candidateQueryData: Bundle,
-    @get:JvmName("requireSystemProvider")
-    final override val requireSystemProvider: Boolean
-) : GetCredentialOption(
-    type,
-    requestData,
-    candidateQueryData,
-    requireSystemProvider
-) {
-    init {
-        require(type.isNotEmpty()) { "type should not be empty" }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetPasswordOption.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetPasswordOption.kt
deleted file mode 100644
index 2b9cfa3..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetPasswordOption.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.credentials.Credential
-import android.os.Bundle
-
-/** A request to retrieve the user's saved application password from their password provider. */
-class GetPasswordOption : GetCredentialOption(
-        Credential.TYPE_PASSWORD_CREDENTIAL,
-        Bundle(),
-        Bundle(),
-        false,
-) {
-    companion object {
-        @JvmStatic
-        fun createFrom(data: Bundle): GetPasswordOption {
-            return GetPasswordOption()
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetPublicKeyCredentialOption.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetPublicKeyCredentialOption.kt
deleted file mode 100644
index 2f9b249..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetPublicKeyCredentialOption.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.os.Bundle
-
-/**
- * A request to get passkeys from the user's public key credential provider.
- *
- * @property requestJson the privileged request in JSON format in the standard webauthn web json
- * shown [here](https://w3c.github.io/webauthn/#dictdef-publickeycredentialrequestoptionsjson).
- * @property preferImmediatelyAvailableCredentials true if you prefer the operation to return
- * immediately when there is no available credential instead of falling back to discovering remote
- * credentials, and false (default) otherwise
- * @throws NullPointerException If [requestJson] is null
- * @throws IllegalArgumentException If [requestJson] is empty
- */
-class GetPublicKeyCredentialOption @JvmOverloads constructor(
-    val requestJson: String,
-    @get:JvmName("preferImmediatelyAvailableCredentials")
-    val preferImmediatelyAvailableCredentials: Boolean = false,
-) : GetCredentialOption(
-    type = PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL,
-    requestData = toRequestDataBundle(requestJson, preferImmediatelyAvailableCredentials),
-    candidateQueryData = toRequestDataBundle(requestJson, preferImmediatelyAvailableCredentials),
-    requireSystemProvider = false
-) {
-    init {
-        require(requestJson.isNotEmpty()) { "requestJson must not be empty" }
-    }
-
-    /** @hide */
-    companion object {
-        internal const val BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS =
-            "androidx.credentials.BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS"
-        internal const val BUNDLE_KEY_REQUEST_JSON = "androidx.credentials.BUNDLE_KEY_REQUEST_JSON"
-        internal const val BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION =
-            "androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION"
-
-        @JvmStatic
-        internal fun toRequestDataBundle(
-            requestJson: String,
-            preferImmediatelyAvailableCredentials: Boolean
-        ): Bundle {
-            val bundle = Bundle()
-            bundle.putString(
-                PublicKeyCredential.BUNDLE_KEY_SUBTYPE,
-                BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION
-            )
-            bundle.putString(BUNDLE_KEY_REQUEST_JSON, requestJson)
-            bundle.putBoolean(BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS,
-                preferImmediatelyAvailableCredentials)
-            return bundle
-        }
-
-        @Suppress("deprecation") // bundle.get() used for boolean value to prevent default
-        // boolean value from being returned.
-        @JvmStatic
-        internal fun createFrom(data: Bundle): GetPublicKeyCredentialOption {
-            try {
-                val requestJson = data.getString(BUNDLE_KEY_REQUEST_JSON)
-                val preferImmediatelyAvailableCredentials =
-                    data.get(BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS)
-                return GetPublicKeyCredentialOption(requestJson!!,
-                    (preferImmediatelyAvailableCredentials!!) as Boolean)
-            } catch (e: Exception) {
-                throw FrameworkClassParsingException()
-            }
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetPublicKeyCredentialOptionPrivileged.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetPublicKeyCredentialOptionPrivileged.kt
deleted file mode 100644
index 6f4782a..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetPublicKeyCredentialOptionPrivileged.kt
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.os.Bundle
-
-/**
- * A privileged request to get passkeys from the user's public key credential provider. The caller
- * can modify the RP. Only callers with privileged permission (e.g. user's public browser or caBLE)
- * can use this. These permissions will be introduced in an upcoming release.
- * TODO("Add specific permission info/annotation")
- *
- * @property requestJson the privileged request in JSON format in the standard webauthn web json
- * shown [here](https://w3c.github.io/webauthn/#dictdef-publickeycredentialrequestoptionsjson).
- * @property preferImmediatelyAvailableCredentials true if you prefer the operation to return
- * immediately when there is no available credential instead of falling back to discovering remote
- * credentials, and false (default) otherwise
- * @property relyingParty the expected true RP ID which will override the one in the [requestJson],
- * where relyingParty is defined [here](https://w3c.github.io/webauthn/#rp-id) in more detail
- * @property clientDataHash a hash that is used to verify the [relyingParty] Identity
- * @throws NullPointerException If any of [requestJson], [relyingParty], or [clientDataHash]
- * is null
- * @throws IllegalArgumentException If any of [requestJson], [relyingParty], or [clientDataHash] is
- * empty
- */
-class GetPublicKeyCredentialOptionPrivileged @JvmOverloads constructor(
-    val requestJson: String,
-    val relyingParty: String,
-    val clientDataHash: String,
-    @get:JvmName("preferImmediatelyAvailableCredentials")
-    val preferImmediatelyAvailableCredentials: Boolean = false
-) : GetCredentialOption(
-    type = PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL,
-    requestData = toBundle(
-        requestJson,
-        relyingParty,
-        clientDataHash,
-        preferImmediatelyAvailableCredentials
-    ),
-    candidateQueryData = toBundle(
-        requestJson,
-        relyingParty,
-        clientDataHash,
-        preferImmediatelyAvailableCredentials
-    ),
-    requireSystemProvider = false,
-) {
-
-    init {
-        require(requestJson.isNotEmpty()) { "requestJson must not be empty" }
-        require(relyingParty.isNotEmpty()) { "rp must not be empty" }
-        require(clientDataHash.isNotEmpty()) { "clientDataHash must not be empty" }
-    }
-
-    /** A builder for [GetPublicKeyCredentialOptionPrivileged]. */
-    class Builder(
-        private var requestJson: String,
-        private var relyingParty: String,
-        private var clientDataHash: String
-    ) {
-
-        private var preferImmediatelyAvailableCredentials: Boolean = false
-
-        /**
-         * Sets the privileged request in JSON format.
-         */
-        fun setRequestJson(requestJson: String): Builder {
-            this.requestJson = requestJson
-            return this
-        }
-
-        /**
-         * Sets to true if you prefer the operation to return immediately when there is no available
-         * credential instead of falling back to discovering remote credentials, and false
-         * otherwise.
-         *
-         * The default value is false.
-         */
-        @Suppress("MissingGetterMatchingBuilder")
-        fun setPreferImmediatelyAvailableCredentials(
-            preferImmediatelyAvailableCredentials: Boolean
-        ): Builder {
-            this.preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials
-            return this
-        }
-
-        /**
-         * Sets the expected true RP ID which will override the one in the [requestJson].
-         */
-        fun setRelyingParty(relyingParty: String): Builder {
-            this.relyingParty = relyingParty
-            return this
-        }
-
-        /**
-         * Sets a hash that is used to verify the [relyingParty] Identity.
-         */
-        fun setClientDataHash(clientDataHash: String): Builder {
-            this.clientDataHash = clientDataHash
-            return this
-        }
-
-        /** Builds a [GetPublicKeyCredentialOptionPrivileged]. */
-        fun build(): GetPublicKeyCredentialOptionPrivileged {
-            return GetPublicKeyCredentialOptionPrivileged(
-                this.requestJson,
-                this.relyingParty, this.clientDataHash, this.preferImmediatelyAvailableCredentials
-            )
-        }
-    }
-
-    /** @hide */
-    companion object {
-        internal const val BUNDLE_KEY_RELYING_PARTY =
-            "androidx.credentials.BUNDLE_KEY_RELYING_PARTY"
-        internal const val BUNDLE_KEY_CLIENT_DATA_HASH =
-            "androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH"
-        internal const val BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS =
-            "androidx.credentials.BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS"
-        internal const val BUNDLE_KEY_REQUEST_JSON = "androidx.credentials.BUNDLE_KEY_REQUEST_JSON"
-        internal const val BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION_PRIVILEGED =
-            "androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION" +
-                    "_PRIVILEGED"
-
-        @JvmStatic
-        internal fun toBundle(
-            requestJson: String,
-            relyingParty: String,
-            clientDataHash: String,
-            preferImmediatelyAvailableCredentials: Boolean
-        ): Bundle {
-            val bundle = Bundle()
-            bundle.putString(
-                PublicKeyCredential.BUNDLE_KEY_SUBTYPE,
-                BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION_PRIVILEGED
-            )
-            bundle.putString(BUNDLE_KEY_REQUEST_JSON, requestJson)
-            bundle.putString(BUNDLE_KEY_RELYING_PARTY, relyingParty)
-            bundle.putString(BUNDLE_KEY_CLIENT_DATA_HASH, clientDataHash)
-            bundle.putBoolean(
-                BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS,
-                preferImmediatelyAvailableCredentials
-            )
-            return bundle
-        }
-
-        @Suppress("deprecation") // bundle.get() used for boolean value to prevent default
-        // boolean value from being returned.
-        @JvmStatic
-        internal fun createFrom(data: Bundle): GetPublicKeyCredentialOptionPrivileged {
-            try {
-                val requestJson = data.getString(BUNDLE_KEY_REQUEST_JSON)
-                val rp = data.getString(BUNDLE_KEY_RELYING_PARTY)
-                val clientDataHash = data.getString(BUNDLE_KEY_CLIENT_DATA_HASH)
-                val preferImmediatelyAvailableCredentials =
-                    data.get(BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS)
-                return GetPublicKeyCredentialOptionPrivileged(
-                    requestJson!!,
-                    rp!!,
-                    clientDataHash!!,
-                    (preferImmediatelyAvailableCredentials!!) as Boolean,
-                )
-            } catch (e: Exception) {
-                throw FrameworkClassParsingException()
-            }
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/PasswordCredential.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/PasswordCredential.kt
deleted file mode 100644
index 1658858..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/PasswordCredential.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.os.Bundle
-
-class PasswordCredential constructor(
-        val id: String,
-        val password: String,
-) : Credential(android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL, toBundle(id, password)) {
-
-    init {
-        require(password.isNotEmpty()) { "password should not be empty" }
-    }
-
-    /** @hide */
-    companion object {
-
-        const val BUNDLE_KEY_ID = "androidx.credentials.BUNDLE_KEY_ID"
-        const val BUNDLE_KEY_PASSWORD = "androidx.credentials.BUNDLE_KEY_PASSWORD"
-
-        @JvmStatic
-        internal fun toBundle(id: String, password: String): Bundle {
-            val bundle = Bundle()
-            bundle.putString(BUNDLE_KEY_ID, id)
-            bundle.putString(BUNDLE_KEY_PASSWORD, password)
-            return bundle
-        }
-
-        @JvmStatic
-        internal fun createFrom(data: Bundle): PasswordCredential {
-            try {
-                val id = data.getString(BUNDLE_KEY_ID)
-                val password = data.getString(BUNDLE_KEY_PASSWORD)
-                return PasswordCredential(id!!, password!!)
-            } catch (e: Exception) {
-                throw FrameworkClassParsingException()
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/PublicKeyCredential.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/PublicKeyCredential.kt
deleted file mode 100644
index 6a81167..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/PublicKeyCredential.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.developer
-
-import android.os.Bundle
-
-/**
- * Represents the user's passkey credential granted by the user for app sign-in.
- *
- * @property authenticationResponseJson the public key credential authentication response in
- * JSON format that follows the standard webauthn json format shown at
- * [this w3c link](https://w3c.github.io/webauthn/#dictdef-authenticationresponsejson)
- * @throws NullPointerException If [authenticationResponseJson] is null. This is handled by the
- * kotlin runtime
- * @throws IllegalArgumentException If [authenticationResponseJson] is empty
- *
- * @hide
- */
-class PublicKeyCredential constructor(
-        val authenticationResponseJson: String
-) : Credential(
-        TYPE_PUBLIC_KEY_CREDENTIAL,
-        toBundle(authenticationResponseJson)
-) {
-
-    init {
-        require(authenticationResponseJson.isNotEmpty()) {
-            "authentication response JSON must not be empty" }
-    }
-    companion object {
-        /** The type value for public key credential related operations. */
-        const val TYPE_PUBLIC_KEY_CREDENTIAL: String =
-                "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL"
-        /** The Bundle key value for the public key credential subtype (privileged or regular). */
-        internal const val BUNDLE_KEY_SUBTYPE = "androidx.credentials.BUNDLE_KEY_SUBTYPE"
-        const val BUNDLE_KEY_AUTHENTICATION_RESPONSE_JSON =
-                "androidx.credentials.BUNDLE_KEY_AUTHENTICATION_RESPONSE_JSON"
-
-        @JvmStatic
-        internal fun toBundle(authenticationResponseJson: String): Bundle {
-            val bundle = Bundle()
-            bundle.putString(BUNDLE_KEY_AUTHENTICATION_RESPONSE_JSON, authenticationResponseJson)
-            return bundle
-        }
-    }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/Action.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/Action.kt
deleted file mode 100644
index 1abf911..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/Action.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.provider
-
-import android.annotation.SuppressLint
-import android.app.PendingIntent
-import android.app.slice.Slice
-import android.app.slice.SliceSpec
-import android.net.Uri
-import android.util.Log
-import java.util.Collections
-
-/**
- * UI representation for a credential entry used during the get credential flow.
- *
- * TODO: move to jetpack.
- */
-class Action constructor(
-        val title: CharSequence,
-        val subTitle: CharSequence?,
-        val pendingIntent: PendingIntent?,
-) {
-
-  init {
-    require(title.isNotEmpty()) { "title must not be empty" }
-  }
-
-  companion object {
-    private const val TAG = "Action"
-    internal const val SLICE_HINT_TITLE =
-            "androidx.credentials.provider.action.HINT_ACTION_TITLE"
-    internal const val SLICE_HINT_SUBTITLE =
-            "androidx.credentials.provider.action.HINT_ACTION_SUBTEXT"
-    internal const val SLICE_HINT_PENDING_INTENT =
-            "androidx.credentials.provider.action.SLICE_HINT_PENDING_INTENT"
-
-    @JvmStatic
-    fun toSlice(action: Action): Slice {
-      // TODO("Put the right spec and version value")
-      val sliceBuilder = Slice.Builder(Uri.EMPTY, SliceSpec("type", 1))
-              .addText(action.title, /*subType=*/null,
-                      listOf(SLICE_HINT_TITLE))
-              .addText(action.subTitle, /*subType=*/null,
-                      listOf(SLICE_HINT_SUBTITLE))
-      if (action.pendingIntent != null) {
-        sliceBuilder.addAction(action.pendingIntent,
-                Slice.Builder(sliceBuilder)
-                        .addHints(Collections.singletonList(SLICE_HINT_PENDING_INTENT))
-                        .build(),
-                /*subType=*/null)
-      }
-      return sliceBuilder.build()
-    }
-
-    /**
-     * Returns an instance of [Action] derived from a [Slice] object.
-     *
-     * @param slice the [Slice] object constructed through [toSlice]
-     */
-    @SuppressLint("WrongConstant") // custom conversion between jetpack and framework
-    @JvmStatic
-    fun fromSlice(slice: Slice): Action? {
-      // TODO("Put the right spec and version value")
-      var title: CharSequence = ""
-      var subTitle: CharSequence? = null
-      var pendingIntent: PendingIntent? = null
-
-      slice.items.forEach {
-        if (it.hasHint(SLICE_HINT_TITLE)) {
-          title = it.text
-        } else if (it.hasHint(SLICE_HINT_SUBTITLE)) {
-          subTitle = it.text
-        } else if (it.hasHint(SLICE_HINT_PENDING_INTENT)) {
-          pendingIntent = it.action
-        }
-      }
-
-      return try {
-        Action(title, subTitle, pendingIntent)
-      } catch (e: Exception) {
-        Log.i(TAG, "fromSlice failed with: " + e.message)
-        null
-      }
-    }
-  }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/AuthenticationAction.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/AuthenticationAction.kt
deleted file mode 100644
index 283c7ba..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/AuthenticationAction.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.provider
-
-import android.app.PendingIntent
-import android.app.slice.Slice
-import android.util.Log
-import androidx.annotation.VisibleForTesting
-
-/**
- * UI representation for a credential entry used during the get credential flow.
- *
- * TODO: move to jetpack.
- */
-class AuthenticationAction constructor(
-        val pendingIntent: PendingIntent
-) {
-
-
-  companion object {
-    private const val TAG = "AuthenticationAction"
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    internal const val SLICE_HINT_PENDING_INTENT =
-            "androidx.credentials.provider.authenticationAction.SLICE_HINT_PENDING_INTENT"
-
-    @JvmStatic
-    fun fromSlice(slice: Slice): AuthenticationAction? {
-      slice.items.forEach {
-        if (it.hasHint(SLICE_HINT_PENDING_INTENT)) {
-          return try {
-            AuthenticationAction(it.action)
-          } catch (e: Exception) {
-            Log.i(TAG, "fromSlice failed with: " + e.message)
-            null
-          }
-        }
-      }
-      return null
-    }
-  }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CreateEntry.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CreateEntry.kt
deleted file mode 100644
index 0ec91d6..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CreateEntry.kt
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.provider
-
-import android.annotation.SuppressLint
-import android.app.PendingIntent
-import android.app.slice.Slice
-import android.app.slice.SliceSpec
-import android.graphics.drawable.Icon
-import android.net.Uri
-import android.os.Bundle
-import android.util.Log
-import java.util.Collections
-
-/**
- * UI representation for a save entry used during the create credential flow.
- *
- * TODO: move to jetpack.
- */
-class CreateEntry internal constructor(
-        val accountName: CharSequence,
-        val pendingIntent: PendingIntent?,
-        val icon: Icon?,
-        val lastUsedTimeMillis: Long,
-        val credentialCountInformationList: List<CredentialCountInformation>,
-        val footerDescription: CharSequence?,
-) {
-
-  init {
-    require(accountName.isNotEmpty()) { "accountName must not be empty" }
-  }
-
-  /**
-   * A builder for [CreateEntry]
-   *
-   * @property accountName the name of the account where the credential will be registered
-   * @property pendingIntent the [PendingIntent] that will be fired when the user selects
-   * this entry
-   *
-   * @hide
-   */
-  class Builder constructor(
-          private val accountName: CharSequence,
-          private val pendingIntent: PendingIntent? = null
-  ) {
-
-    private var credentialCountInformationList: MutableList<CredentialCountInformation> =
-            mutableListOf()
-    private var icon: Icon? = null
-    private var lastUsedTimeMillis: Long = 0
-    private var footerDescription: CharSequence? = null
-
-    /** Adds a [CredentialCountInformation] denoting a given credential
-     * type and the count of credentials that the provider has stored for that
-     * credential type.
-     *
-     * This information will be displayed on the [CreateEntry] to help the user
-     * make a choice.
-     */
-    @Suppress("MissingGetterMatchingBuilder")
-    fun addCredentialCountInformation(info: CredentialCountInformation): Builder {
-      credentialCountInformationList.add(info)
-      return this
-    }
-
-    /** Sets a list of [CredentialCountInformation]. Each item in the list denotes a given
-     * credential type and the count of credentials that the provider has stored of that
-     * credential type.
-     *
-     * This information will be displayed on the [CreateEntry] to help the user
-     * make a choice.
-     */
-    fun setCredentialCountInformationList(infoList: List<CredentialCountInformation>): Builder {
-      credentialCountInformationList = infoList as MutableList<CredentialCountInformation>
-      return this
-    }
-
-    /** Sets an icon to be displayed with the entry on the UI */
-    fun setIcon(icon: Icon?): Builder {
-      this.icon = icon
-      return this
-    }
-
-    /** Sets the last time this account was used */
-    fun setLastUsedTimeMillis(lastUsedTimeMillis: Long): Builder {
-      this.lastUsedTimeMillis = lastUsedTimeMillis
-      return this
-    }
-
-    /** Sets the footer description of this */
-    fun setFooterDescription(footerDescription: CharSequence): Builder {
-      this.footerDescription = footerDescription
-      return this
-    }
-
-    /**
-     * Builds an instance of [CreateEntry]
-     *
-     * @throws IllegalArgumentException If [accountName] is empty
-     */
-    fun build(): CreateEntry {
-      return CreateEntry(accountName, pendingIntent, icon, lastUsedTimeMillis,
-              credentialCountInformationList, footerDescription)
-    }
-  }
-
-  companion object {
-    private const val TAG = "CreateEntry"
-    internal const val SLICE_HINT_ACCOUNT_NAME =
-            "androidx.credentials.provider.createEntry.SLICE_HINT_USER_PROVIDER_ACCOUNT_NAME"
-    internal const val SLICE_HINT_ICON =
-            "androidx.credentials.provider.createEntry.SLICE_HINT_PROFILE_ICON"
-    internal const val SLICE_HINT_CREDENTIAL_COUNT_INFORMATION =
-            "androidx.credentials.provider.createEntry.SLICE_HINT_CREDENTIAL_COUNT_INFORMATION"
-    internal const val SLICE_HINT_LAST_USED_TIME_MILLIS =
-            "androidx.credentials.provider.createEntry.SLICE_HINT_LAST_USED_TIME_MILLIS"
-    internal const val SLICE_HINT_PENDING_INTENT =
-            "androidx.credentials.provider.createEntry.SLICE_HINT_PENDING_INTENT"
-    internal const val SLICE_HINT_FOOTER_DESCRIPTION =
-            "androidx.credentials.provider.createEntry.SLICE_HINT_FOOTER_DESCRIPTION"
-
-    @JvmStatic
-    fun toSlice(createEntry: CreateEntry): Slice {
-      // TODO("Use the right type and revision")
-      val sliceBuilder = Slice.Builder(Uri.EMPTY, SliceSpec("type", 1))
-      sliceBuilder.addText(createEntry.accountName, /*subType=*/null,
-              listOf(SLICE_HINT_ACCOUNT_NAME))
-              .addLong(createEntry.lastUsedTimeMillis, /*subType=*/null, listOf(
-                      SLICE_HINT_LAST_USED_TIME_MILLIS))
-      if (createEntry.icon != null) {
-        sliceBuilder.addIcon(createEntry.icon, /*subType=*/null,
-                listOf(SLICE_HINT_ICON))
-      }
-
-      val credentialCountBundle = convertCredentialCountInfoToBundle(
-              createEntry.credentialCountInformationList)
-      if (credentialCountBundle != null) {
-        sliceBuilder.addBundle(convertCredentialCountInfoToBundle(
-                createEntry.credentialCountInformationList), null, listOf(
-                SLICE_HINT_CREDENTIAL_COUNT_INFORMATION))
-      }
-      if (createEntry.pendingIntent != null) {
-        sliceBuilder.addAction(createEntry.pendingIntent,
-                Slice.Builder(sliceBuilder)
-                        .addHints(Collections.singletonList(SLICE_HINT_PENDING_INTENT))
-                        .build(),
-                /*subType=*/null)
-      }
-      if (createEntry.footerDescription != null) {
-        sliceBuilder.addText(createEntry.footerDescription, /*subType=*/null,
-                listOf(SLICE_HINT_FOOTER_DESCRIPTION))
-      }
-      return sliceBuilder.build()
-    }
-
-    /**
-     * Returns an instance of [CreateEntry] derived from a [Slice] object.
-     *
-     * @param slice the [Slice] object constructed through [toSlice]
-     */
-    @SuppressLint("WrongConstant") // custom conversion between jetpack and framework
-    @JvmStatic
-    fun fromSlice(slice: Slice): CreateEntry? {
-      // TODO("Put the right spec and version value")
-      var accountName: CharSequence = ""
-      var icon: Icon? = null
-      var pendingIntent: PendingIntent? = null
-      var credentialCountInfo: List<CredentialCountInformation> = listOf()
-      var lastUsedTimeMillis: Long = 0
-      var footerDescription: CharSequence? = null
-
-      slice.items.forEach {
-        if (it.hasHint(SLICE_HINT_ACCOUNT_NAME)) {
-          accountName = it.text
-        } else if (it.hasHint(SLICE_HINT_ICON)) {
-          icon = it.icon
-        } else if (it.hasHint(SLICE_HINT_PENDING_INTENT)) {
-          pendingIntent = it.action
-        } else if (it.hasHint(SLICE_HINT_CREDENTIAL_COUNT_INFORMATION)) {
-          credentialCountInfo = convertBundleToCredentialCountInfo(it.bundle)
-        } else if (it.hasHint(SLICE_HINT_LAST_USED_TIME_MILLIS)) {
-          lastUsedTimeMillis = it.long
-        } else if (it.hasHint(SLICE_HINT_FOOTER_DESCRIPTION)) {
-          footerDescription = it.text
-        }
-      }
-
-      return try {
-        CreateEntry(accountName, pendingIntent, icon,
-                lastUsedTimeMillis, credentialCountInfo, footerDescription)
-      } catch (e: Exception) {
-        Log.i(TAG, "fromSlice failed with: " + e.message)
-        null
-      }
-    }
-
-    @JvmStatic
-    internal fun convertBundleToCredentialCountInfo(bundle: Bundle?):
-            List<CredentialCountInformation> {
-      val credentialCountList = ArrayList<CredentialCountInformation>()
-      if (bundle == null) {
-        return credentialCountList
-      }
-      bundle.keySet().forEach {
-        try {
-          credentialCountList.add(
-                  CredentialCountInformation(it, bundle.getInt(it)))
-        } catch (e: Exception) {
-          Log.i(TAG, "Issue unpacking credential count info bundle: " + e.message)
-        }
-      }
-      return credentialCountList
-    }
-
-    @JvmStatic
-    internal fun convertCredentialCountInfoToBundle(
-            credentialCountInformationList: List<CredentialCountInformation>
-    ): Bundle? {
-      if (credentialCountInformationList.isEmpty()) {
-        return null
-      }
-      val bundle = Bundle()
-      credentialCountInformationList.forEach {
-        bundle.putInt(it.type, it.count)
-      }
-      return bundle
-    }
-  }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CredentialCountInformation.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CredentialCountInformation.kt
deleted file mode 100644
index aa77b74..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CredentialCountInformation.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.provider
-
-import android.credentials.Credential
-import com.android.credentialmanager.jetpack.developer.PublicKeyCredential
-
-class CredentialCountInformation constructor(
-        val type: String,
-        val count: Int
-) {
-    companion object {
-        @JvmStatic
-        fun createPasswordCountInformation(count: Int): CredentialCountInformation {
-            return CredentialCountInformation(Credential.TYPE_PASSWORD_CREDENTIAL, count)
-        }
-
-        @JvmStatic
-        fun getPasswordCount(infos: List<CredentialCountInformation>): Int? {
-            return getCountForType(infos, Credential.TYPE_PASSWORD_CREDENTIAL)
-        }
-
-        @JvmStatic
-        fun createPublicKeyCountInformation(count: Int): CredentialCountInformation {
-            return CredentialCountInformation(PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL, count)
-        }
-
-        @JvmStatic
-        fun getPasskeyCount(infos: List<CredentialCountInformation>): Int? {
-            return getCountForType(infos, PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL)
-        }
-
-        @JvmStatic
-        fun createTotalCountInformation(count: Int): CredentialCountInformation {
-            return CredentialCountInformation("TOTAL_COUNT", count)
-        }
-
-        @JvmStatic
-        fun getTotalCount(infos: List<CredentialCountInformation>): Int? {
-            return getCountForType(infos, "TOTAL_COUNT")
-        }
-
-        private fun getCountForType(infos: List<CredentialCountInformation>, type: String): Int? {
-            return infos.firstOrNull { info -> info.type == type }?.count
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CredentialEntry.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CredentialEntry.kt
deleted file mode 100644
index 61a104b..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CredentialEntry.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.credentialmanager.jetpack.provider
-
-import android.annotation.SuppressLint
-import android.app.PendingIntent
-import android.app.slice.Slice
-import android.app.slice.SliceSpec
-import android.graphics.drawable.Icon
-import android.net.Uri
-import android.util.Log
-import java.util.Collections
-
-/**
- * UI representation for a credential entry used during the get credential flow.
- *
- * TODO: move to jetpack.
- */
-open class CredentialEntry constructor(
-        // TODO("Add credential type display name for both CredentialEntry & CreateEntry")
-        val type: String,
-        val typeDisplayName: CharSequence,
-        val username: CharSequence,
-        val displayName: CharSequence?,
-        val pendingIntent: PendingIntent?,
-        // TODO("Consider using Instant or other strongly typed time data type")
-        val lastUsedTimeMillis: Long,
-        val icon: Icon?,
-        var autoSelectAllowed: Boolean
-) {
-  init {
-    require(type.isNotEmpty()) { "type must not be empty" }
-    require(username.isNotEmpty()) { "type must not be empty" }
-  }
-
-  companion object {
-    private const val TAG = "CredentialEntry"
-    internal const val SLICE_HINT_TYPE_DISPLAY_NAME =
-            "androidx.credentials.provider.credentialEntry.SLICE_HINT_TYPE_DISPLAY_NAME"
-    internal const val SLICE_HINT_USERNAME =
-            "androidx.credentials.provider.credentialEntry.SLICE_HINT_USER_NAME"
-    internal const val SLICE_HINT_DISPLAYNAME =
-            "androidx.credentials.provider.credentialEntry.SLICE_HINT_CREDENTIAL_TYPE_DISPLAY_NAME"
-    internal const val SLICE_HINT_LAST_USED_TIME_MILLIS =
-            "androidx.credentials.provider.credentialEntry.SLICE_HINT_LAST_USED_TIME_MILLIS"
-    internal const val SLICE_HINT_ICON =
-            "androidx.credentials.provider.credentialEntry.SLICE_HINT_PROFILE_ICON"
-    internal const val SLICE_HINT_PENDING_INTENT =
-            "androidx.credentials.provider.credentialEntry.SLICE_HINT_PENDING_INTENT"
-    internal const val SLICE_HINT_AUTO_ALLOWED =
-            "androidx.credentials.provider.credentialEntry.SLICE_HINT_AUTO_ALLOWED"
-    internal const val AUTO_SELECT_TRUE_STRING = "true"
-    internal const val AUTO_SELECT_FALSE_STRING = "false"
-
-    @JvmStatic
-    internal fun toSlice(credentialEntry: CredentialEntry): Slice {
-      // TODO("Put the right revision value")
-      val autoSelectAllowed = if (credentialEntry.autoSelectAllowed) {
-        AUTO_SELECT_TRUE_STRING
-      } else {
-        AUTO_SELECT_FALSE_STRING
-      }
-      val sliceBuilder = Slice.Builder(Uri.EMPTY, SliceSpec(
-              credentialEntry.type, 1))
-              .addText(credentialEntry.typeDisplayName, /*subType=*/null,
-                      listOf(SLICE_HINT_TYPE_DISPLAY_NAME))
-              .addText(credentialEntry.username, /*subType=*/null,
-                      listOf(SLICE_HINT_USERNAME))
-              .addText(credentialEntry.displayName, /*subType=*/null,
-                      listOf(SLICE_HINT_DISPLAYNAME))
-              .addLong(credentialEntry.lastUsedTimeMillis, /*subType=*/null,
-                      listOf(SLICE_HINT_LAST_USED_TIME_MILLIS))
-              .addText(autoSelectAllowed, /*subType=*/null,
-                      listOf(SLICE_HINT_AUTO_ALLOWED))
-      if (credentialEntry.icon != null) {
-        sliceBuilder.addIcon(credentialEntry.icon, /*subType=*/null,
-                listOf(SLICE_HINT_ICON))
-      }
-      if (credentialEntry.pendingIntent != null) {
-        sliceBuilder.addAction(credentialEntry.pendingIntent,
-                Slice.Builder(sliceBuilder)
-                        .addHints(Collections.singletonList(SLICE_HINT_PENDING_INTENT))
-                        .build(),
-                /*subType=*/null)
-      }
-      return sliceBuilder.build()
-    }
-
-    /**
-     * Returns an instance of [CredentialEntry] derived from a [Slice] object.
-     *
-     * @param slice the [Slice] object constructed through [toSlice]
-     */
-    @SuppressLint("WrongConstant") // custom conversion between jetpack and framework
-    @JvmStatic
-    fun fromSlice(slice: Slice): CredentialEntry? {
-      var typeDisplayName: CharSequence? = null
-      var username: CharSequence? = null
-      var displayName: CharSequence? = null
-      var icon: Icon? = null
-      var pendingIntent: PendingIntent? = null
-      var lastUsedTimeMillis: Long = 0
-      var autoSelectAllowed = false
-
-      slice.items.forEach {
-        if (it.hasHint(SLICE_HINT_TYPE_DISPLAY_NAME)) {
-          typeDisplayName = it.text
-        } else if (it.hasHint(SLICE_HINT_USERNAME)) {
-          username = it.text
-        } else if (it.hasHint(SLICE_HINT_DISPLAYNAME)) {
-          displayName = it.text
-        } else if (it.hasHint(SLICE_HINT_ICON)) {
-          icon = it.icon
-        } else if (it.hasHint(SLICE_HINT_PENDING_INTENT)) {
-          pendingIntent = it.action
-        } else if (it.hasHint(SLICE_HINT_LAST_USED_TIME_MILLIS)) {
-          lastUsedTimeMillis = it.long
-        } else if (it.hasHint(SLICE_HINT_AUTO_ALLOWED)) {
-          val autoSelectValue = it.text
-          if (autoSelectValue == AUTO_SELECT_TRUE_STRING) {
-            autoSelectAllowed = true
-          }
-        }
-      }
-
-      return try {
-        CredentialEntry(slice.spec!!.type, typeDisplayName!!, username!!,
-                displayName, pendingIntent,
-                lastUsedTimeMillis, icon, autoSelectAllowed)
-      } catch (e: Exception) {
-        Log.i(TAG, "fromSlice failed with: " + e.message)
-        null
-      }
-    }
-  }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/Cat.java b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
index cd59a73..bf09bc7 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/Cat.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
@@ -258,7 +258,7 @@
 
         Notification.BubbleMetadata bubbs = new Notification.BubbleMetadata.Builder()
                 .setIntent(
-                        PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE))
+                        PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_MUTABLE))
                 .setIcon(notificationIcon)
                 .setSuppressNotification(false)
                 .setDesiredHeight(context.getResources().getDisplayMetrics().heightPixels)
diff --git a/packages/PackageInstaller/res/values-af/strings.xml b/packages/PackageInstaller/res/values-af/strings.xml
index fd2aeb1..72fb5d6 100644
--- a/packages/PackageInstaller/res/values-af/strings.xml
+++ b/packages/PackageInstaller/res/values-af/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Program geïnstalleer."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Wil jy hierdie program installeer?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Wil jy hierdie program opdateer?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Opdaterings vir hierdie app word tans deur <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> bestuur.\n\nAs jy opdateer, sal jy toekomstige opdaterings eerder van <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> af ontvang."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Opdaterings vir hierdie app word tans deur <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> bestuur.\n\nWil jy hierdie opdatering vanaf <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> installeer?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Program nie geïnstalleer nie."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Die installering van die pakket is geblokkeer."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Program is nie geïnstalleer nie omdat pakket met \'n bestaande pakket bots."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Deïnstalleer tans <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Deïnstallering is klaar."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Het <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> gedeïnstalleer"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Het <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-kloon uitgevee"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Deïnstallering onsuksesvol."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Kon nie <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> deïnstalleer nie."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Vee tans <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-kloon uit …"</string>
diff --git a/packages/PackageInstaller/res/values-am/strings.xml b/packages/PackageInstaller/res/values-am/strings.xml
index 4ebcd33..378770d 100644
--- a/packages/PackageInstaller/res/values-am/strings.xml
+++ b/packages/PackageInstaller/res/values-am/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"መተግበሪያ ተጭኗል።"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ይህን መተግበሪያ መጫን ይፈልጋሉ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ይህን መተግበሪያ ማዘመን ይፈልጋሉ?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"የዚህ መተግበሪያ ዝማኔዎች አሁን በ<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> በመተዳደር ላይ ናቸው።\n\nበማዘመንዎ የወደፊት ዝማኔዎችን በምትኩ ከ<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ያገኛሉ።"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"የዚህ መተግበሪያ ዝማኔዎች አሁን በ<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> በመተዳደር ላይ ናቸው።\n\nይህን ዝማኔ ከ<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> መጫን ይፈልጋሉ።"</string>
     <string name="install_failed" msgid="5777824004474125469">"መተግበሪያ አልተጫነም።"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ጥቅሉ እንዳይጫን ታግዷል።"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"እንደ ጥቅል ያልተጫነ መተግበሪያ ከነባር ጥቅል ጋር ይጋጫል።"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ን በማራገፍ ላይ…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"ማራግፍ ተጠናቅቋል።"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ተራግፏል"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"የተሰረዘ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ብዜት"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"ማራገፍ አልተሳካም።"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ን ማራገፍ ስኬታማ አልነበረም።"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"የተባዛ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ን በመሰረዝ ላይ…"</string>
diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml
index 88fd1a5..c60f950 100644
--- a/packages/PackageInstaller/res/values-ar/strings.xml
+++ b/packages/PackageInstaller/res/values-ar/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"تم تثبيت التطبيق."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"هل تريد تثبيت هذا التطبيق؟"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"هل تريد تحديث هذا التطبيق؟"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"تتم إدارة تحديثات هذا التطبيق حاليًا من قِبل \"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>\".\n\nمن خلال التحديث، ستتلقّى التحديثات المتوفّرة من \"<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>\" بدلاً من ذلك."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"تتم إدارة تحديثات هذا التطبيق حاليًا من قِبل \"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>\".\n\nهل تريد تثبيت هذا التحديث من <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>\"؟"</string>
     <string name="install_failed" msgid="5777824004474125469">"التطبيق ليس مثبتًا."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"تم حظر تثبيت الحزمة."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"لم يتم تثبيت التطبيق لأن حزمة التثبيت تتعارض مع حزمة حالية."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"جارٍ إلغاء تثبيت <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"تمّ إلغاء تثبيت التطبيق."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"تم إلغاء تثبيت <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"تم حذف النسخة الطبق الأصل عن \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"."</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"تعذّر إلغاء تثبيت التطبيق."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"لم يتم إلغاء تثبيت <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> بنجاح."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"جارٍ حذف النسخة الطبق الأصل عن \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"…"</string>
diff --git a/packages/PackageInstaller/res/values-as/strings.xml b/packages/PackageInstaller/res/values-as/strings.xml
index 401ffdb..2b41b1e 100644
--- a/packages/PackageInstaller/res/values-as/strings.xml
+++ b/packages/PackageInstaller/res/values-as/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"এপ্ ইনষ্টল কৰা হ’ল।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"আপুনি এই এপ্‌টো ইনষ্টল কৰিবলৈ বিচাৰেনে?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"আপুনি এই এপ্‌টো আপডে’ট কৰিবলৈ বিচাৰেনে?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"এই এপ্‌টোৰ আপডে’টসমূহ বৰ্তমান <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>এ পৰিচালনা কৰি আছে।\n\nআপডে’ট কৰিলে, আপুনি ইয়াৰ পৰিবৰ্তে <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>ৰ পৰা ভৱিষ্যত আপডে’টসমূহ পাব।"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"এই এপ্‌টোৰ আপডে’টসমূহ বৰ্তমান <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>এ পৰিচালনা কৰি আছে।\n\nআপুনি <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>ৰ পৰা অহা এই আপডে’টটো ইনষ্টল কৰিব বিচাৰেনে?"</string>
     <string name="install_failed" msgid="5777824004474125469">"এপ্ ইনষ্টল কৰা হোৱা নাই।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"পেকেজটোৰ ইনষ্টল অৱৰোধ কৰা হৈছে।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"এপ্‌টো ইনষ্টল কৰিব পৰা নগ\'ল কাৰণ ইয়াৰ সৈতে আগৰে পৰা থকা এটা পেকেজৰ সংঘাত হৈছে।"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনষ্টল কৰি থকা হৈছে…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"আনইনষ্টল কৰা হ’ল।"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনষ্টল কৰা হ’ল"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ৰ ক্ল’ন মচা হৈছে"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"আনইনষ্টল কৰিব পৰা নগ\'ল।"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনষ্টল কৰিব পৰা নগ\'ল।"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ৰ ক্ল’ন মচি থকা হৈছে…"</string>
diff --git a/packages/PackageInstaller/res/values-az/strings.xml b/packages/PackageInstaller/res/values-az/strings.xml
index 7d46f9d..9e915e3 100644
--- a/packages/PackageInstaller/res/values-az/strings.xml
+++ b/packages/PackageInstaller/res/values-az/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Tətbiq quraşdırılıb."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Bu tətbiqi quraşdırmaq istəyirsiniz?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Bu tətbiqi güncəlləmək istəyirsiniz?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Bu tətbiq üzrə güncəlləmələr hazırda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> tərəfindən idarə olunur.\n\nGüncəlləməklə, <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> adlı mənbədən gələcək güncəlləmələri əldə edəcəksiniz."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Bu tətbiq üzrə güncəlləmələr hazırda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> tərəfindən idarə olunur.\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> adlı mənbədən bu güncəlləməni quraşdırmaq istəyirsinizmi."</string>
     <string name="install_failed" msgid="5777824004474125469">"Tətbiq quraşdırılmayıb."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketin quraşdırılması blok edildi."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Bu paketin mövcud paket ilə ziddiyətinə görə tətbiq quraşdırılmadı."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sistemdən silinir…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Sistemdən silindi."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sistemdən silindi"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klonu silinib"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Sistemdən silinmədi."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sistemdən silinmədi."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kopya silinir…"</string>
diff --git a/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
index 9837d15..b8dbad5 100644
--- a/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
+++ b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacija je instalirana."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Želite da instalirate ovu aplikaciju?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Želite da ažurirate ovu aplikaciju?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Ažuriranjima ove aplikacije trenutno upravlja <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAko ažurirate, buduća ažuriranja ćete dobijati od vlasnika <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Ažuriranjima ove aplikacije trenutno upravlja <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nŽelite li da instalirate ovo ažuriranje vlasnika <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacija nije instalirana."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instaliranje paketa je blokirano."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija nije instalirana jer je paket neusaglašen sa postojećim paketom."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> se deinstalira…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Deinstaliranje je završeno."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je deinstalirana"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Izbrisan je <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klon"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Deinstaliranje nije uspelo."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Deinstaliranje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nije uspelo."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Briše se klon aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-be/strings.xml b/packages/PackageInstaller/res/values-be/strings.xml
index 052750f..05c24ff 100644
--- a/packages/PackageInstaller/res/values-be/strings.xml
+++ b/packages/PackageInstaller/res/values-be/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Праграма ўсталявана."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Усталяваць гэту праграму?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Абнавіць гэту праграму?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Абнаўленнямі гэтай праграмы цяпер кіруе <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nВыканаўшы гэта абнаўленне, усе наступныя вы будзеце атрымліваць ад <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Абнаўленнямі гэтай праграмы цяпер кіруе <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nВы хочаце ўсталяваць гэта абнаўленне ад <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Праграма не ўсталявана."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Усталяванне пакета заблакіравана."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Праграма не ўсталявана, таму што пакет канфліктуе з існуючым пакетам."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> выдаляецца…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Выдаленне завершана."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Выдалена: <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Выдалена копія \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\""</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Не выдалена."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Не ўдалося выдаліць <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Выдаленне клона \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"…"</string>
diff --git a/packages/PackageInstaller/res/values-bg/strings.xml b/packages/PackageInstaller/res/values-bg/strings.xml
index abbd499..110860b 100644
--- a/packages/PackageInstaller/res/values-bg/strings.xml
+++ b/packages/PackageInstaller/res/values-bg/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Приложението бе инсталирано."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Искате ли да инсталирате това приложение?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Искате ли да актуализирате това приложение?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Актуализациите на това приложение понастоящем се управляват от <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nСлед актуализирането ще получавате бъдещите актуализации от <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Актуализациите на това приложение понастоящем се управляват от <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nИскате ли да инсталирате тази актуализация от <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Приложението не бе инсталирано."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Инсталирането на пакета бе блокирано."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Приложението не бе инсталирано, тъй като пакетът е в конфликт със съществуващ пакет."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> се деинсталира…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Деинсталирането завърши."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Деинсталирахте <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Копието на <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> бе изтрито"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Деинсталирането не бе успешно."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Деинсталирането на <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> не бе успешно."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Копието на <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> се изтрива…"</string>
diff --git a/packages/PackageInstaller/res/values-bn/strings.xml b/packages/PackageInstaller/res/values-bn/strings.xml
index 6104121..16353df 100644
--- a/packages/PackageInstaller/res/values-bn/strings.xml
+++ b/packages/PackageInstaller/res/values-bn/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"অ্যাপটি ইনস্টল করা হয়ে গেছে।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"আপনি কি এই অ্যাপটি ইনস্টল করতে চান?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"আপনি কি এই অ্যাপটি আপডেট করতে চান?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"এই অ্যাপের আপডেট বর্তমানে <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ম্যানেজ করছেন।\n\nআপডেট করা হলে, আপনি পরিবর্তে <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>-এর থেকে ভবিষ্যতের আপডেট পাবেন।"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"বর্তমানে <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> এই অ্যাপের আপডেট ম্যানেজ করছেন।\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> থেকে আসা এই আপডেট ইনস্টল করতে চান।"</string>
     <string name="install_failed" msgid="5777824004474125469">"অ্যাপটি ইনস্টল করা হয়নি।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ইনস্টল হওয়া থেকে প্যাকেজটিকে ব্লক করা হয়েছে।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"আগে থেকেই থাকা একটি প্যাকেজের সাথে প্যাকেজটির সমস্যা সৃষ্টি হওয়ায় অ্যাপটি ইনস্টল করা যায়নি।"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনস্টল করা হচ্ছে…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"আনইনস্টল করা শেষ হয়েছে।"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনস্টল করা হয়ে গেছে"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"ক্লোনের <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> মুছে ফেলা হয়েছে"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"আনইনস্টল করা যায়নি।"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> আনইনস্টল করা যায়নি।"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ক্লোন মুছে ফেলা হচ্ছে…"</string>
diff --git a/packages/PackageInstaller/res/values-bs/strings.xml b/packages/PackageInstaller/res/values-bs/strings.xml
index 2f03d02..10ed009 100644
--- a/packages/PackageInstaller/res/values-bs/strings.xml
+++ b/packages/PackageInstaller/res/values-bs/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacija je instalirana."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Želite li instalirati ovu aplikaciju?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Želite li ažurirati ovu aplikaciju?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Ažuriranjima ove aplikacije trenutno upravlja <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAžuriranjem ćete dobivati buduća ažuriranja od <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Ažuriranjima ove aplikacije trenutno upravlja <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nŽelite li instalirati ažuriranje od <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacija nije instalirana."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instaliranje ovog paketa je blokirano."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija nije instalirana jer paket nije usaglašen s postojećim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-ca/strings.xml b/packages/PackageInstaller/res/values-ca/strings.xml
index 369c33b..337e6d9 100644
--- a/packages/PackageInstaller/res/values-ca/strings.xml
+++ b/packages/PackageInstaller/res/values-ca/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"S\'ha instal·lat l\'aplicació."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vols instal·lar aquesta aplicació?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vols actualitzar aquesta aplicació?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Actualment, <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> gestiona les actualitzacions d\'aquesta aplicació.\n\nSi l\'actualitzes, obtindràs novetats de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> en el futur."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Actualment, <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> gestiona les actualitzacions d\'aquesta aplicació.\n\nVols instal·lar aquesta actualització de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"No s\'ha instal·lat l\'aplicació."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"El paquet s\'ha bloquejat perquè no es pugui instal·lar."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"L\'aplicació no s\'ha instal·lat perquè el paquet entra en conflicte amb un d\'existent."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"S\'està desinstal·lant <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"La desinstal·lació ha finalitzat."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"S\'ha desinstal·lat <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"S\'ha suprimit el clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"No s\'ha pogut desinstal·lar."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"No s\'ha pogut desinstal·lar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"S\'està suprimint el clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-cs/strings.xml b/packages/PackageInstaller/res/values-cs/strings.xml
index 85fcfbe..33ec41c1 100644
--- a/packages/PackageInstaller/res/values-cs/strings.xml
+++ b/packages/PackageInstaller/res/values-cs/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikace je nainstalována."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Chcete tuto aplikaci nainstalovat?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Chcete tuto aplikaci aktualizovat?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Aktualizace této aplikace aktuálně spravuje vlastník <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nPokud ji aktualizujete, budete místo toho v budoucnu dostávat aktualizace od vlastníka <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Aktualizace této aplikace aktuálně spravuje vlastník <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nChcete nainstalovat tuto aktualizaci od vlastníka <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikaci nelze nainstalovat."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instalace balíčku byla zablokována."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikaci nelze nainstalovat, protože balíček je v konfliktu se stávajícím balíčkem."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Odinstalace balíčku <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Odinstalace byla dokončena."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Balíček <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> byl odinstalován"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Byl smazán klon balíčku <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Odinstalace se nezdařila."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Odinstalace balíčku <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> se nezdařila."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Mazání klonu <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-da/strings.xml b/packages/PackageInstaller/res/values-da/strings.xml
index b2219a78..657eccb 100644
--- a/packages/PackageInstaller/res/values-da/strings.xml
+++ b/packages/PackageInstaller/res/values-da/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Appen er installeret."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vil du installere denne app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vil du opdatere denne app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Opdateringer af denne app administreres i øjeblikket af <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nNår du opdaterer, vil du fremover få opdateringer fra <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> i stedet."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Opdateringer af denne app administreres i øjeblikket af <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVil du installere denne opdatering fra <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Appen blev ikke installeret."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Pakken blev forhindret i at blive installeret."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Appen blev ikke installeret, da pakken er i strid med en eksisterende pakke."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Afinstallerer <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Afinstallationen er gennemført."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> blev afinstalleret"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Klonen af <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> blev slettet"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Appen blev ikke afinstalleret."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kunne ikke afinstalleres."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Sletter klonen af <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-de/strings.xml b/packages/PackageInstaller/res/values-de/strings.xml
index 0e59529..669bae6 100644
--- a/packages/PackageInstaller/res/values-de/strings.xml
+++ b/packages/PackageInstaller/res/values-de/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App wurde installiert."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Möchtest du diese App installieren?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Möchtest du diese App aktualisieren?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates für diese App werden momentan von <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> verwaltet.\n\nWenn du sie aktualisierst, erhältst du zukünftige Updates stattdessen von <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates für diese App werden momentan von <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> verwaltet.\n\nMöchtest du dieses Update von <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> installieren?"</string>
     <string name="install_failed" msgid="5777824004474125469">"App wurde nicht installiert."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Die Installation des Pakets wurde blockiert."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Die App wurde nicht installiert, da das Paket in Konflikt mit einem bestehenden Paket steht."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> wird deinstalliert…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Deinstallation abgeschlossen."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> deinstalliert"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Duplikat von „<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>“ gelöscht"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Deinstallation fehlgeschlagen."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Deinstallation von <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> fehlgeschlagen."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-Klon wird gelöscht…"</string>
diff --git a/packages/PackageInstaller/res/values-el/strings.xml b/packages/PackageInstaller/res/values-el/strings.xml
index 11cd8f4..ec0cfc7 100644
--- a/packages/PackageInstaller/res/values-el/strings.xml
+++ b/packages/PackageInstaller/res/values-el/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Η εφαρμογή εγκαταστάθηκε."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Θέλετε να εγκαταστήσετε αυτήν την εφαρμογή;"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Θέλετε να ενημερώσετε αυτήν την εφαρμογή;"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Η διαχείριση των ενημερώσεων σε αυτήν την εφαρμογή πραγματοποιείται προς το παρόν από τον κάτοχο <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nΚάνοντας την ενημέρωση, θα λαμβάνετε αντ\' αυτού τις μελλοντικές ενημερώσεις από τον κάτοχο <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Η διαχείριση των ενημερώσεων σε αυτήν την εφαρμογή πραγματοποιείται προς το παρόν από τον κάτοχο <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nΘέλετε να εγκαταστήσετε αυτήν την ενημέρωση από τον κάτοχο <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Η εφαρμογή δεν εγκαταστάθηκε."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Η εγκατάσταση του πακέτου αποκλείστηκε."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Η εφαρμογή δεν εγκαταστάθηκε, επειδή το πακέτο είναι σε διένεξη με κάποιο υπάρχον πακέτο."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Απεγκατάσταση <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Η απεγκατάσταση ολοκληρώθηκε."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Απεγκαταστάθηκε το πακέτο <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Έγινε διαγραφή κλώνου <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Μη επιτυχής απεγκατάσταση."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Μη επιτυχής απεγκατάσταση <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Διαγραφή διπλότυπου εφαρμογής <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-en-rAU/strings.xml b/packages/PackageInstaller/res/values-en-rAU/strings.xml
index 7bcc90f..b718868 100644
--- a/packages/PackageInstaller/res/values-en-rAU/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rAU/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App installed."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> instead."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rCA/strings.xml b/packages/PackageInstaller/res/values-en-rCA/strings.xml
index 1c3197d..03f24c9 100644
--- a/packages/PackageInstaller/res/values-en-rCA/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rCA/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App installed."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> instead."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rGB/strings.xml b/packages/PackageInstaller/res/values-en-rGB/strings.xml
index 7bcc90f..b718868 100644
--- a/packages/PackageInstaller/res/values-en-rGB/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rGB/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App installed."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> instead."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rIN/strings.xml b/packages/PackageInstaller/res/values-en-rIN/strings.xml
index 7bcc90f..b718868 100644
--- a/packages/PackageInstaller/res/values-en-rIN/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rIN/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App installed."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> instead."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rXC/strings.xml b/packages/PackageInstaller/res/values-en-rXC/strings.xml
index a0aaabb..a095216 100644
--- a/packages/PackageInstaller/res/values-en-rXC/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rXC/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎App installed.‎‏‎‎‏‎"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎Do you want to install this app?‎‏‎‎‏‎"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎Do you want to update this app?‎‏‎‎‏‎"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‎Updates to this app are currently managed by ‎‏‎‎‏‏‎<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎By updating, you\'ll get future updates from ‎‏‎‎‏‏‎<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>‎‏‎‎‏‏‏‎ instead.‎‏‎‎‏‎"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‏‎‎Updates to this app are currently managed by ‎‏‎‎‏‏‎<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Do you want to install this update from ‎‏‎‎‏‏‎<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="install_failed" msgid="5777824004474125469">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎App not installed.‎‏‎‎‏‎"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎The package was blocked from being installed.‎‏‎‎‏‎"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎App not installed as package conflicts with an existing package.‎‏‎‎‏‎"</string>
diff --git a/packages/PackageInstaller/res/values-es-rUS/strings.xml b/packages/PackageInstaller/res/values-es-rUS/strings.xml
index 9808e2a..07485ab 100644
--- a/packages/PackageInstaller/res/values-es-rUS/strings.xml
+++ b/packages/PackageInstaller/res/values-es-rUS/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Se instaló la app."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"¿Deseas instalar esta app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"¿Deseas actualizar esta app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"En este momento, las actualizaciones de esta app están administradas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nSi continúas con la actualización, recibirás actualizaciones futuras de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"En este momento, las actualizaciones de esta app están administradas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\n¿Quieres instalar esta actualización de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"No se instaló la app."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Se bloqueó el paquete para impedir la instalación."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"No se instaló la app debido a un conflicto con un paquete."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Se completó la desinstalación."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Se desinstaló <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Se borró el clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"No se pudo completar la desinstalación."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"No se pudo desinstalar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Borrando la clonación de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-es/strings.xml b/packages/PackageInstaller/res/values-es/strings.xml
index de337d3..482ccf6 100644
--- a/packages/PackageInstaller/res/values-es/strings.xml
+++ b/packages/PackageInstaller/res/values-es/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplicación instalada."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"¿Quieres instalar esta aplicación?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"¿Quieres actualizar esta aplicación?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Las actualizaciones de esta aplicación las gestiona <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nSi actualizas, recibirás las futuras actualizaciones por parte de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Las actualizaciones de esta aplicación las gestiona <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\n¿Quieres instalar esta actualización de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"No se ha instalado la aplicación."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Se ha bloqueado la instalación del paquete."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"La aplicación no se ha instalado debido a un conflicto con un paquete."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Se ha completado la desinstalación."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Se ha desinstalado <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Se ha eliminado el clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"No se ha podido completar la desinstalación."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"No se ha podido desinstalar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Eliminando clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-et/strings.xml b/packages/PackageInstaller/res/values-et/strings.xml
index 555c8bf..71b22dba 100644
--- a/packages/PackageInstaller/res/values-et/strings.xml
+++ b/packages/PackageInstaller/res/values-et/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Rakendus on installitud."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Kas soovite selle rakenduse installida?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Kas soovite seda rakendust värskendada?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Selle rakenduse värskendusi haldab praegu <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVärskendamisel saate tulevasi värskendusi hoopis omanikult <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Selle rakenduse värskendusi haldab praegu <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nKas soovite installida omaniku <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> värskenduse."</string>
     <string name="install_failed" msgid="5777824004474125469">"Rakendus pole installitud."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketi installimine blokeeriti."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Rakendust ei installitud, kuna pakett on olemasoleva paketiga vastuolus."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Paketi <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstallimine …"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Desinstallimine on lõpetatud."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> on desinstallitud"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Kustutati üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kloon"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Desinstallimine ebaõnnestus."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstallimine ebaõnnestus."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klooni kustutamine …"</string>
diff --git a/packages/PackageInstaller/res/values-eu/strings.xml b/packages/PackageInstaller/res/values-eu/strings.xml
index 1a50a26..c571020 100644
--- a/packages/PackageInstaller/res/values-eu/strings.xml
+++ b/packages/PackageInstaller/res/values-eu/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Instalatu da aplikazioa."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Aplikazioa instalatu nahi duzu?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Aplikazioa eguneratu nahi duzu?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> arduratzen da aplikazio hau eguneratzeaz.\n\n Eguneratuz gero, hemendik aurrera <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> arduratuko da eguneratzeez."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> arduratzen da aplikazio hau eguneratzeaz.\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> bidez jasotako eguneratze hau instalatu nahi duzu?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Ez da instalatu aplikazioa."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketea instalatzeko aukera blokeatu egin da."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Ez da instalatu aplikazioa, gatazka bat sortu delako lehendik dagoen pakete batekin."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstalatzen…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Desinstalatu da."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Desinstalatu da <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Ezabatu da <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> paketearen klona"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Ezin izan da desinstalatu."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Ezin izan da desinstalatu <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> aplikazioaren klona ezabatzen…"</string>
diff --git a/packages/PackageInstaller/res/values-fa/strings.xml b/packages/PackageInstaller/res/values-fa/strings.xml
index 1c636c7..e9775ce 100644
--- a/packages/PackageInstaller/res/values-fa/strings.xml
+++ b/packages/PackageInstaller/res/values-fa/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"برنامه نصب شد."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"می‌خواهید این برنامه را نصب کنید؟"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"می‌خواهید این برنامه را به‌روزرسانی کنید؟"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"درحال‌حاضر <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> به‌روزرسانی‌های این برنامه را مدیریت می‌کند.\n\nبا به‌روز کردن، به‌روزرسانی‌های آتی را به‌جای مالک قبلی از <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> دریافت خواهید کرد."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"درحال‌حاضر <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> به‌روزرسانی‌های این برنامه را مدیریت می‌کند.\n\nمی‌خواهید این به‌روزرسانی را از <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> نصب کنید؟"</string>
     <string name="install_failed" msgid="5777824004474125469">"برنامه نصب نشد."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"از نصب شدن بسته جلوگیری شد."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"برنامه نصب نشد چون بسته با بسته موجود تداخل دارد."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"درحال حذف نصب <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"حذف نصب انجام شد."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> را حذف نصب کرد"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"همسانه <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> حذف شد"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"حذف نصب انجام نشد."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> باموفقیت حذف نصب شد."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"درحال حذف همسانه <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-fi/strings.xml b/packages/PackageInstaller/res/values-fi/strings.xml
index e117dfb..058633b 100644
--- a/packages/PackageInstaller/res/values-fi/strings.xml
+++ b/packages/PackageInstaller/res/values-fi/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Sovellus on asennettu."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Haluatko asentaa tämän sovelluksen?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Haluatko päivittää tämän sovelluksen?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> hallitsee tämän sovelluksen päivityksiä.\n\nPäivittämisen jälkeen päivityksiä hallitsee <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> hallitsee tämän sovelluksen päivityksiä.\n\nHaluatko ladata tämän päivityksen täältä: <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Sovellusta ei asennettu."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketin asennus estettiin."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Sovellusta ei asennettu, koska paketti on ristiriidassa nykyisen paketin kanssa."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Poistetaan pakettia <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Poisto valmis"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> poistettu"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Kopio (<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>) poistettu"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Poisto epäonnistui."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> on poistettu."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Poistetaan kloonia (<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>)…"</string>
diff --git a/packages/PackageInstaller/res/values-fr-rCA/strings.xml b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
index 8e19690..c1c411c 100644
--- a/packages/PackageInstaller/res/values-fr-rCA/strings.xml
+++ b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Application installée."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Voulez-vous installer cette application?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Voulez-vous mettre à jour cette application?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Les mises à jour pour cette application sont actuellement gérées par <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nEn effectuant une mise à jour, vous recevrez plutôt les futures mises à jour de la part de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Les mises à jour de cette application sont actuellement gérées par <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVoulez-vous installer cette mise à jour de la part de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Application non installée."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"L\'installation du paquet a été bloquée."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"L\'application n\'a pas été installée, car le paquet entre en conflit avec un paquet existant."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Désinstallation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> en cours…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Désinstallation terminée."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"L\'application <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a bien été désinstallée"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Le clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a été supprimé"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Échec de la désinstallation."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"La désinstallation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> n\'a pas réussi."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Suppression du clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-fr/strings.xml b/packages/PackageInstaller/res/values-fr/strings.xml
index b3e76f9..4a61196 100644
--- a/packages/PackageInstaller/res/values-fr/strings.xml
+++ b/packages/PackageInstaller/res/values-fr/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Application installée."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Voulez-vous installer cette appli ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Voulez-vous mettre à jour cette appli ?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Les mises à jour de cette appli sont actuellement gérées par <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nEn procédant à la mise à jour, vous recevrez les futures mises à jour de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> à la place."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Les mises à jour de cette appli sont actuellement gérées par <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVoulez-vous installer cette mise à jour de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Application non installée."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"L\'installation du package a été bloquée."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"L\'application n\'a pas été installée, car le package est en conflit avec un package déjà présent."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Désinstallation de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Désinstallation terminée."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a été désinstallé"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> supprimé"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Échec de la désinstallation."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Échec de la désinstallation du package <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Suppression du clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-gl/strings.xml b/packages/PackageInstaller/res/values-gl/strings.xml
index b3d9973..6a37d7b 100644
--- a/packages/PackageInstaller/res/values-gl/strings.xml
+++ b/packages/PackageInstaller/res/values-gl/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Instalouse a aplicación."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Queres instalar esta aplicación?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Queres actualizar esta aplicación?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Actualmente, as actualizacións desta aplicación xestiónaas <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nSe a actualizas, as futuras actualizacións recibiralas de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Actualmente, as actualizacións desta aplicación xestiónaas <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nQueres instalar esta actualización de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Non se instalou a aplicación"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Bloqueouse a instalación do paquete."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"A aplicación non se instalou porque o paquete presenta un conflito cun paquete que xa hai."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Finalizou a desinstalación."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Desinstalouse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Eliminouse o clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Produciuse un erro na desinstalación."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"A desinstalación de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> non se realizou correctamente."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Eliminando clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-gu/strings.xml b/packages/PackageInstaller/res/values-gu/strings.xml
index 0831270..863c1aa 100644
--- a/packages/PackageInstaller/res/values-gu/strings.xml
+++ b/packages/PackageInstaller/res/values-gu/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ઍપ્લિકેશન ઇન્સ્ટૉલ કરી."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"શું તમે આ ઍપ ઇન્સ્ટૉલ કરવા માગો છો?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"શું તમે આ ઍપ અપડેટ કરવા માગો છો?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"આ ઍપની અપડેટને હાલમાં <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> દ્વારા મેનેજ કરવામાં આવે છે.\n\nઅપડેટ કરવાથી, તમને તેના બદલે <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> તરફથી ભવિષ્યની અપડેટ પ્રાપ્ત થશે."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"આ ઍપની અપડેટને હાલમાં <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> દ્વારા મેનેજ કરવામાં આવે છે.\n\nશું તમે <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> તરફથી આ અપડેટ ઇન્સ્ટૉલ કરવા માગો છો."</string>
     <string name="install_failed" msgid="5777824004474125469">"ઍપ્લિકેશન ઇન્સ્ટૉલ કરી નથી."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"પૅકેજને ઇન્સ્ટૉલ થવાથી બ્લૉક કરવામાં આવ્યું હતું."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"પૅકેજનો અસ્તિત્વમાંના પૅકેજ સાથે વિરોધાભાસ હોવાને કારણે ઍપ્લિકેશન ઇન્સ્ટૉલ થઈ નથી."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ને અનઇન્સ્ટૉલ કરી રહ્યાં છીએ…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"અનઇન્સ્ટૉલ કરવાનું સમાપ્ત થયું."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> અનઇન્સ્ટૉલ કર્યું"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ની ક્લોન ડિલીટ કરવામાં આવી"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"અનઇન્સ્ટૉલ કરવું નિષ્ફળ રહ્યું."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ને અનઇન્સ્ટૉલ કરવું અસફળ રહ્યું."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ની ક્લોન ડિલીટ કરી રહ્યાં છીએ…"</string>
diff --git a/packages/PackageInstaller/res/values-hi/strings.xml b/packages/PackageInstaller/res/values-hi/strings.xml
index 43e6e4d..3339d35 100644
--- a/packages/PackageInstaller/res/values-hi/strings.xml
+++ b/packages/PackageInstaller/res/values-hi/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ऐप्लिकेशन इंस्‍टॉल हो गया."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"क्या आपको यह ऐप्लिकेशन इंस्टॉल करना है?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"क्या आप इस ऐप्लिकेशन को अपडेट करना चाहते हैं?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"फ़िलहाल, इस ऐप्लिकेशन के अपडेट <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> मैनेज करता है.\n\nऐप्लिकेशन अपडेट करने के बाद, नए अपडेट <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> से मिलेंगे."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"फ़िलहाल, इस ऐप्लिकेशन के अपडेट <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> मैनेज करता है.\n\nक्या यह अपडेट <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> से करवाना है."</string>
     <string name="install_failed" msgid="5777824004474125469">"ऐप्लिकेशन इंस्‍टॉल नहीं हुआ."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"पैकेज को इंस्टॉल होने से ब्लॉक किया हुआ है."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ऐप्लिकेशन इंस्टॉल नहीं हुआ क्योंकि पैकेज का किसी मौजूदा पैकेज से विरोध है."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल किया जा रहा है…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"अनइंस्टॉल हो गया."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल किया गया"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> का क्लोन मिटा दिया गया है"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"अनइंस्टॉल नहीं किया जा सका."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> को अनइंस्टॉल नहीं किया जा सका."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> का क्लोन मिटाया जा रहा है…"</string>
diff --git a/packages/PackageInstaller/res/values-hr/strings.xml b/packages/PackageInstaller/res/values-hr/strings.xml
index 8e7f6fe..8961b851 100644
--- a/packages/PackageInstaller/res/values-hr/strings.xml
+++ b/packages/PackageInstaller/res/values-hr/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacija je instalirana."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Želite li instalirati ovu aplikaciju?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Želite li ažurirati ovu aplikaciju?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Ažuriranjima ove aplikacije trenutačno upravlja <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAko je ažurirate, buduća ažuriranja primat ćete od vlasnika <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Ažuriranjima ove aplikacije trenutačno upravlja <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nŽelite li instalirati ažuriranje od vlasnika <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacija nije instalirana."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instaliranje paketa blokirano je."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija koja nije instalirana kao paket u sukobu je s postojećim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-hu/strings.xml b/packages/PackageInstaller/res/values-hu/strings.xml
index 79b1f3d..db085ca 100644
--- a/packages/PackageInstaller/res/values-hu/strings.xml
+++ b/packages/PackageInstaller/res/values-hu/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Alkalmazás telepítve."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Telepíti ezt az alkalmazást?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Frissíti ezt az alkalmazást?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Az alkalmazást érintő frissítéseket jelenleg <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> kezeli.\n\nA mostani frissítés után a jövőbeli frissítéseket helyette tőle érkeznek majd: <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Az alkalmazást érintő frissítéseket jelenleg <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> kezeli.\n\nSzeretné telepíteni a tőle származó frissítést: <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Az alkalmazás nincs telepítve."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"A csomag telepítését letiltotta a rendszer."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"A nem csomagként telepített alkalmazás ütközik egy már létező csomaggal."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"A(z) <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> eltávolítása folyamatban van…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Az eltávolítás befejeződött."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"A(z) <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> eltávolítása befejeződött"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klónja törölve"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Az eltávolítás sikertelen."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"A(z) <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> eltávolítása nem sikerült."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Klónozott <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> törlése…"</string>
diff --git a/packages/PackageInstaller/res/values-hy/strings.xml b/packages/PackageInstaller/res/values-hy/strings.xml
index 4b0b549..211d5bc 100644
--- a/packages/PackageInstaller/res/values-hy/strings.xml
+++ b/packages/PackageInstaller/res/values-hy/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Հավելվածը տեղադրված է:"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Տեղադրե՞լ այս հավելվածը:"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Թարմացնե՞լ այս հավելվածը։"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Այս հավելվածի թարմացումները ներկայումս կառավարվում են <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>-ի կողմից։\n\nԹարմացնելով՝ դուք հետագայում թարմացումներ կստանաք <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>-ից։"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Այս հավելվածի թարմացումները ներկայումս կառավարվում են <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>-ի կողմից։\n\nՈւզո՞ւմ եք տեղադրել այս թարմացումը <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>-ից։"</string>
     <string name="install_failed" msgid="5777824004474125469">"Հավելվածը տեղադրված չէ:"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Փաթեթի տեղադրումն արգելափակվել է:"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Հավելվածը չի տեղադրվել, քանի որ տեղադրման փաթեթն ունի հակասություն առկա փաթեթի հետ:"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> հավելվածն ապատեղադրվում է…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Ապատեղադրվեց:"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> հավելվածն ապատեղադրվեց"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> կլոնը ջնջվել է"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Չհաջողվեց ապատեղադրել:"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Չհաջողվեց ապատեղադրել <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> հավելվածը:"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-ի կրկնօրինակը ջնջվում է…"</string>
diff --git a/packages/PackageInstaller/res/values-in/strings.xml b/packages/PackageInstaller/res/values-in/strings.xml
index a50bf0c..ed6d23f 100644
--- a/packages/PackageInstaller/res/values-in/strings.xml
+++ b/packages/PackageInstaller/res/values-in/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikasi terinstal."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ingin menginstal aplikasi ini?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ingin mengupdate aplikasi ini?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Update aplikasi ini sekarang dikelola oleh <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDengan mengupdate, Anda akan mendapatkan update mendatang dari <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Update aplikasi ini sekarang dikelola oleh <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nIngin menginstal update ini dari <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikasi tidak terinstal."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paket diblokir sehingga tidak dapat diinstal."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikasi tidak diinstal karena paket ini bentrok dengan paket yang sudah ada."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Meng-uninstal <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Uninstal selesai."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> di-uninstal"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> dihapus"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Uninstal gagal."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Gagal meng-uninstal <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Menghapus clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
diff --git a/packages/PackageInstaller/res/values-is/strings.xml b/packages/PackageInstaller/res/values-is/strings.xml
index 7bfaff4..1da54cb 100644
--- a/packages/PackageInstaller/res/values-is/strings.xml
+++ b/packages/PackageInstaller/res/values-is/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Forritið er uppsett."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Viltu setja upp þetta forrit?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Viltu uppfæra þetta forrit?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> stjórnar uppfærslum þessa forrits eins og er.\n\nMeð því að uppfæra færðu síðari uppfærslur frá <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> í staðinn."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> stjórnar uppfærslum þessa forrits eins og er.\n\nViltu setja upp þessa uppfærslu frá <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Forritið er ekki uppsett."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Lokað var á uppsetningu pakkans."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Forritið var ekki sett upp vegna árekstra á milli pakkans og annars pakka."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Fjarlægir <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Forritið hefur verið fjarlægt."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Fjarlægði <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Afriti af <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> var eytt"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Ekki tókst að fjarlægja forritið."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Ekki tókst að fjarlægja <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Eyðir afriti af <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml
index b3eb19b..c288d96 100644
--- a/packages/PackageInstaller/res/values-it/strings.xml
+++ b/packages/PackageInstaller/res/values-it/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App installata."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vuoi installare questa app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vuoi aggiornare questa app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Gli aggiornamenti a questa app sono attualmente gestiti da <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nEseguendo l\'aggiornamento, gli aggiornamenti futuri saranno forniti invece da <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Gli aggiornamenti a questa app sono attualmente gestiti da <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVuoi installare questo aggiornamento da <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"App non installata."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"È stata bloccata l\'installazione del pacchetto."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App non installata poiché il pacchetto è in conflitto con un pacchetto esistente."</string>
diff --git a/packages/PackageInstaller/res/values-iw/strings.xml b/packages/PackageInstaller/res/values-iw/strings.xml
index 2542f0e..e3893d2 100644
--- a/packages/PackageInstaller/res/values-iw/strings.xml
+++ b/packages/PackageInstaller/res/values-iw/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"האפליקציה הותקנה."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"האם ברצונך להתקין אפליקציה זו?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"האם ברצונך לעדכן אפליקציה זו?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"העדכונים של האפליקציה הזו מנוהלים כרגע על ידי <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nלאחר העדכון הנוכחי, העדכונים העתידיים ינוהלו על ידי <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> במקום זאת."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"העדכונים של האפליקציה הזו מנוהלים כרגע על ידי <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nלהתקין את העדכון הזה של <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"האפליקציה לא הותקנה."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"החבילה נחסמה להתקנה."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"האפליקציה לא הותקנה כי החבילה מתנגשת עם חבילה קיימת."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"המערכת מסירה את ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"הסרת ההתקנה הסתיימה."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> הוסרה"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"מחיקת השכפול של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"לא ניתן היה להסיר את ההתקנה."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"לא ניתן היה להסיר את ההתקנה של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"מחיקת השכפול של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> מתבצעת…"</string>
diff --git a/packages/PackageInstaller/res/values-ja/strings.xml b/packages/PackageInstaller/res/values-ja/strings.xml
index cacd022..fd10940 100644
--- a/packages/PackageInstaller/res/values-ja/strings.xml
+++ b/packages/PackageInstaller/res/values-ja/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"アプリをインストールしました。"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"このアプリをインストールしますか?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"このアプリを更新しますか?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"このアプリのアップデートは現在 <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> によって管理されています。\n\n更新すると、今後は代わりに <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> からアップデートを入手するようになります。"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"このアプリのアップデートは現在 <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> によって管理されています。\n\nこのアップデートを <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> からインストールしますか?"</string>
     <string name="install_failed" msgid="5777824004474125469">"アプリはインストールされていません。"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"パッケージのインストールはブロックされています。"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"パッケージが既存のパッケージと競合するため、アプリをインストールできませんでした。"</string>
diff --git a/packages/PackageInstaller/res/values-ka/strings.xml b/packages/PackageInstaller/res/values-ka/strings.xml
index c100740..507a262 100644
--- a/packages/PackageInstaller/res/values-ka/strings.xml
+++ b/packages/PackageInstaller/res/values-ka/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"აპი დაინსტალირებულია."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"გნებავთ ამ აპის დაყენება?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"გსურთ ამ აპის განახლება?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"ამ აპის განახლებებს ამჟამად მართავს <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nგანახლებით მომავალ განახლებებს მიიღებთ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>-გან."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"ამ აპის განახლებებს ამჟამად მართავს <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nგსურთ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>-გან განახლების ინსტალაცია?"</string>
     <string name="install_failed" msgid="5777824004474125469">"აპი დაუინსტალირებელია."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ამ პაკეტის ინსტალაცია დაბლოკილია."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"აპი ვერ დაინსტალირდა, რადგან პაკეტი კონფლიქტშია არსებულ პაკეტთან."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"მიმდინარეობს <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-ის დეინსტალაცია…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"დეინსტალაცია დასრულდა."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> დეინსტალირებულია"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"წაიშალა <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> კლონი"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"დეინსტალაცია ვერ მოხერხდა."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-ის დეინსტალაცია ვერ მოხერხდა."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"მიმდინარეობს <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> კლონის წაშლა…"</string>
diff --git a/packages/PackageInstaller/res/values-kk/strings.xml b/packages/PackageInstaller/res/values-kk/strings.xml
index b973362..6e11f2a 100644
--- a/packages/PackageInstaller/res/values-kk/strings.xml
+++ b/packages/PackageInstaller/res/values-kk/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Қолданба орнатылды."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Бұл қолданбаны орнатқыңыз келе ме?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Бұл қолданбаны жаңартқыңыз келе ме?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Бұл қолданбаны жаңартуды қазір <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> басқарады.\n\nЖаңартсаңыз, келесі жаңартуды <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> беретін болады."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Бұл қолданбаны жаңартуды қазір <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> басқарады.\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> беретін жаңартуды пайдаланғыңыз келе ме?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Қолданба орнатылмады."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Пакетті орнатуға тыйым салынды."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Жаңа пакет пен бұрыннан бар пакеттің арасында қайшылық туындағандықтан, қолданба орнатылмады."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> жойылуда…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Жою аяқталды."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> жойылды"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клоны жойылды."</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Жою мүмкін болмады."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> жою сәтсіз аяқталды."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клоны жойылып жатыр…"</string>
diff --git a/packages/PackageInstaller/res/values-km/strings.xml b/packages/PackageInstaller/res/values-km/strings.xml
index 7b65679..46e2914 100644
--- a/packages/PackageInstaller/res/values-km/strings.xml
+++ b/packages/PackageInstaller/res/values-km/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"បាន​ដំឡើង​កម្មវិធី។"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"តើ​អ្នក​ចង់​ដំឡើង​កម្មវិធី​នេះ​ដែរទេ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"តើអ្នកចង់ដំឡើងកំណែ​កម្មវិធីនេះដែរទេ?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"បច្ចុប្បន្ន ការដំឡើងកំណែកម្មវិធីនេះត្រូវបានគ្រប់គ្រងដោយ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>។\n\nតាមរយៈការដំឡើងកំណែ អ្នកនឹងទទួលបានកំណែថ្មីៗនៅពេលក្រោយពី <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ជំនួសវិញ។"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"បច្ចុប្បន្ន ការដំឡើងកំណែកម្មវិធីនេះត្រូវបានគ្រប់គ្រងដោយ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>។\n\nតើអ្នកចង់ដំឡើងកំណែថ្មីនេះពី <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ឬ។"</string>
     <string name="install_failed" msgid="5777824004474125469">"មិន​បាន​ដំឡើង​កម្មវិធីទេ។"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"កញ្ចប់ត្រូវបានទប់ស្កាត់​មិន​ឱ្យ​ដំឡើង។"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"កម្មវិធីមិនបានដំឡើងទេ ដោយសារកញ្ចប់កម្មវិធីមិនត្រូវគ្នាជាមួយកញ្ចប់ដែលមានស្រាប់។"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"កំពុងលុប <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"បាន​បញ្ចប់​ការ​លុប។"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"បានលុប <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"ក្លូន <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ដែលបានលុប"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"មិន​អាច​លុប​បានទេ។"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"មិនអាចលុប <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> បានទេ។"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"កំពុងលុបក្លូន <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-kn/strings.xml b/packages/PackageInstaller/res/values-kn/strings.xml
index ab00502..fe8144e 100644
--- a/packages/PackageInstaller/res/values-kn/strings.xml
+++ b/packages/PackageInstaller/res/values-kn/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ಆ್ಯಪ್‌ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ನೀವು ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲು ಬಯಸುವಿರಾ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ನೀವು ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಲು ಬಯಸುವಿರಾ?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"ಈ ಆ್ಯಪ್‌ನ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ಪ್ರಸ್ತುತ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ಅವರು ನಿರ್ವಹಿಸುತ್ತಿದ್ದಾರೆ.\n\nಅಪ್‌ಡೇಟ್ ಮಾಡುವುದರಿಂದ, ಬದಲಿಗೆ ನೀವು ಭವಿಷ್ಯದ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ಅವರಿಂದ ಪಡೆಯುತ್ತೀರಿ."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"ಈ ಆ್ಯಪ್‌ನ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ಪ್ರಸ್ತುತ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ಅವರು ನಿರ್ವಹಿಸುತ್ತಿದ್ದಾರೆ.\n\nನೀವು <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ಅವರ ಈ ಅಪ್‌ಡೇಟ್ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ಬಯಸುವಿರಾ."</string>
     <string name="install_failed" msgid="5777824004474125469">"ಆ್ಯಪ್‌ ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗಿಲ್ಲ."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡುವ ಪ್ಯಾಕೇಜ್‌ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ಪ್ಯಾಕೇಜ್‌ನಂತೆ ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗಿರುವ ಆ್ಯಪ್‌ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಪ್ಯಾಕೇಜ್ ಜೊತೆಗೆ ಸಂಘರ್ಷವಾಗುತ್ತದೆ."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>
     <string name="uninstall_done" msgid="439354138387969269">"ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಪೂರ್ಣಗೊಂಡಿದೆ."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗಿದೆ"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಕ್ಲೋನ್ ಅನ್ನು ಅಳಿಸಲಾಗಿದೆ"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ವಿಫಲವಾಗಿದೆ."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡುವಿಕೆ ಯಶಸ್ವಿಯಾಗಿಲ್ಲ."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಕ್ಲೋನ್ ಅನ್ನು ಅಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
diff --git a/packages/PackageInstaller/res/values-ko/strings.xml b/packages/PackageInstaller/res/values-ko/strings.xml
index c401430..4bfa3cc 100644
--- a/packages/PackageInstaller/res/values-ko/strings.xml
+++ b/packages/PackageInstaller/res/values-ko/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"앱이 설치되었습니다."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"이 앱을 설치하시겠습니까?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"이 앱을 업데이트하시겠습니까?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"이 앱 업데이트는 현재 <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>에서 관리합니다.\n\n업데이트할 경우 대신 <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>에서 향후 업데이트를 제공합니다."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"이 앱 업데이트는 현재 <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>에서 관리합니다.\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>에서 제공하는 업데이트를 설치하시겠습니까?"</string>
     <string name="install_failed" msgid="5777824004474125469">"앱이 설치되지 않았습니다."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"패키지 설치가 차단되었습니다."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"패키지가 기존 패키지와 충돌하여 앱이 설치되지 않았습니다."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 제거 중…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"제거를 완료했습니다."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>를 제거했습니다."</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 클론 삭제됨"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"제거하지 못했습니다."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>을(를) 제거하지 못했습니다."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 클론 삭제 중…"</string>
diff --git a/packages/PackageInstaller/res/values-ky/strings.xml b/packages/PackageInstaller/res/values-ky/strings.xml
index d3d82c3..5888b7b 100644
--- a/packages/PackageInstaller/res/values-ky/strings.xml
+++ b/packages/PackageInstaller/res/values-ky/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Колдонмо орнотулду."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Бул колдонмону орнотоюн деп жатасызбы?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Бул колдонмону жаңыртайын деп жатасызбы?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Бул колдонмонун жаңыртууларын учурда <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> тескеп жатат.\n\nЖаңыртуу менен келечектеги жаңыртууларды анын ордуна <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> жөнөтүп калат."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Бул колдонмонун жаңыртууларын учурда <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> тескеп жатат.\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> жөнөткөн жаңыртуунун чыгарып саласызбы?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Колдонмо орнотулган жок."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Топтомду орнотууга болбойт."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Башка топтом менен дал келбегендиктен колдонмо орнотулган жок."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> чыгарылууда…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Чыгарылып салынды."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> чыгарылып салынды"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клону өчүрүлдү"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Чыгарылып салынган жок."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> чыгарылып салынган жок."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клону өчүрүлүүдө…"</string>
diff --git a/packages/PackageInstaller/res/values-lo/strings.xml b/packages/PackageInstaller/res/values-lo/strings.xml
index 7ab33a9..f9866b0 100644
--- a/packages/PackageInstaller/res/values-lo/strings.xml
+++ b/packages/PackageInstaller/res/values-lo/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ຕິດຕັ້ງແອັບແລ້ວ."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ທ່ານຕ້ອງການຕິດຕັ້ງແອັບນີ້ບໍ່?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ທ່ານຕ້ອງການອັບເດດແອັບນີ້ບໍ່?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"ໃນຕອນນີ້ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ເປັນຜູ້ຈັດການການອັບເດດແອັບນີ້.\n\nຫາກອັບເດດ, ທ່ານຈະໄດ້ຮັບການອັບເດດໃນອະນາຄົດຈາກ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ແທນ."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"ໃນຕອນນີ້ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ເປັນຜູ້ຈັດການການອັບເດດແອັບນີ້.\n\nທ່ານຕ້ອງການຕິດຕັ້ງການອັບເດດນີ້ຈາກ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ຫຼືບໍ່."</string>
     <string name="install_failed" msgid="5777824004474125469">"ບໍ່ໄດ້ຕິດຕັ້ງແອັບເທື່ອ."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ແພັກ​ເກດ​ຖືກບ​ລັອກ​ບໍ່​ໃຫ້​ໄດ້​ຮັບ​ການ​ຕິດ​ຕັ້ງ."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ບໍ່ໄດ້ຕິດຕັ້ງແອັບເນື່ອງຈາກແພັກເກດຂັດແຍ່ງກັບແພັກເກດທີ່ມີຢູ່ກ່ອນແລ້ວ."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"ກຳລັງຖອນການຕິດຕັ້ງ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"ຖອນການຕິດຕັ້ງສຳເລັດແລ້ວ."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"ຖອນການຕິດຕັ້ງ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ແລ້ວ"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"ລຶບສຳເນົາ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ແລ້ວ"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"ຖອນການຕິດຕັ້ງບໍ່ສຳເລັດ."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"ຖອນການຕິດຕັ້ງ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ບໍ່ສຳເລັດ."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"ກຳລັງລຶບ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ໂຄລນ…"</string>
diff --git a/packages/PackageInstaller/res/values-lt/strings.xml b/packages/PackageInstaller/res/values-lt/strings.xml
index 9ffa09c..9bf018b 100644
--- a/packages/PackageInstaller/res/values-lt/strings.xml
+++ b/packages/PackageInstaller/res/values-lt/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Programa įdiegta."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ar norite įdiegti šią programą?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ar norite atnaujinti šią programą?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Šios programos naujinius šiuo metu valdo <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAtnaujinę būsimus naujinius gausite iš <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Šios programos naujinius šiuo metu valdo <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAr norite įdiegti šį naujinį iš <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Programa neįdiegta."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketas užblokuotas ir negali būti įdiegtas."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Programa neįdiegta, nes paketas nesuderinamas su esamu paketu."</string>
diff --git a/packages/PackageInstaller/res/values-lv/strings.xml b/packages/PackageInstaller/res/values-lv/strings.xml
index c3e1a88..823858c 100644
--- a/packages/PackageInstaller/res/values-lv/strings.xml
+++ b/packages/PackageInstaller/res/values-lv/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Lietotne ir instalēta."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vai vēlaties instalēt šo lietotni?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vai vēlaties atjaunināt šo lietotni?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Šīs lietotnes atjauninājumus pašlaik pārvalda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nJa veiksiet atjaunināšanu, turpmākos atjauninājumus nodrošinās <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Šīs lietotnes atjauninājumus pašlaik pārvalda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVai vēlaties instalēt atjauninājumu, ko nodrošina <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Lietotne nav instalēta."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Pakotnes instalēšana tika bloķēta."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Lietotne netika instalēta, jo pastāv pakotnes konflikts ar esošu pakotni."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Notiek lietotnes <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> atinstalēšana…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Atinstalēšana ir pabeigta."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Lietotne <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ir atinstalēta"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Izdzēsts lietotnes <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klons"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Atinstalēšana neizdevās."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Lietotnes <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> atinstalēšana nebija sekmīga."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Notiek lietotnes <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klona dzēšana…"</string>
diff --git a/packages/PackageInstaller/res/values-mk/strings.xml b/packages/PackageInstaller/res/values-mk/strings.xml
index e100257..6135e65 100644
--- a/packages/PackageInstaller/res/values-mk/strings.xml
+++ b/packages/PackageInstaller/res/values-mk/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Апликацијата е инсталирана."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Дали сакате да ја инсталирате апликацијава?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Дали сакате да ја ажурирате апликацијава?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Ажурирањата на апликацијава тековно се управуваат од <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nСо ажурирање, ќе добивате ажурирања во иднината од <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Ажурирањата на апликацијава тековно се управуваат од <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nДали сакате да го инсталирате ажурирањево од <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Апликацијата не е инсталирана."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Инсталирањето на пакетот е блокирано."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Апликација што не е инсталирана како пакет е во конфликт со постоечки пакет."</string>
diff --git a/packages/PackageInstaller/res/values-ml/strings.xml b/packages/PackageInstaller/res/values-ml/strings.xml
index ca1ae38..43cac7a 100644
--- a/packages/PackageInstaller/res/values-ml/strings.xml
+++ b/packages/PackageInstaller/res/values-ml/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്‌തു."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ഈ ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യണോ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ഈ ആപ്പ് അപ്‌ഡേറ്റ് ചെയ്യണോ?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"ഈ ആപ്പിലെ അപ്‌ഡേറ്റുകൾ നിലവിൽ മാനേജ് ചെയ്യുന്നത് <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ആണ്.\n\nഅപ്‌ഡേറ്റ് ചെയ്യുന്നതിലൂടെ, പകരം നിങ്ങൾക്ക് ഭാവി അപ്‌ഡേറ്റുകൾ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> എന്നയാളിൽ നിന്ന് ലഭിക്കും."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"ഈ ആപ്പിലെ അപ്‌ഡേറ്റുകൾ നിലവിൽ മാനേജ് ചെയ്യുന്നത് <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ആണ്.\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> എന്നയാളിൽ നിന്ന് ഈ അപ്ഡേറ്റ് ഇൻസ്‌റ്റാൾ ചെയ്യാൻ നിങ്ങൾ താൽപ്പര്യപ്പെടുന്നുണ്ടോ."</string>
     <string name="install_failed" msgid="5777824004474125469">"ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്‌തിട്ടില്ല."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"പാക്കേജ് ഇൻസ്‌റ്റാൾ ചെയ്യുന്നത് ബ്ലോക്ക് ചെയ്‌തു."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"പാക്കേജിന് നിലവിലുള്ള പാക്കേജുമായി പൊരുത്തക്കേടുള്ളതിനാൽ, ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്‌തില്ല."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> അൺ ഇൻസ്‌റ്റാൾ ചെയ്യുന്നു…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"അൺ ഇൻസ്‌റ്റാൾ ചെയ്യൽ പൂർത്തിയായി."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> അൺ ഇൻസ്‌റ്റാൾ ചെയ്‌തു"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ക്ലോൺ ഇല്ലാതാക്കി"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"അൺ ഇൻസ്‌റ്റാൾ ചെയ്യാനായില്ല."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> അൺ ഇൻസ്‌റ്റാൾ ചെയ്യാനായില്ല."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ക്ലോൺ ചെയ്യൽ ഇല്ലാതാക്കുന്നു…"</string>
diff --git a/packages/PackageInstaller/res/values-mn/strings.xml b/packages/PackageInstaller/res/values-mn/strings.xml
index 3be98b5..52bca70 100644
--- a/packages/PackageInstaller/res/values-mn/strings.xml
+++ b/packages/PackageInstaller/res/values-mn/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Аппыг суулгасан."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Та энэ аппыг суулгахыг хүсэж байна уу?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Та энэ аппыг шинэчлэхийг хүсэж байна уу?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Энэ аппын шинэчлэлтийг одоогоор <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>-с удирддаг.\n\nШинэчилснээр та цаашдын шинэчлэлтийг оронд нь <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>-с авна."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Энэ аппын шинэчлэлтийг одоогоор <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>-с удирддаг.\n\nТа <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>-н энэ шинэчлэлтийг суулгахыг хүсэж байна уу?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Аппыг суулгаагүй."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Багц суулгахыг блоклосон байна."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Багц одоо байгаа багцтай тохирохгүй байгаа тул аппыг суулгаж чадсангүй."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-г устгаж байна…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Устгаж дууслаа."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-г устгасан"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клоныг устгасан"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Устгах амжилтгүй боллоо."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-г устгах амжилтгүй боллоо."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клоныг устгаж байна…"</string>
diff --git a/packages/PackageInstaller/res/values-mr/strings.xml b/packages/PackageInstaller/res/values-mr/strings.xml
index ffd6610..8a4ff44 100644
--- a/packages/PackageInstaller/res/values-mr/strings.xml
+++ b/packages/PackageInstaller/res/values-mr/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"अ‍ॅप इंस्टॉल झाले."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"तुम्हाला हे ॲप इंस्टॉल करायचे आहे का?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"तुम्हाला हे ॲप अपडेट करायचे आहे का?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"या अ‍ॅपसाठीचे अपडेट सध्या <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> द्वारे व्यवस्थापित केले जात आहेत.\n\nत्या ऐवजी, अपडेट केल्याने, तुम्हाला भविष्यातील अपडेट <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> कडून मिळतील."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"या अ‍ॅपसाठीचे अपडेट सध्या <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> द्वारे व्यवस्थापित केले जात आहेत.\n\nतुम्हाला हे अपडेट <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> कडून इंस्टॉल करायचे आहे का."</string>
     <string name="install_failed" msgid="5777824004474125469">"अ‍ॅप इंस्टॉल झाले नाही."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"पॅकेज इंस्टॉल होण्यापासून ब्लॉक केले होते."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"पॅकेजचा विद्यमान पॅकेजशी विरोध असल्याने अ‍ॅप इंस्टॉल झाले नाही."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल करत आहे…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"अनइंस्टॉल पूर्ण झाले."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल केले"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> क्लोन हटवला आहे"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"अनइंस्टॉल करता आले नाही."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइंस्टॉल करता आले नाही."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"क्लोन <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> हटवत आहे…"</string>
diff --git a/packages/PackageInstaller/res/values-ms/strings.xml b/packages/PackageInstaller/res/values-ms/strings.xml
index 1c369bc..13531bd 100644
--- a/packages/PackageInstaller/res/values-ms/strings.xml
+++ b/packages/PackageInstaller/res/values-ms/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikasi dipasang."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Adakah anda ingin memasang aplikasi ini?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Adakah anda mahu mengemas kini apl ini?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Kemaskinian pada apl ini diuruskan oleh <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> pada masa ini.\n\nDengan membuat pengemaskinian, anda akan mendapat kemaskinian akan datang daripada <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Kemaskinian pada apl ini diuruskan oleh <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> pada masa ini.\n\nAdakah anda mahu memasang kemaskinian ini daripada <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikasi tidak dipasang."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Pakej ini telah disekat daripada dipasang."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Apl tidak dipasang kerana pakej bercanggah dengan pakej yang sedia ada."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Menyahpasang <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Nyahpasang selesai."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> dinyahpasang"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Klon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> dipadamkan"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Penyahpasangan tidak berjaya."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Tidak berjaya menyahpasang <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Memadamkan klon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-my/strings.xml b/packages/PackageInstaller/res/values-my/strings.xml
index 08135d2..4dbf3fc 100644
--- a/packages/PackageInstaller/res/values-my/strings.xml
+++ b/packages/PackageInstaller/res/values-my/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"အက်ပ်ထည့်သွင်းပြီးပါပြီ။"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ဤအက်ပ်ကို ထည့်သွင်းလိုသလား။"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ဤအက်ပ်ကို အပ်ဒိတ်လုပ်လိုသလား။"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"ဤအက်ပ်ရှိ အပ်ဒိတ်များကို လောလောဆယ်တွင် <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> က စီမံထားသည်။\n\n၎င်းအစား အပ်ဒိတ်လုပ်ခြင်းဖြင့် <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ထံမှ နောက်အပ်ဒိတ်များ ရရှိပါမည်။"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"ဤအက်ပ်ရှိ အပ်ဒိတ်များကို လောလောဆယ်တွင် <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> က စီမံထားသည်။\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ထံမှ ဤအပ်ဒိတ်ကို ထည့်သွင်းလိုပါသလား။"</string>
     <string name="install_failed" msgid="5777824004474125469">"အက်ပ်မထည့်သွင်းရသေးပါ"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ပက်ကေ့ဂျ်ထည့်သွင်းခြင်းကို ပိတ်ထားသည်။"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ပက်ကေ့ဂျ်အဖြစ် ထည့်သွင်းမထားသော အက်ပ်သည် လက်ရှိပက်ကေ့ဂျ်နှင့် တိုက်နေသည်။"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ကို ဖယ်ရှားနေပါသည်…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"ဖယ်ရှားပြီးပါပြီ။"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ကို ဖယ်ရှားလိုက်ပါပြီ"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ပုံတူပွားကို ဖျက်လိုက်ပါပြီ"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"ဖယ်ရှား၍ မရပါ။"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ကို ဖယ်ရှား၍မရပါ။"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ပုံတူပွားကို ဖျက်နေသည်…"</string>
diff --git a/packages/PackageInstaller/res/values-nb/strings.xml b/packages/PackageInstaller/res/values-nb/strings.xml
index ad49d525..8ec94e0 100644
--- a/packages/PackageInstaller/res/values-nb/strings.xml
+++ b/packages/PackageInstaller/res/values-nb/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Appen er installert."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vil du installere denne appen?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vil du oppdatere denne appen?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Oppdateringer for denne appen administreres nå av <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVed å oppdatere får du fremtidige oppdateringer fra <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> i stedet."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Oppdateringer for denne appen administreres nå av <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVil du installere denne oppdateringen fra <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Appen ble ikke installert."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Pakken er blokkert fra å bli installert."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Appen ble ikke installert fordi pakken er i konflikt med en eksisterende pakke."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Avinstallerer <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Avinstalleringen er fullført."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Avinstallerte <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Klonen av <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> er slettet"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Avinstalleringen mislyktes."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Kunne ikke avinstallere <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Sletter <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-klonen …"</string>
diff --git a/packages/PackageInstaller/res/values-ne/strings.xml b/packages/PackageInstaller/res/values-ne/strings.xml
index 034c6f6..e763ae1 100644
--- a/packages/PackageInstaller/res/values-ne/strings.xml
+++ b/packages/PackageInstaller/res/values-ne/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"एप इन्स्टल गरियो।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"तपाईं यो एप इन्स्टल गर्न चाहनुहुन्छ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"तपाईं यो एप अपडेट गर्न चाहनुहुन्छ?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ले हाल यो एपका अपडेटहरू व्यवस्थापन गर्छ।\n\nतपाईंले अपडेट गर्नुभयो भने तपाईं भविष्यमा <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> बाट अपडेटहरू प्राप्त गर्नु हुने छ।"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ले हाल यो एपका अपडेटहरू व्यवस्थापन गर्छ।\n\nतपाईं <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ले उपलब्ध गराएको यो अपडेट इन्स्टल गर्न चाहनुहुन्छ?"</string>
     <string name="install_failed" msgid="5777824004474125469">"एप स्थापना गरिएन।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"यो प्याकेज स्थापना गर्ने क्रममा अवरोध गरियो।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"प्याकेजका रूपमा स्थापना नगरिएको एप विद्यमान प्याकेजसँग मेल खाँदैन।"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> को स्थापना रद्द गर्दै…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"स्थापना रद्द गर्ने काम सम्पन्न भयो।"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> अनइन्स्टल गरियो"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> क्लोन मेटाइयो"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"स्थापना रद्द गर्न सकिएन।"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> को स्थापना रद्द गर्ने कार्य असफल भयो।"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> क्लोन मेटाइँदै छ…"</string>
diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml
index 1a73282..c0a3c8e 100644
--- a/packages/PackageInstaller/res/values-nl/strings.xml
+++ b/packages/PackageInstaller/res/values-nl/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App geïnstalleerd."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Wil je deze app installeren?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Wil je deze app updaten?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates voor deze app worden momenteel beheerd door <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAls je updatet, krijg je volgende updates in plaats daarvan van <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates voor deze app worden momenteel beheerd door <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nWil je deze update van <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> installeren?"</string>
     <string name="install_failed" msgid="5777824004474125469">"App niet geïnstalleerd."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"De installatie van het pakket is geblokkeerd."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"App die niet is geïnstalleerd als pakket conflicteert met een bestaand pakket."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> verwijderen…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Verwijdering voltooid."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> verwijderd"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Kloon van <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> verwijderd"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Verwijdering mislukt."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kan niet worden verwijderd."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-kloon verwijderen…"</string>
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
index 95ad470..965c7d8a 100644
--- a/packages/PackageInstaller/res/values-or/strings.xml
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ଆପ ଇନଷ୍ଟଲ ହୋଇଗଲା।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ଆପଣ ଏହି ଆପକୁ ଇନଷ୍ଟଲ୍ କରିବା ପାଇଁ ଚାହୁଁଛନ୍ତି କି?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ଆପଣ ଏହି ଆପକୁ ଅପଡେଟ୍ କରିବା ପାଇଁ ଚାହୁଁଛନ୍ତି କି?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"ଏହି ଆପରେ ଅପଡେଟଗୁଡ଼ିକ ବର୍ତ୍ତମାନ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ଦ୍ୱାରା ପରିଚାଳିତ ହେଉଛି।\n\nଅପଡେଟ କରି, ଆପଣ ଏହା ପରିବର୍ତ୍ତେ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>ରୁ ଭବିଷ୍ୟତର ଅପଡେଟଗୁଡ଼ିକ ପାଇବେ।"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"ଏହି ଆପରେ ଅପଡେଟଗୁଡ଼ିକ ବର୍ତ୍ତମାନ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ଦ୍ୱାରା ପରିଚାଳିତ ହେଉଛି।\n\nଆପଣ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>ରୁ ଏହି ଅପଡେଟ ଇନଷ୍ଟଲ କରିବାକୁ ଚାହାଁନ୍ତି?"</string>
     <string name="install_failed" msgid="5777824004474125469">"ଆପ୍‍ ଇନଷ୍ଟଲ୍‌ ହୋଇନାହିଁ।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ଏହି ପ୍ୟାକେଜ୍‌କୁ ଇନଷ୍ଟଲ୍‍ କରାଯିବାରୁ ଅବରୋଧ କରାଯାଇଥିଲା।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ପୂର୍ବରୁ ଥିବା ପ୍ୟାକେଜ୍‍ ସହ ଏହି ପ୍ୟାକେଜ୍‌ର ସମସ୍ୟା ଉପୁଯିବାରୁ ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ ହୋଇପାରିଲା ନାହିଁ।"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ଅନଇନଷ୍ଟଲ୍‍ କରାଯାଉଛି…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"ଅନଇନଷ୍ଟଲ୍‌ ହୋଇଗଲା।"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>କୁ ଅନଇନଷ୍ଟଲ୍‌ କରାଗଲା"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ର କ୍ଲୋନକୁ ଡିଲିଟ କରାଯାଇଛି"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"ଅନଇନଷ୍ଟଲ୍‌ କରିହେଲା ନାହିଁ।"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ଅନଇନଷ୍ଟଲ୍‍ କରିବା ସଫଳ ହେଲାନାହିଁ।"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> କ୍ଲୋନକୁ ଡିଲିଟ କରାଯାଉଛି…"</string>
diff --git a/packages/PackageInstaller/res/values-pa/strings.xml b/packages/PackageInstaller/res/values-pa/strings.xml
index 9e6b9b8..2a3068c 100644
--- a/packages/PackageInstaller/res/values-pa/strings.xml
+++ b/packages/PackageInstaller/res/values-pa/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ਐਪ ਸਥਾਪਤ ਕੀਤੀ ਗਈ।"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"ਫ਼ਿਲਹਾਲ ਇਸ ਐਪ ਦੇ ਅੱਪਡੇਟਾਂ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।\n\nਅੱਪਡੇਟ ਕਰਨ ਨਾਲ, ਇਸਦੀ ਬਜਾਏ ਤੁਹਾਨੂੰ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ਤੋਂ ਭਵਿੱਖੀ ਅੱਪਡੇਟ ਪ੍ਰਾਪਤ ਹੋਣਗੇ।"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"ਫ਼ਿਲਹਾਲ ਇਸ ਐਪ ਦੇ ਅੱਪਡੇਟਾਂ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।\n\nਕੀ ਤੁਸੀਂ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ਵੱਲੋਂ ਇਸ ਅੱਪਡੇਟ ਨੂੰ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ।"</string>
     <string name="install_failed" msgid="5777824004474125469">"ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ਪੈਕੇਜ ਨੂੰ ਸਥਾਪਤ ਹੋਣ ਤੋਂ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਸੀ।"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ਪੈਕੇਜ ਦੇ ਇੱਕ ਮੌਜੂਦਾ ਪੈਕੇਜ ਨਾਲ ਵਿਵਾਦ ਹੋਣ ਕਰਕੇ ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਨੂੰ ਅਣਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"ਅਣਸਥਾਪਤ ਕਰਨਾ ਮੁਕੰਮਲ ਹੋਇਆ।"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਨੂੰ ਅਣਸਥਾਪਤ ਕੀਤਾ ਗਿਆ"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਕਲੋਨ ਨੂੰ ਮਿਟਾਇਆ ਗਿਆ"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"ਅਣਸਥਾਪਤ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ।"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਨੂੰ ਅਣਸਥਾਪਤ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ।"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਦੇ ਕਲੋਨ ਨੂੰ ਮਿਟਾਇਆ ਜਾ ਰਿਹਾ ਹੈ…"</string>
diff --git a/packages/PackageInstaller/res/values-pl/strings.xml b/packages/PackageInstaller/res/values-pl/strings.xml
index 6784325..dc4e0c9 100644
--- a/packages/PackageInstaller/res/values-pl/strings.xml
+++ b/packages/PackageInstaller/res/values-pl/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacja została zainstalowana."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Zainstalować tę aplikację?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Zaktualizować tę aplikację?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Aktualizacjami tej aplikacji zarządza obecnie <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nJeśli pobierzesz aktualizację, przyszłe aktualizacje będzie zapewniać <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Aktualizacjami tej aplikacji zarządza obecnie <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nChcesz zainstalować tę aktualizację ze źródła <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacja nie została zainstalowana."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instalacja pakietu została zablokowana."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacja nie została zainstalowana, bo powoduje konflikt z istniejącym pakietem."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Odinstalowuję <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Odinstalowywanie zakończone."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Odinstalowano aplikację <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Usunięto klon aplikacji <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Nie udało się odinstalować."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Nie udało się odinstalować pakietu <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Usuwam klona aplikacji <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-pt-rBR/strings.xml b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
index 8514aeb..a5ee82b 100644
--- a/packages/PackageInstaller/res/values-pt-rBR/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App instalado."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Quer instalar esse app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Quer atualizar esse app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"No momento, as atualizações deste app são gerenciadas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAo atualizar, você receberá as atualizações futuras de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"No momento, as atualizações deste app são gerenciadas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nGostaria de instalar esta atualização de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"O app não foi instalado."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"A instalação do pacote foi bloqueada."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Como o pacote tem um conflito com um pacote já existente, o app não foi instalado."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Desinstalação concluída."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstalado"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"O clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> foi excluído"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Falha na desinstalação."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Falha na desinstalação de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Excluindo o clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-pt-rPT/strings.xml b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
index 248c366..9e80a97 100644
--- a/packages/PackageInstaller/res/values-pt-rPT/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App instalada."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Instalar esta app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Pretende atualizar esta app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Atualmente, as atualizações desta app são geridas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAo atualizar, vai obter atualizações futuras de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Atualmente, as atualizações desta app são geridas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nQuer instalar esta atualização de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplicação não instalada."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Foi bloqueada a instalação do pacote."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"A app não foi instalada porque o pacote entra em conflito com um pacote existente."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"A desinstalar a app <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Desinstalação concluída."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"A app <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> foi desinstalada"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> apagado"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Desinstalação sem êxito."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Falha ao desinstalar a app <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"A apagar o clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-pt/strings.xml b/packages/PackageInstaller/res/values-pt/strings.xml
index 8514aeb..a5ee82b 100644
--- a/packages/PackageInstaller/res/values-pt/strings.xml
+++ b/packages/PackageInstaller/res/values-pt/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"App instalado."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Quer instalar esse app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Quer atualizar esse app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"No momento, as atualizações deste app são gerenciadas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAo atualizar, você receberá as atualizações futuras de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"No momento, as atualizações deste app são gerenciadas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nGostaria de instalar esta atualização de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"O app não foi instalado."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"A instalação do pacote foi bloqueada."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Como o pacote tem um conflito com um pacote já existente, o app não foi instalado."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Desinstalando <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Desinstalação concluída."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstalado"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"O clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> foi excluído"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Falha na desinstalação."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Falha na desinstalação de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Excluindo o clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-ro/strings.xml b/packages/PackageInstaller/res/values-ro/strings.xml
index 2dc2b0c..09693bf 100644
--- a/packages/PackageInstaller/res/values-ro/strings.xml
+++ b/packages/PackageInstaller/res/values-ro/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplicație instalată."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vrei să instalezi această aplicație?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vrei să actualizezi această aplicație?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Actualizările acestei aplicații sunt gestionate de <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDacă actualizezi, vei primi actualizări de la <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Actualizările acestei aplicații sunt gestionate de <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVrei să instalezi această actualizare de la <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplicația nu a fost instalată."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instalarea pachetului a fost blocată."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplicația nu a fost instalată deoarece pachetul intră în conflict cu un pachet existent."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Se dezinstalează <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Dezinstalare finalizată."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> s-a dezinstalat"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Clona pentru <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> a fost ștearsă"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Dezinstalare nefinalizată."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nu s-a putut dezinstala."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Se șterge clona <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-ru/strings.xml b/packages/PackageInstaller/res/values-ru/strings.xml
index e811b4e..957f294 100644
--- a/packages/PackageInstaller/res/values-ru/strings.xml
+++ b/packages/PackageInstaller/res/values-ru/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Приложение установлено."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Установить приложение?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Обновить приложение?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"В настоящее время обновлениями этого приложения управляет <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nЕсли вы установите обновление, то все последующие будете получать от <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"В настоящее время обновлениями этого приложения управляет <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nВы хотите установить это обновление от <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Приложение не установлено."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Установка пакета заблокирована."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Приложение не установлено, так как оно конфликтует с другим пакетом."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Удаление приложения \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Удаление завершено."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Приложение \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\" удалено."</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Клон приложения \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\" удален."</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"При удалении произошла ошибка."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Не удалось удалить приложение \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Удаление клона пакета \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"…"</string>
diff --git a/packages/PackageInstaller/res/values-si/strings.xml b/packages/PackageInstaller/res/values-si/strings.xml
index dfd88ef..cfe29cb 100644
--- a/packages/PackageInstaller/res/values-si/strings.xml
+++ b/packages/PackageInstaller/res/values-si/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"යෙදුම ස්ථාපනය කර ඇත."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"මෙම යෙදුම ස්ථාපනය කිරීමට ඔබට අවශ්‍යද?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"ඔබට මෙම යෙදුම යාවත්කාලීන කිරීමට අවශ්‍යද?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"මෙම යෙදුම වෙත යාවත්කාලීන කිරීම් දැනට <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> විසින් කළමනාකරණය කරනු ලැබේ.\n\nයාවත්කාලීන කිරීමෙන්, ඔබට <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> වෙතින් අනාගත යාවත්කාලීන ලැබෙනු ඇත."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"මෙම යෙදුම වෙත යාවත්කාලීන කිරීම් දැනට <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> විසින් කළමනාකරණය කරනු ලැබේ.\n\nඔබට <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> වෙතින් මෙම යාවත්කාලීනය ස්ථාපනය කිරීමට අවශ්‍ය ද?"</string>
     <string name="install_failed" msgid="5777824004474125469">"යෙදුම ස්ථාපනය කර නැත."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"මෙම පැකේජය ස්ථාපනය කිරීම අවහිර කරන ලදි."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"පැකේජය දැනට පවතින පැකේජයක් සමග ගැටෙන නිසා යෙදුම ස්ථාපනය නොකරන ලදී."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> අස්ථාපනය කරමින්…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"අස්ථාපනය කිරීම අවසානයි."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> අස්ථාපනය කරන ලදී"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ක්ලෝනය මකන ලදි"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"අස්ථාපනය කිරිම අසාර්ථක විය."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> අස්ථාපනය කිරීම සාර්ථකයි."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ක්ලෝනය මකමින්…"</string>
diff --git a/packages/PackageInstaller/res/values-sk/strings.xml b/packages/PackageInstaller/res/values-sk/strings.xml
index 8620d60..f4d5631 100644
--- a/packages/PackageInstaller/res/values-sk/strings.xml
+++ b/packages/PackageInstaller/res/values-sk/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikácia bola nainštalovaná."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Chcete túto aplikáciu nainštalovať?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Chcete túto aplikáciu aktualizovať?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Aktualizácie tejto aplikácie momentálne spravuje vlastník <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nPo aktualizovaní budete namiesto toho získavať budúce aplikácie od vlastníka <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Aktualizácie tejto aplikácie momentálne spravuje vlastník <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nChcete túto aktualizáciu nainštalovať od vlastníka <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikácia nebola nainštalovaná."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Inštalácia balíka bola zablokovaná."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikácia sa nenainštalovala, pretože balík je v konflikte s existujúcim balíkom."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Prebieha odinštalovanie balíka <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Odinštalovanie bolo dokončené."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Balík <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> bol odinštalovaný"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Klon balíka <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> bol odstránený"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Nepodarilo sa odinštalovať."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Balík <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sa nepodarilo odinštalovať."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Klon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sa odstraňuje…"</string>
diff --git a/packages/PackageInstaller/res/values-sl/strings.xml b/packages/PackageInstaller/res/values-sl/strings.xml
index f083ec2..f12935e 100644
--- a/packages/PackageInstaller/res/values-sl/strings.xml
+++ b/packages/PackageInstaller/res/values-sl/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacija je nameščena."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ali želite namestiti to aplikacijo?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ali želite posodobiti to aplikacijo?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Posodobitve te aplikacije trenutno upravlja <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nČe posodobite, bo pošiljatelj prihodnjih posodobitev <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Posodobitve te aplikacije trenutno upravlja <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAli želite namestiti to posodobitev, ki jo je poslal <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacija ni nameščena."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Namestitev paketa je bila blokirana."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija ni bila nameščena, ker je paket v navzkrižju z obstoječim paketom."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Odmeščanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Odstranitev je končana."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je bila odstranjena."</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Klonirani paket <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> je izbrisan"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Odstranitev ni uspela."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Odmeščanje aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ni uspelo."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Brisanje kloniranega paketa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
diff --git a/packages/PackageInstaller/res/values-sq/strings.xml b/packages/PackageInstaller/res/values-sq/strings.xml
index 271a7b3..f58efea 100644
--- a/packages/PackageInstaller/res/values-sq/strings.xml
+++ b/packages/PackageInstaller/res/values-sq/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Aplikacioni u instalua."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Dëshiron ta instalosh këtë aplikacion?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Dëshiron ta përditësosh këtë aplikacion?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Përditësimet për këtë aplikacion menaxhohen aktualisht nga <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDuke e përditësuar, përditësimet në të ardhmen do t\'i marrësh nga <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Përditësimet për këtë aplikacion menaxhohen aktualisht nga <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDëshiron ta instalosh këtë përditësim nga <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Aplikacioni nuk u instalua."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Instalimi paketës u bllokua."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacioni nuk u instalua pasi paketa është në konflikt me një paketë ekzistuese."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> po çinstalohet…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Çinstalimi përfundoi."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> u çinstalua"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"U fshi kloni i <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Çinstalimi nuk pati sukses."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Çinstalimi i <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nuk u krye me sukses."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Po fshihet kloni i <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-sr/strings.xml b/packages/PackageInstaller/res/values-sr/strings.xml
index 3ac1995..2bfcf65 100644
--- a/packages/PackageInstaller/res/values-sr/strings.xml
+++ b/packages/PackageInstaller/res/values-sr/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Апликација је инсталирана."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Желите да инсталирате ову апликацију?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Желите да ажурирате ову апликацију?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Ажурирањима ове апликације тренутно управља <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nАко ажурирате, будућа ажурирања ћете добијати од власника <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Ажурирањима ове апликације тренутно управља <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nЖелите ли да инсталирате ово ажурирање власника <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Апликација није инсталирана."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Инсталирање пакета је блокирано."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Апликација није инсталирана јер је пакет неусаглашен са постојећим пакетом."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> се деинсталира…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Деинсталирање је завршено."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Апликација <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> је деинсталирана"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Избрисан је <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клон"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Деинсталирање није успело."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Деинсталирање апликације <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> није успело."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Брише се клон апликације <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-sv/strings.xml b/packages/PackageInstaller/res/values-sv/strings.xml
index 8681392..cb12c91 100644
--- a/packages/PackageInstaller/res/values-sv/strings.xml
+++ b/packages/PackageInstaller/res/values-sv/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Appen har installerats."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Vill du installera den här appen?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Vill du uppdatera den här appen?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Uppdateringar av den här appen hanteras för närvarande av <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nNär du uppdaterar får du i stället uppdateringar från <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Uppdateringar av den här appen hanteras för närvarande av <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nVill du installera den här uppdateringen från <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Appen har inte installerats."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketet har blockerats för installation."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Appen har inte installerats på grund av en konflikt mellan detta paket och ett befintligt paket."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> avinstalleras …"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Avinstallationen har slutförts."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> har avinstallerats"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Klonen <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> har raderats"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Det gick inte att avinstallera."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Det gick inte att avinstallera <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Raderar klonen av <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> …"</string>
diff --git a/packages/PackageInstaller/res/values-sw/strings.xml b/packages/PackageInstaller/res/values-sw/strings.xml
index 849a042..64e24f9 100644
--- a/packages/PackageInstaller/res/values-sw/strings.xml
+++ b/packages/PackageInstaller/res/values-sw/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Imesakinisha programu."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ungependa kusakinisha programu hii?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ungependa kusasisha programu hii?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Masasisho ya programu hii kwa sasa yanadhibitiwa na <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nKwa kusasisha, utapata masasisho yajayo kutoka kwa <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> badala yake."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Masasisho ya programu hii kwa sasa yanasimamiwa na <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>\n\nJe, ungependa kusakinisha sasisho hili kutoka kwa <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Imeshindwa kusakinisha programu."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Kifurushi kimezuiwa kisisakinishwe."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Programu haikusakinishwa kwa sababu kifurushi kinakinzana na kifurushi kingine kilichopo."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Inaondoa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Imeondolewa."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Imeondoa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Nakala ya <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> imefutwa"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Imeshindwa kuondoa."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Imeshindwa kuondoa <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Inafuta nakala ya <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-ta/strings.xml b/packages/PackageInstaller/res/values-ta/strings.xml
index 564606a..71970c4 100644
--- a/packages/PackageInstaller/res/values-ta/strings.xml
+++ b/packages/PackageInstaller/res/values-ta/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ஆப்ஸ் நிறுவப்பட்டது."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"இந்த ஆப்ஸை நிறுவ வேண்டுமா?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"இந்த ஆப்ஸைப் புதுப்பிக்க வேண்டுமா?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"இந்த ஆப்ஸுக்கான புதுப்பிப்புகள் தற்போது <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> மூலம் நிர்வகிக்கப்படுகின்றன.\n\nபுதுப்பிப்பதன் மூலம் இனிவரும் புதுப்பிப்புகளை <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> மூலம் பெறுவீர்கள்."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"இந்த ஆப்ஸுக்கான புதுப்பிப்புகள் தற்போது <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> மூலம் நிர்வகிக்கப்படுகின்றன.\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> மூலம் இந்தப் புதுப்பிப்பை நிறுவ விரும்புகிறீர்களா?"</string>
     <string name="install_failed" msgid="5777824004474125469">"ஆப்ஸ் நிறுவப்படவில்லை."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"இந்தத் தொகுப்பு நிறுவப்படுவதிலிருந்து தடுக்கப்பட்டது."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"இந்தத் தொகுப்பு ஏற்கனவே உள்ள தொகுப்புடன் முரண்படுவதால் ஆப்ஸ் நிறுவப்படவில்லை."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ஐ நிறுவல் நீக்குகிறது…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"நிறுவல் நீக்கம் முடிந்தது."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> நிறுவல் நீக்கப்பட்டது"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> குளோன் நீக்கபட்டது"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"நிறுவல் நீக்க இயலவில்லை."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ஐ நிறுவல் நீக்குவதில் தோல்வி."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> குளோனை நீக்குகிறது…"</string>
diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml
index b1662eb..67a15fb 100644
--- a/packages/PackageInstaller/res/values-te/strings.xml
+++ b/packages/PackageInstaller/res/values-te/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"యాప్ ఇన్‌స్టాల్ చేయబడింది."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"మీరు ఈ యాప్‌ను ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"మీరు ఈ యాప్‌ను అప్‌డేట్ చేయాలనుకుంటున్నారా?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"ఈ యాప్‌కి అప్‌డేట్‌లు ప్రస్తుతం <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ద్వారా మేనేజ్ చేయబడుతున్నాయి.\n\nఅప్‌డేట్ చేయడం ద్వారా, మీరు అందుకు బదులుగా <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> నుండి భవిష్యత్తు అప్‌డేట్‌లను పొందుతారు."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"ఈ యాప్‌కి అప్‌డేట్‌లు ప్రస్తుతం<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ద్వారా మేనేజ్ చేయబడుతున్నాయి.\n\nమీరు <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> నుండి ఈ అప్‌డేట్‌ను ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా."</string>
     <string name="install_failed" msgid="5777824004474125469">"యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"ప్యాకేజీ ఇన్‌స్టాల్ కాకుండా బ్లాక్ చేయబడింది."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ప్యాకేజీ, అలాగే ఇప్పటికే ఉన్న ప్యాకేజీ మధ్య వైరుధ్యం ఉన్నందున యాప్ ఇన్‌స్టాల్ చేయబడలేదు."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ని అన్ఇన్‌స్టాల్ చేస్తోంది…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"అన్‌ఇన్‌స్టాల్ చేయడం ముగిసింది."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> అన్ఇన్‌స్టాల్ చేయబడింది"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"తొలగించబడిన <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> క్లోన్"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"అన్ఇన్‌స్టాల్ చేయడం విజయవంతం కాలేదు."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> అన్ఇన్‌స్టాల్ చేయడంలో విఫలమైంది."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> క్లోన్‌ను తొలగిస్తోంది…"</string>
diff --git a/packages/PackageInstaller/res/values-th/strings.xml b/packages/PackageInstaller/res/values-th/strings.xml
index c0fe2ed..de8f727 100644
--- a/packages/PackageInstaller/res/values-th/strings.xml
+++ b/packages/PackageInstaller/res/values-th/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ติดตั้งแอปแล้ว"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"คุณต้องการติดตั้งแอปนี้ไหม"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"คุณต้องการอัปเดตแอปนี้ไหม"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"ขณะนี้ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> เป็นผู้จัดการการอัปเดตแอปนี้\n\nหากอัปเดต คุณจะได้รับการอัปเดตในอนาคตจาก <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> แทน"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"ขณะนี้ <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> เป็นผู้จัดการการอัปเดตแอปนี้\n\nคุณต้องการติดตั้งการอัปเดตนี้จาก <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> ไหม"</string>
     <string name="install_failed" msgid="5777824004474125469">"ไม่ได้ติดตั้งแอป"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"มีการบล็อกแพ็กเกจไม่ให้ติดตั้ง"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ไม่ได้ติดตั้งแอปเพราะแพ็กเกจขัดแย้งกับแพ็กเกจที่มีอยู่"</string>
diff --git a/packages/PackageInstaller/res/values-tl/strings.xml b/packages/PackageInstaller/res/values-tl/strings.xml
index f194e86..add4258 100644
--- a/packages/PackageInstaller/res/values-tl/strings.xml
+++ b/packages/PackageInstaller/res/values-tl/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Na-install na ang app."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Gusto mo bang i-install ang app na ito?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Gusto mo bang i-update ang app na ito?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Kasalukuyang pinamamahalaan ng <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ang mga update sa app na ito.\n\nSa pamamagitan ng pag-update, makakakuha ka na lang ng mga update sa hinaharap mula sa <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Kasalukuyang pinamamahalaan ng <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> ang mga update sa app na ito.\n\nGusto mo bang i-install ang update na ito mula sa <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Hindi na-install ang app."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Na-block ang pag-install sa package."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Hindi na-install ang app dahil nagkakaproblema ang package sa isang dati nang package."</string>
diff --git a/packages/PackageInstaller/res/values-tr/strings.xml b/packages/PackageInstaller/res/values-tr/strings.xml
index fb64517..a006c06 100644
--- a/packages/PackageInstaller/res/values-tr/strings.xml
+++ b/packages/PackageInstaller/res/values-tr/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Uygulama yüklendi."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Bu uygulamayı yüklemek istiyor musunuz?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Bu uygulamayı güncellemek istiyor musunuz?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Bu uygulamadaki güncellemeler şu anda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> tarafından yönetiliyor.\n\nUygulamayı güncellerseniz bundan sonraki güncellemeleri <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> gönderecektir."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Bu uygulamadaki güncellemeler şu anda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> tarafından yönetiliyor.\n\n<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> tarafından gönderilen bu güncellemeyi yüklemek istiyor musunuz?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Uygulama yüklenmedi."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paketin yüklemesi engellendi."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Paket, mevcut bir paketle çakıştığından uygulama yüklenemedi."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> uygulamasının yüklemesi kaldırılıyor…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Yüklemeyi kaldırma işlemi tamamlandı."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> uygulamasının yüklemesi kaldırıldı"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klonu silindi"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Yükleme kaldırılamadı."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> uygulamasının yüklemesi kaldırılamadı."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klonu siliniyor…"</string>
diff --git a/packages/PackageInstaller/res/values-uk/strings.xml b/packages/PackageInstaller/res/values-uk/strings.xml
index 1b805d3..d8928e5 100644
--- a/packages/PackageInstaller/res/values-uk/strings.xml
+++ b/packages/PackageInstaller/res/values-uk/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Програму встановлено."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Установити цей додаток?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Оновити цей додаток?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Оновленнями для цього додатка наразі керує <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nОновивши його зараз, ви надалі отримуватимете оновлення від <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Оновленнями для цього додатка наразі керує <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nУстановити це оновлення від <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Програму не встановлено."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Встановлення пакета заблоковано."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Додаток не встановлено, оскільки пакет конфліктує з наявним пакетом."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Видалення додатка <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Видалено."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Додаток <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> видалено"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Копію <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> видалено"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Не видалено."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Не вдалося видалити додаток <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Видалення копії додатка <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-ur/strings.xml b/packages/PackageInstaller/res/values-ur/strings.xml
index 03ee46a..ab11cd8 100644
--- a/packages/PackageInstaller/res/values-ur/strings.xml
+++ b/packages/PackageInstaller/res/values-ur/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"ایپ انسٹال ہو گئی۔"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"کیا آپ یہ ایپ انسٹال کرنا چاہتے ہیں؟"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"کیا آپ یہ ایپ اپ ڈیٹ کرنا چاہتے ہیں؟"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"اس ایپس میں اپ ڈیٹس <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> کے زیر انتظام ہیں۔\n\nاپ ڈیٹ کر کے، آپ اس کے بجائے <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> سے مستقبل کی اپ ڈیٹس موصول کر سکتے ہیں۔"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"اس ایپس میں اپ ڈیٹس <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> کے زیر انتظام ہیں۔\n\nآپ یہ اپ ڈیٹ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> سے انسٹال کرنا چاہتے ہیں۔"</string>
     <string name="install_failed" msgid="5777824004474125469">"ایپ انسٹال نہیں ہوئی۔"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"پیکج کو انسٹال ہونے سے مسدود کر دیا گیا تھا۔"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"ایپ انسٹال نہیں ہوئی کیونکہ پیکج ایک موجودہ پیکیج سے متصادم ہے۔"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ان انسٹال ہو رہا ہے…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"اَن انسٹال مکمل ہو گیا۔"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> اَن انسٹال ہو گیا"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> کا کلون حذف کر دیا گیا ہے"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"اَن انسٹال ناکام ہو گیا۔"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> کو ان انسٹال کرنا ناکام ہو گیا۔"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> کلون کو حذف کیا جا رہا ہے…"</string>
diff --git a/packages/PackageInstaller/res/values-uz/strings.xml b/packages/PackageInstaller/res/values-uz/strings.xml
index aeb00cc..bb225bc 100644
--- a/packages/PackageInstaller/res/values-uz/strings.xml
+++ b/packages/PackageInstaller/res/values-uz/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Ilova o‘rnatildi."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Bu ilovani oʻrnatmoqchimisiz?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Bu ilova yangilansinmi?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Bu ilova yangilanishlari hozirda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> boshqaruvida.\n\nYangilanishida kelgusi oʻzgarishlar <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> dan keladi."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Bu ilova yangilanishlari hozirda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> boshqaruvida.\n\nBu yangilanish <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> dan oʻrnatilsinmi?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Ilova o‘rnatilmadi."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Paket o‘rnatilishga qarshi bloklangan."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Paket mavjud paket bilan zid kelganligi uchun ilovani o‘rnatib bo‘lmadi."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> o‘chirilmoqda…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"O‘chirib tashlandi."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> o‘chirib tashlandi"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nusxasi oʻchirildi"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"O‘chirib tashlanmadi."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ilovasini o‘chirib bo‘lmadi."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nusxasi oʻchirilmoqda…"</string>
diff --git a/packages/PackageInstaller/res/values-vi/strings.xml b/packages/PackageInstaller/res/values-vi/strings.xml
index 7fbc74c..1e0df14 100644
--- a/packages/PackageInstaller/res/values-vi/strings.xml
+++ b/packages/PackageInstaller/res/values-vi/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Ứng dụng đã được cài đặt."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Bạn có muốn cài đặt ứng dụng này không?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Bạn có muốn cập nhật ứng dụng này không?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Hiện tại, <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> đang quản lý các bản cập nhật của ứng dụng này.\n\nBằng việc cập nhật, bạn sẽ nhận được các bản cập nhật sau này của <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Hiện tại, <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> đang quản lý các bản cập nhật của ứng dụng này.\n\nBạn có muốn cài đặt bản cập nhật này của <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> không?"</string>
     <string name="install_failed" msgid="5777824004474125469">"Ứng dụng chưa được cài đặt."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Đã chặn cài đặt gói."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Chưa cài đặt được ứng dụng do gói xung đột với một gói hiện có."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Đang gỡ cài đặt <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Đã gỡ cài đặt xong."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Đã gỡ cài đặt <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Đã xoá bản sao của <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Gỡ cài đặt không thành công."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Gỡ cài đặt <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> không thành công."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Đang xoá bản sao của <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
diff --git a/packages/PackageInstaller/res/values-zh-rCN/strings.xml b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
index b5f3cba..f25da81 100644
--- a/packages/PackageInstaller/res/values-zh-rCN/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"已安装应用。"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"要安装此应用吗?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"要更新此应用吗?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"此应用的更新目前由<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>管理。\n\n更新后,将改由<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>向您提供日后的更新。"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"此应用的更新目前由<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>管理。\n\n要安装这个来自<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>的更新吗?"</string>
     <string name="install_failed" msgid="5777824004474125469">"未安装应用。"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"系统已禁止安装该软件包。"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"应用未安装:软件包与现有软件包存在冲突。"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"正在卸载<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"卸载完成。"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"已卸载<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"已删除<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>克隆"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"卸载失败。"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"卸载<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>失败。"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"正在删除 <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 克隆应用…"</string>
diff --git a/packages/PackageInstaller/res/values-zh-rHK/strings.xml b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
index 74e8bea..46f3b9f 100644
--- a/packages/PackageInstaller/res/values-zh-rHK/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"已安裝應用程式。"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"要安裝此應用程式嗎?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"要更新此應用程式嗎?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"此應用程式的更新目前由「<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>」管理。\n\n更新後將改由「<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>」提供更新。"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"此應用程式的更新目前由「<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>」管理。\n\n是否要安裝這項由「<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>」提供的更新?"</string>
     <string name="install_failed" msgid="5777824004474125469">"未安裝應用程式。"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"套件已遭封鎖,無法安裝。"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"套件與現有的套件發生衝突,無法安裝應用程式。"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"正在解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"完成解除安裝。"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"已解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"已刪除「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」複製本"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"解除安裝失敗。"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」失敗。"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"正在刪除「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」複製本…"</string>
diff --git a/packages/PackageInstaller/res/values-zh-rTW/strings.xml b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
index a338015..cf8cd59 100644
--- a/packages/PackageInstaller/res/values-zh-rTW/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"已安裝應用程式。"</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"要安裝這個應用程式嗎?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"要更新這個應用程式嗎?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"這個應用程式的更新目前是由「<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>」管理。\n\n更新後,將改由「<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>」提供更新。"</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"這個應用程式的更新目前是由「<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>」管理。\n\n是否要安裝「<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>」提供的這項更新?"</string>
     <string name="install_failed" msgid="5777824004474125469">"未安裝應用程式。"</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"系統已封鎖這個套件,因此無法安裝。"</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"應用程式套件與現有套件衝突,因此未能完成安裝。"</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"正在解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"已順利解除安裝。"</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"已解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"已刪除「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」副本"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"無法解除安裝。"</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"無法解除安裝「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」。"</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"正在刪除「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」副本…"</string>
diff --git a/packages/PackageInstaller/res/values-zu/strings.xml b/packages/PackageInstaller/res/values-zu/strings.xml
index 9298cbd..afdfd82 100644
--- a/packages/PackageInstaller/res/values-zu/strings.xml
+++ b/packages/PackageInstaller/res/values-zu/strings.xml
@@ -26,8 +26,6 @@
     <string name="install_done" msgid="5987363587661783896">"Uhlelo lokusebenza olufakiwe."</string>
     <string name="install_confirm_question" msgid="7663733664476363311">"Ingabe ufuna ukufaka le app?"</string>
     <string name="install_confirm_question_update" msgid="3348888852318388584">"Ingabe ufuna ukubuyekeza le app?"</string>
-    <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Izibuyekezo zale app okwamanje ziphethwe yi-<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nNgokubuyekeza, kunalokho uzothola izibuyekezo zesikhathi esizayo ezivela ku-<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> esikhundleni."</string>
-    <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Izibuyekezo zale app okwamanje ziphethwe yi-<xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nUyafuna ukufaka lesi sibuyekezo esivela ku-<xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
     <string name="install_failed" msgid="5777824004474125469">"Uhlelo lokusebenza alufakiwe."</string>
     <string name="install_failed_blocked" msgid="8512284352994752094">"Iphakheji livinjiwe kusukela ekufakweni."</string>
     <string name="install_failed_conflict" msgid="3493184212162521426">"Uhlelo lokusebenza alufakiwe njengoba ukuphakheja kushayisana nephakheji elikhona."</string>
@@ -70,8 +68,7 @@
     <string name="uninstalling_app" msgid="8866082646836981397">"Ikhipha i-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Ukukhipha kuqedile."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"Kukhishwe i-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
-    <!-- no translation found for uninstall_done_clone_app (5578308154544195413) -->
-    <skip />
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Sula iclone ye-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Ukukhipha akuphumelelanga."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Ukukhipha i-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> akuphumelele."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Isula <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> i-clone…"</string>
diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml
index ae6f71c..ab680b0 100644
--- a/packages/PackageInstaller/res/values/strings.xml
+++ b/packages/PackageInstaller/res/values/strings.xml
@@ -38,10 +38,11 @@
     <!-- Message for updating an existing app [CHAR LIMIT=NONE] -->
     <string name="install_confirm_question_update">Do you want to update this app?</string>
     <!-- TODO(b/244413073) Revise the description after getting UX input and UXR on this. -->
-    <!-- Message for updating an existing app when updating owner changed [CHAR LIMIT=NONE] -->
+    <!-- Message for updating an existing app when updating owner changed [DO NOT TRANSLATE][CHAR LIMIT=NONE] -->
     <string name="install_confirm_question_update_owner_changed">Updates to this app are currently managed by <xliff:g id="existing_update_owner">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="new_update_owner">%2$s</xliff:g> instead.</string>
-    <!-- Message for updating an existing app with update owner reminder [CHAR LIMIT=NONE] -->
-    <string name="install_confirm_question_update_owner_reminder">Updates to this app are currently managed by <xliff:g id="existing_update_owner">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="new_update_owner">%2$s</xliff:g>.</string>
+    <!-- TODO(b/244413073) Revise the description after getting UX input and UXR on this. -->
+    <!-- Message for updating an existing app with update owner reminder [DO NOT TRANSLATE][CHAR LIMIT=NONE] -->
+    <string name="install_confirm_question_update_owner_reminder">Updates to this app are currently managed by <xliff:g id="existing_update_owner">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="new_update_owner">%2$s</xliff:g>?</string>
     <!-- [CHAR LIMIT=100] -->
     <string name="install_failed">App not installed.</string>
     <!-- Reason displayed when installation fails because the package was blocked
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
old mode 100755
new mode 100644
index 93387e2..c6217ec
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
@@ -141,7 +141,7 @@
                 File file = new File(mPackageURI.getPath());
                 try {
                     final InstallInfo result = getPackageManager().getPackageInstaller()
-                            .getInstallInfo(file, 0);
+                            .readInstallInfo(file, 0);
                     params.setAppPackageName(result.getPackageName());
                     params.setInstallLocation(result.getInstallLocation());
                     try {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
index 7338e64..ac32020 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
@@ -80,7 +80,10 @@
         final int originatingUid = getOriginatingUid(sourceInfo);
         boolean isTrustedSource = false;
         if (sourceInfo != null && sourceInfo.isPrivilegedApp()) {
-            isTrustedSource = intent.getBooleanExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, false);
+            isTrustedSource = intent.getBooleanExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, false) || (
+                    originatingUid != Process.INVALID_UID && checkPermission(
+                            Manifest.permission.INSTALL_PACKAGES, -1 /* pid */, originatingUid)
+                            == PackageManager.PERMISSION_GRANTED);
         }
 
         if (!isTrustedSource && originatingUid != Process.INVALID_UID) {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 49c9188..fd41f5f 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -246,26 +246,28 @@
 
     @Override
     public void onActivityResult(int request, int result, Intent data) {
-        if (request == REQUEST_TRUST_EXTERNAL_SOURCE && result == RESULT_OK) {
-            // The user has just allowed this package to install other packages (via Settings).
-            mAllowUnknownSources = true;
-
+        if (request == REQUEST_TRUST_EXTERNAL_SOURCE) {
             // Log the fact that the app is requesting an install, and is now allowed to do it
             // (before this point we could only log that it's requesting an install, but isn't
             // allowed to do it yet).
             String appOpStr =
                     AppOpsManager.permissionToOp(Manifest.permission.REQUEST_INSTALL_PACKAGES);
-            mAppOpsManager.noteOpNoThrow(appOpStr, mOriginatingUid, mOriginatingPackage,
-                    mCallingAttributionTag,
+            int appOpMode = mAppOpsManager.noteOpNoThrow(appOpStr, mOriginatingUid,
+                    mOriginatingPackage, mCallingAttributionTag,
                     "Successfully started package installation activity");
-
-            DialogFragment currentDialog =
-                    (DialogFragment) getFragmentManager().findFragmentByTag("dialog");
-            if (currentDialog != null) {
-                currentDialog.dismissAllowingStateLoss();
+            if (appOpMode == AppOpsManager.MODE_ALLOWED) {
+                // The user has just allowed this package to install other packages
+                // (via Settings).
+                mAllowUnknownSources = true;
+                DialogFragment currentDialog =
+                        (DialogFragment) getFragmentManager().findFragmentByTag("dialog");
+                if (currentDialog != null) {
+                    currentDialog.dismissAllowingStateLoss();
+                }
+                initiateInstall();
+            } else {
+                finish();
             }
-
-            initiateInstall();
         } else {
             finish();
         }
@@ -297,6 +299,10 @@
                 return false;
             }
         }
+        if (mSourceInfo != null && checkPermission(Manifest.permission.INSTALL_PACKAGES,
+                -1 /* pid */, mSourceInfo.uid) == PackageManager.PERMISSION_GRANTED) {
+            return false;
+        }
         return true;
     }
 
@@ -392,7 +398,7 @@
             final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
                     -1 /* defaultValue */);
             final SessionInfo info = mInstaller.getSessionInfo(sessionId);
-            if (info == null || !info.getIsPreApprovalRequested()) {
+            if (info == null || !info.isPreApprovalRequested()) {
                 Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
                 finish();
                 return;
diff --git a/packages/PrintSpooler/res/values-or/strings.xml b/packages/PrintSpooler/res/values-or/strings.xml
index 6f215d3..dd29700 100644
--- a/packages/PrintSpooler/res/values-or/strings.xml
+++ b/packages/PrintSpooler/res/values-or/strings.xml
@@ -47,7 +47,7 @@
     <string name="savetopdf_button" msgid="2976186791686924743">"PDFରେ ସେଭ୍‍ କରନ୍ତୁ"</string>
     <string name="print_options_expanded" msgid="6944679157471691859">"ପ୍ରିଣ୍ଟ ବିକଳ୍ପକୁ ବଡ଼ କରାଯାଇଛି"</string>
     <string name="print_options_collapsed" msgid="7455930445670414332">"ପ୍ରିଣ୍ଟ ବିକଳ୍ପକୁ ଛୋଟ କରାଯାଇଛି"</string>
-    <string name="search" msgid="5421724265322228497">"ସନ୍ଧାନ କରନ୍ତୁ"</string>
+    <string name="search" msgid="5421724265322228497">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"ସମସ୍ତ ପ୍ରିଣ୍ଟର୍‌"</string>
     <string name="add_print_service_label" msgid="5356702546188981940">"ସେବା ଯୋଗ କରନ୍ତୁ"</string>
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ସର୍ଚ୍ଚ ବକ୍ସ ଦେଖାଯାଇଛି"</string>
diff --git a/packages/SettingsLib/ActivityEmbedding/Android.bp b/packages/SettingsLib/ActivityEmbedding/Android.bp
index c35fb3b..4b4cfb7 100644
--- a/packages/SettingsLib/ActivityEmbedding/Android.bp
+++ b/packages/SettingsLib/ActivityEmbedding/Android.bp
@@ -30,5 +30,6 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.permission",
+        "com.android.healthconnect",
     ],
 }
diff --git a/packages/SettingsLib/ActivityEmbedding/OWNERS b/packages/SettingsLib/ActivityEmbedding/OWNERS
new file mode 100644
index 0000000..7022402
--- /dev/null
+++ b/packages/SettingsLib/ActivityEmbedding/OWNERS
@@ -0,0 +1,5 @@
+# Default reviewers for this and subdirectories.
+arcwang@google.com
+chiujason@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java b/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
index 1407725..f89be9f 100644
--- a/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
+++ b/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
@@ -23,7 +23,7 @@
 import android.util.Log;
 
 import androidx.core.os.BuildCompat;
-import androidx.window.embedding.SplitController;
+import androidx.window.embedding.ActivityEmbeddingController;
 
 import com.android.settingslib.utils.BuildCompatUtils;
 
@@ -84,7 +84,7 @@
      * @param activity Activity that needs the check
      */
     public static boolean isActivityEmbedded(Activity activity) {
-        return SplitController.getInstance().isActivityEmbedded(activity);
+        return ActivityEmbeddingController.getInstance(activity).isActivityEmbedded(activity);
     }
 
     /**
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index f170ead..af20a4b 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -42,7 +42,7 @@
         "SettingsLibAdaptiveIcon",
         "SettingsLibRadioButtonPreference",
         "SettingsLibSelectorWithWidgetPreference",
-        "SettingsLibDisplayDensityUtils",
+        "SettingsLibDisplayUtils",
         "SettingsLibUtils",
         "SettingsLibEmergencyNumber",
         "SettingsLibTopIntroPreference",
diff --git a/packages/SettingsLib/DisplayDensityUtils/Android.bp b/packages/SettingsLib/DisplayUtils/Android.bp
similarity index 90%
rename from packages/SettingsLib/DisplayDensityUtils/Android.bp
rename to packages/SettingsLib/DisplayUtils/Android.bp
index b7bfb5f..136f883 100644
--- a/packages/SettingsLib/DisplayDensityUtils/Android.bp
+++ b/packages/SettingsLib/DisplayUtils/Android.bp
@@ -8,7 +8,7 @@
 }
 
 android_library {
-    name: "SettingsLibDisplayDensityUtils",
+    name: "SettingsLibDisplayUtils",
 
     srcs: ["src/**/*.java"],
 
diff --git a/packages/SettingsLib/DisplayUtils/AndroidManifest.xml b/packages/SettingsLib/DisplayUtils/AndroidManifest.xml
new file mode 100644
index 0000000..e064cab
--- /dev/null
+++ b/packages/SettingsLib/DisplayUtils/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.settingslib.display">
+
+</manifest>
diff --git a/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java b/packages/SettingsLib/DisplayUtils/src/com/android/settingslib/display/BrightnessUtils.java
similarity index 98%
rename from packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
rename to packages/SettingsLib/DisplayUtils/src/com/android/settingslib/display/BrightnessUtils.java
index 4f86afaa9..66ed1043 100644
--- a/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
+++ b/packages/SettingsLib/DisplayUtils/src/com/android/settingslib/display/BrightnessUtils.java
@@ -18,6 +18,7 @@
 
 import android.util.MathUtils;
 
+/** Utility methods for calculating the display brightness. */
 public class BrightnessUtils {
 
     public static final int GAMMA_SPACE_MIN = 0;
diff --git a/packages/SettingsLib/DisplayDensityUtils/src/com/android/settingslib/display/DisplayDensityConfiguration.java b/packages/SettingsLib/DisplayUtils/src/com/android/settingslib/display/DisplayDensityConfiguration.java
similarity index 100%
rename from packages/SettingsLib/DisplayDensityUtils/src/com/android/settingslib/display/DisplayDensityConfiguration.java
rename to packages/SettingsLib/DisplayUtils/src/com/android/settingslib/display/DisplayDensityConfiguration.java
diff --git a/packages/SettingsLib/IllustrationPreference/res/values/attrs.xml b/packages/SettingsLib/IllustrationPreference/res/values/attrs.xml
new file mode 100644
index 0000000..141886c
--- /dev/null
+++ b/packages/SettingsLib/IllustrationPreference/res/values/attrs.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<resources>
+    <declare-styleable name="IllustrationPreference">
+        <attr name="dynamicColor" format="boolean" />
+    </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index 1592094..3b90275 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -61,6 +61,8 @@
     private View mMiddleGroundView;
     private OnBindListener mOnBindListener;
 
+    private boolean mLottieDynamicColor;
+
     /**
      * Interface to listen in on when {@link #onBindViewHolder(PreferenceViewHolder)} occurs.
      */
@@ -146,6 +148,10 @@
             ColorUtils.applyDynamicColors(getContext(), illustrationView);
         }
 
+        if (mLottieDynamicColor) {
+            LottieColorUtils.applyDynamicColors(getContext(), illustrationView);
+        }
+
         if (mOnBindListener != null) {
             mOnBindListener.onBind(illustrationView);
         }
@@ -262,6 +268,21 @@
         }
     }
 
+    /**
+     * Sets the lottie illustration apply dynamic color.
+     */
+    public void applyDynamicColor() {
+        mLottieDynamicColor = true;
+        notifyChanged();
+    }
+
+    /**
+     * Return if the lottie illustration apply dynamic color or not.
+     */
+    public boolean isApplyDynamicColor() {
+        return mLottieDynamicColor;
+    }
+
     private void resetImageResourceCache() {
         mImageDrawable = null;
         mImageUri = null;
@@ -403,9 +424,15 @@
 
         mIsAutoScale = false;
         if (attrs != null) {
-            final TypedArray a = context.obtainStyledAttributes(attrs,
+            TypedArray a = context.obtainStyledAttributes(attrs,
                     R.styleable.LottieAnimationView, 0 /*defStyleAttr*/, 0 /*defStyleRes*/);
             mImageResId = a.getResourceId(R.styleable.LottieAnimationView_lottie_rawRes, 0);
+
+            a = context.obtainStyledAttributes(attrs,
+                    R.styleable.IllustrationPreference, 0 /*defStyleAttr*/, 0 /*defStyleRes*/);
+            mLottieDynamicColor = a.getBoolean(R.styleable.IllustrationPreference_dynamicColor,
+                    false);
+
             a.recycle();
         }
     }
diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS
index 36315b5..1b3020a 100644
--- a/packages/SettingsLib/OWNERS
+++ b/packages/SettingsLib/OWNERS
@@ -1,12 +1,11 @@
 # People who can approve changes for submission
 dsandler@android.com
 edgarwang@google.com
-emilychuang@google.com
 evanlaird@google.com
-hanxu@google.com
 juliacr@google.com
+lijun@google.com
+songchenxi@google.com
 yantingyang@google.com
-ykhung@google.com
 
 # Exempt resource files (because they are in a flat directory and too hard to manage via OWNERS)
 per-file *.xml=*
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
index e54e276..c702f59 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
@@ -24,6 +24,9 @@
 import com.android.settingslib.spa.gallery.button.ActionButtonPageProvider
 import com.android.settingslib.spa.gallery.dialog.AlterDialogPageProvider
 import com.android.settingslib.spa.gallery.home.HomePageProvider
+import com.android.settingslib.spa.gallery.itemList.ItemListPageProvider
+import com.android.settingslib.spa.gallery.itemList.ItemOperatePageProvider
+import com.android.settingslib.spa.gallery.itemList.OperateListPageProvider
 import com.android.settingslib.spa.gallery.page.ArgumentPageProvider
 import com.android.settingslib.spa.gallery.page.ChartPageProvider
 import com.android.settingslib.spa.gallery.page.FooterPageProvider
@@ -50,6 +53,8 @@
     HOME("home"),
     PREFERENCE("preference"),
     ARGUMENT("argument"),
+    ITEM_LIST("itemList"),
+    ITEM_OP_PAGE("itemOp"),
 
     // Add your SPPs
 }
@@ -76,6 +81,9 @@
                 LoadingBarPageProvider,
                 ChartPageProvider,
                 AlterDialogPageProvider,
+                ItemListPageProvider,
+                ItemOperatePageProvider,
+                OperateListPageProvider,
             ),
             rootPages = listOf(
                 HomePageProvider.createSettingsPage(),
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/button/ActionButtonsPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/button/ActionButtonsPage.kt
index decc292..df1d7d1 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/button/ActionButtonsPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/button/ActionButtonsPage.kt
@@ -24,8 +24,8 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.button.ActionButton
@@ -39,13 +39,24 @@
 object ActionButtonPageProvider : SettingsPageProvider {
     override val name = "ActionButton"
 
+    override fun getTitle(arguments: Bundle?): String {
+        return TITLE
+    }
+
     @Composable
     override fun Page(arguments: Bundle?) {
-        ActionButtonPage()
+        RegularScaffold(title = TITLE) {
+            val actionButtons = listOf(
+                ActionButton(text = "Open", imageVector = Icons.Outlined.Launch) {},
+                ActionButton(text = "Uninstall", imageVector = Icons.Outlined.Delete) {},
+                ActionButton(text = "Force stop", imageVector = Icons.Outlined.WarningAmber) {},
+            )
+            ActionButtons(actionButtons)
+        }
     }
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner = createSettingsPage())
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
@@ -55,22 +66,10 @@
     }
 }
 
-@Composable
-fun ActionButtonPage() {
-    RegularScaffold(title = TITLE) {
-        val actionButtons = listOf(
-            ActionButton(text = "Open", imageVector = Icons.Outlined.Launch) {},
-            ActionButton(text = "Uninstall", imageVector = Icons.Outlined.Delete) {},
-            ActionButton(text = "Force stop", imageVector = Icons.Outlined.WarningAmber) {},
-        )
-        ActionButtons(actionButtons)
-    }
-}
-
 @Preview(showBackground = true)
 @Composable
 private fun ActionButtonPagePreview() {
     SettingsTheme {
-        ActionButtonPage()
+        ActionButtonPageProvider.Page(null)
     }
 }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
index 5d26b34..0878fc0 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
@@ -18,6 +18,7 @@
 
 import android.os.Bundle
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
@@ -28,6 +29,7 @@
 import com.android.settingslib.spa.gallery.SettingsPageProviderEnum
 import com.android.settingslib.spa.gallery.button.ActionButtonPageProvider
 import com.android.settingslib.spa.gallery.dialog.AlterDialogPageProvider
+import com.android.settingslib.spa.gallery.itemList.OperateListPageProvider
 import com.android.settingslib.spa.gallery.page.ArgumentPageModel
 import com.android.settingslib.spa.gallery.page.ArgumentPageProvider
 import com.android.settingslib.spa.gallery.page.ChartPageProvider
@@ -50,6 +52,7 @@
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
         return listOf(
             PreferenceMainPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+            OperateListPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             ArgumentPageProvider.buildInjectEntry("foo")!!.setLink(fromPage = owner).build(),
             SliderPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             SpinnerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
@@ -71,8 +74,10 @@
 
     @Composable
     override fun Page(arguments: Bundle?) {
-        HomeScaffold(title = getTitle(arguments)) {
-            for (entry in buildEntry(arguments)) {
+        val title = remember { getTitle(arguments) }
+        val entries = remember { buildEntry(arguments) }
+        HomeScaffold(title) {
+            for (entry in entries) {
                 if (entry.owner.isCreateBy(SettingsPageProviderEnum.ARGUMENT.name)) {
                     entry.UiLayout(ArgumentPageModel.buildArgument(intParam = 0))
                 } else {
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemListPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemListPage.kt
new file mode 100644
index 0000000..08e6452
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemListPage.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.settingslib.spa.gallery.itemList
+
+import android.os.Bundle
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.core.os.bundleOf
+import androidx.navigation.NavType
+import androidx.navigation.navArgument
+import com.android.settingslib.spa.framework.common.EntrySearchData
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.util.getStringArg
+import com.android.settingslib.spa.framework.util.navLink
+import com.android.settingslib.spa.gallery.SettingsPageProviderEnum
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.RegularScaffold
+
+private const val OPERATOR_PARAM_NAME = "opParam"
+
+object ItemListPageProvider : SettingsPageProvider {
+    override val name = SettingsPageProviderEnum.ITEM_LIST.name
+    override val displayName = SettingsPageProviderEnum.ITEM_LIST.displayName
+    override val parameter = listOf(
+        navArgument(OPERATOR_PARAM_NAME) { type = NavType.StringType },
+    )
+
+    override fun getTitle(arguments: Bundle?): String {
+        val operation = parameter.getStringArg(OPERATOR_PARAM_NAME, arguments) ?: "NULL"
+        return "Operation: $operation"
+    }
+
+    override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+        if (!ItemOperatePageProvider.isValidArgs(arguments)) return emptyList()
+        val operation = parameter.getStringArg(OPERATOR_PARAM_NAME, arguments)!!
+        val owner = createSettingsPage(arguments)
+        return listOf(
+            ItemOperatePageProvider.buildInjectEntry(operation)!!.setLink(fromPage = owner).build(),
+        )
+    }
+
+    fun buildInjectEntry(opParam: String): SettingsEntryBuilder? {
+        val arguments = bundleOf(OPERATOR_PARAM_NAME to opParam)
+        if (!ItemOperatePageProvider.isValidArgs(arguments)) return null
+
+        return SettingsEntryBuilder.createInject(
+            owner = createSettingsPage(arguments),
+            displayName = "ItemList_$opParam",
+        ).setUiLayoutFn {
+            Preference(
+                object : PreferenceModel {
+                    override val title = opParam
+                    override val onClick = navigator(
+                        SettingsPageProviderEnum.ITEM_LIST.name + parameter.navLink(it)
+                    )
+                }
+            )
+        }.setSearchDataFn {
+            EntrySearchData(title = "Operation: $opParam")
+        }
+    }
+
+    @Composable
+    override fun Page(arguments: Bundle?) {
+        val title = remember { getTitle(arguments) }
+        val entries = remember { buildEntry(arguments) }
+        val itemList = remember {
+            // Add logic to get item List during runtime.
+            listOf("itemFoo", "itemBar", "itemToy")
+        }
+        RegularScaffold(title) {
+            for (item in itemList) {
+                val rtArgs = ItemOperatePageProvider.genRuntimeArguments(item)
+                for (entry in entries) {
+                    entry.UiLayout(rtArgs)
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt
new file mode 100644
index 0000000..8179356
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt
@@ -0,0 +1,125 @@
+/*
+ * 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.settingslib.spa.gallery.itemList
+
+import android.os.Bundle
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.core.os.bundleOf
+import androidx.navigation.NavType
+import androidx.navigation.navArgument
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.util.getStringArg
+import com.android.settingslib.spa.framework.util.navLink
+import com.android.settingslib.spa.gallery.SettingsPageProviderEnum
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.preference.SwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
+
+private const val OPERATOR_PARAM_NAME = "opParam"
+private const val ITEM_NAME_PARAM_NAME = "rt_nameParam"
+private val ALLOWED_OPERATOR_LIST = listOf("opDnD", "opPiP", "opInstall", "opConnect")
+
+object ItemOperatePageProvider : SettingsPageProvider {
+    override val name = SettingsPageProviderEnum.ITEM_OP_PAGE.name
+    override val displayName = SettingsPageProviderEnum.ITEM_OP_PAGE.displayName
+    override val parameter = listOf(
+        navArgument(OPERATOR_PARAM_NAME) { type = NavType.StringType },
+        navArgument(ITEM_NAME_PARAM_NAME) { type = NavType.StringType },
+    )
+
+    override fun getTitle(arguments: Bundle?): String {
+        // Operation name is not a runtime parameter, which should always available
+        val operation = parameter.getStringArg(OPERATOR_PARAM_NAME, arguments) ?: "opInValid"
+        // Item name is a runtime parameter, which could be missing
+        val itemName = parameter.getStringArg(ITEM_NAME_PARAM_NAME, arguments) ?: "[unset]"
+        return "$operation on $itemName"
+    }
+
+    override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+        if (!isValidArgs(arguments)) return emptyList()
+
+        val owner = createSettingsPage(arguments)
+        val entryList = mutableListOf<SettingsEntry>()
+        entryList.add(
+            SettingsEntryBuilder.create("ItemName", owner)
+                .setUiLayoutFn {
+                    // Item name is a runtime parameter, which needs to be read inside UiLayoutFn
+                    val itemName = parameter.getStringArg(ITEM_NAME_PARAM_NAME, it) ?: "NULL"
+                    Preference(
+                        object : PreferenceModel {
+                            override val title = "Item $itemName"
+                        }
+                    )
+                }.build()
+        )
+
+        // Operation name is not a runtime parameter, which can be read outside.
+        val opName = parameter.getStringArg(OPERATOR_PARAM_NAME, arguments)!!
+        entryList.add(
+            SettingsEntryBuilder.create("ItemOp", owner)
+                .setUiLayoutFn {
+                    val checked = rememberSaveable { mutableStateOf(false) }
+                    SwitchPreference(remember {
+                        object : SwitchPreferenceModel {
+                            override val title = "Item operation: $opName"
+                            override val checked = checked
+                            override val onCheckedChange =
+                                { newChecked: Boolean -> checked.value = newChecked }
+                        }
+                    })
+                }.build(),
+        )
+        return entryList
+    }
+
+    fun buildInjectEntry(opParam: String): SettingsEntryBuilder? {
+        val arguments = bundleOf(OPERATOR_PARAM_NAME to opParam)
+        if (!isValidArgs(arguments)) return null
+
+        return SettingsEntryBuilder.createInject(
+            owner = createSettingsPage(arguments),
+            displayName = "ItemOp_$opParam",
+        ).setUiLayoutFn {
+            // Item name is a runtime parameter, which needs to be read inside UiLayoutFn
+            val itemName = parameter.getStringArg(ITEM_NAME_PARAM_NAME, it) ?: "NULL"
+            Preference(
+                object : PreferenceModel {
+                    override val title = "item: $itemName"
+                    override val onClick = navigator(
+                        SettingsPageProviderEnum.ITEM_OP_PAGE.name + parameter.navLink(it)
+                    )
+                }
+            )
+        }
+    }
+
+    fun isValidArgs(arguments: Bundle?): Boolean {
+        val opParam = parameter.getStringArg(OPERATOR_PARAM_NAME, arguments)
+        return (opParam != null && ALLOWED_OPERATOR_LIST.contains(opParam))
+    }
+
+    fun genRuntimeArguments(itemName: String): Bundle {
+        return bundleOf(ITEM_NAME_PARAM_NAME to itemName)
+    }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/OperateListPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/OperateListPage.kt
new file mode 100644
index 0000000..e0baf86
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/OperateListPage.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.settingslib.spa.gallery.itemList
+
+import android.os.Bundle
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+
+private const val TITLE = "Operate List Main"
+
+object OperateListPageProvider : SettingsPageProvider {
+    override val name = "OpList"
+    private val owner = createSettingsPage()
+
+    override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+        return listOf(
+            ItemListPageProvider.buildInjectEntry("opPiP")!!.setLink(fromPage = owner).build(),
+            ItemListPageProvider.buildInjectEntry("opInstall")!!.setLink(fromPage = owner).build(),
+            ItemListPageProvider.buildInjectEntry("opDnD")!!.setLink(fromPage = owner).build(),
+            ItemListPageProvider.buildInjectEntry("opConnect")!!.setLink(fromPage = owner).build(),
+        )
+    }
+
+    override fun getTitle(arguments: Bundle?): String {
+        return TITLE
+    }
+
+    fun buildInjectEntry(): SettingsEntryBuilder {
+        return SettingsEntryBuilder.createInject(owner = owner)
+            .setUiLayoutFn {
+                Preference(object : PreferenceModel {
+                    override val title = TITLE
+                    override val onClick = navigator(name)
+                })
+            }
+    }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
index 42ac1ac..eca47b6 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPage.kt
@@ -18,6 +18,7 @@
 
 import android.os.Bundle
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
@@ -101,10 +102,13 @@
 
     @Composable
     override fun Page(arguments: Bundle?) {
-        RegularScaffold(title = getTitle(arguments)) {
-            for (entry in buildEntry(arguments)) {
+        val title = remember { getTitle(arguments) }
+        val entries = remember { buildEntry(arguments) }
+        val rtArgNext = remember { ArgumentPageModel.buildNextArgument(arguments) }
+        RegularScaffold(title) {
+            for (entry in entries) {
                 if (entry.toPage != null) {
-                    entry.UiLayout(ArgumentPageModel.buildNextArgument(arguments))
+                    entry.UiLayout(rtArgNext)
                 } else {
                     entry.UiLayout()
                 }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt
index 5f15865..5d6aa03 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt
@@ -132,7 +132,7 @@
             override val title = PAGE_TITLE
             override val summary = stateOf(summaryArray.joinToString(", "))
             override val onClick = navigator(
-                SettingsPageProviderEnum.ARGUMENT.displayName + parameter.navLink(arguments)
+                SettingsPageProviderEnum.ARGUMENT.name + parameter.navLink(arguments)
             )
         }
     }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ChartPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ChartPage.kt
index 7f21a4d..69c4705 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ChartPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ChartPage.kt
@@ -21,8 +21,8 @@
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.chart.BarChart
@@ -36,7 +36,6 @@
 import com.android.settingslib.spa.widget.chart.PieChartModel
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
-import com.android.settingslib.spa.widget.scaffold.RegularScaffold
 import com.github.mikephil.charting.formatter.IAxisValueFormatter
 import java.text.NumberFormat
 
@@ -47,9 +46,13 @@
 
 object ChartPageProvider : SettingsPageProvider {
     override val name = "Chart"
+    private val owner = createSettingsPage()
+
+    override fun getTitle(arguments: Bundle?): String {
+        return TITLE
+    }
 
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
-        val owner = SettingsPage.create(name)
         val entryList = mutableListOf<SettingsEntry>()
         entryList.add(
             SettingsEntryBuilder.create("Line Chart", owner)
@@ -133,7 +136,7 @@
     }
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner)
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
@@ -141,15 +144,6 @@
                 })
             }
     }
-
-    @Composable
-    override fun Page(arguments: Bundle?) {
-        RegularScaffold(title = TITLE) {
-            for (entry in buildEntry(arguments)) {
-                entry.UiLayout(arguments)
-            }
-        }
-    }
 }
 
 @Preview(showBackground = true)
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
index 9f24ea9..9c7e0ce 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPage.kt
@@ -23,8 +23,8 @@
 import com.android.settingslib.spa.framework.common.EntrySearchData
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -37,9 +37,9 @@
 
 object FooterPageProvider : SettingsPageProvider {
     override val name = "Footer"
+    private val owner = createSettingsPage()
 
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
-        val owner = SettingsPage.create(name)
         val entryList = mutableListOf<SettingsEntry>()
         entryList.add(
             SettingsEntryBuilder.create( "Some Preference", owner)
@@ -58,7 +58,7 @@
     }
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner)
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt
index 44f0343..ee22b96 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/IllustrationPage.kt
@@ -21,8 +21,8 @@
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.gallery.R
@@ -36,9 +36,9 @@
 
 object IllustrationPageProvider : SettingsPageProvider {
     override val name = "Illustration"
+    private val owner = createSettingsPage()
 
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
-        val owner = SettingsPage.create(name)
         val entryList = mutableListOf<SettingsEntry>()
         entryList.add(
             SettingsEntryBuilder.create( "Lottie Illustration", owner)
@@ -71,7 +71,7 @@
     }
 
      fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner)
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/LoadingBarPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/LoadingBarPage.kt
index 4332a81..247990c 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/LoadingBarPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/LoadingBarPage.kt
@@ -29,8 +29,8 @@
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
@@ -45,7 +45,7 @@
     override val name = "LoadingBar"
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner = createSettingsPage())
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ProgressBarPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ProgressBarPage.kt
index 20d90dd..9026a24 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ProgressBarPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ProgressBarPage.kt
@@ -28,8 +28,8 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
@@ -47,7 +47,7 @@
     override val name = "ProgressBar"
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner = createSettingsPage())
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
index c0d0abc..dc45e6d 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SettingsPagerPage.kt
@@ -23,8 +23,8 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
@@ -39,7 +39,7 @@
     override val name = "SettingsPager"
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner = createSettingsPage())
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
index a62ec7b..1051549 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SliderPage.kt
@@ -29,8 +29,8 @@
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.SliderPreference
@@ -42,9 +42,9 @@
 
 object SliderPageProvider : SettingsPageProvider {
     override val name = "Slider"
+    private val owner = createSettingsPage()
 
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
-        val owner = SettingsPage.create(name)
         val entryList = mutableListOf<SettingsEntry>()
         entryList.add(
             SettingsEntryBuilder.create("Simple Slider", owner)
@@ -104,7 +104,7 @@
     }
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner)
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
index 67e35dc..442ace8 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
@@ -24,8 +24,8 @@
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -38,9 +38,9 @@
 
 object MainSwitchPreferencePageProvider : SettingsPageProvider {
     override val name = "MainSwitchPreference"
+    private val owner = createSettingsPage()
 
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
-        val owner = SettingsPage.create(name)
         val entryList = mutableListOf<SettingsEntry>()
         entryList.add(
             SettingsEntryBuilder.create( "MainSwitchPreference", owner)
@@ -59,7 +59,7 @@
     }
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner)
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
index 067911c..b67e066 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
@@ -27,8 +27,8 @@
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -43,9 +43,9 @@
 
 object SwitchPreferencePageProvider : SettingsPageProvider {
     override val name = "SwitchPreference"
+    private val owner = createSettingsPage()
 
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
-        val owner = SettingsPage.create(name)
         val entryList = mutableListOf<SettingsEntry>()
         entryList.add(
             SettingsEntryBuilder.create( "SwitchPreference", owner)
@@ -82,7 +82,7 @@
     }
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner)
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
index 33e5e8d..a2cd283 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
@@ -25,8 +25,8 @@
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -40,9 +40,9 @@
 
 object TwoTargetSwitchPreferencePageProvider : SettingsPageProvider {
     override val name = "TwoTargetSwitchPreference"
+    private val owner = createSettingsPage()
 
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
-        val owner = SettingsPage.create(name)
         val entryList = mutableListOf<SettingsEntry>()
         entryList.add(
             SettingsEntryBuilder.create( "TwoTargetSwitchPreference", owner)
@@ -73,7 +73,7 @@
     }
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner)
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPage.kt
index cb58abf6..7a1fad0 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/CategoryPage.kt
@@ -18,16 +18,17 @@
 
 import android.os.Bundle
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
 import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.framework.common.EntrySearchData
+import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.preference.SimplePreferenceMacro
 import com.android.settingslib.spa.widget.scaffold.RegularScaffold
 import com.android.settingslib.spa.widget.ui.Category
 import com.android.settingslib.spa.widget.ui.CategoryTitle
@@ -36,50 +37,60 @@
 
 object CategoryPageProvider : SettingsPageProvider {
     override val name = "Category"
+    private val owner = createSettingsPage()
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner)
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
                     override val onClick = navigator(name)
                 })
             }
+            .setSearchDataFn { EntrySearchData(title = TITLE) }
     }
 
     override fun getTitle(arguments: Bundle?): String {
         return TITLE
     }
 
+    override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
+        val entryList = mutableListOf<SettingsEntry>()
+        entryList.add(
+            SettingsEntryBuilder.create("Preference 1", owner)
+                .setMacro { SimplePreferenceMacro(title = "Preference 1", summary = "Summary 1") }
+                .build()
+        )
+        entryList.add(
+            SettingsEntryBuilder.create("Preference 2", owner)
+                .setMacro { SimplePreferenceMacro(title = "Preference 2", summary = "Summary 2") }
+                .build()
+        )
+        entryList.add(
+            SettingsEntryBuilder.create("Preference 3", owner)
+                .setMacro { SimplePreferenceMacro(title = "Preference 2", summary = "Summary 3") }
+                .build()
+
+        )
+        entryList.add(
+            SettingsEntryBuilder.create("Preference 4", owner)
+                .setMacro { SimplePreferenceMacro(title = "Preference 4", summary = "Summary 4") }
+                .build()
+        )
+        return entryList
+    }
+
     @Composable
     override fun Page(arguments: Bundle?) {
+        val entries = buildEntry(arguments)
         RegularScaffold(title = getTitle(arguments)) {
             CategoryTitle("Category A")
-            Preference(remember {
-                object : PreferenceModel {
-                    override val title = "Preference 1"
-                    override val summary = stateOf("Summary 1")
-                }
-            })
-            Preference(remember {
-                object : PreferenceModel {
-                    override val title = "Preference 2"
-                    override val summary = stateOf("Summary 2")
-                }
-            })
+            entries[0].UiLayout()
+            entries[1].UiLayout()
+
             Category("Category B") {
-                Preference(remember {
-                    object : PreferenceModel {
-                        override val title = "Preference 3"
-                        override val summary = stateOf("Summary 3")
-                    }
-                })
-                Preference(remember {
-                    object : PreferenceModel {
-                        override val title = "Preference 4"
-                        override val summary = stateOf("Summary 4")
-                    }
-                })
+                entries[2].UiLayout()
+                entries[3].UiLayout()
             }
         }
     }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
index 8fdc22f..aeba6ea 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
@@ -26,8 +26,8 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
@@ -42,7 +42,7 @@
     override val name = "Spinner"
 
     fun buildInjectEntry(): SettingsEntryBuilder {
-        return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
+        return SettingsEntryBuilder.createInject(owner = createSettingsPage())
             .setUiLayoutFn {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugActivity.kt
index 72f662f..078c925 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugActivity.kt
@@ -175,6 +175,7 @@
         RegularScaffold(title = "Page - ${page.debugBrief()}") {
             Text(text = "id = ${page.id}")
             Text(text = page.debugArguments())
+            Text(text = "enabled = ${page.isEnabled()}")
             Text(text = "Entry size: ${pageWithEntry.entries.size}")
             Preference(model = object : PreferenceModel {
                 override val title = "open page"
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugFormat.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugFormat.kt
index 6ecf9c3..d95ed05 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugFormat.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugFormat.kt
@@ -66,6 +66,11 @@
         "linkFrom = ${fromPage?.debugBrief()} ${fromPage?.debugArguments()}",
         "linkTo = ${toPage?.debugBrief()} ${toPage?.debugArguments()}",
         "hierarchy_path = $entryPathWithName",
+        "------ ATTRIBUTION ------",
+        "allowSearch = $isAllowSearch",
+        "isSearchDynamic = $isSearchDataDynamic",
+        "isSearchMutable = $hasMutableStatus",
+        "hasSlice = $hasSliceSupport",
         "------ SEARCH ------",
         "search_path = $entryPathWithTitle",
         searchData?.debugContent() ?: "no search data",
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugProvider.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugProvider.kt
index 838c0cf..494e3cc 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugProvider.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugProvider.kt
@@ -161,7 +161,7 @@
                 .add(ColumnEnum.PAGE_ROUTE.id, page.buildRoute())
                 .add(ColumnEnum.PAGE_INTENT_URI.id, intent.toUri(URI_INTENT_SCHEME))
                 .add(ColumnEnum.PAGE_ENTRY_COUNT.id, pageWithEntry.entries.size)
-                .add(ColumnEnum.HAS_RUNTIME_PARAM.id, if (page.hasRuntimeParam()) 1 else 0)
+                .add(ColumnEnum.PAGE_BROWSABLE.id, if (page.isBrowsable()) 1 else 0)
         }
         return cursor
     }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/ProviderColumn.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/ProviderColumn.kt
index bb9a134..fc6160e 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/ProviderColumn.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/ProviderColumn.kt
@@ -28,7 +28,7 @@
     PAGE_ROUTE("pageRoute"),
     PAGE_INTENT_URI("pageIntent"),
     PAGE_ENTRY_COUNT("entryCount"),
-    HAS_RUNTIME_PARAM("hasRuntimeParam"),
+    PAGE_BROWSABLE("pageBrowsable"),
     PAGE_START_ADB("pageStartAdb"),
 
     // Columns related to entry
@@ -67,7 +67,7 @@
             ColumnEnum.PAGE_ROUTE,
             ColumnEnum.PAGE_INTENT_URI,
             ColumnEnum.PAGE_ENTRY_COUNT,
-            ColumnEnum.HAS_RUNTIME_PARAM,
+            ColumnEnum.PAGE_BROWSABLE,
         )
     ),
 
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
index 4d8b89b..f1b1abd 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/BrowseActivity.kt
@@ -32,16 +32,18 @@
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.ui.unit.IntOffset
 import androidx.core.view.WindowCompat
 import androidx.navigation.NavGraph.Companion.findStartDestination
 import com.android.settingslib.spa.R
 import com.android.settingslib.spa.framework.common.LogCategory
-import com.android.settingslib.spa.framework.common.SettingsPage
+import com.android.settingslib.spa.framework.common.NullPageProvider
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.AnimatedNavHost
 import com.android.settingslib.spa.framework.compose.LocalNavController
 import com.android.settingslib.spa.framework.compose.NavControllerWrapperImpl
@@ -104,14 +106,13 @@
 
 @Composable
 private fun NavControllerWrapperImpl.NavContent(allProvider: Collection<SettingsPageProvider>) {
-    val nullPage = SettingsPage.createNull()
     AnimatedNavHost(
         navController = navController,
-        startDestination = nullPage.sppName,
+        startDestination = NullPageProvider.name,
     ) {
         val slideEffect = tween<IntOffset>(durationMillis = 300)
         val fadeEffect = tween<Float>(durationMillis = 300)
-        composable(nullPage.sppName) {}
+        composable(NullPageProvider.name) {}
         for (spp in allProvider) {
             composable(
                 route = spp.name + spp.parameter.navRoute(),
@@ -136,7 +137,10 @@
                         AnimatedContentScope.SlideDirection.Right, animationSpec = slideEffect
                     ) + fadeOut(animationSpec = fadeEffect)
                 },
-            ) { navBackStackEntry -> spp.PageWithEvent(navBackStackEntry.arguments) }
+            ) { navBackStackEntry ->
+                val page = remember { spp.createSettingsPage(navBackStackEntry.arguments) }
+                page.PageWithEvent()
+            }
         }
     }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt
index 2175e55..b92729d 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntry.kt
@@ -25,9 +25,6 @@
 import androidx.compose.runtime.remember
 import com.android.settingslib.spa.framework.compose.LocalNavController
 
-private const val INJECT_ENTRY_NAME = "INJECT"
-private const val ROOT_ENTRY_NAME = "ROOT"
-
 interface EntryData {
     val pageId: String?
         get() = null
@@ -163,147 +160,3 @@
         }
     }
 }
-
-/**
- * The helper to build a Settings Entry instance.
- */
-class SettingsEntryBuilder(private val name: String, private val owner: SettingsPage) {
-    private var displayName = name
-    private var fromPage: SettingsPage? = null
-    private var toPage: SettingsPage? = null
-
-    // Attributes
-    private var isAllowSearch: Boolean = false
-    private var isSearchDataDynamic: Boolean = false
-    private var hasMutableStatus: Boolean = false
-    private var hasSliceSupport: Boolean = false
-
-    // Functions
-    private var uiLayoutFn: UiLayerRenderer = { }
-    private var statusDataFn: StatusDataGetter = { null }
-    private var searchDataFn: SearchDataGetter = { null }
-    private var sliceDataFn: SliceDataGetter = { _: Uri, _: Bundle? -> null }
-
-    fun build(): SettingsEntry {
-        val page = fromPage ?: owner
-        val isEnabled = page.isEnabled()
-        return SettingsEntry(
-            id = id(),
-            name = name,
-            owner = owner,
-            displayName = displayName,
-
-            // linking data
-            fromPage = fromPage,
-            toPage = toPage,
-
-            // attributes
-            isAllowSearch = isEnabled && isAllowSearch,
-            isSearchDataDynamic = isSearchDataDynamic,
-            hasMutableStatus = hasMutableStatus,
-            hasSliceSupport = isEnabled && hasSliceSupport,
-
-            // functions
-            statusDataImpl = statusDataFn,
-            searchDataImpl = searchDataFn,
-            sliceDataImpl = sliceDataFn,
-            uiLayoutImpl = uiLayoutFn,
-        )
-    }
-
-    fun setDisplayName(displayName: String): SettingsEntryBuilder {
-        this.displayName = displayName
-        return this
-    }
-
-    fun setLink(
-        fromPage: SettingsPage? = null,
-        toPage: SettingsPage? = null
-    ): SettingsEntryBuilder {
-        if (fromPage != null) this.fromPage = fromPage
-        if (toPage != null) this.toPage = toPage
-        return this
-    }
-
-    fun setIsSearchDataDynamic(isDynamic: Boolean): SettingsEntryBuilder {
-        this.isSearchDataDynamic = isDynamic
-        return this
-    }
-
-    fun setHasMutableStatus(hasMutableStatus: Boolean): SettingsEntryBuilder {
-        this.hasMutableStatus = hasMutableStatus
-        return this
-    }
-
-    fun setMacro(fn: (arguments: Bundle?) -> EntryMacro): SettingsEntryBuilder {
-        setStatusDataFn { fn(it).getStatusData() }
-        setSearchDataFn { fn(it).getSearchData() }
-        setUiLayoutFn {
-            val macro = remember { fn(it) }
-            macro.UiLayout()
-        }
-        return this
-    }
-
-    fun setStatusDataFn(fn: StatusDataGetter): SettingsEntryBuilder {
-        this.statusDataFn = fn
-        return this
-    }
-
-    fun setSearchDataFn(fn: SearchDataGetter): SettingsEntryBuilder {
-        this.searchDataFn = fn
-        this.isAllowSearch = true
-        return this
-    }
-
-    fun clearSearchDataFn(): SettingsEntryBuilder {
-        this.searchDataFn = { null }
-        this.isAllowSearch = false
-        return this
-    }
-
-    fun setSliceDataFn(fn: SliceDataGetter): SettingsEntryBuilder {
-        this.sliceDataFn = fn
-        this.hasSliceSupport = true
-        return this
-    }
-
-    fun setUiLayoutFn(fn: UiLayerRenderer): SettingsEntryBuilder {
-        this.uiLayoutFn = fn
-        return this
-    }
-
-    // The unique id of this entry, which is computed by name + owner + fromPage + toPage.
-    private fun id(): String {
-        return "$name:${owner.id}(${fromPage?.id}-${toPage?.id})".toHashId()
-    }
-
-    companion object {
-        fun create(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
-            return SettingsEntryBuilder(entryName, owner)
-        }
-
-        fun createLinkFrom(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
-            return create(entryName, owner).setLink(fromPage = owner)
-        }
-
-        fun createLinkTo(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
-            return create(entryName, owner).setLink(toPage = owner)
-        }
-
-        fun create(owner: SettingsPage, entryName: String, displayName: String? = null):
-            SettingsEntryBuilder {
-            return SettingsEntryBuilder(entryName, owner).setDisplayName(displayName ?: entryName)
-        }
-
-        fun createInject(owner: SettingsPage, displayName: String? = null): SettingsEntryBuilder {
-            val name = displayName ?: "${INJECT_ENTRY_NAME}_${owner.displayName}"
-            return createLinkTo(INJECT_ENTRY_NAME, owner).setDisplayName(name)
-        }
-
-        fun createRoot(owner: SettingsPage, displayName: String? = null): SettingsEntryBuilder {
-            val name = displayName ?: "${ROOT_ENTRY_NAME}_${owner.displayName}"
-            return createLinkTo(ROOT_ENTRY_NAME, owner).setDisplayName(name)
-        }
-    }
-}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryBuilder.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryBuilder.kt
new file mode 100644
index 0000000..67f9ea5
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryBuilder.kt
@@ -0,0 +1,165 @@
+/*
+ * 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.settingslib.spa.framework.common
+
+import android.net.Uri
+import android.os.Bundle
+import androidx.compose.runtime.remember
+import com.android.settingslib.spa.framework.util.genEntryId
+
+private const val INJECT_ENTRY_NAME = "INJECT"
+private const val ROOT_ENTRY_NAME = "ROOT"
+
+/**
+ * The helper to build a Settings Entry instance.
+ */
+class SettingsEntryBuilder(private val name: String, private val owner: SettingsPage) {
+    private var displayName = name
+    private var fromPage: SettingsPage? = null
+    private var toPage: SettingsPage? = null
+
+    // Attributes
+    private var isAllowSearch: Boolean = false
+    private var isSearchDataDynamic: Boolean = false
+    private var hasMutableStatus: Boolean = false
+    private var hasSliceSupport: Boolean = false
+
+    // Functions
+    private var uiLayoutFn: UiLayerRenderer = { }
+    private var statusDataFn: StatusDataGetter = { null }
+    private var searchDataFn: SearchDataGetter = { null }
+    private var sliceDataFn: SliceDataGetter = { _: Uri, _: Bundle? -> null }
+
+    fun build(): SettingsEntry {
+        val page = fromPage ?: owner
+        val isEnabled = page.isEnabled()
+        return SettingsEntry(
+            id = genEntryId(name, owner, fromPage, toPage),
+            name = name,
+            owner = owner,
+            displayName = displayName,
+
+            // linking data
+            fromPage = fromPage,
+            toPage = toPage,
+
+            // attributes
+            // TODO: set isEnabled & (isAllowSearch, hasSliceSupport) separately
+            isAllowSearch = isEnabled && isAllowSearch,
+            isSearchDataDynamic = isSearchDataDynamic,
+            hasMutableStatus = hasMutableStatus,
+            hasSliceSupport = isEnabled && hasSliceSupport,
+
+            // functions
+            statusDataImpl = statusDataFn,
+            searchDataImpl = searchDataFn,
+            sliceDataImpl = sliceDataFn,
+            uiLayoutImpl = uiLayoutFn,
+        )
+    }
+
+    fun setDisplayName(displayName: String): SettingsEntryBuilder {
+        this.displayName = displayName
+        return this
+    }
+
+    fun setLink(
+        fromPage: SettingsPage? = null,
+        toPage: SettingsPage? = null
+    ): SettingsEntryBuilder {
+        if (fromPage != null) this.fromPage = fromPage
+        if (toPage != null) this.toPage = toPage
+        return this
+    }
+
+    fun setIsSearchDataDynamic(isDynamic: Boolean): SettingsEntryBuilder {
+        this.isSearchDataDynamic = isDynamic
+        return this
+    }
+
+    fun setHasMutableStatus(hasMutableStatus: Boolean): SettingsEntryBuilder {
+        this.hasMutableStatus = hasMutableStatus
+        return this
+    }
+
+    fun setMacro(fn: (arguments: Bundle?) -> EntryMacro): SettingsEntryBuilder {
+        setStatusDataFn { fn(it).getStatusData() }
+        setSearchDataFn { fn(it).getSearchData() }
+        setUiLayoutFn {
+            val macro = remember { fn(it) }
+            macro.UiLayout()
+        }
+        return this
+    }
+
+    fun setStatusDataFn(fn: StatusDataGetter): SettingsEntryBuilder {
+        this.statusDataFn = fn
+        return this
+    }
+
+    fun setSearchDataFn(fn: SearchDataGetter): SettingsEntryBuilder {
+        this.searchDataFn = fn
+        this.isAllowSearch = true
+        return this
+    }
+
+    fun clearSearchDataFn(): SettingsEntryBuilder {
+        this.searchDataFn = { null }
+        this.isAllowSearch = false
+        return this
+    }
+
+    fun setSliceDataFn(fn: SliceDataGetter): SettingsEntryBuilder {
+        this.sliceDataFn = fn
+        this.hasSliceSupport = true
+        return this
+    }
+
+    fun setUiLayoutFn(fn: UiLayerRenderer): SettingsEntryBuilder {
+        this.uiLayoutFn = fn
+        return this
+    }
+
+    companion object {
+        fun create(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
+            return SettingsEntryBuilder(entryName, owner)
+        }
+
+        fun createLinkFrom(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
+            return create(entryName, owner).setLink(fromPage = owner)
+        }
+
+        fun createLinkTo(entryName: String, owner: SettingsPage): SettingsEntryBuilder {
+            return create(entryName, owner).setLink(toPage = owner)
+        }
+
+        fun create(owner: SettingsPage, entryName: String, displayName: String? = null):
+            SettingsEntryBuilder {
+            return SettingsEntryBuilder(entryName, owner).setDisplayName(displayName ?: entryName)
+        }
+
+        fun createInject(owner: SettingsPage, displayName: String? = null): SettingsEntryBuilder {
+            val name = displayName ?: "${INJECT_ENTRY_NAME}_${owner.displayName}"
+            return createLinkTo(INJECT_ENTRY_NAME, owner).setDisplayName(name)
+        }
+
+        fun createRoot(owner: SettingsPage, displayName: String? = null): SettingsEntryBuilder {
+            val name = displayName ?: "${ROOT_ENTRY_NAME}_${owner.displayName}"
+            return createLinkTo(ROOT_ENTRY_NAME, owner).setDisplayName(name)
+        }
+    }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt
index 14b1629..429f97b 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsEntryRepository.kt
@@ -30,14 +30,10 @@
     val injectEntry: SettingsEntry,
 )
 
-private fun SettingsPage.getTitle(sppRepository: SettingsPageProviderRepository): String {
-    return sppRepository.getProviderOrNull(sppName)!!.getTitle(arguments)
-}
-
 /**
  * The repository to maintain all Settings entries
  */
-class SettingsEntryRepository(private val sppRepository: SettingsPageProviderRepository) {
+class SettingsEntryRepository(sppRepository: SettingsPageProviderRepository) {
     // Map of entry unique Id to entry
     private val entryMap: Map<String, SettingsEntry>
 
@@ -49,7 +45,7 @@
         entryMap = mutableMapOf()
         pageWithEntryMap = mutableMapOf()
 
-        val nullPage = SettingsPage.createNull()
+        val nullPage = NullPageProvider.createSettingsPage()
         val entryQueue = LinkedList<SettingsEntry>()
         for (page in sppRepository.getAllRootPages()) {
             val rootEntry =
@@ -66,6 +62,9 @@
             if (page == null || pageWithEntryMap.containsKey(page.id)) continue
             val spp = sppRepository.getProviderOrNull(page.sppName) ?: continue
             val newEntries = spp.buildEntry(page.arguments)
+            // The page id could be existed already, if there are 2+ pages go to the same one.
+            // For now, override the previous ones, which means only the last from-page is kept.
+            // TODO: support multiple from-pages if necessary.
             pageWithEntryMap[page.id] = SettingsPageWithEntry(
                 page = page,
                 entries = newEntries,
@@ -123,7 +122,7 @@
             if (it.toPage == null)
                 defaultTitle
             else {
-                it.toPage.getTitle(sppRepository)
+                it.toPage.getTitle()
             }
         }
     }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
index a362877..724588f 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
@@ -17,12 +17,11 @@
 package com.android.settingslib.spa.framework.common
 
 import android.os.Bundle
+import androidx.compose.runtime.Composable
 import androidx.navigation.NamedNavArgument
+import com.android.settingslib.spa.framework.util.genPageId
 import com.android.settingslib.spa.framework.util.isRuntimeParam
 import com.android.settingslib.spa.framework.util.navLink
-import com.android.settingslib.spa.framework.util.normalize
-
-private const val NULL_PAGE_NAME = "NULL"
 
 /**
  * Defines data to identify a Settings page.
@@ -44,10 +43,7 @@
     val arguments: Bundle? = null,
 ) {
     companion object {
-        fun createNull(): SettingsPage {
-            return create(NULL_PAGE_NAME)
-        }
-
+        // TODO: cleanup it once all its usage in Settings are switched to Spp.createSettingsPage
         fun create(
             name: String,
             displayName: String? = null,
@@ -55,23 +51,13 @@
             arguments: Bundle? = null
         ): SettingsPage {
             return SettingsPage(
-                id = id(name, parameter, arguments),
+                id = genPageId(name, parameter, arguments),
                 sppName = name,
                 displayName = displayName ?: name,
                 parameter = parameter,
                 arguments = arguments
             )
         }
-
-        // The unique id of this page, which is computed by name + normalized(arguments)
-        private fun id(
-            name: String,
-            parameter: List<NamedNavArgument> = emptyList(),
-            arguments: Bundle? = null
-        ): String {
-            val normArguments = parameter.normalize(arguments, eraseRuntimeValues = true)
-            return "$name:${normArguments?.toString()}".toHashId()
-        }
     }
 
     // Returns if this Settings Page is created by the given Spp.
@@ -83,34 +69,24 @@
         return sppName + parameter.navLink(arguments)
     }
 
-    fun hasRuntimeParam(): Boolean {
-        for (navArg in parameter) {
-            if (navArg.isRuntimeParam()) return true
-        }
-        return false
-    }
-
     fun isBrowsable(): Boolean {
-        return !isCreateBy(NULL_PAGE_NAME) &&
-            !hasRuntimeParam()
+        if (sppName == NullPageProvider.name) return false
+        for (navArg in parameter) {
+            if (navArg.isRuntimeParam()) return false
+        }
+        return true
     }
 
     fun isEnabled(): Boolean {
-        if (!SpaEnvironmentFactory.isReady()) return false
-        val pageProviderRepository by SpaEnvironmentFactory.instance.pageProviderRepository
-        return pageProviderRepository.getProviderOrNull(sppName)?.isEnabled(arguments) ?: false
+        return getPageProvider(sppName)?.isEnabled(arguments) ?: false
     }
-}
 
-fun SettingsPageProvider.createSettingsPage(arguments: Bundle? = null): SettingsPage {
-    return SettingsPage.create(
-        name = name,
-        displayName = displayName,
-        parameter = parameter,
-        arguments = arguments
-    )
-}
+    fun getTitle(): String {
+        return getPageProvider(sppName)?.getTitle(arguments) ?: ""
+    }
 
-fun String.toHashId(): String {
-    return this.hashCode().toUInt().toString(36)
+    @Composable
+    fun UiLayout() {
+        getPageProvider(sppName)?.Page(arguments)
+    }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt
index 42e5f7e..18f964e 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPageProvider.kt
@@ -18,9 +18,14 @@
 
 import android.os.Bundle
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
 import androidx.navigation.NamedNavArgument
+import com.android.settingslib.spa.framework.util.genPageId
+import com.android.settingslib.spa.framework.util.normalizeArgList
 import com.android.settingslib.spa.widget.scaffold.RegularScaffold
 
+private const val NULL_PAGE_NAME = "NULL"
+
 /**
  * An SettingsPageProvider which is used to create Settings page instances.
  */
@@ -52,10 +57,33 @@
     /** The [Composable] used to render this page. */
     @Composable
     fun Page(arguments: Bundle?) {
-        RegularScaffold(title = getTitle(arguments)) {
-            for (entry in buildEntry(arguments)) {
+        val title = remember { getTitle(arguments) }
+        val entries = remember { buildEntry(arguments) }
+        RegularScaffold(title) {
+            for (entry in entries) {
                 entry.UiLayout()
             }
         }
     }
 }
+
+fun SettingsPageProvider.createSettingsPage(arguments: Bundle? = null): SettingsPage {
+    return SettingsPage(
+        id = genPageId(name, parameter, arguments),
+        sppName = name,
+        displayName = displayName + parameter.normalizeArgList(arguments, eraseRuntimeValues = true)
+            .joinToString("") { arg -> "/$arg" },
+        parameter = parameter,
+        arguments = arguments,
+    )
+}
+
+object NullPageProvider : SettingsPageProvider {
+    override val name = NULL_PAGE_NAME
+}
+
+fun getPageProvider(sppName: String): SettingsPageProvider? {
+    if (!SpaEnvironmentFactory.isReady()) return null
+    val pageProviderRepository by SpaEnvironmentFactory.instance.pageProviderRepository
+    return pageProviderRepository.getProviderOrNull(sppName)
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt
index f672ee0..02962a5 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt
@@ -71,11 +71,15 @@
 
     val sliceDataRepository = lazy { SettingsSliceDataRepository(entryRepository.value) }
 
-    // In Robolectric test, applicationContext is not available. Use context as fallback.
+    // The application context. Use local context as fallback when applicationContext is not
+    // available (e.g. in Robolectric test).
     val appContext: Context = context.applicationContext ?: context
 
+    // Set your SpaLogger implementation, for any SPA events logging.
     open val logger: SpaLogger = object : SpaLogger {}
 
+    // Specify class name of browse activity and slice broadcast receiver, which is used to
+    // generate the necessary intents.
     open val browseActivityClass: Class<out Activity>? = null
     open val sliceBroadcastReceiverClass: Class<out BroadcastReceiver>? = null
 
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/PageLogger.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/PageLogger.kt
index 22a4563..dde4e04 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/PageLogger.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/PageLogger.kt
@@ -16,32 +16,27 @@
 
 package com.android.settingslib.spa.framework.util
 
-import android.os.Bundle
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
 import androidx.core.os.bundleOf
 import com.android.settingslib.spa.framework.common.LOG_DATA_DISPLAY_NAME
 import com.android.settingslib.spa.framework.common.LOG_DATA_SESSION_NAME
 import com.android.settingslib.spa.framework.common.LogCategory
 import com.android.settingslib.spa.framework.common.LogEvent
 import com.android.settingslib.spa.framework.common.SettingsPage
-import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
-import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.LifecycleEffect
 import com.android.settingslib.spa.framework.compose.LocalNavController
 import com.android.settingslib.spa.framework.compose.NavControllerWrapper
 
 @Composable
-internal fun SettingsPageProvider.PageWithEvent(arguments: Bundle? = null) {
-    if (!isEnabled(arguments)) return
-    val page = remember(arguments) { createSettingsPage(arguments) }
+internal fun SettingsPage.PageWithEvent() {
+    if (!isEnabled()) return
     val navController = LocalNavController.current
     LifecycleEffect(
-        onStart = { page.logPageEvent(LogEvent.PAGE_ENTER, navController) },
-        onStop = { page.logPageEvent(LogEvent.PAGE_LEAVE, navController) },
+        onStart = { logPageEvent(LogEvent.PAGE_ENTER, navController) },
+        onStop = { logPageEvent(LogEvent.PAGE_LEAVE, navController) },
     )
-    Page(arguments)
+    UiLayout()
 }
 
 private fun SettingsPage.logPageEvent(event: LogEvent, navController: NavControllerWrapper) {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt
index be303f0..f0eeb13 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Parameter.kt
@@ -29,8 +29,16 @@
 }
 
 fun List<NamedNavArgument>.navLink(arguments: Bundle? = null): String {
+    return normalizeArgList(arguments).joinToString("") { arg -> "/$arg" }
+}
+
+fun List<NamedNavArgument>.normalizeArgList(
+    arguments: Bundle? = null,
+    eraseRuntimeValues: Boolean = false
+): List<String> {
     val argsArray = mutableListOf<String>()
     for (navArg in this) {
+        if (eraseRuntimeValues && navArg.isRuntimeParam()) continue
         if (arguments == null || !arguments.containsKey(navArg.name)) {
             argsArray.add(UNSET_PARAM_VALUE)
             continue
@@ -44,7 +52,7 @@
             }
         }
     }
-    return argsArray.joinToString("") { arg -> "/$arg" }
+    return argsArray
 }
 
 fun List<NamedNavArgument>.normalize(
@@ -55,7 +63,7 @@
     val normArgs = Bundle()
     for (navArg in this) {
         // Erase value of runtime parameters.
-        if (navArg.isRuntimeParam() && eraseRuntimeValues) {
+        if (eraseRuntimeValues && navArg.isRuntimeParam()) {
             normArgs.putString(navArg.name, null)
             continue
         }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/UniqueId.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/UniqueId.kt
new file mode 100644
index 0000000..3b0ff7d
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/UniqueId.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.settingslib.spa.framework.util
+
+import android.os.Bundle
+import androidx.navigation.NamedNavArgument
+import com.android.settingslib.spa.framework.common.SettingsPage
+
+fun genPageId(
+    sppName: String,
+    parameter: List<NamedNavArgument> = emptyList(),
+    arguments: Bundle? = null
+): String {
+    val normArguments = parameter.normalize(arguments, eraseRuntimeValues = true)
+    return "$sppName:${normArguments?.toString()}".toHashId()
+}
+
+fun genEntryId(
+    name: String,
+    owner: SettingsPage,
+    fromPage: SettingsPage? = null,
+    toPage: SettingsPage? = null
+): String {
+    return "$name:${owner.id}(${fromPage?.id}-${toPage?.id})".toHashId()
+}
+
+// TODO: implement a better hash function
+private fun String.toHashId(): String {
+    return this.hashCode().toUInt().toString(36)
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt
index d6f5328..207c174 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt
@@ -30,9 +30,9 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
-import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.window.DialogProperties
 
@@ -74,7 +74,6 @@
     return alertDialogPresenter
 }
 
-@OptIn(ExperimentalComposeUiApi::class)
 @Composable
 private fun AlertDialogPresenter.SettingsAlertDialog(
     confirmButton: AlertDialogButton?,
@@ -82,15 +81,9 @@
     title: String?,
     text: @Composable (() -> Unit)?,
 ) {
-    val configuration = LocalConfiguration.current
     AlertDialog(
         onDismissRequest = ::close,
-        modifier = when (configuration.orientation) {
-            Configuration.ORIENTATION_LANDSCAPE -> {
-                Modifier.width(configuration.screenWidthDp.dp * 0.6f)
-            }
-            else -> Modifier
-        },
+        modifier = Modifier.width(getDialogWidth()),
         confirmButton = { confirmButton?.let { Button(it) } },
         dismissButton = dismissButton?.let { { Button(it) } },
         title = title?.let { { Text(it) } },
@@ -106,6 +99,15 @@
 }
 
 @Composable
+private fun getDialogWidth(): Dp {
+    val configuration = LocalConfiguration.current
+    return configuration.screenWidthDp.dp * when (configuration.orientation) {
+        Configuration.ORIENTATION_LANDSCAPE -> 0.6f
+        else -> 0.8f
+    }
+}
+
+@Composable
 private fun AlertDialogPresenter.Button(button: AlertDialogButton) {
     TextButton(
         onClick = {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
index 32b283e..62189dc 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
@@ -24,7 +24,12 @@
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.draw.scale
+import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.LayoutDirection
 import com.android.settingslib.spa.framework.compose.LocalNavController
 
 /** Action that navigates back to last page. */
@@ -50,6 +55,7 @@
         Icon(
             imageVector = Icons.Outlined.ArrowBack,
             contentDescription = contentDescription,
+            modifier = Modifier.autoMirrored(),
         )
     }
 }
@@ -75,3 +81,10 @@
         )
     }
 }
+
+private fun Modifier.autoMirrored() = composed {
+    when (LocalLayoutDirection.current) {
+        LayoutDirection.Rtl -> scale(scaleX = -1f, scaleY = 1f)
+        else -> this
+    }
+}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt
index c0b7464..379b9a7 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryRepositoryTest.kt
@@ -19,12 +19,12 @@
 import android.content.Context
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.framework.util.genEntryId
+import com.android.settingslib.spa.framework.util.genPageId
 import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
 import com.android.settingslib.spa.tests.testutils.SppHome
 import com.android.settingslib.spa.tests.testutils.SppLayer1
 import com.android.settingslib.spa.tests.testutils.SppLayer2
-import com.android.settingslib.spa.tests.testutils.getUniqueEntryId
-import com.android.settingslib.spa.tests.testutils.getUniquePageId
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -41,18 +41,18 @@
         val pageWithEntry = entryRepository.getAllPageWithEntry()
         assertThat(pageWithEntry.size).isEqualTo(3)
         assertThat(
-            entryRepository.getPageWithEntry(getUniquePageId("SppHome"))
+            entryRepository.getPageWithEntry(genPageId("SppHome"))
                 ?.entries?.size
         ).isEqualTo(1)
         assertThat(
-            entryRepository.getPageWithEntry(getUniquePageId("SppLayer1"))
+            entryRepository.getPageWithEntry(genPageId("SppLayer1"))
                 ?.entries?.size
         ).isEqualTo(3)
         assertThat(
-            entryRepository.getPageWithEntry(getUniquePageId("SppLayer2"))
+            entryRepository.getPageWithEntry(genPageId("SppLayer2"))
                 ?.entries?.size
         ).isEqualTo(2)
-        assertThat(entryRepository.getPageWithEntry(getUniquePageId("SppWithParam"))).isNull()
+        assertThat(entryRepository.getPageWithEntry(genPageId("SppWithParam"))).isNull()
     }
 
     @Test
@@ -61,17 +61,17 @@
         assertThat(entry.size).isEqualTo(7)
         assertThat(
             entryRepository.getEntry(
-                getUniqueEntryId(
+                genEntryId(
                     "ROOT",
                     SppHome.createSettingsPage(),
-                    SettingsPage.createNull(),
+                    NullPageProvider.createSettingsPage(),
                     SppHome.createSettingsPage(),
                 )
             )
         ).isNotNull()
         assertThat(
             entryRepository.getEntry(
-                getUniqueEntryId(
+                genEntryId(
                     "INJECT",
                     SppLayer1.createSettingsPage(),
                     SppHome.createSettingsPage(),
@@ -81,7 +81,7 @@
         ).isNotNull()
         assertThat(
             entryRepository.getEntry(
-                getUniqueEntryId(
+                genEntryId(
                     "INJECT",
                     SppLayer2.createSettingsPage(),
                     SppLayer1.createSettingsPage(),
@@ -91,45 +91,46 @@
         ).isNotNull()
         assertThat(
             entryRepository.getEntry(
-                getUniqueEntryId("Layer1Entry1", SppLayer1.createSettingsPage())
+                genEntryId("Layer1Entry1", SppLayer1.createSettingsPage())
             )
         ).isNotNull()
         assertThat(
             entryRepository.getEntry(
-                getUniqueEntryId("Layer1Entry2", SppLayer1.createSettingsPage())
+                genEntryId("Layer1Entry2", SppLayer1.createSettingsPage())
             )
         ).isNotNull()
         assertThat(
             entryRepository.getEntry(
-                getUniqueEntryId("Layer2Entry1", SppLayer2.createSettingsPage())
+                genEntryId("Layer2Entry1", SppLayer2.createSettingsPage())
             )
         ).isNotNull()
         assertThat(
             entryRepository.getEntry(
-                getUniqueEntryId("Layer2Entry2", SppLayer2.createSettingsPage())
+                genEntryId("Layer2Entry2", SppLayer2.createSettingsPage())
             )
         ).isNotNull()
     }
 
     @Test
     fun testGetEntryPath() {
+        SpaEnvironmentFactory.reset(spaEnvironment)
         assertThat(
             entryRepository.getEntryPathWithDisplayName(
-                getUniqueEntryId("Layer2Entry1", SppLayer2.createSettingsPage())
+                genEntryId("Layer2Entry1", SppLayer2.createSettingsPage())
             )
         ).containsExactly("Layer2Entry1", "INJECT_SppLayer2", "INJECT_SppLayer1", "ROOT_SppHome")
             .inOrder()
 
         assertThat(
             entryRepository.getEntryPathWithTitle(
-                getUniqueEntryId("Layer2Entry2", SppLayer2.createSettingsPage()),
+                genEntryId("Layer2Entry2", SppLayer2.createSettingsPage()),
                 "entryTitle"
             )
         ).containsExactly("entryTitle", "SppLayer2", "TitleLayer1", "TitleHome").inOrder()
 
         assertThat(
             entryRepository.getEntryPathWithDisplayName(
-                getUniqueEntryId(
+                genEntryId(
                     "INJECT",
                     SppLayer1.createSettingsPage(),
                     SppHome.createSettingsPage(),
@@ -140,7 +141,7 @@
 
         assertThat(
             entryRepository.getEntryPathWithTitle(
-                getUniqueEntryId(
+                genEntryId(
                     "INJECT",
                     SppLayer2.createSettingsPage(),
                     SppLayer1.createSettingsPage(),
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryTest.kt
index 6de1ae5..5754c9b 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsEntryTest.kt
@@ -23,11 +23,12 @@
 import androidx.core.os.bundleOf
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.framework.util.genEntryId
+import com.android.settingslib.spa.framework.util.genPageId
 import com.android.settingslib.spa.slice.appendSpaParams
 import com.android.settingslib.spa.slice.getEntryId
 import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
-import com.android.settingslib.spa.tests.testutils.getUniqueEntryId
-import com.android.settingslib.spa.tests.testutils.getUniquePageId
+import com.android.settingslib.spa.tests.testutils.createSettingsPage
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -64,9 +65,9 @@
 
     @Test
     fun testBuildBasic() {
-        val owner = SettingsPage.create("mySpp")
+        val owner = createSettingsPage("mySpp")
         val entry = SettingsEntryBuilder.create(owner, "myEntry").build()
-        assertThat(entry.id).isEqualTo(getUniqueEntryId("myEntry", owner))
+        assertThat(entry.id).isEqualTo(genEntryId("myEntry", owner))
         assertThat(entry.displayName).isEqualTo("myEntry")
         assertThat(entry.owner.sppName).isEqualTo("mySpp")
         assertThat(entry.owner.displayName).isEqualTo("mySpp")
@@ -80,19 +81,19 @@
 
     @Test
     fun testBuildWithLink() {
-        val owner = SettingsPage.create("mySpp")
-        val fromPage = SettingsPage.create("fromSpp")
-        val toPage = SettingsPage.create("toSpp")
+        val owner = createSettingsPage("mySpp")
+        val fromPage = createSettingsPage("fromSpp")
+        val toPage = createSettingsPage("toSpp")
         val entryFrom =
             SettingsEntryBuilder.createLinkFrom("myEntry", owner).setLink(toPage = toPage).build()
-        assertThat(entryFrom.id).isEqualTo(getUniqueEntryId("myEntry", owner, owner, toPage))
+        assertThat(entryFrom.id).isEqualTo(genEntryId("myEntry", owner, owner, toPage))
         assertThat(entryFrom.displayName).isEqualTo("myEntry")
         assertThat(entryFrom.fromPage!!.sppName).isEqualTo("mySpp")
         assertThat(entryFrom.toPage!!.sppName).isEqualTo("toSpp")
 
         val entryTo =
             SettingsEntryBuilder.createLinkTo("myEntry", owner).setLink(fromPage = fromPage).build()
-        assertThat(entryTo.id).isEqualTo(getUniqueEntryId("myEntry", owner, fromPage, owner))
+        assertThat(entryTo.id).isEqualTo(genEntryId("myEntry", owner, fromPage, owner))
         assertThat(entryTo.displayName).isEqualTo("myEntry")
         assertThat(entryTo.fromPage!!.sppName).isEqualTo("fromSpp")
         assertThat(entryTo.toPage!!.sppName).isEqualTo("mySpp")
@@ -100,10 +101,10 @@
 
     @Test
     fun testBuildInject() {
-        val owner = SettingsPage.create("mySpp")
+        val owner = createSettingsPage("mySpp")
         val entryInject = SettingsEntryBuilder.createInject(owner).build()
         assertThat(entryInject.id).isEqualTo(
-            getUniqueEntryId(
+            genEntryId(
                 INJECT_ENTRY_NAME_TEST, owner, toPage = owner
             )
         )
@@ -114,10 +115,10 @@
 
     @Test
     fun testBuildRoot() {
-        val owner = SettingsPage.create("mySpp")
+        val owner = createSettingsPage("mySpp")
         val entryInject = SettingsEntryBuilder.createRoot(owner, "myRootEntry").build()
         assertThat(entryInject.id).isEqualTo(
-            getUniqueEntryId(
+            genEntryId(
                 ROOT_ENTRY_NAME_TEST, owner, toPage = owner
             )
         )
@@ -129,7 +130,7 @@
     @Test
     fun testSetAttributes() {
         SpaEnvironmentFactory.reset(spaEnvironment)
-        val owner = SettingsPage.create("SppHome")
+        val owner = createSettingsPage("SppHome")
         val entryBuilder =
             SettingsEntryBuilder.create(owner, "myEntry")
                 .setDisplayName("myEntryDisplay")
@@ -138,7 +139,7 @@
                 .setSearchDataFn { null }
                 .setSliceDataFn { _, _ -> null }
         val entry = entryBuilder.build()
-        assertThat(entry.id).isEqualTo(getUniqueEntryId("myEntry", owner))
+        assertThat(entry.id).isEqualTo(genEntryId("myEntry", owner))
         assertThat(entry.displayName).isEqualTo("myEntryDisplay")
         assertThat(entry.fromPage).isNull()
         assertThat(entry.toPage).isNull()
@@ -148,7 +149,7 @@
         assertThat(entry.hasSliceSupport).isTrue()
 
         // Test disabled Spp
-        val ownerDisabled = SettingsPage.create("SppDisabled")
+        val ownerDisabled = createSettingsPage("SppDisabled")
         val entryBuilderDisabled =
             SettingsEntryBuilder.create(ownerDisabled, "myEntry")
                 .setDisplayName("myEntryDisplay")
@@ -157,7 +158,7 @@
                 .setSearchDataFn { null }
                 .setSliceDataFn { _, _ -> null }
         val entryDisabled = entryBuilderDisabled.build()
-        assertThat(entryDisabled.id).isEqualTo(getUniqueEntryId("myEntry", ownerDisabled))
+        assertThat(entryDisabled.id).isEqualTo(genEntryId("myEntry", ownerDisabled))
         assertThat(entryDisabled.displayName).isEqualTo("myEntryDisplay")
         assertThat(entryDisabled.fromPage).isNull()
         assertThat(entryDisabled.toPage).isNull()
@@ -173,7 +174,7 @@
         // Clear SppHome in spa environment
         SpaEnvironmentFactory.reset()
         val entry3 = entryBuilder.build()
-        assertThat(entry3.id).isEqualTo(getUniqueEntryId("myEntry", owner))
+        assertThat(entry3.id).isEqualTo(genEntryId("myEntry", owner))
         assertThat(entry3.displayName).isEqualTo("myEntryDisplay")
         assertThat(entry3.fromPage).isNull()
         assertThat(entry3.toPage).isNull()
@@ -186,12 +187,12 @@
     @Test
     fun testSetMarco() {
         SpaEnvironmentFactory.reset(spaEnvironment)
-        val owner = SettingsPage.create("SppHome", arguments = bundleOf("param" to "v1"))
+        val owner = createSettingsPage("SppHome", arguments = bundleOf("param" to "v1"))
         val entry = SettingsEntryBuilder.create(owner, "myEntry").setMacro {
             assertThat(it?.getString("param")).isEqualTo("v1")
             assertThat(it?.getString("rtParam")).isEqualTo("v2")
             assertThat(it?.getString("unknown")).isNull()
-            MacroForTest(getUniquePageId("SppHome"), getUniqueEntryId("myEntry", owner))
+            MacroForTest(genPageId("SppHome"), genEntryId("myEntry", owner))
         }.build()
 
         val rtArguments = bundleOf("rtParam" to "v2")
@@ -211,8 +212,8 @@
     @Test
     fun testSetSliceDataFn() {
         SpaEnvironmentFactory.reset(spaEnvironment)
-        val owner = SettingsPage.create("SppHome")
-        val entryId = getUniqueEntryId("myEntry", owner)
+        val owner = createSettingsPage("SppHome")
+        val entryId = genEntryId("myEntry", owner)
         val emptySliceData = EntrySliceData()
 
         val entryBuilder = SettingsEntryBuilder.create(owner, "myEntry").setSliceDataFn { uri, _ ->
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepositoryTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepositoryTest.kt
index 6c0c652..8576573 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepositoryTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageProviderRepositoryTest.kt
@@ -17,6 +17,7 @@
 package com.android.settingslib.spa.framework.common
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.tests.testutils.createSettingsPage
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -29,13 +30,14 @@
         assertThat(sppRepoEmpty.getDefaultStartPage()).isEqualTo("")
         assertThat(sppRepoEmpty.getAllRootPages()).isEmpty()
 
+        val nullPage = NullPageProvider.createSettingsPage()
         val sppRepoNull =
-            SettingsPageProviderRepository(emptyList(), listOf(SettingsPage.createNull()))
+            SettingsPageProviderRepository(emptyList(), listOf(nullPage))
         assertThat(sppRepoNull.getDefaultStartPage()).isEqualTo("NULL")
-        assertThat(sppRepoNull.getAllRootPages()).contains(SettingsPage.createNull())
+        assertThat(sppRepoNull.getAllRootPages()).contains(nullPage)
 
-        val rootPage1 = SettingsPage.create(name = "Spp1", displayName = "Spp1")
-        val rootPage2 = SettingsPage.create(name = "Spp2", displayName = "Spp2")
+        val rootPage1 = createSettingsPage(sppName = "Spp1", displayName = "Spp1")
+        val rootPage2 = createSettingsPage(sppName = "Spp2", displayName = "Spp2")
         val sppRepo = SettingsPageProviderRepository(emptyList(), listOf(rootPage1, rootPage2))
         val allRoots = sppRepo.getAllRootPages()
         assertThat(sppRepo.getDefaultStartPage()).isEqualTo("Spp1")
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageTest.kt
index 1f5de2d..dc74a10 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/common/SettingsPageTest.kt
@@ -22,8 +22,9 @@
 import androidx.navigation.navArgument
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.framework.util.genPageId
 import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
-import com.android.settingslib.spa.tests.testutils.getUniquePageId
+import com.android.settingslib.spa.tests.testutils.createSettingsPage
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -35,27 +36,25 @@
 
     @Test
     fun testNullPage() {
-        val page = SettingsPage.createNull()
-        assertThat(page.id).isEqualTo(getUniquePageId("NULL"))
+        val page = NullPageProvider.createSettingsPage()
+        assertThat(page.id).isEqualTo(genPageId("NULL"))
         assertThat(page.sppName).isEqualTo("NULL")
         assertThat(page.displayName).isEqualTo("NULL")
         assertThat(page.buildRoute()).isEqualTo("NULL")
         assertThat(page.isCreateBy("NULL")).isTrue()
         assertThat(page.isCreateBy("Spp")).isFalse()
-        assertThat(page.hasRuntimeParam()).isFalse()
         assertThat(page.isBrowsable()).isFalse()
     }
 
     @Test
     fun testRegularPage() {
-        val page = SettingsPage.create("mySpp", "SppDisplayName")
-        assertThat(page.id).isEqualTo(getUniquePageId("mySpp"))
+        val page = createSettingsPage("mySpp", "SppDisplayName")
+        assertThat(page.id).isEqualTo(genPageId("mySpp"))
         assertThat(page.sppName).isEqualTo("mySpp")
         assertThat(page.displayName).isEqualTo("SppDisplayName")
         assertThat(page.buildRoute()).isEqualTo("mySpp")
         assertThat(page.isCreateBy("NULL")).isFalse()
         assertThat(page.isCreateBy("mySpp")).isTrue()
-        assertThat(page.hasRuntimeParam()).isFalse()
         assertThat(page.isBrowsable()).isTrue()
     }
 
@@ -67,7 +66,7 @@
         )
         val page = spaEnvironment.createPage("SppWithParam", arguments)
         assertThat(page.id).isEqualTo(
-            getUniquePageId(
+            genPageId(
                 "SppWithParam", listOf(
                     navArgument("string_param") { type = NavType.StringType },
                     navArgument("int_param") { type = NavType.IntType },
@@ -75,10 +74,9 @@
             )
         )
         assertThat(page.sppName).isEqualTo("SppWithParam")
-        assertThat(page.displayName).isEqualTo("SppWithParam")
+        assertThat(page.displayName).isEqualTo("SppWithParam/myStr/10")
         assertThat(page.buildRoute()).isEqualTo("SppWithParam/myStr/10")
         assertThat(page.isCreateBy("SppWithParam")).isTrue()
-        assertThat(page.hasRuntimeParam()).isFalse()
         assertThat(page.isBrowsable()).isTrue()
     }
 
@@ -91,7 +89,7 @@
         )
         val page = spaEnvironment.createPage("SppWithRtParam", arguments)
         assertThat(page.id).isEqualTo(
-            getUniquePageId(
+            genPageId(
                 "SppWithRtParam", listOf(
                     navArgument("string_param") { type = NavType.StringType },
                     navArgument("int_param") { type = NavType.IntType },
@@ -100,10 +98,9 @@
             )
         )
         assertThat(page.sppName).isEqualTo("SppWithRtParam")
-        assertThat(page.displayName).isEqualTo("SppWithRtParam")
+        assertThat(page.displayName).isEqualTo("SppWithRtParam/myStr/10")
         assertThat(page.buildRoute()).isEqualTo("SppWithRtParam/myStr/10/rtStr")
         assertThat(page.isCreateBy("SppWithRtParam")).isTrue()
-        assertThat(page.hasRuntimeParam()).isTrue()
         assertThat(page.isBrowsable()).isFalse()
     }
 }
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/SpaIntentTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/SpaIntentTest.kt
index 1854728..f974cca 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/SpaIntentTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/SpaIntentTest.kt
@@ -19,9 +19,10 @@
 import android.content.Context
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.framework.common.NullPageProvider
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
-import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
+import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
 import com.google.common.truth.Truth
 import org.junit.Before
@@ -40,7 +41,7 @@
 
     @Test
     fun testCreateIntent() {
-        val nullPage = SettingsPage.createNull()
+        val nullPage = NullPageProvider.createSettingsPage()
         Truth.assertThat(nullPage.createIntent()).isNull()
         Truth.assertThat(SettingsEntryBuilder.createInject(nullPage).build().createIntent())
             .isNull()
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/UniqueIdTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/UniqueIdTest.kt
new file mode 100644
index 0000000..c17f83b
--- /dev/null
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/UniqueIdTest.kt
@@ -0,0 +1,67 @@
+/*
+ * 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.settingslib.spa.framework.util
+
+import androidx.core.os.bundleOf
+import androidx.navigation.NavType
+import androidx.navigation.navArgument
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.tests.testutils.createSettingsPage
+import com.google.common.truth.Truth
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class UniqueIdTest {
+    @Test
+    fun testUniquePageId() {
+        Truth.assertThat(genPageId("mySpp")).isEqualTo("1byojwa")
+
+        val parameter = listOf(
+            navArgument("string_param") { type = NavType.StringType },
+            navArgument("int_param") { type = NavType.IntType },
+        )
+        val arguments = bundleOf(
+            "string_param" to "myStr",
+            "int_param" to 10,
+        )
+        Truth.assertThat(genPageId("mySppWithParam", parameter, arguments)).isEqualTo("1sz4pbq")
+
+        val parameter2 = listOf(
+            navArgument("string_param") { type = NavType.StringType },
+            navArgument("int_param") { type = NavType.IntType },
+            navArgument("rt_param") { type = NavType.StringType },
+        )
+        val arguments2 = bundleOf(
+            "string_param" to "myStr",
+            "int_param" to 10,
+            "rt_param" to "myRtStr",
+        )
+        Truth.assertThat(genPageId("mySppWithRtParam", parameter2, arguments2)).isEqualTo("ts6d8k")
+    }
+
+    @Test
+    fun testUniqueEntryId() {
+        val owner = createSettingsPage("mySpp")
+        val fromPage = createSettingsPage("fromSpp")
+        val toPage = createSettingsPage("toSpp")
+
+        Truth.assertThat(genEntryId("myEntry", owner)).isEqualTo("145pppn")
+        Truth.assertThat(genEntryId("myEntry", owner, fromPage = fromPage, toPage = toPage))
+            .isEqualTo("1m7jzew")
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/slice/SettingsSliceDataRepositoryTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/slice/SettingsSliceDataRepositoryTest.kt
index 530d2ed..341a4a5 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/slice/SettingsSliceDataRepositoryTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/slice/SettingsSliceDataRepositoryTest.kt
@@ -25,10 +25,10 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
 import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.framework.util.genEntryId
 import com.android.settingslib.spa.tests.testutils.SpaEnvironmentForTest
 import com.android.settingslib.spa.tests.testutils.SppHome
 import com.android.settingslib.spa.tests.testutils.SppLayer2
-import com.android.settingslib.spa.tests.testutils.getUniqueEntryId
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -52,7 +52,7 @@
 
         // Slice supported
         val page = SppLayer2.createSettingsPage()
-        val entryId = getUniqueEntryId("Layer2Entry1", page)
+        val entryId = genEntryId("Layer2Entry1", page)
         val sliceUri = Uri.Builder().appendSpaParams(page.buildRoute(), entryId).build()
         assertThat(sliceUri.getDestination()).isEqualTo("SppLayer2")
         assertThat(sliceUri.getSliceId()).isEqualTo("${entryId}_Bundle[{}]")
@@ -61,7 +61,7 @@
         assertThat(sliceDataRepository.getOrBuildSliceData(sliceUri)).isSameInstanceAs(sliceData)
 
         // Slice unsupported
-        val entryId2 = getUniqueEntryId("Layer2Entry2", page)
+        val entryId2 = genEntryId("Layer2Entry2", page)
         val sliceUri2 = Uri.Builder().appendSpaParams(page.buildRoute(), entryId2).build()
         assertThat(sliceUri2.getDestination()).isEqualTo("SppLayer2")
         assertThat(sliceUri2.getSliceId()).isEqualTo("${entryId2}_Bundle[{}]")
@@ -73,7 +73,7 @@
         SpaEnvironmentFactory.reset(spaEnvironment)
 
         val page = SppLayer2.createSettingsPage()
-        val entryId = getUniqueEntryId("Layer2Entry1", page)
+        val entryId = genEntryId("Layer2Entry1", page)
         val sliceUri = Uri.Builder().appendSpaParams(page.buildRoute(), entryId).build()
 
         // build slice data first
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SettingsPageHelper.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SettingsPageHelper.kt
new file mode 100644
index 0000000..caf4136
--- /dev/null
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/SettingsPageHelper.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.tests.testutils
+
+import android.os.Bundle
+import androidx.navigation.NamedNavArgument
+import com.android.settingslib.spa.framework.common.SettingsPage
+import com.android.settingslib.spa.framework.util.genPageId
+
+fun createSettingsPage(
+    sppName: String,
+    displayName: String? = null,
+    parameter: List<NamedNavArgument> = emptyList(),
+    arguments: Bundle? = null
+): SettingsPage {
+    return SettingsPage(
+        id = genPageId(sppName, parameter, arguments),
+        sppName = sppName,
+        displayName = displayName ?: sppName,
+        parameter = parameter,
+        arguments = arguments
+    )
+}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/UniqueIdHelper.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/UniqueIdHelper.kt
deleted file mode 100644
index ce9b791..0000000
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/tests/testutils/UniqueIdHelper.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.spa.tests.testutils
-
-import android.os.Bundle
-import androidx.navigation.NamedNavArgument
-import com.android.settingslib.spa.framework.common.SettingsPage
-import com.android.settingslib.spa.framework.common.toHashId
-import com.android.settingslib.spa.framework.util.normalize
-
-fun getUniquePageId(
-    name: String,
-    parameter: List<NamedNavArgument> = emptyList(),
-    arguments: Bundle? = null
-): String {
-    val normArguments = parameter.normalize(arguments, eraseRuntimeValues = true)
-    return "$name:${normArguments?.toString()}".toHashId()
-}
-
-fun getUniquePageId(page: SettingsPage): String {
-    return getUniquePageId(page.sppName, page.parameter, page.arguments)
-}
-
-fun getUniqueEntryId(
-    name: String,
-    owner: SettingsPage,
-    fromPage: SettingsPage? = null,
-    toPage: SettingsPage? = null
-): String {
-    val ownerId = getUniquePageId(owner)
-    val fromId = if (fromPage == null) "null" else getUniquePageId(fromPage)
-    val toId = if (toPage == null) "null" else getUniquePageId(toPage)
-    return "$name:$ownerId($fromId-$toId)".toHashId()
-}
diff --git a/packages/SettingsLib/Spa/testutils/build.gradle b/packages/SettingsLib/Spa/testutils/build.gradle
index dd7058d..b898a4f 100644
--- a/packages/SettingsLib/Spa/testutils/build.gradle
+++ b/packages/SettingsLib/Spa/testutils/build.gradle
@@ -20,6 +20,7 @@
 }
 
 android {
+    namespace 'com.android.settingslib.spa.testutils'
     compileSdk TARGET_SDK
     buildToolsVersion = BUILD_TOOLS_VERSION
 
@@ -55,7 +56,7 @@
 dependencies {
     api project(":spa")
 
-    api "androidx.arch.core:core-testing:2.1.0"
+    api "androidx.arch.core:core-testing:2.2.0-alpha01"
     api "androidx.compose.ui:ui-test-junit4:$jetpack_compose_version"
     api "com.google.truth:truth:1.1.3"
     api "org.mockito:mockito-core:2.21.0"
diff --git a/packages/SettingsLib/res/drawable/ic_media_avr_device.xml b/packages/SettingsLib/res/drawable/ic_media_avr_device.xml
new file mode 100644
index 0000000..3de0d84
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_media_avr_device.xml
@@ -0,0 +1,40 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path
+        android:pathData="M18.918,7C18.963,7 19,7.037 19,7.082V14.918C19,14.963 18.963,15 18.918,15H3.082C3.037,15 3,14.963 3,14.918V7.082C3,7.037 3.037,7 3.082,7H18.918ZM18.918,5H3.082C1.932,5 1,5.932 1,7.082V14.918C1,16.068 1.932,17 3.082,17H18.918C20.068,17 21,16.068 21,14.918V7.082C21,5.932 20.068,5 18.918,5Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M18,15H17C16.448,15 16,15.448 16,16V17C16,17.552 16.448,18 17,18H18C18.552,18 19,17.552 19,17V16C19,15.448 18.552,15 18,15Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M5,15H4C3.448,15 3,15.448 3,16V17C3,17.552 3.448,18 4,18H5C5.552,18 6,17.552 6,17V16C6,15.448 5.552,15 5,15Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M15.5,12.5C16.328,12.5 17,11.828 17,11C17,10.172 16.328,9.5 15.5,9.5C14.672,9.5 14,10.172 14,11C14,11.828 14.672,12.5 15.5,12.5Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M15.5,10C16.052,10 16.5,10.448 16.5,11C16.5,11.552 16.052,12 15.5,12C14.948,12 14.5,11.552 14.5,11C14.5,10.448 14.948,10 15.5,10ZM15.5,9C14.397,9 13.5,9.897 13.5,11C13.5,12.103 14.397,13 15.5,13C16.603,13 17.5,12.103 17.5,11C17.5,9.897 16.603,9 15.5,9Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M5,9h7v4h-7z"
+        android:fillColor="#ffffff"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 978f745..193c51f 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Hierdie foon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Hierdie tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Hierdie foon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kan nie koppel nie. Skakel toestel af en weer aan"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedrade oudiotoestel"</string>
     <string name="help_label" msgid="3528360748637781274">"Hulp en terugvoer"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Voorspellingteruggebaaranimasies"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Aktiveer stelselanimasies vir voorspellingteruggebaar."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Hierdie instelling aktiveer stelselanimasies vir voorspellinggebaaranimasie. Dit vereis dat enableOnBackInvokedCallback per program op waar gestel word in die manifeslêer."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 8f1a2a9..60812d8 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ይህ ስልክ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ይህ ጡባዊ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ይህ ስልክ"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"መገናኘት ላይ ችግር። መሳሪያውን ያጥፉት እና እንደገና ያብሩት"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ባለገመድ የኦዲዮ መሣሪያ"</string>
     <string name="help_label" msgid="3528360748637781274">"እገዛ እና ግብረመልስ"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"የግምት ጀርባ እነማዎች"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"ለግምት ጀርባ የስርዓት እንማዎችን ያንቁ።"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ይህ ቅንብር የስርዓት እነማዎችን ለመገመት የምልክት እነማን ያነቃል። በዝርዝር ሰነድ ፋይሉ ውስጥ በእያንዳንዱ መተግበሪያ enableOnBackInvokedCallbackን ወደ እውነት ማቀናበር ያስፈልገዋል።"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 669f85f..b8474a7 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"هذا الهاتف"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"هذا الجهاز اللوحي"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"هذا الهاتف"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string>
     <string name="help_label" msgid="3528360748637781274">"المساعدة والملاحظات"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"صور متحركة تعرض إيماءة الرجوع إلى الخلف التنبؤية"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"فعِّل الصور المتحركة في النظام لإيماءة الرجوع إلى الخلف التنبؤية."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"‏يفعّل هذا الإعداد الصور المتحركة في النظام للصور المتحركة التي تعرض إيماءة الرجوع إلى الخلف التنبؤية. يتطلب الإعداد ضبط enableOnBackInvokedCallback إلى true لكل تطبيق في ملف البيان."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index f9745e0..6afced7 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফ’নটো"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"এই টেবলেটটো"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফ’নটো"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"সংযোগ হোৱাত সমস্যা হৈছে। ডিভাইচটো অফ কৰি পুনৰ অন কৰক"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"তাঁৰযুক্ত অডিঅ’ ডিভাইচ"</string>
     <string name="help_label" msgid="3528360748637781274">"সহায় আৰু মতামত"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"প্ৰেডিক্টিভ বেক এনিমেশ্বন"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"প্ৰেডিক্টিভ বেকৰ বাবে ছিষ্টেম এনিমেশ্বন সক্ষম কৰক।"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"এই ছেটিংটোৱে প্ৰেডিক্টিভ বেক এনিমেশ্বনৰ বাবে ছিষ্টেম এনিমেশ্বন সক্ষম কৰে। ইয়াৰ বাবে মেনিফেষ্ট ফাইলত প্ৰতি এপত enableOnBackInvokedCallback সত্য বুলি ছেট কৰাৰ প্ৰয়োজন।"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index efcc0bc..74bb158 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Bu planşet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Qoşulmaqla bağlı problem. Cihazı deaktiv edin, sonra yenidən aktiv edin"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio cihaz"</string>
     <string name="help_label" msgid="3528360748637781274">"Yardım və rəy"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Proqnozlaşdırılan geri animasiyalar"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Proqnozlaşdırıcı geri jest üçün sistem animasiyalarını aktiv edin."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Bu ayar proqnozlaşdırıcı jest animasiyası üçün sistem animasiyalarını aktiv edir. Bu, manifest faylında hər bir tətbiq üçün enableOnBackInvokedCallback-in doğru kimi ayarlanmasını tələb edir."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index c8955e8..ff4d083 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem pri povezivanju. Isključite uređaj, pa ga ponovo uključite"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animacije za pokret povratka sa predviđanjem"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Omogućite animacije sistema za pokret povratka sa predviđanjem."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ovo podešavanje omogućava animacije sistema za pokret povratka sa predviđanjem. Zahteva podešavanje dozvole enableOnBackInvokedCallback po aplikaciji na true u fajlu manifesta."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index cd7b198..47404db 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Гэты тэлефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Гэты планшэт"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Гэты тэлефон"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Праблема з падключэннем. Выключыце і зноў уключыце прыладу"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Правадная аўдыяпрылада"</string>
     <string name="help_label" msgid="3528360748637781274">"Даведка і водгукі"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Анімацыя падказкі для жэста вяртання"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Уключыць сістэмную анімацыю падказкі для жэстаў вяртання."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Гэта налада ўключае сістэмную анімацыю падказкі для жэста вяртання. Для гэтага неабходна задаць у файле маніфеста для параметра enableOnBackInvokedCallback значэнне \"True\" для кожнай праграмы."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index a337429..b98027b 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Този телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Този таблет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Този телефон"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"При свързването възникна проблем. Изключете устройството и го включете отново"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Аудиоустройство с кабел"</string>
     <string name="help_label" msgid="3528360748637781274">"Помощ и отзиви"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Анимации за предвиждащия жест за връщане назад"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Активиране на системните анимации за предвиждащия жест за връщане назад."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Тази настройка активира системните анимации за предвиждащите жестове. За целта във файла на манифеста трябва да зададете enableOnBackInvokedCallback на true за отделните приложения."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 28a1598..f2a574e 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফোন"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"এই ট্যাবলেট"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফোনটি"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"কানেক্ট করতে সমস্যা হচ্ছে। ডিভাইস বন্ধ করে আবার চালু করুন"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ওয়্যার অডিও ডিভাইস"</string>
     <string name="help_label" msgid="3528360748637781274">"সহায়তা ও মতামত"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"ফিরে যাওয়ার পূর্বাভাস সংক্রান্ত অ্যানিমেশন"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"ফিরে যাওয়া সংক্রান্ত পূর্বাভাসের জন্য সিস্টেম অ্যানিমেশন চালু করুন।"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"জেসচারের পূর্বাভাস সংক্রান্ত অ্যানিমেশন দেখাতে এই সেটিং সিস্টেম অ্যানিমেশন চালু করে। এই সেটিংয়ে \'ম্যানিফেস্ট\' ফাইলে প্রত্যেক অ্যাপে enableOnBackInvokedCallback অ্যাট্রিবিউটকে \'ট্রু\' (true) হিসেবে সেট করতে হয়।"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index e24c68d..947aaaf 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Došlo je do problema prilikom povezivanja. Isključite, pa ponovo uključite uređaj"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animacije predvidljivog pokreta unazad"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Omogućite animacije sistema za predvidljivi pokret unazad."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ova postavka omogućava animacije sistema za animaciju predvidljivih pokreta. Potrebno je po aplikaciji postaviti vrijednost za enableOnBackInvokedCallback na tačno u fajlu deklaracije."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 2abdf00..4d1d983 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Aquest telèfon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Aquesta tauleta"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Aquest telèfon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Hi ha hagut un problema amb la connexió. Apaga el dispositiu i torna\'l a encendre."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositiu d\'àudio amb cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda i suggeriments"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animacions de retrocés predictiu"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activa animacions del sistema de retrocés predictiu."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Aquesta configuració activa animacions del sistema per a accions gestuals predictives. Requereix definir enableOnBackInvokedCallback com a \"true\" en cada aplicació al fitxer de manifest."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index d82b472..530627f 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tento tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problém s připojením. Vypněte zařízení a znovu jej zapněte"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kabelové audiozařízení"</string>
     <string name="help_label" msgid="3528360748637781274">"Nápověda a zpětná vazba"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Prediktivní animace gesta Zpět"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Povolit systémové animace prediktivního gesta Zpět"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Toto nastavení aktivuje systémové prediktivní animace gest. Vyžaduje, aby v souborech manifestu jednotlivých aplikací byl nastaven atribut enableOnBackInvokedCallback na hodnotu True."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 9726f8c..a071200 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Denne tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Der kunne ikke oprettes forbindelse. Sluk og tænd enheden"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhed med ledning"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjælp og feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Foreslåede animationer for Tilbage"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Aktivér systemanimationer for foreslåede animationer for Tilbage."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Denne indstilling aktiverer systemanimationer for de foreslåede animationer for bevægelsen Tilbage. Dette forudsætter konfiguration af enableOnBackInvokedCallback som sand for hver app i manifestfilen."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 68199dd..f0bd6ba 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Dieses Smartphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Dieses Tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Dieses Smartphone"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Verbindung kann nicht hergestellt werden. Schalte das Gerät aus &amp; und wieder ein."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Netzbetriebenes Audiogerät"</string>
     <string name="help_label" msgid="3528360748637781274">"Hilfe und Feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animationen für intelligente „Zurück“-Touch-Geste"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Du kannst Systemanimationen für die intelligente „Zurück“-Touch-Geste aktivieren."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Diese Einstellung aktiviert Systemanimationen für intelligente Touch-Gesten. Dazu muss in der Manifestdatei enableOnBackInvokedCallback auf App-Ebene auf „true“ gesetzt werden."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 974c998..60de1b5 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Αυτό το τηλέφωνο"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Αυτό το tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Αυτό το τηλέφωνο"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Πρόβλημα κατά τη σύνδεση. Απενεργοποιήστε τη συσκευή και ενεργοποιήστε την ξανά"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ενσύρματη συσκευή ήχου"</string>
     <string name="help_label" msgid="3528360748637781274">"Βοήθεια και σχόλια"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Κινούμ. εικόνες μετάβασης προς τα πίσω με πρόβλεψη"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Ενεργοποίηση κινούμενων εικόνων συστήματος για μετάβαση προς τα πίσω με πρόβλεψη."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Αυτή η ρύθμιση ενεργοποιεί τις κινούμενες εικόνες συστήματος για τις κινούμενες εικόνες κινήσεων με πρόβλεψη. Απαιτεί τη ρύθμιση της παραμέτρου enableOnBackInvokedCallback ως αληθούς σε κάθε εφαρμογή στο αρχείο μανιφέστου."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index c6443bd..521bcf6 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -540,6 +540,12 @@
     <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>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Predictive back animations"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Enable system animations for predictive back."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"This setting enables system animations for predictive gesture animation. It requires setting per-app enableOnBackInvokedCallback to true in the manifest file."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 03475be..90d1106 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -540,6 +540,9 @@
     <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>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade account to switch"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Cant play downloads here"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Try again after the ad"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off &amp; back on"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
@@ -666,4 +669,10 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Predictive back animations"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Enable system animations for predictive back."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"This setting enables system animations for predictive gesture animation. It requires setting per-app enableOnBackInvokedCallback to true in the manifest file."</string>
+  <string-array name="udfps_accessibility_touch_hints">
+    <item msgid="1737722959616802157">"Move left"</item>
+    <item msgid="5425394847942513942">"Move down"</item>
+    <item msgid="7728484337962740316">"Move right"</item>
+    <item msgid="324200556467459329">"Move up"</item>
+  </string-array>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index c6443bd..521bcf6 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -540,6 +540,12 @@
     <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>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Predictive back animations"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Enable system animations for predictive back."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"This setting enables system animations for predictive gesture animation. It requires setting per-app enableOnBackInvokedCallback to true in the manifest file."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index c6443bd..521bcf6 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -540,6 +540,12 @@
     <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>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Predictive back animations"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Enable system animations for predictive back."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"This setting enables system animations for predictive gesture animation. It requires setting per-app enableOnBackInvokedCallback to true in the manifest file."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 113ea19..1074338 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -540,6 +540,9 @@
     <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>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‎‏‎‏‏‎This phone‎‏‎‎‏‎"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎Upgrade account to switch‎‏‎‎‏‎"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎Cant play downloads here‎‏‎‎‏‎"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎Try again after the ad‎‏‎‎‏‎"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‏‎Problem connecting. Turn device off &amp; back on‎‏‎‎‏‎"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎Wired audio device‎‏‎‎‏‎"</string>
     <string name="help_label" msgid="3528360748637781274">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‎Help &amp; feedback‎‏‎‎‏‎"</string>
@@ -666,4 +669,10 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎Predictive back animations‎‏‎‎‏‎"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‎‎Enable system animations for predictive back.‎‏‎‎‏‎"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎This setting enables system animations for predictive gesture animation. It requires setting per-app enableOnBackInvokedCallback to true in the manifest file.‎‏‎‎‏‎"</string>
+  <string-array name="udfps_accessibility_touch_hints">
+    <item msgid="1737722959616802157">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‏‎Move left‎‏‎‎‏‎"</item>
+    <item msgid="5425394847942513942">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‎‎Move down‎‏‎‎‏‎"</item>
+    <item msgid="7728484337962740316">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎Move right‎‏‎‎‏‎"</item>
+    <item msgid="324200556467459329">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‎‎‎‏‎Move up‎‏‎‎‏‎"</item>
+  </string-array>
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 220ca44..7e7fd15 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Error al establecer la conexión. Apaga el dispositivo y vuelve a encenderlo."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Ayuda y comentarios"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animaciones de retroceso predictivas"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Habilitar animaciones del sistema para gestos de retroceso predictivos."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Esta configuración habilita las animaciones del sistema para la animación de gestos predictiva. Se requiere la configuración por app de enableOnBackInvokedCallback en verdadero en el archivo de manifiesto."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index bdd1ff2..58206eb 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"No se ha podido conectar; reinicia el dispositivo"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Ayuda y comentarios"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animaciones para acciones de retorno predictivas"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Habilitar animaciones del sistema para acciones de retorno predictivas."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Este ajuste habilita animaciones del sistema para acciones gestuales predictivas. Exige definir el valor de enableOnBackInvokedCallback en \"verdadero\" para cada aplicación en el archivo de manifiesto."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index cdc5051..6bdb938 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"See telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"See tahvelarvuti"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"See telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem ühendamisel. Lülitage seade välja ja uuesti sisse"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Juhtmega heliseade"</string>
     <string name="help_label" msgid="3528360748637781274">"Abi ja tagasiside"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Tagasiliigutuse prognoosi animatsioon"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Lubage süsteemi animatsioonid, et näha prognoositud tagasiliigutusi."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"See seade võimaldab süsteemi animatsioonidel prognoosida tagasiliigutusi. See nõuab manifestifailis rakendusepõhise atribuudi enableOnBackInvokedCallback määramist tõeseks."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 9d6a10a..872b3b6 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefono hau"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tableta hau"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefono hau"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Arazo bat izan da konektatzean. Itzali gailua eta pitz ezazu berriro."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio-gailu kableduna"</string>
     <string name="help_label" msgid="3528360748637781274">"Laguntza eta iritziak"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Atzera egiteko keinuaren animazio-igarleak"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Gaitu atzera egiteko keinuaren sistemaren animazio-igarleak."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Atzera egiteko keinuaren sistemaren animazio-igarleak gaitzen ditu ezarpenak. enableOnBackInvokedCallback-ek egiazko gisa ezarrita egon behar du aplikazio bakoitzaren manifestu-fitxategian."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index b922640..378fa19 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -183,7 +183,7 @@
     <string name="tts_lang_use_system" msgid="6312945299804012406">"استفاده از زبان سیستم"</string>
     <string name="tts_lang_not_selected" msgid="7927823081096056147">"زبان انتخاب نشده است"</string>
     <string name="tts_default_lang_summary" msgid="9042620014800063470">"صدای خاص یک زبان را برای متن گفتاری تنظیم می‌کند"</string>
-    <string name="tts_play_example_title" msgid="1599468547216481684">"به نمونه‌ای گوش کنید"</string>
+    <string name="tts_play_example_title" msgid="1599468547216481684">"شنیدن نمونه"</string>
     <string name="tts_play_example_summary" msgid="634044730710636383">"قسمت کوتاهی از ترکیب گفتار پخش شود"</string>
     <string name="tts_install_data_title" msgid="1829942496472751703">"نصب داده‌های صوتی"</string>
     <string name="tts_install_data_summary" msgid="3608874324992243851">"نصب داده‌های صوتی مورد نیاز برای ترکیب گفتار"</string>
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"این تلفن"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"این رایانه لوحی"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"این تلفن"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"مشکل در اتصال. دستگاه را خاموش و دوباره روشن کنید"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"دستگاه صوتی سیمی"</string>
     <string name="help_label" msgid="3528360748637781274">"راهنما و بازخورد"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"پویانمایی‌های اشاره برگشت پیش‌گویانه"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"پویانمایی‌های سیستم را برای اشاره برگشت پیش‌گویانه فعال کنید."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"‏این تنظیم پویانمایی‌های سیستم را برای پویانمایی اشاره برگشت پیش‌بینانه فعال می‌کند. این تنظیم مستلزم تنظیم شدن enableOnBackInvokedCallback مربوط به هر برنامه روی صحیح در فایل مانیفست است."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 1bebe1c..f9527f86 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tämä puhelin"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tämä tabletti"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tämä puhelin"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Yhteysvirhe. Sammuta laite ja käynnistä se uudelleen."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Langallinen äänilaite"</string>
     <string name="help_label" msgid="3528360748637781274">"Ohje ja palaute"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Takaisin siirtymisen ennakoivat animaatiot"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Ota käyttöön takaisin siirtymisen ennakoivat järjestelmäanimaatiot."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Asetus ottaa järjestelmäanimaatiot käyttöön ennakoiville eleanimaatioille. Se edellyttää, että enableOnBackInvokedCallback-arvo on Tosi sovelluksen manifestitiedostossa."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 5721d0b..0fa7ab2 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Cette tablette"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteingez et rallumez l\'appareil"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio à câble"</string>
     <string name="help_label" msgid="3528360748637781274">"Aide et commentaires"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animations pour le retour prédictif"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activer les animations système pour le retour prédictif."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ce paramètre permet d\'activer les animations du système pour l\'animation des gestes prédictifs. Cela exige de définir le paramètre enableOnBackInvokedCallback à Vrai pour chaque application dans le fichier de configuration."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 2088854..d9efc2d 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Cette tablette"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteignez l\'appareil, puis rallumez-le"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio filaire"</string>
     <string name="help_label" msgid="3528360748637781274">"Aide et commentaires"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animations pour prévisualiser le retour en arrière"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activer les animations système pour la prévisualisation du geste de retour."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ce paramètre active les animations système pour la prévisualisation du geste de retour. Pour cela, enableOnBackInvokedCallback doit être défini sur \"True\" dans le fichier manifeste de chaque appli."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index fec8a71..34dc307 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -180,7 +180,7 @@
     <string name="tts_default_pitch_title" msgid="6988592215554485479">"Ton"</string>
     <string name="tts_default_pitch_summary" msgid="9132719475281551884">"Afecta ao ton da voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="4698933575028098940">"Idioma"</string>
-    <string name="tts_lang_use_system" msgid="6312945299804012406">"Utiliza o idioma do sistema"</string>
+    <string name="tts_lang_use_system" msgid="6312945299804012406">"Utilizar o idioma do sistema"</string>
     <string name="tts_lang_not_selected" msgid="7927823081096056147">"Idioma non seleccionado"</string>
     <string name="tts_default_lang_summary" msgid="9042620014800063470">"Define a voz específica do idioma para o texto falado"</string>
     <string name="tts_play_example_title" msgid="1599468547216481684">"Escoitar un exemplo"</string>
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tableta"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Produciuse un problema coa conexión. Apaga e acende o dispositivo."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Axuda e comentarios"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animacións de retroceso preditivo"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activa as animacións do sistema para o retroceso preditivo."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Esta opción de configuración activa as animacións xestuais preditivas. É preciso definir enableOnBackInvokedCallback como True (verdadeiro) para cada aplicación no ficheiro de manifesto."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 0feef07..9533ea8 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"આ ફોન"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"આ ટૅબ્લેટ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"આ ફોન"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"કનેક્ટ કરવામાં સમસ્યા આવી રહી છે. ડિવાઇસને બંધ કરીને ફરી ચાલુ કરો"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"વાયરવાળો ઑડિયો ડિવાઇસ"</string>
     <string name="help_label" msgid="3528360748637781274">"સહાય અને પ્રતિસાદ"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"પાછળના પૂર્વાનુમાનિત ઍનિમેશન્સ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"પાછળના પૂર્વાનુમાનિત સંકેત માટે સિસ્ટમ ઍનિમેશન ચાલુ કરો."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"આ સેટિંગ પૂર્વાનુમાનિત સંકેત ઍનિમેશન માટે સિસ્ટમ ઍનિમેશન ચાલુ કરે છે. તેના માટે દરેક ઍપ માટે મેનિફેસ્ટ ફાઇલમાં enableOnBackInvokedCallbackને true પર સેટ કરવાની જરૂર પડે છે."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index ea8d4d45..c575858 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यह फ़ोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"यह टैबलेट"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"यह फ़ोन"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करने में समस्या हो रही है. डिवाइस को बंद करके चालू करें"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर वाला ऑडियो डिवाइस"</string>
     <string name="help_label" msgid="3528360748637781274">"सहायता और सुझाव"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"प्रिडिक्टिव बैक ऐनिमेशन"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"प्रिडिक्टिव बैक के लिए सिस्टम ऐनिमेशन चालू करें."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"यह सेटिंग, सिस्टम के ऐनिमेशन को प्रिडिक्टिव जेस्चर ऐनिमेशन के लिए चालू कर देती है. मेनिफ़ेस्ट फ़ाइल में enableOnBackInvokedCallback की सेटिंग को हर ऐप्लिकेशन के हिसाब से \'सही\' पर सेट होना चाहिए."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index bccb9d7..33a6a71 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem s povezivanjem. Isključite i ponovo uključite uređaj"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audiouređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animacije za pokret povratka s predviđanjem"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Omogući animaciju kad korisnik napravi povratnu kretnju."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ova postavka omogućuje animacije sustava za animaciju pokreta s predviđanjem. Zahtijeva postavljanje dopuštenja enableOnBackInvokedCallback po aplikaciji na True u datoteci manifesta."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 5af85ea..83e7824 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ez a telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ez a táblagép"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ez a telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sikertelen csatlakozás. Kapcsolja ki az eszközt, majd kapcsolja be újra."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vezetékes audioeszköz"</string>
     <string name="help_label" msgid="3528360748637781274">"Súgó és visszajelzés"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Prediktív „vissza” kézmozdulat-animációk"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Rendszeranimációk engedélyezése prediktív „vissza” kézmozdulatok esetén."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"A beállítás engedélyezi a rendszeranimációkat a prediktív kézmozdulat-animációk esetén. A használatukhoz az enableOnBackInvokedCallback beállítást true értékre kell állítani az egyes alkalmazások manifestfájljaiban."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 2d01b37..17ef168 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Այս հեռախոսը"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Այս պլանշետը"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Այս հեռախոսը"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Կապի խնդիր կա: Սարքն անջատեք և նորից միացրեք:"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Լարով աուդիո սարք"</string>
     <string name="help_label" msgid="3528360748637781274">"Օգնություն և հետադարձ կապ"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"«Հետ» ժեստի հուշման շարժանկարներ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Միացնել համակարգի անիմացիաները «Հետ» ժեստի հուշման համար"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Այս կարգավորման միջոցով կարելի է միացնել համակարգային շարժանկարները ժեստի հուշման համար։ Կարգավորումը պահանջում է մանիֆեստի ֆայլում սահմանել true արժեքը per-app enableOnBackInvokedCallback հատկության համար։"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index e78b339..761b271b 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ponsel ini"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tablet ini"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ponsel ini"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ada masalah saat menghubungkan. Nonaktifkan perangkat &amp; aktifkan kembali"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Perangkat audio berkabel"</string>
     <string name="help_label" msgid="3528360748637781274">"Bantuan &amp; masukan"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animasi kembali prediktif"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Aktifkan animasi sistem untuk kembali prediktif."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Setelan ini mengaktifkan animasi sistem untuk animasi gestur prediktif. Setelan ini mewajibkan enableOnBackInvokedCallback per-aplikasi disetel ke benar (true) dalam file manifes."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 9094af6..7374445b 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Þessi sími"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Þessi spjaldtölva"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Þessi sími"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Vandamál í tengingu. Slökktu og kveiktu á tækinu"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Snúrutengt hljómtæki"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjálp og ábendingar"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Hreyfimyndir flýtiritunar við bendinguna „til baka“"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Kveikja á hreyfimyndum í kerfinu til að sýna hreyfimyndir þegar bendingin „til baka“ er gerð."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Þessi stilling kveikir á hreyfimyndum í kerfinu til að sýna hreyfimyndir flýtiritunar með bendingum. Stillingin krefst þess að kveikt sé á enableOnBackInvokedCallback í upplýsingaskránni fyrir hvert forrit."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 138f341..47c5d87 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Questo telefono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Questo tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Questo telefono"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema di connessione. Spegni e riaccendi il dispositivo"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo audio cablato"</string>
     <string name="help_label" msgid="3528360748637781274">"Guida e feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animazioni predittive per Indietro"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Attiva le animazioni di sistema per il gesto Indietro predittivo."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Questa impostazione attiva le animazioni di sistema per il gesto Indietro predittivo. Richiede di impostare il metodo enableOnBackInvokedCallback su true nel file manifest di tutte le app."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 58fede9..453c3c0 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"הטלפון הזה"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"הטאבלט הזה"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"הטלפון הזה"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"יש בעיה בחיבור. עליך לכבות את המכשיר ולהפעיל אותו מחדש"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"התקן אודיו חוטי"</string>
     <string name="help_label" msgid="3528360748637781274">"עזרה ומשוב"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"חיזוי אנימציה של תנועת החזרה"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"הפעלת אנימציות מערכת עבור חיזוי של תנועת החזרה."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"‏ההגדרה הזו מפעילה אנימציות מערכת עבור חיזוי אנימציה של תנועת החזרה. היא מחייבת הגדרה בכל אפליקציה של ערך true בשדה enableOnBackInvokedCallback בקובץ המניפסט."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index a2c59ff..25006eb 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"このスマートフォン"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"このタブレット"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"このスマートフォン"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"接続エラーです。デバイスを OFF にしてから ON に戻してください"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線オーディオ デバイス"</string>
     <string name="help_label" msgid="3528360748637781274">"ヘルプとフィードバック"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"予測型「戻る」アニメーション"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"予測型「戻る」のシステム アニメーションを有効にする。"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"この設定は、予測型操作のシステム アニメーションを有効にします。アプリごとにマニフェスト ファイルで enableOnBackInvokedCallback を true に設定する必要があります。"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index cc04f56..8204c12 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ეს ტელეფონი"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ეს ტაბლეტი"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ეს ტელეფონი"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"დაკავშირებისას წარმოიქმნა პრობლემა. გამორთეთ და კვლავ ჩართეთ მოწყობილობა"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"სადენიანი აუდიო მოწყობილობა"</string>
     <string name="help_label" msgid="3528360748637781274">"დახმარება და გამოხმაურება"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"უკან დაბრუნების ანიმაციის პროგნოზირება"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"უკან დაბრუნების პროგნოზირებადი ანიმაციისთვის სისტემის ანიმაციების ჩართვა."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ეს პარამეტრი ჩართავს სისტემის ანიმაციებს ჟესტების პროგნოზირებადი ანიმაციებისთვის. საჭიროა, რომ აღწერის ფაილში აპის enableOnBackInvokedCallback პარამეტრი იყოს ჭეშმარიტი."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 43a72db..c643ae2 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Осы телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Осы планшет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Осы телефон"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Байланыс орнату қатесі шығуып жатыр. Құрылғыны өшіріп, қайта қосыңыз."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Сымды аудио құрылғысы"</string>
     <string name="help_label" msgid="3528360748637781274">"Анықтама және пікір"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"\"Артқа\" қимылына арналған тұспал анимациясы"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"\"Артқа\" қимылына арналған жүйелік тұспал анимацияларын іске қосу."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Бұл параметр қимылға арналған жүйелік тұспал анимацияларын іске қосады. Ол үшін әр қолданбаның манифест файлында enableOnBackInvokedCallback үшін \"True\" мәні қойылуы керек."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index a340188..bc9c781 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ទូរសព្ទនេះ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ថេប្លេតនេះ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ទូរសព្ទនេះ"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"មាន​បញ្ហា​ក្នុងការ​ភ្ជាប់។ បិទ រួច​បើក​ឧបករណ៍​វិញ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ឧបករណ៍​សំឡេងប្រើខ្សែ"</string>
     <string name="help_label" msgid="3528360748637781274">"ជំនួយ និងមតិកែលម្អ"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"ចលនា​ថយក្រោយ​ដែល​ព្យាករ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"បើក​ចលនា​ប្រព័ន្ធ​សម្រាប់​ការ​ថយក្រោយ​ព្យាករ។"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ការ​កំណត់នេះ​បើក​ចលនា​ប្រព័ន្ធ​សម្រាប់​ចលនាព្យាករ។ ចលនា​នេះ​ទាមទារ​ការ​កំណត់ enableOnBackInvokedCallback នៅ​ក្នុងកម្មវិធី​ទៅពិត​នៅ​ក្នុង​ឯកសារ​មេនីហ្វេសថ៍។"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 0348795..07ca44d 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ಈ ಫೋನ್"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ಈ ಟ್ಯಾಬ್ಲೆಟ್"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ಈ ಫೋನ್"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ ಸಾಧನವನ್ನು ಆಫ್ ಮಾಡಿ ಹಾಗೂ ನಂತರ ಪುನಃ ಆನ್ ಮಾಡಿ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ವೈರ್ ಹೊಂದಿರುವ ಆಡಿಯೋ ಸಾಧನ"</string>
     <string name="help_label" msgid="3528360748637781274">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"ಮುನ್ಸೂಚಕ ಬ್ಯಾಕ್ ಆ್ಯನಿಮೇಶನ್‌ಗಳು"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"ಮುನ್ಸೂಚಕ ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್‌ಗಾಗಿ ಸಿಸ್ಟಂ ಆ್ಯನಿಮೇಶನ್‌ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ಮುನ್ನೋಟದ ಗೆಸ್ಚರ್ ಆ್ಯನಿಮೇಶನ್‌ಗಾಗಿ ಸಿಸ್ಟಂ ಆ್ಯನಿಮೇಶನ್‌ಗಳನ್ನು ಈ ಸೆಟ್ಟಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸುತ್ತವೆ. ಇದನ್ನು ಮಾಡಲು, ಪ್ರತಿ ಆ್ಯಪ್‌ನ ಮ್ಯಾನಿಫೆಸ್ಟ್ ಫೈಲ್‌ನಲ್ಲಿರುವ enableOnBackInvokedCallback ಪ್ಯಾರಾಮೀಟರ್ ಅನ್ನು ಸರಿ ಎಂದು ಹೊಂದಿಸಬೇಕು."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 73de9bb..e4285d5 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"이 휴대전화"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"태블릿"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"이 휴대전화"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"연결 중에 문제가 발생했습니다. 기기를 껐다가 다시 켜 보세요."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"유선 오디오 기기"</string>
     <string name="help_label" msgid="3528360748637781274">"고객센터"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"예측된 뒤로 동작 애니메이션"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"예측된 뒤로 동작에 시스템 애니메이션을 사용하도록 설정합니다."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"이 설정은 예측된 동작 애니메이션에 시스템 애니메이션을 사용하도록 합니다. 매니페스트 파일에서 앱별 enableOnBackInvokedCallback을 True로 설정해야 합니다."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index b2a8459..ba38500 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ушул телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ушул планшет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ушул телефон"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Туташууда маселе келип чыкты. Түзмөктү өчүрүп, кайра күйгүзүп көрүңүз"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Зымдуу аудио түзмөк"</string>
     <string name="help_label" msgid="3528360748637781274">"Жардам/Пикир билдирүү"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Божомолдонгон анимациялар"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Божомолдоп билүү үчүн системанын анимацияларын иштетиңиз."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Бул параметр жаңсоо анимациясын божомолдоп билүү үчүн системанын анимацияларын иштетет. Ал үчүн манифест файлындагы enableOnBackInvokedCallback параметри ар бир колдонмо үчүн \"true\" деп коюлушу керек."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index fcc4f04..8ba766f 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ໂທລະສັບນີ້"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ແທັບເລັດນີ້"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ໂທລະສັບນີ້"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ເກີດບັນຫາໃນການເຊື່ອມຕໍ່. ປິດອຸປະກອນແລ້ວເປີດກັບຄືນມາໃໝ່"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ອຸປະກອນສຽງແບບມີສາຍ"</string>
     <string name="help_label" msgid="3528360748637781274">"ຊ່ວຍເຫຼືອ ແລະ ຕິຊົມ"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"ອະນິເມຊັນກັບຫຼັງແບບຄາດເດົາ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"ເປີດການນຳໃຊ້ອະນິເມຊັນລະບົບສຳລັບການກັບຫຼັງແບບຄາດເດົາ."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ການຕັ້ງຄ່ານີ້ຈະເປີດການນຳໃຊ້ອະນິເມຊັນລະບົບສຳລັບອະນິເມຊັນທ່າທາງແບບຄາດເດົາ. ມັນຕ້ອງໃຊ້ການຕັ້ງຄ່າຕໍ່ແອັບ enableOnBackInvokedCallback ເປັນ true ໃນໄຟລ໌ manifest."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 5b8b93f..72de8b2 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -540,6 +540,9 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis telefonas"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Šis planšetinis kompiuteris"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis telefonas"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Jei norite perjungti, naujovinkite paskyrą"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Čia negalima paleisti atsisiuntimų"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Bandykite dar kartą po skelbimo"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Prisijungiant kilo problema. Išjunkite įrenginį ir vėl jį įjunkite"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Laidinis garso įrenginys"</string>
     <string name="help_label" msgid="3528360748637781274">"Pagalba ir atsiliepimai"</string>
@@ -666,4 +669,10 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Numatomos grįžimo atgal gestų animacijos"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Įgalinkite sistemos animacijas, kad būtų galima naudoti numatomus grįžimo atgal gestus."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Šis nustatymas įgalina numatomų grįžimo atgal gestų sistemos animacijas. Aprašo faile programos lauką „enableOnBackInvokedCallback“ reikia nustatyti į vertę „true“."</string>
+  <string-array name="udfps_accessibility_touch_hints">
+    <item msgid="1737722959616802157">"Perkelti kairėn"</item>
+    <item msgid="5425394847942513942">"Perkelti žemyn"</item>
+    <item msgid="7728484337962740316">"Perkelti dešinėn"</item>
+    <item msgid="324200556467459329">"Perkelti aukštyn"</item>
+  </string-array>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 59c3b0f..b2c6aa6 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis tālrunis"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Šis planšetdators"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis tālrunis"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Radās problēma ar savienojuma izveidi. Izslēdziet un atkal ieslēdziet ierīci."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vadu audioierīce"</string>
     <string name="help_label" msgid="3528360748637781274">"Palīdzība un atsauksmes"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animāciju prognozēšana pāriešanai atpakaļ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Iespējot sistēmas animācijas prognozētam žestam pāriešanai atpakaļ."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Šis iestatījums iespējo sistēmas animācijas prognozēto žestu animācijām. Lai to varētu izmantot, parametram “enableOnBackInvokedCallback” lietotnes manifesta failā jāiestata vērtība “true”."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 4a010d3..9f02f4a 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овој телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Овој таблет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Овој телефон"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем со поврзување. Исклучете го уредот и повторно вклучете го"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичен аудиоуред"</string>
     <string name="help_label" msgid="3528360748637781274">"Помош и повратни информации"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Анимации за движењето за враќање"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Овозможете системски анимации за движењето за враќање."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Поставкава ги овозможува системските анимации за предвидливи движења. Поставката треба да се постави на „точно“ преку апликација enableOnBackInvokedCallback во датотеката за манифест."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 46ffa9f..11208ae 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ഈ ഫോൺ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ഈ ടാബ്‌ലെറ്റ്"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ഈ ഫോൺ"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"കണക്‌റ്റ് ചെയ്യുന്നതിൽ പ്രശ്‌നമുണ്ടായി. ഉപകരണം ഓഫാക്കി വീണ്ടും ഓണാക്കുക"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"വയർ മുഖേന ബന്ധിപ്പിച്ച ഓഡിയോ ഉപകരണം"</string>
     <string name="help_label" msgid="3528360748637781274">"സഹായവും ഫീഡ്‌ബാക്കും"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"പ്രെഡിക്റ്റീവ് ബാക്ക് ആനിമേഷനുകൾ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"പ്രെഡിക്റ്റീവ് ബാക്കിനായി സിസ്റ്റം ആനിമേഷനുകൾ പ്രവർത്തനക്ഷമമാക്കുക."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ഈ ക്രമീകരണം പ്രെഡിക്റ്റീവ് ജെസ്ച്ചർ ആനിമേഷന് വേണ്ടി സിസ്റ്റം ആനിമേഷനുകളെ പ്രവർത്തനക്ഷമമാക്കുന്നു. ഇതിന് ഓരോ ആപ്പിലും enableOnBackInvokedCallback എന്നത് മാനിഫെസ്റ്റ് ഫയലിൽ ശരി എന്ന് സജ്ജീകരിക്കേണ്ടതുണ്ട്."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 0a4e4ae..c7a583e 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Энэ утас"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Энэ таблет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Энэ утас"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Холбогдоход асуудал гарлаа. Төхөөрөмжийг унтраагаад дахин асаана уу"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Утастай аудио төхөөрөмж"</string>
     <string name="help_label" msgid="3528360748637781274">"Тусламж, санал хүсэлт"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Таамаглах боломжтой буцаах анимаци"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Таамаглах боломжтой буцаах зангаанд системийн анимацийг идэвхжүүлнэ үү."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Энэ тохиргоо нь таамаглах боломжтой зангааны анимацид системийн анимацийг идэвхжүүлнэ. Үүнд апп бүрд тодорхойлогч файлл enableOnBackInvokedCallback-г үнэн болгож тохируулахыг шаардана."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index f74cd54..952ac41 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"हा फोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"हा टॅबलेट"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"हा फोन"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्‍ट करण्‍यात समस्‍या आली. डिव्हाइस बंद करा आणि नंतर सुरू करा"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर असलेले ऑडिओ डिव्हाइस"</string>
     <string name="help_label" msgid="3528360748637781274">"मदत आणि फीडबॅक"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"पूर्वानुमानित मागे जाण्याचे अ‍ॅनिमेशन"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"पूर्वानुमानित मागे जाण्यासाठीचे सिस्टीम अ‍ॅनिमेशन सुरू करा."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"हे सेटिंग पूर्वानुमानित जेश्चर ॲनिमेशनसाठी सिस्टीम ॲनिमेशन सुरू करते. यासाठी मॅनिफेस्ट फाइलमध्ये प्रति ॲप enableOnBackInvokedCallback सत्य वर सेट करणे आवश्यक आहे."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index f6350b3..b30e4ce 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefon ini"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tablet ini"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefon ini"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Masalah penyambungan. Matikan &amp; hidupkan kembali peranti"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Peranti audio berwayar"</string>
     <string name="help_label" msgid="3528360748637781274">"Bantuan &amp; maklum balas"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animasi kembali ramalan"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Dayakan animasi sistem untuk kembali ramalan."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Tetapan ini mendayakan animasi sistem untuk animasi gerak isyarat ramalan. Animasi sistem memerlukan tetapan enableOnBackInvokedCallback untuk setiap apl kepada benar dalam fail manifes."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index c148eba..2baafde 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ဤဖုန်း"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ဤတက်ဘလက်"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ဤဖုန်း"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ချိတ်ဆက်ရာတွင် ပြဿနာရှိပါသည်။ စက်ကိုပိတ်ပြီး ပြန်ဖွင့်ပါ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ကြိုးတပ် အသံစက်ပစ္စည်း"</string>
     <string name="help_label" msgid="3528360748637781274">"အကူအညီနှင့် အကြံပြုချက်"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"နောက်ခလုတ်၏ ရှေ့ပြေးလှုပ်ရှားသက်ဝင်ပုံ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"နောက်ခလုတ်ရှေ့ပြေးအတွက် စနစ်လှုပ်ရှားသက်ဝင်ပုံများကို ဖွင့်ပါသည်။"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ဤဆက်တင်သည် လက်ဟန် ရှေ့ပြေးလှုပ်ရှားသက်ဝင်ပုံအတွက် စနစ်လှုပ်ရှားသက်ဝင်ပုံများကို ဖွင့်ပါသည်။ အက်ပ်တစ်ခုစီ၏ ဆက်တင်အတွက် enableOnBackInvokedCallback ကို မန်နီးဖက်စ် (manifest) ဖိုင်၌ ဖွင့်ထားရန်လိုအပ်သည်။"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 4f70669..c63dc03 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefonen"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Dette nettbrettet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefonen"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Tilkoblingsproblemer. Slå enheten av og på igjen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhet med kabel"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjelp og tilbakemelding"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Tilbake-animasjoner med forslag"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Slå på systemanimasjoner for tilbakebevegelser med forslag."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Denne innstillingen slår på systemanimasjoner for bevegelsesanimasjoner med forslag. Den krever at enableOnBackInvokedCallback settes til sann i manifestfilen for hver app."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 703ee0a..687b436 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यो फोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"यो ट्याब्लेट"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"यो फोन"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"जोड्ने क्रममा समस्या भयो। यन्त्रलाई निष्क्रिय पारेर फेरि अन गर्नुहोस्"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"तारयुक्त अडियो यन्त्र"</string>
     <string name="help_label" msgid="3528360748637781274">"मद्दत र प्रतिक्रिया"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"पूर्वानुमानयुक्त ब्याक एनिमेसनहरू"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"पूर्वानुमानयुक्त ब्याक एनिमेसनका हकमा सिस्टम एनिमेसनहरू लागू गर्नुहोस्।"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"यो सेटिङले पूर्वानुमानयुक्त जेस्चर एनिमेसनका हकमा सिस्टम एनिमेनसहरू लागू गर्छ। म्यानिफेस्ट फाइलमा हरेक एपका हकमा enableOnBackInvokedCallback सेट गरी TRUE बनाएपछि मात्र यो सेटिङ अन गर्न मिल्छ।"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 344cf01..455aa99 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Deze telefoon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Deze tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Deze telefoon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem bij verbinding maken. Zet het apparaat uit en weer aan."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedraad audioapparaat"</string>
     <string name="help_label" msgid="3528360748637781274">"Hulp en feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Voorspellende animaties voor gebaren voor terug"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Systeemanimaties aanzetten voor voorspellende animaties voor gebaren voor terug."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Met deze instelling zet je systeemanimaties aan voor voorspellende gebaaranimaties. Je moet enableOnBackInvokedCallback per app instellen op True in het manifestbestand."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 445942d..d58c817 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ଏହି ଫୋନ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ଏହି ଟାବଲେଟ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ଏହି ଫୋନ୍"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ସଂଯୋଗ କରିବାରେ ସମସ୍ୟା ହେଉଛି। ଡିଭାଇସ୍ ବନ୍ଦ କରି ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ତାରଯୁକ୍ତ ଅଡିଓ ଡିଭାଇସ୍"</string>
     <string name="help_label" msgid="3528360748637781274">"ସାହାଯ୍ୟ ଓ ମତାମତ"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"ପ୍ରେଡିକ୍ଟିଭ ବ୍ୟାକ ଆନିମେସନ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"ପ୍ରେଡିକ୍ଟିଭ ବ୍ୟାକ ପାଇଁ ସିଷ୍ଟମ ଆନିମେସନଗୁଡ଼ିକୁ ସକ୍ଷମ କରନ୍ତୁ।"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ଏହି ସେଟିଂ ପ୍ରେଡିକ୍ଟିଭ ଜେଶ୍ଚର ଆନିମେସନ ପାଇଁ ସିଷ୍ଟମ ଆନିମେସନଗୁଡ଼ିକୁ ସକ୍ଷମ କରେ। ଏଥିପାଇଁ ମାନିଫେଷ୍ଟ ଫାଇଲରେ ପ୍ରତି-ଆପ enableOnBackInvokedCallbackକୁ \"ଠିକ\"ରେ ସେଟ କରିବା ଆବଶ୍ୟକ।"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 36694db..1ccfdb7 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ਇਹ ਫ਼ੋਨ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ਇਹ ਟੈਬਲੈੱਟ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ਇਹ ਫ਼ੋਨ"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ। ਡੀਵਾਈਸ ਨੂੰ ਬੰਦ ਕਰਕੇ ਵਾਪਸ ਚਾਲੂ ਕਰੋ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ਤਾਰ ਵਾਲਾ ਆਡੀਓ ਡੀਵਾਈਸ"</string>
     <string name="help_label" msgid="3528360748637781274">"ਮਦਦ ਅਤੇ ਵਿਚਾਰ"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"ਪਿਛਲੇ ਐਨੀਮੇਸ਼ਨਾਂ ਦਾ ਪੂਰਵ-ਅਨੁਮਾਨ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"ਪੂਰਵ-ਅਨੁਮਾਨ ਵਾਪਸੀ ਲਈ ਸਿਸਟਮ ਐਨੀਮੇਸ਼ਨਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ।"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ਇਹ ਸੈਟਿੰਗ ਪੂਰਵ-ਅਨੁਮਾਨ ਇਸ਼ਾਰਾ ਐਨੀਮੇਸ਼ਨ ਲਈ ਸਿਸਟਮ ਐਨੀਮੇਸ਼ਨਾਂ ਨੂੰ ਚਾਲੂ ਕਰਦੀ ਹੈ। ਮੈਨੀਫ਼ੈਸਟ ਫ਼ਾਈਲ ਵਿੱਚ enableOnBackInvokedCallback ਸੈਟਿੰਗ ਨੂੰ ਪ੍ਰਤੀ-ਐਪ \'ਸਹੀ\' \'ਤੇ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index debc6c9..ab45681 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ten telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ten tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ten telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem z połączeniem. Wyłącz i ponownie włącz urządzenie"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Przewodowe urządzenie audio"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoc i opinie"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animacje przewidywanego przejścia wstecz"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Włącz animacje systemowe dla przewidywanego przejścia wstecz."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"To ustawienie uruchamia animacje systemowe dla przewidywanych gestów. Wymaga ustawienia w pliku manifestu wartości true w polu enableOnBackInvokedCallback dla każdej aplikacji."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index c0c1c72..7b501f3 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este smartphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este smartphone"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animações de gestos \"Voltar\" preditivos"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Ativar animações do sistema para gestos \"Voltar\" preditivos."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Esta configuração ativa animações do sistema para gestos preditivos. Ela requer que a política enableOnBackInvokedCallback por app seja definida como verdadeira no arquivo de manifesto."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 69245dc..3bef621 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -540,6 +540,9 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este telemóvel"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telemóvel"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Atualize a conta para mudar"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Não é possível reproduzir as transferências aqui"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Tente novamente depois do anúncio"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema ao ligar. Desligue e volte a ligar o dispositivo."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fios"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda e comentários"</string>
@@ -666,4 +669,10 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animações de gestos para voltar preditivos"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Ative as animações do sistema para gestos para voltar preditivos."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Esta definição ativa animações do sistema para a animação de gestos preditivos. Requer a definição do atributo enableOnBackInvokedCallback por app como verdadeiro no ficheiro de manifesto."</string>
+  <string-array name="udfps_accessibility_touch_hints">
+    <item msgid="1737722959616802157">"Mover para a esquerda"</item>
+    <item msgid="5425394847942513942">"Mover para baixo"</item>
+    <item msgid="7728484337962740316">"Mover para a direita"</item>
+    <item msgid="324200556467459329">"Mover para cima"</item>
+  </string-array>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index c0c1c72..7b501f3 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este smartphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este smartphone"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animações de gestos \"Voltar\" preditivos"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Ativar animações do sistema para gestos \"Voltar\" preditivos."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Esta configuração ativa animações do sistema para gestos preditivos. Ela requer que a política enableOnBackInvokedCallback por app seja definida como verdadeira no arquivo de manifesto."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 9edca36..b209676 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Acest telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Această tabletă"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Acest telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problemă la conectare. Oprește și repornește dispozitivul."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispozitiv audio cu fir"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajutor și feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animații pentru gestul înapoi predictiv"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activează animațiile de sistem pentru gestul înapoi predictiv."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Această setare activează animațiile de sistem pentru animația gesturilor predictive. Necesită setarea valorii true în cazul atributului enableOnBackInvokedCallback pentru fiecare aplicație în fișierul manifest."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 98a8e88..b92fb4f 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Этот смартфон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Этот планшет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Этот смартфон"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ошибка подключения. Выключите и снова включите устройство."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Проводное аудиоустройство"</string>
     <string name="help_label" msgid="3528360748637781274">"Справка/отзыв"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Анимации подсказки для жеста \"Назад\""</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Включить системную анимацию подсказки для жеста \"Назад\"."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"С помощью этого параметра можно включить системные анимации подсказок для жестов. Для этого нужно установить значение true для enableOnBackInvokedCallback в файле манифеста приложения."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index f5437fe..16a0886 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"මෙම දුරකථනය"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"මෙම ටැබ්ලටය"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"මෙම දුරකථනය"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"සම්බන්ධ කිරීමේ ගැටලුවකි උපාංගය ක්‍රියාවිරහිත කර &amp; ආපසු ක්‍රියාත්මක කරන්න"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"රැහැන්ගත කළ ඕඩියෝ උපාංගය"</string>
     <string name="help_label" msgid="3528360748637781274">"උදවු &amp; ප්‍රතිපෝෂණ"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"පුරෝකථනමය පසු සජීවිකරණ"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"පුරෝකථනමය ආපසු සඳහා පද්ධති සජීවිකරණ සබල කරන්න."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"මෙම සැකසීම පුරෝකථනමය ඉංගිත සජීවිකරණය සඳහා පද්ධති සජීවිකරණ සබල කරයි. එයට මැනිෆෙස්ට් ගොනුව තුළ එක් යෙදුමකට enableOnBackInvokedCallback සත්‍ය ලෙස සැකසීම අවශ්‍ය වේ."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index fb46ed9b..cfe5d39 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -540,6 +540,9 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefón"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tento tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefón"</string>
+    <string name="media_output_status_require_premium" msgid="8411255800047014822">"Inovujte účet a prejdite naň"</string>
+    <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Tu sa nedajú prehrať stiahnuté súbory"</string>
+    <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Skúste to znova po reklame"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Pri pripájaní sa vyskytol problém. Zariadenie vypnite a znova zapnite."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio zariadenie s káblom"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomocník a spätná väzba"</string>
@@ -666,4 +669,10 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Prediktívne animácie gesta Späť"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Povoľte animácie v systéme pre prediktívne gesto Späť"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Toto nastavenie povoľuje animácie v systéme na účely prediktívnej animácie gest. Vyžaduje nastavenie povolenia enableOnBackInvokedCallback na pravdu v súbore manifestu konkrétnej aplikácie."</string>
+  <string-array name="udfps_accessibility_touch_hints">
+    <item msgid="1737722959616802157">"Posuňte doľava"</item>
+    <item msgid="5425394847942513942">"Posuňte nadol"</item>
+    <item msgid="7728484337962740316">"Posuňte doprava"</item>
+    <item msgid="324200556467459329">"Presuňte nahor"</item>
+  </string-array>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index c9f8692..2d65328 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ta telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ta tablični računalnik"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ta telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Težava pri povezovanju. Napravo izklopite in znova vklopite."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žična zvočna naprava"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoč in povratne informacije"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animacije poteze za nazaj s predvidevanjem"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Omogoči sistemske animacije za potezo za nazaj s predvidevanjem."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ta nastavitev omogoča sistemske animacije za animacijo poteze s predvidevanjem. V datoteki manifesta mora biti parameter »enableOnBackInvokedCallback« za posamezno aplikacijo nastavljen na »true«."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 73b52de..4dab506 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ky telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ky tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ky telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem me lidhjen. Fike dhe ndize përsëri pajisjen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Pajisja audio me tel"</string>
     <string name="help_label" msgid="3528360748637781274">"Ndihma dhe komentet"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Animacionet për gjestin e parashikuar të kthimit prapa"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Aktivizo animacionet e sistemit për gjestin e parashikuar të kthimit prapa."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ky cilësim aktivizon animacionet e sistemit për animacionin e gjestit të parashikuar. Ai kërkon që enableOnBackInvokedCallback për aplikacionin të jetë caktuar si i vërtetë në skedarin e manifestit."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 957c243..b8d6ab4 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овај телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Овај таблет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Овај телефон"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем при повезивању. Искључите уређај, па га поново укључите"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичани аудио уређај"</string>
     <string name="help_label" msgid="3528360748637781274">"Помоћ и повратне информације"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Анимације за покрет повратка са предвиђањем"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Омогућите анимације система за покрет повратка са предвиђањем."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ово подешавање омогућава анимације система за покрет повратка са предвиђањем. Захтева подешавање дозволе enableOnBackInvokedCallback по апликацији на true у фајлу манифеста."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 4e10e54..faf6212 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Den här telefonen"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Den här surfplattan"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Den här telefonen"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Det gick inte att ansluta. Stäng av enheten och slå på den igen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ljudenhet med kabelanslutning"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjälp och feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Förhandsanimationer för bakåtrörelser"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Aktivera systemanimationer som förhandsvisar bakåtrörelser."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Den här inställningen aktiverar systemanimationer som förhandsvisar vart rörelserna leder. Du måste ställa in enableOnBackInvokedCallback som sant per app i manifestfilen."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 2c4166a..5023fed 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Simu hii"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Kompyuta kibao hii"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Simu hii"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kuna tatizo la kuunganisha kwenye Intaneti. Zima kisha uwashe kifaa"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kifaa cha sauti kinachotumia waya"</string>
     <string name="help_label" msgid="3528360748637781274">"Usaidizi na maoni"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Uhuishaji wa utabiri wa kurudi nyuma"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Ruhusu uhuishaji wa mfumo wa utabiri wa kurudi nyuma."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Mipangilio hii inaruhusu uhuishaji wa mfumo wa uhuishaji wa utabiri wa ishara. Inahitaji kuweka mipangilio kwa kila programu enableOnBackInvokedCallback kuwa true katika faili ya maelezo."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index eb2b7b2..44c8354 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"இந்த மொபைல்"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"இந்த டேப்லெட்"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"இந்த மொபைல்"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"இணைப்பதில் சிக்கல். சாதனத்தை ஆஃப் செய்து மீண்டும் ஆன் செய்யவும்"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"வயருடன்கூடிய ஆடியோ சாதனம்"</string>
     <string name="help_label" msgid="3528360748637781274">"உதவியும் கருத்தும்"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"கணிக்கக்கூடிய பின்செல் சைகைக்கான அனிமேஷன்கள்"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"கணிக்கக்கூடிய பின்செல் சைகைக்காகச் சிஸ்டம் அனிமேஷன்களை இயக்கும்."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"கணிக்கக்கூடிய சைகைக்கான அனிமேஷனுக்காக இந்த அமைப்பு சிஸ்டம் அனிமேஷன்களை இயக்கும். மெனிஃபெஸ்ட் ஃபைலில் ஒவ்வொரு ஆப்ஸுக்கும் enableOnBackInvokedCallbackகை \'சரி\' என அமைக்க வேண்டும்."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 9d6c29d..3c2b4df 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ఈ ఫోన్"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ఈ టాబ్లెట్"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ఈ ఫోన్"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"కనెక్ట్ చేయడంలో సమస్య ఉంది. పరికరాన్ని ఆఫ్ చేసి, ఆపై తిరిగి ఆన్ చేయండి"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"వైర్ గల ఆడియో పరికరం"</string>
     <string name="help_label" msgid="3528360748637781274">"సహాయం &amp; ఫీడ్‌బ్యాక్"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"ఊహించదగిన బ్యాక్ యానిమేషన్‌లు"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"ఊహించదగిన బ్యాక్ యానిమేషన్‌ల కోసం సిస్టమ్ యానిమేషన్‌లను ఎనేబుల్ చేయండి."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"ఊహించదగిన సంజ్ఞ యానిమేషన్ కోసం ఈ సెట్టింగ్ సిస్టమ్ యానిమేషన్‌లను ఎనేబుల్ చేస్తుంది. దీనికి మ్యానిఫెస్ట్ ఫైల్‌లో ఒక్కో యాప్‌లో enableOnBackInvokedCallback సెట్టింగ్‌ను ఒప్పునకు సెట్ చేయవలసి ఉంటుంది."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 6dc2608..aeae2e1 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"โทรศัพท์เครื่องนี้"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"แท็บเล็ตเครื่องนี้"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"โทรศัพท์เครื่องนี้"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"เกิดปัญหาในการเชื่อมต่อ ปิดอุปกรณ์แล้วเปิดใหม่อีกครั้ง"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"อุปกรณ์เสียงแบบมีสาย"</string>
     <string name="help_label" msgid="3528360748637781274">"ความช่วยเหลือและความคิดเห็น"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"การเคลื่อนไหวย้อนกลับแบบคาดเดา"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"เปิดใช้การเคลื่อนไหวของระบบสำหรับท่าทางสัมผัสย้อนกลับแบบคาดเดา"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"การตั้งค่านี้จะเปิดใช้การเคลื่อนไหวของระบบสำหรับการเคลื่อนไหวจากท่าทางสัมผัสแบบคาดเดา โดยต้องตั้งค่า enableOnBackInvokedCallback สำหรับแต่ละแอปให้เป็น \"จริง\" ในไฟล์ Manifest"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 71b1fdc..9b01d54 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ang teleponong ito"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ang tablet na ito"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ang teleponong ito"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Nagkaproblema sa pagkonekta. I-off at pagkatapos ay i-on ang device"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired na audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Tulong at feedback"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Mga animation ng predictive na pagbalik"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"I-enable ang mga animation ng system para sa predictive na pagbalik."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Ine-enable ng setting na ito ang mga animation ng system para sa animation ng predictive na galaw. Kinakailangan nitong itakda sa true ang enableOnBackInvokedCallback sa bawat app sa manifest file."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 76449d5..ad8152d 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Bu tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Bağlanırken sorun oluştu. Cihazı kapatıp tekrar açın"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kablolu ses cihazı"</string>
     <string name="help_label" msgid="3528360748637781274">"Yardım ve geri bildirim"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Tahmine dayalı geri hareketi animasyonları"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Tahmine dayalı geri hareketi için sistem animasyonlarını etkinleştirin"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Bu ayar, tahmine dayalı hareket animasyonu için sistem animasyonlarını etkinleştirir. Her uygulamanın manifest dosyasında enableOnBackInvokedCallback\'in doğru değerine ayarlanması gerekir."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index e23dae7..71aff76 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Цей телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Цей планшет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Цей телефон"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Не вдається підключитися. Перезавантажте пристрій."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Дротовий аудіопристрій"</string>
     <string name="help_label" msgid="3528360748637781274">"Довідка й відгуки"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Анімації з підказками для жесту \"Назад\""</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Увімкніть системну анімацію з підказками для жесту \"Назад\"."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Якщо вибрати це налаштування, для жесту \"Назад\" відображатиметься анімація з підказками. У файлі маніфесту атрибуту enableOnBackInvokedCallback додатка потрібно присвоїти значення true."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 452cf77..0707658 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"یہ فون"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"یہ ٹیبلیٹ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"یہ فون"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"منسلک کرنے میں مسئلہ پیش آ گیا۔ آلہ کو آف اور بیک آن کریں"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"وائرڈ آڈیو آلہ"</string>
     <string name="help_label" msgid="3528360748637781274">"مدد اور تاثرات"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"پیچھے جانے کے اشارے کی پیش گوئی والی اینیمیشنز"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"پیچھے جانے کے پیش گوئی والے اشارے کے لیے سسٹم اینیمیشنز فعال کریں۔"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"‏یہ ترتیب پیش گوئی والی اشارے کی اینیمیشن کے لیے سسٹم کی اینیمیشنز کو فعال کرتی ہے۔ اس کے لیے manifest فائل میں فی ایپ enableOnBackInvokedCallback کو درست پر سیٹ کرنے کی ضرورت ہے۔"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index e55c40e..7551536 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Shu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Shu planshet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Shu telefon"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ulanishda muammo yuz berdi. Qurilmani oʻchiring va yoqing"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio qurilma"</string>
     <string name="help_label" msgid="3528360748637781274">"Yordam/fikr-mulohaza"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Taxminiy qaytish animatsiyalari"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Taxminiy qaytish uchun tizim animatsiyalarini yoqish."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Bu sozlamalar taxminiy qaytish animatsiyalari uchun tizim animatsiyalarini faollashtiradi. Buning uchun har bir ilovaning manifest faylida enableOnBackInvokedCallback parametri “true” qiymatida boʻlishi lozim."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 359fab9..76de4a8 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -315,7 +315,7 @@
     <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"Chọn cấu hình USB"</string>
     <string name="allow_mock_location" msgid="2102650981552527884">"Cho phép vị trí mô phỏng"</string>
     <string name="allow_mock_location_summary" msgid="179780881081354579">"Cho phép vị trí mô phỏng"</string>
-    <string name="debug_view_attributes" msgid="3539609843984208216">"Cho phép kiểm tra thuộc tính của chế độ xem"</string>
+    <string name="debug_view_attributes" msgid="3539609843984208216">"Cho phép kiểm tra thuộc tính khung hiển thị"</string>
     <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Luôn bật dữ liệu di động ngay cả khi Wi-Fi đang hoạt động (để chuyển đổi mạng nhanh)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Sử dụng tính năng tăng tốc phần cứng khi chia sẻ Internet nếu có"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Cho phép gỡ lỗi qua USB?"</string>
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Điện thoại này"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Máy tính bảng này"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Điện thoại này"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sự cố kết nối. Hãy tắt thiết bị rồi bật lại"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Thiết bị âm thanh có dây"</string>
     <string name="help_label" msgid="3528360748637781274">"Trợ giúp và phản hồi"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Ảnh xem trước thao tác quay lại"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Bật ảnh của hệ thống để xem trước thao tác quay lại"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Cài đặt này cho phép sử dụng ảnh động hệ thống cho ảnh động cử chỉ dự đoán. Nó yêu cầu cài đặt cho mỗi ứng dụng chuyển enableOnBackInvokedCallback thành lệnh true trong tệp kê khai."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 73c5a97..20d4c17 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"这部手机"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"这台平板电脑"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"这部手机"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"连接时遇到问题。请关闭并重新开启设备"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有线音频设备"</string>
     <string name="help_label" msgid="3528360748637781274">"帮助和反馈"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"预见式返回动画"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"启用系统动画作为预见式返回动画。"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"此设置将启用系统动画作为预测性手势动画。这要求在清单文件中将单个应用的 enableOnBackInvokedCallback 设为 true。"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 36267e2..cc741d8 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"此手機"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"此平板電腦"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"這部手機"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連接,請關閉裝置然後重新開機"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音響裝置"</string>
     <string name="help_label" msgid="3528360748637781274">"說明與意見反映"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"預測返回手勢動畫"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"為預測返回手勢啟用系統動畫。"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"此設定會啟用系統動畫作為預測手勢動畫。這必須在資訊清單檔案中將個別應用程式的 enableOnBackInvokedCallback 設定為 true。"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 24bf57e..8af3e34 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"這支手機"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"這台平板電腦"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"這支手機"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連線,請關閉裝置後再重新開啟"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音訊裝置"</string>
     <string name="help_label" msgid="3528360748637781274">"說明與意見回饋"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"預測返回操作動畫"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"為預測返回操作啟用系統動畫。"</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"這項設定會啟用系統動畫做為預測手勢動畫。這必須在資訊清單檔案中將個別應用程式的 enableOnBackInvokedCallback 設為 true。"</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 4413d3a..9397020 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -540,6 +540,12 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Le foni"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Le thebulethi"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Le foni"</string>
+    <!-- no translation found for media_output_status_require_premium (8411255800047014822) -->
+    <skip />
+    <!-- no translation found for media_output_status_not_support_downloads (4523828729240373315) -->
+    <skip />
+    <!-- no translation found for media_output_status_try_after_ad (8312579066856015441) -->
+    <skip />
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Inkinga yokuxhumeka. Vala idivayisi futhi uphinde uyivule"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Idivayisi yomsindo enentambo"</string>
     <string name="help_label" msgid="3528360748637781274">"Usizo nempendulo"</string>
@@ -666,4 +672,8 @@
     <string name="back_navigation_animation" msgid="8105467568421689484">"Ukubikezelwa kwasemuva kopopayi"</string>
     <string name="back_navigation_animation_summary" msgid="741292224121599456">"Nika amandla ukubikezela emuva kopopayi besistimu."</string>
     <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Leli sethingi livumela opopayi besistimu mayelana nokuthinta okubikezelwayo kopopayi. Idinga ukusetha i-app ngayinye ku-enableOnBackInvokedCallback ukuze iqinisekise ifayela le-manifest."</string>
+    <!-- no translation found for udfps_accessibility_touch_hints:0 (1737722959616802157) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:1 (5425394847942513942) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:2 (7728484337962740316) -->
+    <!-- no translation found for udfps_accessibility_touch_hints:3 (324200556467459329) -->
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 8508878..b92b3d6 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1315,6 +1315,20 @@
     <string name="media_transfer_this_device_name" product="tablet">This tablet</string>
     <!-- Name of the phone device with an active remote session. [CHAR LIMIT=30] -->
     <string name="media_transfer_this_phone">This phone</string>
+    <!-- Sub status indicates device is not available due to an unknown error. [CHAR LIMIT=NONE] -->
+    <string name="media_output_status_unknown_error">Can\’t play on this device</string>
+    <!-- Sub status indicates device need premium account. [CHAR LIMIT=NONE] -->
+    <string name="media_output_status_require_premium">Upgrade account to switch</string>
+    <!-- Sub status indicates device not support download content. [CHAR LIMIT=NONE] -->
+    <string name="media_output_status_not_support_downloads">Can\’t play downloads here</string>
+    <!-- Sub status indicates device need to wait after ad. [CHAR LIMIT=NONE] -->
+    <string name="media_output_status_try_after_ad">Try again after the ad</string>
+    <!-- Sub status indicates device is in low-power mode. [CHAR LIMIT=NONE] -->
+    <string name="media_output_status_device_in_low_power_mode">Wake up device to play here</string>
+    <!-- Sub status indicates the device does not authorize the user. [CHAR LIMIT=NONE] -->
+    <string name="media_output_status_unauthorized">Device not approved to play</string>
+    <!-- Sub status indicates the device does not support the current media track. [CHAR LIMIT=NONE] -->
+    <string name="media_output_status_track_unsupported">Can\’t play this media here</string>
 
     <!-- Warning message to tell user is have problem during profile connect, it need to turn off device and back on. [CHAR_LIMIT=NONE] -->
     <string name="profile_connect_timeout_subtext">Problem connecting. Turn device off &amp; back on</string>
@@ -1626,4 +1640,12 @@
     <string name="back_navigation_animation_summary">Enable system animations for predictive back.</string>
     <!-- Developer setting: enable animations when a back gesture is executed, full explanation[CHAR LIMIT=NONE] -->
     <string name="back_navigation_animation_dialog">This setting enables system animations for predictive gesture animation. It requires setting per-app "enableOnBackInvokedCallback" to true in the manifest file.</string>
+
+    <!-- [CHAR LIMIT=NONE] Messages shown when users press outside of udfps region during -->
+    <string-array name="udfps_accessibility_touch_hints">
+        <item>Move left</item>
+        <item>Move down</item>
+        <item>Move right</item>
+        <item>Move up</item>
+    </string-array>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 21e7d81..48d449d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -101,6 +101,9 @@
     @VisibleForTesting
     static ApplicationsState sInstance;
 
+    // Whether the app icon cache mechanism is enabled or not.
+    private static boolean sAppIconCacheEnabled = false;
+
     public static ApplicationsState getInstance(Application app) {
         return getInstance(app, AppGlobals.getPackageManager());
     }
@@ -115,6 +118,11 @@
         }
     }
 
+    /** Set whether the app icon cache mechanism is enabled or not. */
+    public static void setAppIconCacheEnabled(boolean enabled) {
+        sAppIconCacheEnabled = enabled;
+    }
+
     final Context mContext;
     final PackageManager mPm;
     final IPackageManager mIpm;
@@ -776,7 +784,8 @@
     }
 
     private static boolean isAppIconCacheEnabled(Context context) {
-        return SETTING_PKG.equals(context.getPackageName());
+        return SETTING_PKG.equals(context.getPackageName())
+                || sAppIconCacheEnabled;
     }
 
     void rebuildActiveSessions() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
index a82f070..96e875b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
@@ -70,6 +70,8 @@
             "com.android.settings.category.ia.smart_battery_settings";
     public static final String CATEGORY_COMMUNAL_SETTINGS =
             "com.android.settings.category.ia.communal";
+    public static final String CATEGORY_MORE_SECURITY_PRIVACY_SETTINGS =
+            "com.android.settings.category.ia.more_security_privacy_settings";
 
     public static final Map<String, String> KEY_COMPAT_MAP;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/OWNERS b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/OWNERS
new file mode 100644
index 0000000..09e7991
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/OWNERS
@@ -0,0 +1,5 @@
+# Default reviewers for this and subdirectories.
+emilychuang@google.com
+ykhung@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/ComplexMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/ComplexMediaDevice.java
new file mode 100644
index 0000000..c38dfe3
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/ComplexMediaDevice.java
@@ -0,0 +1,71 @@
+/*
+ * 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.settingslib.media;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
+import android.media.RouteListingPreference;
+
+import com.android.settingslib.R;
+
+/**
+ * ComplexMediaDevice extends MediaDevice to represents device with signals from a number of
+ * sources.
+ */
+public class ComplexMediaDevice extends MediaDevice {
+
+    private final String mSummary = "";
+
+    ComplexMediaDevice(Context context, MediaRouter2Manager routerManager,
+            MediaRoute2Info info, String packageName,
+            RouteListingPreference.Item item) {
+        super(context, routerManager, info, packageName, item);
+    }
+
+    // MediaRoute2Info.getName was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
+    @Override
+    public String getName() {
+        return mRouteInfo.getName().toString();
+    }
+
+    @Override
+    public String getSummary() {
+        return mSummary;
+    }
+
+    @Override
+    public Drawable getIcon() {
+        return mContext.getDrawable(R.drawable.ic_media_avr_device);
+    }
+
+    @Override
+    public Drawable getIconWithoutBackground() {
+        return mContext.getDrawable(R.drawable.ic_media_avr_device);
+    }
+
+    @Override
+    public String getId() {
+        return MediaDeviceUtils.getId(mRouteInfo);
+    }
+
+    public boolean isConnected() {
+        return true;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 6fb5555..c036fdb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -73,6 +73,8 @@
     }
 
     @VisibleForTesting
+    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
     int getDrawableResId() {
         int resId;
         switch (mRouteInfo.getType()) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 2bdbb16..1b832bf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -22,6 +22,7 @@
 import static android.media.MediaRoute2Info.TYPE_GROUP;
 import static android.media.MediaRoute2Info.TYPE_HDMI;
 import static android.media.MediaRoute2Info.TYPE_HEARING_AID;
+import static android.media.MediaRoute2Info.TYPE_REMOTE_AUDIO_VIDEO_RECEIVER;
 import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
 import static android.media.MediaRoute2Info.TYPE_REMOTE_TV;
 import static android.media.MediaRoute2Info.TYPE_UNKNOWN;
@@ -34,10 +35,12 @@
 
 import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_SELECTED;
 
+import android.annotation.Nullable;
 import android.annotation.TargetApi;
 import android.app.Notification;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.content.ComponentName;
 import android.content.Context;
 import android.media.MediaRoute2Info;
 import android.media.MediaRouter2Manager;
@@ -103,6 +106,15 @@
         mMediaDevices.clear();
         mRouterManager.registerCallback(mExecutor, mMediaRouterCallback);
         mRouterManager.registerScanRequest();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+                && !TextUtils.isEmpty(mPackageName)) {
+            RouteListingPreference routeListingPreference =
+                    mRouterManager.getRouteListingPreference(mPackageName);
+            if (routeListingPreference != null) {
+                Api34Impl.onRouteListingPreferenceUpdated(null, routeListingPreference,
+                        mPreferenceItemMap);
+            }
+        }
         refreshDevices();
     }
 
@@ -191,6 +203,14 @@
                 && Api34Impl.preferRouteListingOrdering(mRouterManager, mPackageName);
     }
 
+    @Nullable
+    ComponentName getLinkedItemComponentName() {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+            return null;
+        }
+        return Api34Impl.getLinkedItemComponentName(mRouterManager, mPackageName);
+    }
+
     /**
      * Remove a {@code device} from current media.
      *
@@ -433,6 +453,8 @@
         dispatchDeviceListAdded();
     }
 
+    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
     private void buildAllRoutes() {
         for (MediaRoute2Info route : mRouterManager.getAllRoutes()) {
             if (DEBUG) {
@@ -452,6 +474,8 @@
         return infos;
     }
 
+    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
     private synchronized void buildAvailableRoutes() {
         for (MediaRoute2Info route : getAvailableRoutes(mPackageName)) {
             if (DEBUG) {
@@ -485,7 +509,8 @@
                 infos.add(transferableRoute);
             }
         }
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+                && !TextUtils.isEmpty(mPackageName)) {
             RouteListingPreference routeListingPreference =
                     mRouterManager.getRouteListingPreference(mPackageName);
             if (routeListingPreference != null) {
@@ -502,6 +527,8 @@
         }
     }
 
+    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
     @VisibleForTesting
     void addMediaDevice(MediaRoute2Info route) {
         //TODO(b/258141461): Attach flag and disable reason in MediaDevice
@@ -546,6 +573,9 @@
                             route, mPackageName);
                 }
                 break;
+            case TYPE_REMOTE_AUDIO_VIDEO_RECEIVER:
+                mediaDevice = new ComplexMediaDevice(mContext, mRouterManager, route,
+                        mPackageName, mPreferenceItemMap.get(route.getId()));
             default:
                 Log.w(TAG, "addMediaDevice() unknown device type : " + deviceType);
                 break;
@@ -613,6 +643,7 @@
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
                 Api34Impl.onRouteListingPreferenceUpdated(packageName, routeListingPreference,
                         mPreferenceItemMap);
+                refreshDevices();
             }
         }
     }
@@ -625,8 +656,8 @@
             List<RouteListingPreference.Item> finalizedItemList = new ArrayList<>();
             List<RouteListingPreference.Item> itemList = routeListingPreference.getItems();
             for (RouteListingPreference.Item item : itemList) {
-                //Put suggested devices on the top first before further organization
-                if (item.getFlags() == RouteListingPreference.Item.FLAG_SUGGESTED_ROUTE) {
+                // Put suggested devices on the top first before further organization
+                if ((item.getFlags() & RouteListingPreference.Item.FLAG_SUGGESTED) != 0) {
                     finalizedItemList.add(0, item);
                 } else {
                     finalizedItemList.add(item);
@@ -675,6 +706,9 @@
         @DoNotInline
         static boolean preferRouteListingOrdering(MediaRouter2Manager mediaRouter2Manager,
                 String packageName) {
+            if (TextUtils.isEmpty(packageName)) {
+                return false;
+            }
             RouteListingPreference routeListingPreference =
                     mediaRouter2Manager.getRouteListingPreference(packageName);
             return routeListingPreference != null
@@ -682,6 +716,19 @@
         }
 
         @DoNotInline
+        @Nullable
+        static ComponentName getLinkedItemComponentName(
+                MediaRouter2Manager mediaRouter2Manager, String packageName) {
+            if (TextUtils.isEmpty(packageName)) {
+                return null;
+            }
+            RouteListingPreference routeListingPreference =
+                    mediaRouter2Manager.getRouteListingPreference(packageName);
+            return routeListingPreference == null ? null
+                    : routeListingPreference.getLinkedItemComponentName();
+        }
+
+        @DoNotInline
         static void onRouteListingPreferenceUpdated(
                 String packageName,
                 RouteListingPreference routeListingPreference,
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index aec1767..24acf8a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -20,6 +20,7 @@
 import android.app.Notification;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
@@ -217,6 +218,16 @@
     }
 
     /**
+     * Returns required component name for system to take the user back to the app by launching an
+     * intent with the returned {@link ComponentName}, using action {@link #ACTION_TRANSFER_MEDIA},
+     * with the extra {@link #EXTRA_ROUTE_ID}.
+     */
+    @Nullable
+    public ComponentName getLinkedItemComponentName() {
+        return mInfoMediaManager.getLinkedItemComponentName();
+    }
+
+    /**
      * Start scan connected MediaDevice
      */
     public void startScan() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index d708e57..6b9866b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -30,8 +30,19 @@
 import static android.media.MediaRoute2Info.TYPE_USB_HEADSET;
 import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
 import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
-import static android.media.RouteListingPreference.Item.DISABLE_REASON_NONE;
-import static android.media.RouteListingPreference.Item.FLAG_SUGGESTED_ROUTE;
+import static android.media.RouteListingPreference.Item.FLAG_ONGOING_SESSION;
+import static android.media.RouteListingPreference.Item.FLAG_ONGOING_SESSION_MANAGED;
+import static android.media.RouteListingPreference.Item.FLAG_SUGGESTED;
+import static android.media.RouteListingPreference.Item.SELECTION_BEHAVIOR_TRANSFER;
+import static android.media.RouteListingPreference.Item.SUBTEXT_AD_ROUTING_DISALLOWED;
+import static android.media.RouteListingPreference.Item.SUBTEXT_CUSTOM;
+import static android.media.RouteListingPreference.Item.SUBTEXT_DEVICE_LOW_POWER;
+import static android.media.RouteListingPreference.Item.SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED;
+import static android.media.RouteListingPreference.Item.SUBTEXT_ERROR_UNKNOWN;
+import static android.media.RouteListingPreference.Item.SUBTEXT_NONE;
+import static android.media.RouteListingPreference.Item.SUBTEXT_SUBSCRIPTION_REQUIRED;
+import static android.media.RouteListingPreference.Item.SUBTEXT_TRACK_UNSUPPORTED;
+import static android.media.RouteListingPreference.Item.SUBTEXT_UNAUTHORIZED;
 
 import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_SELECTED;
 
@@ -51,6 +62,8 @@
 import androidx.annotation.RequiresApi;
 import androidx.annotation.VisibleForTesting;
 
+import com.android.settingslib.R;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -106,6 +119,8 @@
         setType(info);
     }
 
+    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
     private void setType(MediaRoute2Info info) {
         if (info == null) {
             mType = MediaDeviceType.TYPE_BLUETOOTH_DEVICE;
@@ -194,24 +209,66 @@
     public abstract String getId();
 
     /**
-     * Get disabled reason of device
+     * Get selection behavior of device
      *
-     * @return disabled reason of device
+     * @return selection behavior of device
      */
-    @RouteListingPreference.Item.DisableReason
-    public int getDisableReason() {
+    @RouteListingPreference.Item.SubText
+    public int getSelectionBehavior() {
         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && mItem != null
-                ? mItem.getDisableReason() : -1;
+                ? mItem.getSelectionBehavior() : SELECTION_BEHAVIOR_TRANSFER;
     }
 
     /**
-     * Checks if device is has disabled reason
+     * Checks if device is has subtext
      *
-     * @return true if device has disabled reason
+     * @return true if device has subtext
      */
-    public boolean hasDisabledReason() {
+    public boolean hasSubtext() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+                && mItem != null
+                && mItem.getSubText() != SUBTEXT_NONE;
+    }
+
+    /**
+     * Get subtext of device
+     *
+     * @return subtext of device
+     */
+    @RouteListingPreference.Item.SubText
+    public int getSubtext() {
         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && mItem != null
-                && mItem.getDisableReason() != DISABLE_REASON_NONE;
+                ? mItem.getSubText() : SUBTEXT_NONE;
+    }
+
+    /**
+     * Returns subtext string for current route.
+     *
+     * @return subtext string for this route
+     */
+    public String getSubtextString() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && mItem != null
+                ? Api34Impl.composeSubtext(mItem, mContext) : null;
+    }
+
+    /**
+     * Checks if device has ongoing shared session, which allow user to join
+     *
+     * @return true if device has ongoing session
+     */
+    public boolean hasOngoingSession() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+                && Api34Impl.hasOngoingSession(mItem);
+    }
+
+    /**
+     * Checks if device is the host for ongoing shared session, which allow user to adjust volume
+     *
+     * @return true if device is the host for ongoing shared session
+     */
+    public boolean isHostForOngoingSession() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+                && Api34Impl.isHostForOngoingSession(mItem);
     }
 
     /**
@@ -295,6 +352,8 @@
      *
      * @return true if the RouteInfo equals TYPE_BLE_HEADSET.
      */
+    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
     public boolean isBLEDevice() {
         return mRouteInfo.getType() == TYPE_BLE_HEADSET;
     }
@@ -510,8 +569,43 @@
     @RequiresApi(34)
     private static class Api34Impl {
         @DoNotInline
+        static boolean isHostForOngoingSession(RouteListingPreference.Item item) {
+            int flags = item != null ? item.getFlags() : 0;
+            return (flags & FLAG_ONGOING_SESSION) != 0
+                    && (flags & FLAG_ONGOING_SESSION_MANAGED) != 0;
+        }
+
+        @DoNotInline
         static boolean isSuggestedDevice(RouteListingPreference.Item item) {
-            return item != null && item.getFlags() == FLAG_SUGGESTED_ROUTE;
+            return item != null && (item.getFlags() & FLAG_SUGGESTED) != 0;
+        }
+
+        @DoNotInline
+        static boolean hasOngoingSession(RouteListingPreference.Item item) {
+            return item != null && (item.getFlags() & FLAG_ONGOING_SESSION) != 0;
+        }
+
+        @DoNotInline
+        static String composeSubtext(RouteListingPreference.Item item, Context context) {
+            switch (item.getSubText()) {
+                case SUBTEXT_ERROR_UNKNOWN:
+                    return context.getString(R.string.media_output_status_unknown_error);
+                case SUBTEXT_SUBSCRIPTION_REQUIRED:
+                    return context.getString(R.string.media_output_status_require_premium);
+                case SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED:
+                    return context.getString(R.string.media_output_status_not_support_downloads);
+                case SUBTEXT_AD_ROUTING_DISALLOWED:
+                    return context.getString(R.string.media_output_status_try_after_ad);
+                case SUBTEXT_DEVICE_LOW_POWER:
+                    return context.getString(R.string.media_output_status_device_in_low_power_mode);
+                case SUBTEXT_UNAUTHORIZED:
+                    return context.getString(R.string.media_output_status_unauthorized);
+                case SUBTEXT_TRACK_UNSUPPORTED:
+                    return context.getString(R.string.media_output_status_track_unsupported);
+                case SUBTEXT_CUSTOM:
+                    return (String) item.getCustomSubtextMessage();
+            }
+            return "";
         }
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/OWNERS b/packages/SettingsLib/src/com/android/settingslib/media/OWNERS
index d40f322..3cae39f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/media/OWNERS
@@ -1,2 +1,5 @@
 # Default reviewers for this and subdirectories.
 shaoweishen@google.com
+
+#Android Media - For minor changes and renames only.
+aquilescanta@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index de16d4a..1c82be9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -56,6 +56,8 @@
         initDeviceRecord();
     }
 
+    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
     @Override
     public String getName() {
         CharSequence name;
@@ -94,11 +96,15 @@
         return mContext.getDrawable(getDrawableResId());
     }
 
+    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
     @VisibleForTesting
     int getDrawableResId() {
         return mDeviceIconUtil.getIconResIdFromMediaRouteType(mRouteInfo.getType());
     }
 
+    // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
+    @SuppressWarnings("NewApi")
     @Override
     public String getId() {
         String id;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsOverlayParams.kt
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
rename to packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsOverlayParams.kt
index 7f3846c..d55a027 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsOverlayParams.kt
@@ -1,4 +1,4 @@
-package com.android.systemui.biometrics
+package com.android.settingslib.udfps
 
 import android.graphics.Rect
 import android.view.Surface
diff --git a/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
new file mode 100644
index 0000000..dc8a862
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
@@ -0,0 +1,159 @@
+/*
+ * 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.settingslib.udfps;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.util.DisplayUtils;
+import android.util.Log;
+import android.util.RotationUtils;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.MotionEvent;
+import android.view.Surface;
+
+import com.android.settingslib.R;
+
+/** Utility class for working with udfps. */
+public class UdfpsUtils {
+    private static final String TAG = "UdfpsUtils";
+
+    /**
+     * Gets the scale factor representing the user's current resolution / the stable (default)
+     * resolution.
+     *
+     * @param displayInfo The display information.
+     */
+    public float getScaleFactor(DisplayInfo displayInfo) {
+        Display.Mode maxDisplayMode =
+                DisplayUtils.getMaximumResolutionDisplayMode(displayInfo.supportedModes);
+        float scaleFactor =
+                DisplayUtils.getPhysicalPixelDisplaySizeRatio(
+                        maxDisplayMode.getPhysicalWidth(),
+                        maxDisplayMode.getPhysicalHeight(),
+                        displayInfo.getNaturalWidth(),
+                        displayInfo.getNaturalHeight()
+                );
+        return (scaleFactor == Float.POSITIVE_INFINITY) ? 1f : scaleFactor;
+    }
+
+    /**
+     * Gets the touch in native coordinates. Map the touch to portrait mode if the device is in
+     * landscape mode.
+     *
+     * @param idx                The pointer identifier.
+     * @param event              The MotionEvent object containing full information about the event.
+     * @param udfpsOverlayParams The [UdfpsOverlayParams] used.
+     * @return The mapped touch event.
+     */
+    public Point getTouchInNativeCoordinates(int idx, MotionEvent event,
+            UdfpsOverlayParams udfpsOverlayParams) {
+        Point portraitTouch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx));
+        int rot = udfpsOverlayParams.getRotation();
+        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
+            RotationUtils.rotatePoint(
+                    portraitTouch,
+                    RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
+                    udfpsOverlayParams.getLogicalDisplayWidth(),
+                    udfpsOverlayParams.getLogicalDisplayHeight()
+            );
+        }
+
+        // Scale the coordinates to native resolution.
+        float scale = udfpsOverlayParams.getScaleFactor();
+        portraitTouch.x = (int) (portraitTouch.x / scale);
+        portraitTouch.y = (int) (portraitTouch.y / scale);
+        return portraitTouch;
+    }
+
+    /**
+     * This function computes the angle of touch relative to the sensor and maps the angle to a list
+     * of help messages which are announced if accessibility is enabled.
+     *
+     * @return Whether the announcing string is null
+     */
+    public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled,
+            Context context, int touchX, int touchY, UdfpsOverlayParams udfpsOverlayParams) {
+        if (!touchExplorationEnabled) {
+            return null;
+        }
+
+        String[] touchHints = context.getResources().getStringArray(
+                R.array.udfps_accessibility_touch_hints);
+        if (touchHints.length != 4) {
+            Log.e(TAG, "expected exactly 4 touch hints, got " + touchHints.length + "?");
+            return null;
+        }
+
+        // Scale the coordinates to native resolution.
+        float scale = udfpsOverlayParams.getScaleFactor();
+        float scaledSensorX = udfpsOverlayParams.getSensorBounds().centerX() / scale;
+        float scaledSensorY = udfpsOverlayParams.getSensorBounds().centerY() / scale;
+        String theStr =
+                onTouchOutsideOfSensorAreaImpl(
+                        touchHints,
+                        touchX,
+                        touchY,
+                        scaledSensorX,
+                        scaledSensorY,
+                        udfpsOverlayParams.getRotation()
+                );
+        Log.v(TAG, "Announcing touch outside : $theStr");
+        return theStr;
+    }
+
+    /**
+     * This function computes the angle of touch relative to the sensor and maps the angle to a list
+     * of help messages which are announced if accessibility is enabled.
+     *
+     * There are 4 quadrants of the circle (90 degree arcs)
+     *
+     * [315, 360] && [0, 45) -> touchHints[0] = "Move Fingerprint to the left" [45, 135) ->
+     * touchHints[1] = "Move Fingerprint down" And so on.
+     */
+    private String onTouchOutsideOfSensorAreaImpl(String[] touchHints, float touchX,
+            float touchY, float sensorX, float sensorY, int rotation) {
+        float xRelativeToSensor = touchX - sensorX;
+        // Touch coordinates are with respect to the upper left corner, so reverse
+        // this calculation
+        float yRelativeToSensor = sensorY - touchY;
+        double angleInRad = Math.atan2(yRelativeToSensor, xRelativeToSensor);
+        // If the radians are negative, that means we are counting clockwise.
+        // So we need to add 360 degrees
+        if (angleInRad < 0.0) {
+            angleInRad += 2.0 * Math.PI;
+        }
+        // rad to deg conversion
+        double degrees = Math.toDegrees(angleInRad);
+        double degreesPerBucket = 360.0 / touchHints.length;
+        double halfBucketDegrees = degreesPerBucket / 2.0;
+        // The mapping should be as follows
+        // [315, 360] && [0, 45] -> 0
+        // [45, 135]             -> 1
+        int index = (int) ((degrees + halfBucketDegrees) % 360 / degreesPerBucket);
+        index %= touchHints.length;
+
+        // A rotation of 90 degrees corresponds to increasing the index by 1.
+        if (rotation == Surface.ROTATION_90) {
+            index = (index + 1) % touchHints.length;
+        }
+        if (rotation == Surface.ROTATION_270) {
+            index = (index + 3) % touchHints.length;
+        }
+        return touchHints[index];
+    }
+}
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 2c8aa26..04c1c31 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
@@ -35,6 +35,7 @@
 import static org.mockito.Mockito.when;
 
 import android.bluetooth.BluetoothDevice;
+import android.content.ComponentName;
 import android.content.Context;
 import android.media.MediaRoute2Info;
 import android.media.MediaRouter2Manager;
@@ -88,6 +89,8 @@
     private MediaManager.MediaDeviceCallback mCallback;
     @Mock
     private MediaSessionManager mMediaSessionManager;
+    @Mock
+    private ComponentName mComponentName;
 
     private InfoMediaManager mInfoMediaManager;
     private Context mContext;
@@ -256,8 +259,10 @@
         ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT",
                 Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
         final List<RouteListingPreference.Item> preferenceItemList = new ArrayList<>();
-        RouteListingPreference.Item item1 = new RouteListingPreference.Item.Builder(
-                TEST_ID_4).setFlags(RouteListingPreference.Item.FLAG_SUGGESTED_ROUTE).build();
+        RouteListingPreference.Item item1 =
+                new RouteListingPreference.Item.Builder(TEST_ID_4)
+                        .setFlags(RouteListingPreference.Item.FLAG_SUGGESTED)
+                        .build();
         RouteListingPreference.Item item2 = new RouteListingPreference.Item.Builder(
                 TEST_ID_3).build();
         preferenceItemList.add(item1);
@@ -372,6 +377,24 @@
         assertThat(mInfoMediaManager.preferRouteListingOrdering()).isFalse();
     }
 
+    @Test
+    public void getInAppOnlyItemRoutingReceiver_oldSdkVersion_returnsNull() {
+        assertThat(mInfoMediaManager.getLinkedItemComponentName()).isNull();
+    }
+
+    @Test
+    public void getInAppOnlyItemRoutingReceiver_newSdkVersionWithReceiverExist_returns() {
+        ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT",
+                Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
+        when(mRouterManager.getRouteListingPreference(any())).thenReturn(
+                new RouteListingPreference.Builder().setItems(
+                        ImmutableList.of()).setUseSystemOrdering(
+                        false).setLinkedItemComponentName(mComponentName).build());
+        mInfoMediaManager.mRouterManager = mRouterManager;
+
+        assertThat(mInfoMediaManager.getLinkedItemComponentName()).isEqualTo(mComponentName);
+    }
+
     private List<MediaRoute2Info> getRoutesListWithDuplicatedIds() {
         final List<MediaRoute2Info> routes = new ArrayList<>();
         final MediaRoute2Info info = mock(MediaRoute2Info.class);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/udfps/UdfpsUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/udfps/UdfpsUtilsTest.java
new file mode 100644
index 0000000..f4f0ef9
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/udfps/UdfpsUtilsTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.settingslib.udfps;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.Surface;
+
+import com.android.settingslib.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+
+@RunWith(RobolectricTestRunner.class)
+public class UdfpsUtilsTest {
+    @Rule
+    public final MockitoRule rule = MockitoJUnit.rule();
+
+    private Context mContext;
+    private String[] mTouchHints;
+    private UdfpsUtils mUdfpsUtils;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mTouchHints = mContext.getResources().getStringArray(
+                R.array.udfps_accessibility_touch_hints);
+        mUdfpsUtils = new UdfpsUtils();
+    }
+
+    @Test
+    public void testTouchOutsideAreaNoRotation() {
+        int rotation = Surface.ROTATION_0;
+        // touch at 0 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        0 /* touchX */, 0/* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[0]);
+        // touch at 90 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        0 /* touchX */, -1/* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[1]);
+        // touch at 180 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        -1 /* touchX */, 0/* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[2]);
+        // touch at 270 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        0 /* touchX */, 1/* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[3]);
+    }
+
+
+    @Test
+    public void testTouchOutsideAreaNoRotation90Degrees() {
+        int rotation = Surface.ROTATION_90;
+        // touch at 0 degrees -> 90 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        0 /* touchX */, 0 /* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[1]);
+        // touch at 90 degrees -> 180 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        0 /* touchX */, -1 /* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[2]);
+        // touch at 180 degrees -> 270 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        -1 /* touchX */, 0 /* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[3]);
+        // touch at 270 degrees -> 0 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        0 /* touchX */, 1/* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[0]);
+    }
+
+
+    @Test
+    public void testTouchOutsideAreaNoRotation270Degrees() {
+        int rotation = Surface.ROTATION_270;
+        // touch at 0 degrees -> 270 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        0 /* touchX */, 0/* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[3]);
+        // touch at 90 degrees -> 0 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        0 /* touchX */, -1/* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[0]);
+        // touch at 180 degrees -> 90 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        -1 /* touchX */, 0/* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[1]);
+        // touch at 270 degrees -> 180 degrees
+        assertThat(
+                mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
+                        0 /* touchX */, 1/* touchY */,
+                        new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
+                )
+        ).isEqualTo(mTouchHints[2]);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
index 103512d..21e119a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
@@ -215,4 +215,20 @@
 
         assertThat(mOnBindListenerAnimationView).isNull();
     }
+
+    @Test
+    public void onBindViewHolder_default_shouldNotApplyDynamicColor() {
+        mPreference.onBindViewHolder(mViewHolder);
+
+        assertThat(mPreference.isApplyDynamicColor()).isFalse();
+    }
+
+    @Test
+    public void onBindViewHolder_applyDynamicColor_shouldReturnTrue() {
+        mPreference.applyDynamicColor();
+
+        mPreference.onBindViewHolder(mViewHolder);
+
+        assertThat(mPreference.isApplyDynamicColor()).isTrue();
+    }
 }
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 4a10427..1ac20471 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -33,7 +33,7 @@
     static_libs: [
         "junit",
         "SettingsLibDeviceStateRotationLock",
-        "SettingsLibDisplayDensityUtils",
+        "SettingsLibDisplayUtils",
     ],
     platform_apis: true,
     certificate: "platform",
@@ -57,7 +57,7 @@
         "androidx.test.rules",
         "mockito-target-minus-junit4",
         "SettingsLibDeviceStateRotationLock",
-        "SettingsLibDisplayDensityUtils",
+        "SettingsLibDisplayUtils",
         "platform-test-annotations",
         "truth-prebuilt",
     ],
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index c0818a8..7cd8d70 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -99,5 +99,7 @@
         Settings.Global.Wearable.WEAR_ACTIVITY_AUTO_RESUME_TIMEOUT_MS,
         Settings.Global.Wearable.WEAR_ACTIVITY_AUTO_RESUME_TIMEOUT_SET_BY_USER,
         Settings.Global.Wearable.DYNAMIC_COLOR_THEME_ENABLED,
+        Settings.Global.HDR_CONVERSION_MODE,
+        Settings.Global.HDR_FORCE_CONVERSION_TYPE,
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/LargeScreenSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/LargeScreenSettings.java
new file mode 100644
index 0000000..bdd4869
--- /dev/null
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/LargeScreenSettings.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.settings.backup;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+
+/** Settings that should not be restored when target device is a large screen
+ *  i.e. tablets and foldables in unfolded state
+ */
+public class LargeScreenSettings {
+    private static final float LARGE_SCREEN_MIN_DPS = 600;
+    private static final String LARGE_SCREEN_DO_NOT_RESTORE = "accelerometer_rotation";
+
+   /**
+    * Autorotation setting should not be restored when the target device is a large screen.
+    * (b/243489549)
+    */
+    public static boolean doNotRestoreIfLargeScreenSetting(String key, Context context) {
+        return isLargeScreen(context) && LARGE_SCREEN_DO_NOT_RESTORE.equals(key);
+    }
+
+    // copied from systemui/shared/...Utilities.java
+    // since we don't want to add compile time dependency on sys ui package
+    private static boolean isLargeScreen(Context context) {
+        final WindowManager windowManager = context.getSystemService(WindowManager.class);
+        final Rect bounds = windowManager.getCurrentWindowMetrics().getBounds();
+        float smallestWidth = dpiFromPx(Math.min(bounds.width(), bounds.height()),
+                context.getResources().getConfiguration().densityDpi);
+        return smallestWidth >= LARGE_SCREEN_MIN_DPS;
+    }
+
+    private static float dpiFromPx(float size, int densityDpi) {
+        float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT;
+        return (size / densityRatio);
+    }
+}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index c133097..a08d7cd 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -130,6 +130,7 @@
         Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ERRORS,
         Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO,
         Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED,
+        Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS,
         Settings.Secure.VR_DISPLAY_MODE,
         Settings.Secure.NOTIFICATION_BADGING,
         Settings.Secure.NOTIFICATION_DISMISS_RTL,
@@ -210,6 +211,7 @@
         Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE,
         Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY,
         Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
+        Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED,
         Settings.Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED,
         Settings.Secure.NOTIFICATION_BUBBLES,
         Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
@@ -227,6 +229,7 @@
         Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE,
         Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME,
         Settings.Secure.CUSTOM_BUGREPORT_HANDLER_APP,
-        Settings.Secure.CUSTOM_BUGREPORT_HANDLER_USER
+        Settings.Secure.CUSTOM_BUGREPORT_HANDLER_USER,
+        Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 673a3ab..3ffbabd 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -16,6 +16,9 @@
 
 package android.provider.settings.validators;
 
+import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_FORCE;
+import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_PASSTHROUGH;
+import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_SYSTEM;
 import static android.media.AudioFormat.SURROUND_SOUND_ENCODING;
 import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
@@ -26,6 +29,11 @@
 import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.PERCENTAGE_INTEGER_VALIDATOR;
 import static android.view.Display.HdrCapabilities.HDR_TYPES;
+import static android.view.Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION;
+import static android.view.Display.HdrCapabilities.HDR_TYPE_HDR10;
+import static android.view.Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS;
+import static android.view.Display.HdrCapabilities.HDR_TYPE_HLG;
+import static android.view.Display.HdrCapabilities.HDR_TYPE_INVALID;
 
 import android.os.BatteryManager;
 import android.provider.Settings.Global;
@@ -346,6 +354,20 @@
         VALIDATORS.put(Global.USER_PREFERRED_REFRESH_RATE, NON_NEGATIVE_FLOAT_VALIDATOR);
         VALIDATORS.put(Global.USER_PREFERRED_RESOLUTION_HEIGHT, ANY_INTEGER_VALIDATOR);
         VALIDATORS.put(Global.USER_PREFERRED_RESOLUTION_WIDTH, ANY_INTEGER_VALIDATOR);
+        VALIDATORS.put(Global.HDR_CONVERSION_MODE,  new DiscreteValueValidator(
+                new String[] {
+                        String.valueOf(HDR_CONVERSION_PASSTHROUGH),
+                        String.valueOf(HDR_CONVERSION_SYSTEM),
+                        String.valueOf(HDR_CONVERSION_FORCE)
+                }));
+        VALIDATORS.put(Global.HDR_FORCE_CONVERSION_TYPE, new DiscreteValueValidator(
+                new String[] {
+                        String.valueOf(HDR_TYPE_INVALID),
+                        String.valueOf(HDR_TYPE_DOLBY_VISION),
+                        String.valueOf(HDR_TYPE_HDR10),
+                        String.valueOf(HDR_TYPE_HLG),
+                        String.valueOf(HDR_TYPE_HDR10_PLUS)
+                }));
         VALIDATORS.put(Global.RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO_ENABLED,
                        new DiscreteValueValidator(new String[]{"0", "1"}));
         VALIDATORS.put(Global.Wearable.WET_MODE_ON, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 03921e1..154987d 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -189,6 +189,8 @@
         VALIDATORS.put(Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO, ANY_STRING_VALIDATOR);
         VALIDATORS.put(Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED,
                 ANY_STRING_VALIDATOR);
+        VALIDATORS.put(Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS,
+                ANY_STRING_VALIDATOR);
         VALIDATORS.put(Secure.ASSIST_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ASSIST_GESTURE_WAKE_ENABLED, BOOLEAN_VALIDATOR);
@@ -295,6 +297,7 @@
                         Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
                         Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL));
         VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(
                 Secure.ACCESSIBILITY_BUTTON_TARGETS,
                 ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
@@ -359,5 +362,6 @@
         VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME, ANY_STRING_VALIDATOR);
         VALIDATORS.put(Secure.CUSTOM_BUGREPORT_HANDLER_APP, ANY_STRING_VALIDATOR);
         VALIDATORS.put(Secure.CUSTOM_BUGREPORT_HANDLER_USER, ANY_INTEGER_VALIDATOR);
+        VALIDATORS.put(Secure.LOCK_SCREEN_WEATHER_ENABLED, BOOLEAN_VALIDATOR);
     }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 6aa08f2..574fd5a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -37,6 +37,7 @@
 import android.provider.Settings;
 import android.provider.settings.backup.DeviceSpecificSettings;
 import android.provider.settings.backup.GlobalSettings;
+import android.provider.settings.backup.LargeScreenSettings;
 import android.provider.settings.backup.SecureSettings;
 import android.provider.settings.backup.SystemSettings;
 import android.provider.settings.validators.GlobalSettingsValidators;
@@ -812,6 +813,12 @@
                 continue;
             }
 
+            if (LargeScreenSettings.doNotRestoreIfLargeScreenSetting(key, getBaseContext())) {
+                Log.i(TAG, "Skipping restore for setting " + key + " as the target device "
+                        + "is a large screen (i.e tablet or foldable in unfolded state)");
+                continue;
+            }
+
             String value = null;
             boolean hasValueToRestore = false;
             if (cachedEntries.indexOfKey(key) >= 0) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 25b9906..159f2dd 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -238,6 +238,15 @@
         dumpSetting(s, p,
                 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
                 GlobalSettingsProto.AUDIO_SAFE_VOLUME_STATE);
+        dumpSetting(s, p,
+                Settings.Global.AUDIO_SAFE_CSD_CURRENT_VALUE,
+                GlobalSettingsProto.AUDIO_SAFE_CSD_CURRENT_VALUE);
+        dumpSetting(s, p,
+                Settings.Global.AUDIO_SAFE_CSD_NEXT_WARNING,
+                GlobalSettingsProto.AUDIO_SAFE_CSD_NEXT_WARNING);
+        dumpSetting(s, p,
+                Settings.Global.AUDIO_SAFE_CSD_DOSE_RECORDS,
+                GlobalSettingsProto.AUDIO_SAFE_CSD_DOSE_RECORDS);
 
         final long autofillToken = p.start(GlobalSettingsProto.AUTOFILL);
         dumpSetting(s, p,
@@ -1823,6 +1832,10 @@
                 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED,
                 SecureSettingsProto.Accessibility
                         .ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED);
+        dumpSetting(s, p,
+                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED,
+                SecureSettingsProto.Accessibility
+                        .ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED);
         p.end(accessibilityToken);
 
         final long adaptiveSleepToken = p.start(SecureSettingsProto.ADAPTIVE_SLEEP);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 3782ce4..222aaa3 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -131,6 +131,9 @@
                     Settings.Global.ART_VERIFIER_VERIFY_DEBUGGABLE,
                     Settings.Global.ASSISTED_GPS_ENABLED,
                     Settings.Global.AUDIO_SAFE_VOLUME_STATE,
+                    Settings.Global.AUDIO_SAFE_CSD_CURRENT_VALUE,
+                    Settings.Global.AUDIO_SAFE_CSD_NEXT_WARNING,
+                    Settings.Global.AUDIO_SAFE_CSD_DOSE_RECORDS,
                     Settings.Global.AUTOFILL_LOGGING_LEVEL,
                     Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
                     Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
@@ -773,7 +776,7 @@
                  Settings.Secure.SLEEP_TIMEOUT,
                  Settings.Secure.SMS_DEFAULT_APPLICATION,
                  Settings.Secure.SPELL_CHECKER_ENABLED,  // Intentionally removed in Q
-                 Settings.Secure.STYLUS_BUTTONS_DISABLED,
+                 Settings.Secure.STYLUS_BUTTONS_ENABLED,
                  Settings.Secure.TRUST_AGENTS_INITIALIZED,
                  Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED,
                  Settings.Secure.TV_APP_USES_NON_SYSTEM_INPUTS,
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index cb37c07..a719d77 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -677,7 +677,7 @@
         if (mScreenshotFd != null) {
             writeScreenshotFile(mScreenshotFd, SCREENSHOT_CONTENT);
         }
-        mIDumpstateListener.onFinished();
+        mIDumpstateListener.onFinished("");
         getInstrumentation().waitForIdleSync();
     }
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 628fb38..4e18222 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -68,6 +68,7 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
@@ -418,6 +419,34 @@
                  android:permission="com.android.systemui.permission.SELF"
                  android:exported="false" />
 
+        <activity android:name=".screenshot.AppClipsTrampolineActivity"
+            android:theme="@style/AppClipsTrampolineActivity"
+            android:label="@string/screenshot_preview_description"
+            android:permission="android.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE"
+            android:exported="true">
+            <intent-filter android:priority="1">
+                <action android:name="android.intent.action.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".screenshot.AppClipsActivity"
+            android:theme="@style/AppClipsActivity"
+            android:process=":appclips.screenshot"
+            android:label="@string/screenshot_preview_description"
+            android:permission="com.android.systemui.permission.SELF"
+            android:excludeFromRecents="true"
+            android:exported="false"
+            android:noHistory="true" />
+
+        <service android:name=".screenshot.appclips.AppClipsScreenshotHelperService"
+            android:permission="com.android.systemui.permission.SELF"
+            android:exported="false" />
+
+        <service android:name=".screenshot.appclips.AppClipsService"
+            android:permission="android.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE"
+            android:exported="true" />
+
         <service android:name=".screenrecord.RecordingService"
                  android:foregroundServiceType="systemExempted"/>
 
@@ -690,6 +719,7 @@
             <intent-filter>
                 <action android:name="android.telecom.action.SHOW_SWITCH_TO_WORK_PROFILE_FOR_CALL_DIALOG" />
                 <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="tel" />
             </intent-filter>
         </activity>
 
@@ -914,7 +944,7 @@
                   android:showWhenLocked="true"
                   android:showForAllUsers="true"
                   android:finishOnTaskLaunch="true"
-                  android:launchMode="singleInstance"
+                  android:lockTaskMode="if_whitelisted"
                   android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
                   android:visibleToInstantApps="true">
         </activity>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index 0b1a3e2..2c04630 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -25,8 +25,17 @@
         "androidx.coordinatorlayout_coordinatorlayout",
         "androidx.core_core",
         "androidx.viewpager_viewpager",
+        "SettingsLibDisplayUtils",
     ],
 
+    optimize: {
+        enabled: true,
+        optimize: true,
+        shrink: true,
+        shrink_resources: true,
+        proguard_compatibility: false,
+    },
+
     uses_libs: [
         "org.apache.http.legacy",
     ],
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
index 26748a9..77412d9 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
@@ -16,11 +16,15 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     package="com.android.systemui.accessibility.accessibilitymenu">
-    <application>
+
+    <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/>
+
+    <application android:supportsRtl="true">
         <service
             android:name="com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService"
             android:exported="false"
-            android:label="Accessibility Menu (System)"
+            android:label="@string/accessibility_menu_service_name"
+            android:icon="@drawable/ic_logo_app"
             android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
             <intent-filter>
                 <action android:name="android.accessibilityservice.AccessibilityService"/>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp-night/a11ymenu_intro.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp-night/a11ymenu_intro.xml
new file mode 100644
index 0000000..7a4fbb2
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp-night/a11ymenu_intro.xml
@@ -0,0 +1,276 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="412dp"
+    android:height="300dp"
+    android:viewportWidth="412"
+    android:viewportHeight="300">
+  <group>
+    <clip-path
+        android:pathData="M62.23,50.19L349.77,50.19A16,16 0,0 1,365.77 66.19L365.77,236.14A16,16 0,0 1,349.77 252.14L62.23,252.14A16,16 0,0 1,46.23 236.14L46.23,66.19A16,16 0,0 1,62.23 50.19z"/>
+    <path
+        android:pathData="M62.23,50.19L349.77,50.19A16,16 0,0 1,365.77 66.19L365.77,236.14A16,16 0,0 1,349.77 252.14L62.23,252.14A16,16 0,0 1,46.23 236.14L46.23,66.19A16,16 0,0 1,62.23 50.19z"
+        android:fillColor="#3B4043"/>
+    <path
+        android:pathData="M46.23,52.14h160v200h-160z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M86.21,240.04L86.91,239.34L84.21,236.64H90.11V235.64H84.21L86.91,232.94L86.21,232.24L82.31,236.14L86.21,240.04Z"
+        android:fillColor="#3B4043"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M125.71,220.14V252.14H127.71V220.14H125.71Z"
+        android:fillColor="#3B4043"/>
+    <path
+        android:pathData="M166.21,232.24L165.51,232.94L168.21,235.64H162.31V236.64H168.21L165.51,239.34L166.21,240.04L170.11,236.14L166.21,232.24Z"
+        android:fillColor="#7F868C"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M46.71,221.14H206.71V219.14H46.71V221.14Z"
+        android:fillColor="#3B4043"/>
+    <path
+        android:pathData="M78.71,120.5L78.71,120.5A16,16 0,0 1,94.71 136.5L94.71,136.5A16,16 0,0 1,78.71 152.5L78.71,152.5A16,16 0,0 1,62.71 136.5L62.71,136.5A16,16 0,0 1,78.71 120.5z"
+        android:fillColor="#327969"/>
+    <group>
+      <clip-path
+          android:pathData="M73.36,138.95V134.15H76.56L80.56,130.15V142.85L76.56,138.85H73.36V138.95ZM82.06,133.35C83.26,133.95 84.06,135.15 84.06,136.55C84.06,137.95 83.26,139.15 82.06,139.75V133.35Z"
+          android:fillType="evenOdd"/>
+      <path
+          android:pathData="M88.36,127.05H69.36V146.05H88.36V127.05Z"
+          android:fillColor="#000000"/>
+    </group>
+    <path
+        android:pathData="M78.71,172.5L78.71,172.5A16,16 0,0 1,94.71 188.5L94.71,188.5A16,16 0,0 1,78.71 204.5L78.71,204.5A16,16 0,0 1,62.71 188.5L62.71,188.5A16,16 0,0 1,78.71 172.5z"
+        android:fillColor="#DE9834"/>
+    <path
+        android:pathData="M87.66,188.5L85.06,191.1V194.8H81.36L78.76,197.4L76.16,194.8H72.36V191.1L69.76,188.5L72.36,185.9V182.2H76.06L78.66,179.6L81.26,182.2H84.96V185.9L87.66,188.5ZM73.96,188.5C73.96,191.1 76.06,193.3 78.76,193.3C81.36,193.3 83.56,191.2 83.56,188.5C83.56,185.8 81.46,183.7 78.76,183.7C76.06,183.7 73.96,185.8 73.96,188.5Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M80.66,187.9H76.66V189.4H80.66V187.9Z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M126.71,120.5L126.71,120.5A16,16 0,0 1,142.71 136.5L142.71,136.5A16,16 0,0 1,126.71 152.5L126.71,152.5A16,16 0,0 1,110.71 136.5L110.71,136.5A16,16 0,0 1,126.71 120.5z"
+        android:fillColor="#327969"/>
+    <path
+        android:pathData="M128.31,131.1V129.5C131.51,130.2 133.91,133.1 133.91,136.5C133.91,139.9 131.51,142.7 128.31,143.5V141.9C130.61,141.2 132.31,139.1 132.31,136.6C132.31,134.1 130.61,131.8 128.31,131.1ZM130.31,136.4C130.31,135 129.51,133.8 128.31,133.2V139.6C129.41,139 130.31,137.8 130.31,136.4Z"
+        android:fillColor="#8B3737"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M126.72,142.79V130.13L122.71,134.08H119.5V138.78H122.71L126.72,142.79Z"
+        android:fillColor="#8B3737"/>
+    <group>
+      <clip-path
+          android:pathData="M126.72,142.79V130.13L122.71,134.08H119.5V138.78H122.71L126.72,142.79Z"/>
+      <clip-path
+          android:pathData="M128.31,131.1V129.5C131.51,130.2 133.91,133.1 133.91,136.5C133.91,139.9 131.51,142.7 128.31,143.5V141.9C130.61,141.2 132.31,139.1 132.31,136.6C132.31,134.1 130.61,131.8 128.31,131.1ZM130.31,136.4C130.31,135 129.51,133.8 128.31,133.2V139.6C129.41,139 130.31,137.8 130.31,136.4Z"
+          android:fillType="evenOdd"/>
+      <path
+          android:pathData="M128.31,131.1H78.31V168.15L113.75,178.94L128.31,131.1ZM128.31,129.5L138.99,80.66L78.31,67.38V129.5H128.31ZM128.31,143.5H78.31V207.54L140.44,192.01L128.31,143.5ZM128.31,141.9L113.75,94.07L78.31,104.86V141.9H128.31ZM128.31,133.2L150.67,88.48L78.31,52.3V133.2H128.31ZM128.31,139.6H78.31V223.83L152.25,183.5L128.31,139.6ZM126.72,130.13H176.73V10.79L91.66,94.5L126.72,130.13ZM126.72,142.79L91.37,178.15L176.73,263.5V142.79H126.72ZM122.71,138.78L158.07,103.43L143.43,88.78H122.71V138.78ZM119.5,138.78H69.5V188.78H119.5V138.78ZM119.5,134.08V84.08H69.5V134.08H119.5ZM122.71,134.08V184.08H143.19L157.78,169.72L122.71,134.08ZM178.31,131.1V129.5H78.31V131.1H178.31ZM117.63,178.35C98.03,174.06 83.91,156.76 83.91,136.5H183.91C183.91,109.44 164.99,86.34 138.99,80.66L117.63,178.35ZM83.91,136.5C83.91,115.15 98.93,99.31 116.18,94.99L140.44,192.01C164.09,186.1 183.91,164.66 183.91,136.5H83.91ZM178.31,143.5V141.9H78.31V143.5H178.31ZM142.87,189.74C164.72,183.09 182.31,162.64 182.31,136.6H82.31C82.31,115.57 96.5,99.32 113.75,94.07L142.87,189.74ZM182.31,136.6C182.31,112.64 166.74,90.53 142.87,83.27L113.75,178.94C94.48,173.07 82.31,155.56 82.31,136.6H182.31ZM180.31,136.4C180.31,115.04 167.88,97.08 150.67,88.48L105.95,177.92C91.14,170.52 80.31,154.96 80.31,136.4H180.31ZM78.31,133.2V139.6H178.31V133.2H78.31ZM152.25,183.5C166.09,175.95 180.31,159.6 180.31,136.4H80.31C80.31,116 92.73,102.06 104.37,95.71L152.25,183.5ZM76.72,130.13V142.79H176.73V130.13H76.72ZM162.08,107.44L158.07,103.43L87.36,174.14L91.37,178.15L162.08,107.44ZM122.71,88.78H119.5V188.78H122.71V88.78ZM169.5,138.78V134.08H69.5V138.78H169.5ZM119.5,184.08H122.71V84.08H119.5V184.08ZM157.78,169.72L161.79,165.77L91.66,94.5L87.65,98.44L157.78,169.72Z"
+          android:fillColor="#000000"/>
+    </group>
+    <path
+        android:pathData="M78.71,68.5L78.71,68.5A16,16 0,0 1,94.71 84.5L94.71,84.5A16,16 0,0 1,78.71 100.5L78.71,100.5A16,16 0,0 1,62.71 84.5L62.71,84.5A16,16 0,0 1,78.71 68.5z"
+        android:fillColor="#3B4043"/>
+    <path
+        android:pathData="M86.26,82.15C86.92,82.15 87.46,81.61 87.46,80.95C87.46,80.29 86.92,79.75 86.26,79.75C85.6,79.75 85.06,80.29 85.06,80.95C85.06,81.61 85.6,82.15 86.26,82.15Z"
+        android:fillColor="#34A853"/>
+    <path
+        android:pathData="M82.66,86.15C83.99,86.15 85.06,85.08 85.06,83.75C85.06,82.43 83.99,81.35 82.66,81.35C81.34,81.35 80.26,82.43 80.26,83.75C80.26,85.08 81.34,86.15 82.66,86.15Z"
+        android:fillColor="#EA4335"/>
+    <path
+        android:pathData="M82.66,92.45C84.21,92.45 85.46,91.2 85.46,89.65C85.46,88.11 84.21,86.85 82.66,86.85C81.11,86.85 79.86,88.11 79.86,89.65C79.86,91.2 81.11,92.45 82.66,92.45Z"
+        android:fillColor="#FBBC04"/>
+    <path
+        android:pathData="M74.76,86.15C77.41,86.15 79.56,84 79.56,81.35C79.56,78.7 77.41,76.55 74.76,76.55C72.11,76.55 69.96,78.7 69.96,81.35C69.96,84 72.11,86.15 74.76,86.15Z"
+        android:fillColor="#4285F4"/>
+    <path
+        android:pathData="M174.71,120.5L174.71,120.5A16,16 0,0 1,190.71 136.5L190.71,136.5A16,16 0,0 1,174.71 152.5L174.71,152.5A16,16 0,0 1,158.71 136.5L158.71,136.5A16,16 0,0 1,174.71 120.5z"
+        android:fillColor="#9F3EBF"/>
+    <path
+        android:pathData="M178.53,130.5H171.03V142.2H178.53V130.5Z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M170.23,132.8H167.53V140H170.23V132.8Z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M182.23,132.8H179.53V140H182.23V132.8Z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M126.71,172.5L126.71,172.5A16,16 0,0 1,142.71 188.5L142.71,188.5A16,16 0,0 1,126.71 204.5L126.71,204.5A16,16 0,0 1,110.71 188.5L110.71,188.5A16,16 0,0 1,126.71 172.5z"
+        android:fillColor="#DE9834"/>
+    <path
+        android:pathData="M135.71,188.5L133.11,191.1V194.8H129.31L126.71,197.4L124.11,194.8H120.31V191.1L117.71,188.5L120.31,185.9V182.2H124.01L126.61,179.6L129.21,182.2H132.91V185.9L135.71,188.5ZM121.91,188.5C121.91,191.1 124.01,193.3 126.71,193.3C129.31,193.3 131.51,191.2 131.51,188.5C131.51,185.8 129.41,183.7 126.71,183.7C124.11,183.7 121.91,185.8 121.91,188.5Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M127.21,187.9V186.4H126.21V187.9H124.71V188.9H126.21V190.4H127.21V188.9H128.71V187.9H127.21Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M126.71,68.5L126.71,68.5A16,16 0,0 1,142.71 84.5L142.71,84.5A16,16 0,0 1,126.71 100.5L126.71,100.5A16,16 0,0 1,110.71 84.5L110.71,84.5A16,16 0,0 1,126.71 68.5z"
+        android:fillColor="#521BBF"/>
+    <path
+        android:pathData="M128.36,78.51C128.36,79.31 127.66,80.01 126.76,80.01C125.86,80.01 125.16,79.31 125.16,78.51C125.16,77.71 125.86,77.01 126.76,77.01C127.66,76.91 128.36,77.61 128.36,78.51ZM126.76,80.71C128.96,80.71 131.46,80.51 133.46,79.91L133.86,81.41C132.36,81.81 130.66,82.01 129.06,82.21V92.01H127.46V87.51H125.86V92.01H124.36V82.21C122.76,82.11 121.06,81.81 119.56,81.41L119.96,79.91C122.06,80.51 124.46,80.71 126.76,80.71Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M174.71,172.5L174.71,172.5A16,16 0,0 1,190.71 188.5L190.71,188.5A16,16 0,0 1,174.71 204.5L174.71,204.5A16,16 0,0 1,158.71 188.5L158.71,188.5A16,16 0,0 1,174.71 172.5z"
+        android:fillColor="#438947"/>
+    <path
+        android:pathData="M179.11,185.95H178.41V184.45C178.41,182.45 176.81,180.75 174.71,180.75C172.61,180.75 171.01,182.35 171.01,184.45V185.95H170.31C169.51,185.95 168.81,186.65 168.81,187.45V194.75C168.81,195.55 169.51,196.25 170.31,196.25H179.11C179.91,196.25 180.61,195.55 180.61,194.75V187.45C180.61,186.65 179.91,185.95 179.11,185.95ZM174.71,192.55C173.91,192.55 173.21,191.85 173.21,191.05C173.21,190.25 173.91,189.55 174.71,189.55C175.51,189.55 176.21,190.25 176.21,191.05C176.21,191.95 175.51,192.55 174.71,192.55ZM172.41,185.95H176.91V184.45C176.91,183.15 175.91,182.15 174.61,182.15C173.31,182.15 172.31,183.15 172.31,184.45V185.95H172.41Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M174.71,68.5L174.71,68.5A16,16 0,0 1,190.71 84.5L190.71,84.5A16,16 0,0 1,174.71 100.5L174.71,100.5A16,16 0,0 1,158.71 84.5L158.71,84.5A16,16 0,0 1,174.71 68.5z"
+        android:fillColor="#80868B"/>
+    <path
+        android:pathData="M173.91,77.35H175.51V85.25H173.91V77.35ZM178.21,80.25L179.31,79.15C180.81,80.45 181.81,82.35 181.81,84.55C181.81,88.45 178.61,91.65 174.71,91.65C170.81,91.65 167.61,88.45 167.61,84.55C167.61,82.35 168.61,80.45 170.11,79.15L171.21,80.25C170.01,81.25 169.21,82.85 169.21,84.55C169.21,87.65 171.71,90.15 174.81,90.15C177.91,90.15 180.41,87.65 180.41,84.55C180.31,82.75 179.41,81.25 178.21,80.25Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+  </group>
+  <path
+      android:pathData="M62.23,51.69L349.77,51.69A14.5,14.5 0,0 1,364.27 66.19L364.27,236.14A14.5,14.5 0,0 1,349.77 250.64L62.23,250.64A14.5,14.5 0,0 1,47.73 236.14L47.73,66.19A14.5,14.5 0,0 1,62.23 51.69z"
+      android:strokeWidth="3"
+      android:fillColor="#00000000"
+      android:strokeColor="#7F868C"/>
+  <path
+      android:pathData="M311.45,50.35C311.45,48.98 312.56,47.87 313.92,47.87L322.84,47.87C324.2,47.87 325.32,48.98 325.32,50.35L319.37,51.34L311.45,50.35Z"
+      android:fillColor="#7F868C"/>
+  <path
+      android:pathData="M263.59,50.35C263.59,48.98 264.7,47.87 266.06,47.87L287.85,47.87C289.22,47.87 290.33,48.98 290.33,50.35L277.45,51.34L263.59,50.35Z"
+      android:fillColor="#7F868C"/>
+  <group>
+    <clip-path
+        android:pathData="M62,50.32L349.54,50.32A16,16 0,0 1,365.54 66.32L365.54,236.27A16,16 0,0 1,349.54 252.27L62,252.27A16,16 0,0 1,46 236.27L46,66.32A16,16 0,0 1,62 50.32z"/>
+    <path
+        android:pathData="M62,50.32L349.54,50.32A16,16 0,0 1,365.54 66.32L365.54,236.27A16,16 0,0 1,349.54 252.27L62,252.27A16,16 0,0 1,46 236.27L46,66.32A16,16 0,0 1,62 50.32z"
+        android:fillColor="#3B4043"/>
+    <path
+        android:pathData="M46,52.27h160v200h-160z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M85.98,240.17L86.68,239.47L83.98,236.77H89.88V235.77H83.98L86.68,233.07L85.98,232.37L82.08,236.27L85.98,240.17Z"
+        android:fillColor="#3B4043"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M125.48,220.27V252.27H127.48V220.27H125.48Z"
+        android:fillColor="#3B4043"/>
+    <path
+        android:pathData="M165.98,232.37L165.28,233.07L167.98,235.77H162.08V236.77H167.98L165.28,239.47L165.98,240.17L169.88,236.27L165.98,232.37Z"
+        android:fillColor="#7F868C"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M46.48,221.27H206.48V219.27H46.48V221.27Z"
+        android:fillColor="#3B4043"/>
+    <path
+        android:pathData="M78.48,120.64L78.48,120.64A16,16 0,0 1,94.48 136.64L94.48,136.64A16,16 0,0 1,78.48 152.64L78.48,152.64A16,16 0,0 1,62.48 136.64L62.48,136.64A16,16 0,0 1,78.48 120.64z"
+        android:fillColor="#7AE2D4"/>
+    <group>
+      <clip-path
+          android:pathData="M73.13,139.09V134.29H76.33L80.33,130.29V142.99L76.33,138.99H73.13V139.09ZM81.83,133.49C83.03,134.09 83.83,135.29 83.83,136.69C83.83,138.09 83.03,139.29 81.83,139.89V133.49Z"
+          android:fillType="evenOdd"/>
+      <path
+          android:pathData="M88.13,127.19H69.13V146.19H88.13V127.19Z"
+          android:fillColor="#000000"/>
+    </group>
+    <path
+        android:pathData="M78.48,172.64L78.48,172.64A16,16 0,0 1,94.48 188.64L94.48,188.64A16,16 0,0 1,78.48 204.64L78.48,204.64A16,16 0,0 1,62.48 188.64L62.48,188.64A16,16 0,0 1,78.48 172.64z"
+        android:fillColor="#FDD663"/>
+    <path
+        android:pathData="M87.43,188.64L84.83,191.24V194.94H81.13L78.53,197.54L75.93,194.94H72.13V191.24L69.53,188.64L72.13,186.04V182.34H75.83L78.43,179.74L81.03,182.34H84.73V186.04L87.43,188.64ZM73.73,188.64C73.73,191.24 75.83,193.44 78.53,193.44C81.13,193.44 83.33,191.34 83.33,188.64C83.33,185.94 81.23,183.84 78.53,183.84C75.83,183.84 73.73,185.94 73.73,188.64Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M80.43,188.04H76.43V189.54H80.43V188.04Z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M126.48,120.64L126.48,120.64A16,16 0,0 1,142.48 136.64L142.48,136.64A16,16 0,0 1,126.48 152.64L126.48,152.64A16,16 0,0 1,110.48 136.64L110.48,136.64A16,16 0,0 1,126.48 120.64z"
+        android:fillColor="#7AE2D4"/>
+    <path
+        android:pathData="M128.08,131.24V129.64C131.28,130.34 133.68,133.24 133.68,136.64C133.68,140.04 131.28,142.84 128.08,143.64V142.04C130.38,141.34 132.08,139.24 132.08,136.74C132.08,134.24 130.38,131.94 128.08,131.24ZM130.08,136.54C130.08,135.14 129.28,133.94 128.08,133.34V139.74C129.18,139.14 130.08,137.94 130.08,136.54Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M126.49,142.93V130.27L122.49,134.21H119.27V138.92H122.49L126.49,142.93Z"
+        android:fillColor="#000000"/>
+    <group>
+      <clip-path
+          android:pathData="M126.49,142.93V130.27L122.49,134.21H119.27V138.92H122.49L126.49,142.93Z"/>
+      <clip-path
+          android:pathData="M128.08,131.24V129.64C131.28,130.34 133.68,133.24 133.68,136.64C133.68,140.04 131.28,142.84 128.08,143.64V142.04C130.38,141.34 132.08,139.24 132.08,136.74C132.08,134.24 130.38,131.94 128.08,131.24ZM130.08,136.54C130.08,135.14 129.28,133.94 128.08,133.34V139.74C129.18,139.14 130.08,137.94 130.08,136.54Z"
+          android:fillType="evenOdd"/>
+      <path
+          android:pathData="M128.08,131.24H78.08V168.28L113.52,179.07L128.08,131.24ZM128.08,129.64L138.76,80.79L78.08,67.52V129.64H128.08ZM128.08,143.64H78.08V207.68L140.21,192.14L128.08,143.64ZM128.08,142.04L113.52,94.2L78.08,104.99V142.04H128.08ZM128.08,133.34L150.44,88.62L78.08,52.44V133.34H128.08ZM128.08,139.74H78.08V223.96L152.02,183.63L128.08,139.74ZM126.49,130.27H176.49V10.92L91.43,94.63L126.49,130.27ZM126.49,142.93L91.14,178.28L176.49,263.64V142.93H126.49ZM122.49,138.92L157.84,103.56L143.2,88.92H122.49V138.92ZM119.27,138.92H69.27V188.92H119.27V138.92ZM119.27,134.21V84.22H69.27V134.21H119.27ZM122.49,134.21V184.21H142.96L157.55,169.85L122.49,134.21ZM178.08,131.24V129.64H78.08V131.24H178.08ZM117.39,178.48C97.8,174.2 83.68,156.9 83.68,136.64H183.68C183.68,109.57 164.76,86.48 138.76,80.79L117.39,178.48ZM83.68,136.64C83.68,115.28 98.7,99.44 115.95,95.13L140.21,192.14C163.86,186.23 183.68,164.79 183.68,136.64H83.68ZM178.08,143.64V142.04H78.08V143.64H178.08ZM142.64,189.87C164.49,183.22 182.08,162.77 182.08,136.74H82.08C82.08,115.7 96.27,99.45 113.52,94.2L142.64,189.87ZM182.08,136.74C182.08,112.78 166.51,90.67 142.64,83.4L113.52,179.07C94.25,173.2 82.08,155.69 82.08,136.74H182.08ZM180.08,136.54C180.08,115.18 167.65,97.22 150.44,88.62L105.72,178.06C90.91,170.65 80.08,155.1 80.08,136.54H180.08ZM78.08,133.34V139.74H178.08V133.34H78.08ZM152.02,183.63C165.86,176.08 180.08,159.73 180.08,136.54H80.08C80.08,116.14 92.5,102.19 104.14,95.84L152.02,183.63ZM76.49,130.27V142.93H176.49V130.27H76.49ZM161.85,107.57L157.84,103.56L87.13,174.27L91.14,178.28L161.85,107.57ZM122.49,88.92H119.27V188.92H122.49V88.92ZM169.27,138.92V134.21H69.27V138.92H169.27ZM119.27,184.21H122.49V84.22H119.27V184.21ZM157.55,169.85L161.56,165.91L91.43,94.63L87.42,98.58L157.55,169.85Z"
+          android:fillColor="#000000"/>
+    </group>
+    <path
+        android:pathData="M78.48,68.64L78.48,68.64A16,16 0,0 1,94.48 84.64L94.48,84.64A16,16 0,0 1,78.48 100.64L78.48,100.64A16,16 0,0 1,62.48 84.64L62.48,84.64A16,16 0,0 1,78.48 68.64z"
+        android:fillColor="#3B4043"/>
+    <path
+        android:pathData="M86.03,82.29C86.69,82.29 87.23,81.75 87.23,81.09C87.23,80.42 86.69,79.89 86.03,79.89C85.37,79.89 84.83,80.42 84.83,81.09C84.83,81.75 85.37,82.29 86.03,82.29Z"
+        android:fillColor="#34A853"/>
+    <path
+        android:pathData="M82.43,86.29C83.76,86.29 84.83,85.21 84.83,83.89C84.83,82.56 83.76,81.49 82.43,81.49C81.11,81.49 80.03,82.56 80.03,83.89C80.03,85.21 81.11,86.29 82.43,86.29Z"
+        android:fillColor="#EA4335"/>
+    <path
+        android:pathData="M82.43,92.59C83.98,92.59 85.23,91.33 85.23,89.79C85.23,88.24 83.98,86.99 82.43,86.99C80.88,86.99 79.63,88.24 79.63,89.79C79.63,91.33 80.88,92.59 82.43,92.59Z"
+        android:fillColor="#FBBC04"/>
+    <path
+        android:pathData="M74.53,86.29C77.18,86.29 79.33,84.14 79.33,81.49C79.33,78.84 77.18,76.69 74.53,76.69C71.88,76.69 69.73,78.84 69.73,81.49C69.73,84.14 71.88,86.29 74.53,86.29Z"
+        android:fillColor="#4285F4"/>
+    <path
+        android:pathData="M174.48,120.64L174.48,120.64A16,16 0,0 1,190.48 136.64L190.48,136.64A16,16 0,0 1,174.48 152.64L174.48,152.64A16,16 0,0 1,158.48 136.64L158.48,136.64A16,16 0,0 1,174.48 120.64z"
+        android:fillColor="#EFA5DE"/>
+    <path
+        android:pathData="M178.3,130.64H170.8V142.34H178.3V130.64Z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M170,132.94H167.3V140.14H170V132.94Z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M182,132.94H179.3V140.14H182V132.94Z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M126.48,172.64L126.48,172.64A16,16 0,0 1,142.48 188.64L142.48,188.64A16,16 0,0 1,126.48 204.64L126.48,204.64A16,16 0,0 1,110.48 188.64L110.48,188.64A16,16 0,0 1,126.48 172.64z"
+        android:fillColor="#FDD663"/>
+    <path
+        android:pathData="M135.48,188.64L132.88,191.24V194.94H129.08L126.48,197.54L123.88,194.94H120.08V191.24L117.48,188.64L120.08,186.04V182.34H123.78L126.38,179.74L128.98,182.34H132.68V186.04L135.48,188.64ZM121.68,188.64C121.68,191.24 123.78,193.44 126.48,193.44C129.08,193.44 131.28,191.34 131.28,188.64C131.28,185.94 129.18,183.84 126.48,183.84C123.88,183.84 121.68,185.94 121.68,188.64Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M126.98,188.04V186.54H125.98V188.04H124.48V189.04H125.98V190.54H126.98V189.04H128.48V188.04H126.98Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M126.48,68.64L126.48,68.64A16,16 0,0 1,142.48 84.64L142.48,84.64A16,16 0,0 1,126.48 100.64L126.48,100.64A16,16 0,0 1,110.48 84.64L110.48,84.64A16,16 0,0 1,126.48 68.64z"
+        android:fillColor="#D9AFFD"/>
+    <path
+        android:pathData="M128.13,78.64C128.13,79.44 127.43,80.14 126.53,80.14C125.63,80.14 124.93,79.44 124.93,78.64C124.93,77.84 125.63,77.14 126.53,77.14C127.43,77.04 128.13,77.74 128.13,78.64ZM126.53,80.84C128.73,80.84 131.23,80.64 133.23,80.04L133.63,81.54C132.13,81.94 130.43,82.14 128.83,82.34V92.14H127.23V87.64H125.63V92.14H124.13V82.34C122.53,82.24 120.83,81.94 119.33,81.54L119.73,80.04C121.83,80.64 124.23,80.84 126.53,80.84Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M174.48,172.64L174.48,172.64A16,16 0,0 1,190.48 188.64L190.48,188.64A16,16 0,0 1,174.48 204.64L174.48,204.64A16,16 0,0 1,158.48 188.64L158.48,188.64A16,16 0,0 1,174.48 172.64z"
+        android:fillColor="#84E39F"/>
+    <path
+        android:pathData="M178.88,186.09H178.18V184.59C178.18,182.59 176.58,180.89 174.48,180.89C172.38,180.89 170.78,182.49 170.78,184.59V186.09H170.08C169.28,186.09 168.58,186.79 168.58,187.59V194.89C168.58,195.69 169.28,196.39 170.08,196.39H178.88C179.68,196.39 180.38,195.69 180.38,194.89V187.59C180.38,186.79 179.68,186.09 178.88,186.09ZM174.48,192.69C173.68,192.69 172.98,191.99 172.98,191.19C172.98,190.39 173.68,189.69 174.48,189.69C175.28,189.69 175.98,190.39 175.98,191.19C175.98,192.09 175.28,192.69 174.48,192.69ZM172.18,186.09H176.68V184.59C176.68,183.29 175.68,182.29 174.38,182.29C173.08,182.29 172.08,183.29 172.08,184.59V186.09H172.18Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M174.48,68.64L174.48,68.64A16,16 0,0 1,190.48 84.64L190.48,84.64A16,16 0,0 1,174.48 100.64L174.48,100.64A16,16 0,0 1,158.48 84.64L158.48,84.64A16,16 0,0 1,174.48 68.64z"
+        android:fillColor="#DBDCE0"/>
+    <path
+        android:pathData="M173.68,77.49H175.28V85.39H173.68V77.49ZM177.98,80.39L179.08,79.29C180.58,80.59 181.58,82.49 181.58,84.69C181.58,88.59 178.38,91.79 174.48,91.79C170.58,91.79 167.38,88.59 167.38,84.69C167.38,82.49 168.38,80.59 169.88,79.29L170.98,80.39C169.78,81.39 168.98,82.99 168.98,84.69C168.98,87.79 171.48,90.29 174.58,90.29C177.68,90.29 180.18,87.79 180.18,84.69C180.08,82.89 179.18,81.39 177.98,80.39Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+  </group>
+  <path
+      android:pathData="M62,51.82L349.54,51.82A14.5,14.5 0,0 1,364.04 66.32L364.04,236.27A14.5,14.5 0,0 1,349.54 250.77L62,250.77A14.5,14.5 0,0 1,47.5 236.27L47.5,66.32A14.5,14.5 0,0 1,62 51.82z"
+      android:strokeWidth="3"
+      android:fillColor="#00000000"
+      android:strokeColor="#7F868C"/>
+  <path
+      android:pathData="M311.22,50.49C311.22,49.11 312.33,48 313.7,48L322.61,48C323.98,48 325.08,49.11 325.08,50.49L319.14,51.48L311.22,50.49Z"
+      android:fillColor="#7F868C"/>
+  <path
+      android:pathData="M263.36,50.49C263.36,49.11 264.47,48 265.83,48L287.62,48C288.99,48 290.1,49.11 290.1,50.49L277.22,51.48L263.36,50.49Z"
+      android:fillColor="#7F868C"/>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp/a11ymenu_intro.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp/a11ymenu_intro.xml
new file mode 100644
index 0000000..f0fbc48
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp/a11ymenu_intro.xml
@@ -0,0 +1,141 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="412dp"
+    android:height="300dp"
+    android:viewportWidth="412"
+    android:viewportHeight="300">
+  <group>
+    <clip-path
+        android:pathData="M62.23,50.19L349.77,50.19A16,16 0,0 1,365.77 66.19L365.77,236.14A16,16 0,0 1,349.77 252.14L62.23,252.14A16,16 0,0 1,46.23 236.14L46.23,66.19A16,16 0,0 1,62.23 50.19z"/>
+    <path
+        android:pathData="M62.23,50.19L349.77,50.19A16,16 0,0 1,365.77 66.19L365.77,236.14A16,16 0,0 1,349.77 252.14L62.23,252.14A16,16 0,0 1,46.23 236.14L46.23,66.19A16,16 0,0 1,62.23 50.19z"
+        android:fillColor="#E8EAED"/>
+    <path
+        android:pathData="M46.23,52.14h160v200h-160z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M86.21,240.04L86.91,239.34L84.21,236.64H90.11V235.64H84.21L86.91,232.94L86.21,232.24L82.31,236.14L86.21,240.04Z"
+        android:fillColor="#E8EAED"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M125.71,220.14V252.14H127.71V220.14H125.71Z"
+        android:fillColor="#E8EAED"/>
+    <path
+        android:pathData="M166.21,232.24L165.51,232.94L168.21,235.64H162.31V236.64H168.21L165.51,239.34L166.21,240.04L170.11,236.14L166.21,232.24Z"
+        android:fillColor="#7F868C"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M46.71,221.14H206.71V219.14H46.71V221.14Z"
+        android:fillColor="#E8EAED"/>
+    <path
+        android:pathData="M78.71,120.5L78.71,120.5A16,16 0,0 1,94.71 136.5L94.71,136.5A16,16 0,0 1,78.71 152.5L78.71,152.5A16,16 0,0 1,62.71 136.5L62.71,136.5A16,16 0,0 1,78.71 120.5z"
+        android:fillColor="#327969"/>
+    <group>
+      <clip-path
+          android:pathData="M73.36,138.95V134.15H76.56L80.56,130.15V142.85L76.56,138.85H73.36V138.95ZM82.06,133.35C83.26,133.95 84.06,135.15 84.06,136.55C84.06,137.95 83.26,139.15 82.06,139.75V133.35Z"
+          android:fillType="evenOdd"/>
+      <path
+          android:pathData="M88.36,127.05H69.36V146.05H88.36V127.05Z"
+          android:fillColor="#ffffff"/>
+    </group>
+    <path
+        android:pathData="M78.71,172.5L78.71,172.5A16,16 0,0 1,94.71 188.5L94.71,188.5A16,16 0,0 1,78.71 204.5L78.71,204.5A16,16 0,0 1,62.71 188.5L62.71,188.5A16,16 0,0 1,78.71 172.5z"
+        android:fillColor="#DE9834"/>
+    <path
+        android:pathData="M87.66,188.5L85.06,191.1V194.8H81.36L78.76,197.4L76.16,194.8H72.36V191.1L69.76,188.5L72.36,185.9V182.2H76.06L78.66,179.6L81.26,182.2H84.96V185.9L87.66,188.5ZM73.96,188.5C73.96,191.1 76.06,193.3 78.76,193.3C81.36,193.3 83.56,191.2 83.56,188.5C83.56,185.8 81.46,183.7 78.76,183.7C76.06,183.7 73.96,185.8 73.96,188.5Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M80.66,187.9H76.66V189.4H80.66V187.9Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M126.71,120.5L126.71,120.5A16,16 0,0 1,142.71 136.5L142.71,136.5A16,16 0,0 1,126.71 152.5L126.71,152.5A16,16 0,0 1,110.71 136.5L110.71,136.5A16,16 0,0 1,126.71 120.5z"
+        android:fillColor="#327969"/>
+    <path
+        android:pathData="M128.31,131.1V129.5C131.51,130.2 133.91,133.1 133.91,136.5C133.91,139.9 131.51,142.7 128.31,143.5V141.9C130.61,141.2 132.31,139.1 132.31,136.6C132.31,134.1 130.61,131.8 128.31,131.1ZM130.31,136.4C130.31,135 129.51,133.8 128.31,133.2V139.6C129.41,139 130.31,137.8 130.31,136.4Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M126.72,142.79V130.13L122.71,134.08H119.5V138.78H122.71L126.72,142.79Z"
+        android:fillColor="#ffffff"/>
+    <group>
+      <clip-path
+          android:pathData="M126.72,142.79V130.13L122.71,134.08H119.5V138.78H122.71L126.72,142.79Z"/>
+      <clip-path
+          android:pathData="M128.31,131.1V129.5C131.51,130.2 133.91,133.1 133.91,136.5C133.91,139.9 131.51,142.7 128.31,143.5V141.9C130.61,141.2 132.31,139.1 132.31,136.6C132.31,134.1 130.61,131.8 128.31,131.1ZM130.31,136.4C130.31,135 129.51,133.8 128.31,133.2V139.6C129.41,139 130.31,137.8 130.31,136.4Z"
+          android:fillType="evenOdd"/>
+      <path
+          android:pathData="M128.31,131.1H78.31V168.15L113.75,178.94L128.31,131.1ZM128.31,129.5L138.99,80.66L78.31,67.38V129.5H128.31ZM128.31,143.5H78.31V207.54L140.44,192.01L128.31,143.5ZM128.31,141.9L113.75,94.07L78.31,104.86V141.9H128.31ZM128.31,133.2L150.67,88.48L78.31,52.3V133.2H128.31ZM128.31,139.6H78.31V223.83L152.25,183.5L128.31,139.6ZM126.72,130.13H176.73V10.79L91.66,94.5L126.72,130.13ZM126.72,142.79L91.37,178.15L176.73,263.5V142.79H126.72ZM122.71,138.78L158.07,103.43L143.43,88.78H122.71V138.78ZM119.5,138.78H69.5V188.78H119.5V138.78ZM119.5,134.08V84.08H69.5V134.08H119.5ZM122.71,134.08V184.08H143.19L157.78,169.72L122.71,134.08ZM178.31,131.1V129.5H78.31V131.1H178.31ZM117.63,178.35C98.03,174.06 83.91,156.76 83.91,136.5H183.91C183.91,109.44 164.99,86.34 138.99,80.66L117.63,178.35ZM83.91,136.5C83.91,115.15 98.93,99.31 116.18,94.99L140.44,192.01C164.09,186.1 183.91,164.66 183.91,136.5H83.91ZM178.31,143.5V141.9H78.31V143.5H178.31ZM142.87,189.74C164.72,183.09 182.31,162.64 182.31,136.6H82.31C82.31,115.57 96.5,99.32 113.75,94.07L142.87,189.74ZM182.31,136.6C182.31,112.64 166.74,90.53 142.87,83.27L113.75,178.94C94.48,173.07 82.31,155.56 82.31,136.6H182.31ZM180.31,136.4C180.31,115.04 167.88,97.08 150.67,88.48L105.95,177.92C91.14,170.52 80.31,154.96 80.31,136.4H180.31ZM78.31,133.2V139.6H178.31V133.2H78.31ZM152.25,183.5C166.09,175.95 180.31,159.6 180.31,136.4H80.31C80.31,116 92.73,102.06 104.37,95.71L152.25,183.5ZM76.72,130.13V142.79H176.73V130.13H76.72ZM162.08,107.44L158.07,103.43L87.36,174.14L91.37,178.15L162.08,107.44ZM122.71,88.78H119.5V188.78H122.71V88.78ZM169.5,138.78V134.08H69.5V138.78H169.5ZM119.5,184.08H122.71V84.08H119.5V184.08ZM157.78,169.72L161.79,165.77L91.66,94.5L87.65,98.44L157.78,169.72Z"
+          android:fillColor="#ffffff"/>
+    </group>
+    <path
+        android:pathData="M78.71,68.5L78.71,68.5A16,16 0,0 1,94.71 84.5L94.71,84.5A16,16 0,0 1,78.71 100.5L78.71,100.5A16,16 0,0 1,62.71 84.5L62.71,84.5A16,16 0,0 1,78.71 68.5z"
+        android:fillColor="#E8EAED"/>
+    <path
+        android:pathData="M86.26,82.15C86.92,82.15 87.46,81.61 87.46,80.95C87.46,80.29 86.92,79.75 86.26,79.75C85.6,79.75 85.06,80.29 85.06,80.95C85.06,81.61 85.6,82.15 86.26,82.15Z"
+        android:fillColor="#34A853"/>
+    <path
+        android:pathData="M82.66,86.15C83.99,86.15 85.06,85.08 85.06,83.75C85.06,82.43 83.99,81.35 82.66,81.35C81.34,81.35 80.26,82.43 80.26,83.75C80.26,85.08 81.34,86.15 82.66,86.15Z"
+        android:fillColor="#EA4335"/>
+    <path
+        android:pathData="M82.66,92.45C84.21,92.45 85.46,91.2 85.46,89.65C85.46,88.11 84.21,86.85 82.66,86.85C81.11,86.85 79.86,88.11 79.86,89.65C79.86,91.2 81.11,92.45 82.66,92.45Z"
+        android:fillColor="#FBBC04"/>
+    <path
+        android:pathData="M74.76,86.15C77.41,86.15 79.56,84 79.56,81.35C79.56,78.7 77.41,76.55 74.76,76.55C72.11,76.55 69.96,78.7 69.96,81.35C69.96,84 72.11,86.15 74.76,86.15Z"
+        android:fillColor="#4285F4"/>
+    <path
+        android:pathData="M174.71,120.5L174.71,120.5A16,16 0,0 1,190.71 136.5L190.71,136.5A16,16 0,0 1,174.71 152.5L174.71,152.5A16,16 0,0 1,158.71 136.5L158.71,136.5A16,16 0,0 1,174.71 120.5z"
+        android:fillColor="#9F3EBF"/>
+    <path
+        android:pathData="M178.53,130.5H171.03V142.2H178.53V130.5Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M170.23,132.8H167.53V140H170.23V132.8Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M182.23,132.8H179.53V140H182.23V132.8Z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M126.71,172.5L126.71,172.5A16,16 0,0 1,142.71 188.5L142.71,188.5A16,16 0,0 1,126.71 204.5L126.71,204.5A16,16 0,0 1,110.71 188.5L110.71,188.5A16,16 0,0 1,126.71 172.5z"
+        android:fillColor="#DE9834"/>
+    <path
+        android:pathData="M135.71,188.5L133.11,191.1V194.8H129.31L126.71,197.4L124.11,194.8H120.31V191.1L117.71,188.5L120.31,185.9V182.2H124.01L126.61,179.6L129.21,182.2H132.91V185.9L135.71,188.5ZM121.91,188.5C121.91,191.1 124.01,193.3 126.71,193.3C129.31,193.3 131.51,191.2 131.51,188.5C131.51,185.8 129.41,183.7 126.71,183.7C124.11,183.7 121.91,185.8 121.91,188.5Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M127.21,187.9V186.4H126.21V187.9H124.71V188.9H126.21V190.4H127.21V188.9H128.71V187.9H127.21Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M126.71,68.5L126.71,68.5A16,16 0,0 1,142.71 84.5L142.71,84.5A16,16 0,0 1,126.71 100.5L126.71,100.5A16,16 0,0 1,110.71 84.5L110.71,84.5A16,16 0,0 1,126.71 68.5z"
+        android:fillColor="#521BBF"/>
+    <path
+        android:pathData="M128.36,78.51C128.36,79.31 127.66,80.01 126.76,80.01C125.86,80.01 125.16,79.31 125.16,78.51C125.16,77.71 125.86,77.01 126.76,77.01C127.66,76.91 128.36,77.61 128.36,78.51ZM126.76,80.71C128.96,80.71 131.46,80.51 133.46,79.91L133.86,81.41C132.36,81.81 130.66,82.01 129.06,82.21V92.01H127.46V87.51H125.86V92.01H124.36V82.21C122.76,82.11 121.06,81.81 119.56,81.41L119.96,79.91C122.06,80.51 124.46,80.71 126.76,80.71Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M174.71,172.5L174.71,172.5A16,16 0,0 1,190.71 188.5L190.71,188.5A16,16 0,0 1,174.71 204.5L174.71,204.5A16,16 0,0 1,158.71 188.5L158.71,188.5A16,16 0,0 1,174.71 172.5z"
+        android:fillColor="#438947"/>
+    <path
+        android:pathData="M179.11,185.95H178.41V184.45C178.41,182.45 176.81,180.75 174.71,180.75C172.61,180.75 171.01,182.35 171.01,184.45V185.95H170.31C169.51,185.95 168.81,186.65 168.81,187.45V194.75C168.81,195.55 169.51,196.25 170.31,196.25H179.11C179.91,196.25 180.61,195.55 180.61,194.75V187.45C180.61,186.65 179.91,185.95 179.11,185.95ZM174.71,192.55C173.91,192.55 173.21,191.85 173.21,191.05C173.21,190.25 173.91,189.55 174.71,189.55C175.51,189.55 176.21,190.25 176.21,191.05C176.21,191.95 175.51,192.55 174.71,192.55ZM172.41,185.95H176.91V184.45C176.91,183.15 175.91,182.15 174.61,182.15C173.31,182.15 172.31,183.15 172.31,184.45V185.95H172.41Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="M174.71,68.5L174.71,68.5A16,16 0,0 1,190.71 84.5L190.71,84.5A16,16 0,0 1,174.71 100.5L174.71,100.5A16,16 0,0 1,158.71 84.5L158.71,84.5A16,16 0,0 1,174.71 68.5z"
+        android:fillColor="#80868B"/>
+    <path
+        android:pathData="M173.91,77.35H175.51V85.25H173.91V77.35ZM178.21,80.25L179.31,79.15C180.81,80.45 181.81,82.35 181.81,84.55C181.81,88.45 178.61,91.65 174.71,91.65C170.81,91.65 167.61,88.45 167.61,84.55C167.61,82.35 168.61,80.45 170.11,79.15L171.21,80.25C170.01,81.25 169.21,82.85 169.21,84.55C169.21,87.65 171.71,90.15 174.81,90.15C177.91,90.15 180.41,87.65 180.41,84.55C180.31,82.75 179.41,81.25 178.21,80.25Z"
+        android:fillColor="#ffffff"
+        android:fillType="evenOdd"/>
+  </group>
+  <path
+      android:pathData="M62.23,51.69L349.77,51.69A14.5,14.5 0,0 1,364.27 66.19L364.27,236.14A14.5,14.5 0,0 1,349.77 250.64L62.23,250.64A14.5,14.5 0,0 1,47.73 236.14L47.73,66.19A14.5,14.5 0,0 1,62.23 51.69z"
+      android:strokeWidth="3"
+      android:fillColor="#00000000"
+      android:strokeColor="#DADCE0"/>
+  <path
+      android:pathData="M311.45,50.35C311.45,48.98 312.56,47.87 313.92,47.87L322.84,47.87C324.2,47.87 325.32,48.98 325.32,50.35L319.37,51.34L311.45,50.35Z"
+      android:fillColor="#DADCE0"/>
+  <path
+      android:pathData="M263.59,50.35C263.59,48.98 264.7,47.87 266.06,47.87L287.85,47.87C289.22,47.87 290.33,48.98 290.33,50.35L277.45,51.34L263.59,50.35Z"
+      android:fillColor="#DADCE0"/>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_menu.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_menu.xml
deleted file mode 100644
index 79e0e08d..0000000
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_menu.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<vector android:height="48dp" android:viewportHeight="192.0"
-    android:viewportWidth="192.0" android:width="48dp"
-    xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillColor="#34a853" android:pathData="M37.14,173.74l-28.53,-90a14.53,14.53 0,0 1,5 -15.63L87.15,11a14.21,14.21 0,0 1,17.61 0.12l73.81,58.94a14.53,14.53 0,0 1,4.8 15.57l-28.48,88.18A14.32,14.32 0,0 1,141.22 184H50.84A14.33,14.33 0,0 1,37.14 173.74Z"/>
-    <path android:pathData="M137.61,94.07l-17,17 -17,-17 -17,17L70.3,94.72l-17,17L125.66,184h15.56a14.32,14.32 0,0 0,13.67 -10.19l15.25,-47.21Z">
-        <aapt:attr name="android:fillColor">
-            <gradient android:endX="27152.64"
-                android:endY="32745.600000000002"
-                android:startX="20910.72"
-                android:startY="21934.079999999998" android:type="linear">
-                <item android:color="#33263238" android:offset="0.0"/>
-                <item android:color="#11205432" android:offset="0.47"/>
-                <item android:color="#051E6130" android:offset="1.0"/>
-            </gradient>
-        </aapt:attr>
-    </path>
-    <path android:fillAlpha="0.2" android:fillColor="#263238" android:pathData="M50.14,100.11a12,12 0,1 1,11.39 15.77,11.72 11.72,0 0,1 -5,-1.1l-3.41,-3.4ZM129.4,91.88a12,12 0,1 1,-12 12A12,12 0,0 1,129.4 91.88ZM95.4,91.88a12,12 0,1 1,-12 12A12,12 0,0 1,95.42 91.88Z"/>
-    <path android:fillColor="#fff"
-        android:pathData="M61.53,90.88a12,12 0,1 1,-12 12A12,12 0,0 1,61.53 90.88ZM129.41,90.88a12,12 0,1 1,-12 12A12,12 0,0 1,129.41 90.88ZM95.41,90.88a12,12 0,1 1,-12 12A12,12 0,0 1,95.42 90.88Z"
-        android:strokeAlpha="0" android:strokeColor="#000"
-        android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="0.5"/>
-    <path android:fillAlpha="0.2" android:fillColor="#263238" android:pathData="M184,80.91a14.33,14.33 0,0 1,-0.63 4.7l-28.48,88.18A14.33,14.33 0,0 1,141.21 184H50.84a14.33,14.33 0,0 1,-13.7 -10.26l-28.53,-90A14.49,14.49 0,0 1,8 79.11a14.3,14.3 0,0 0,0.61 3.64l28.53,90A14.33,14.33 0,0 0,50.84 183h90.37a14.33,14.33 0,0 0,13.67 -10.19l28.48,-88.18A14.79,14.79 0,0 0,184 80.91Z"/>
-    <path android:fillAlpha="0.2" android:fillColor="#fff" android:pathData="M184,81.89A14.46,14.46 0,0 0,178.57 71L104.76,12.1A14.21,14.21 0,0 0,87.15 12L13.58,69.12A14.5,14.5 0,0 0,8 80.09a14.5,14.5 0,0 1,5.57 -12L87.15,11a14.21,14.21 0,0 1,17.61 0.12L178.57,70A14.48,14.48 0,0 1,184 81.89Z"/>
-    <path android:pathData="M37.14,173.74l-28.53,-90a14.53,14.53 0,0 1,5 -15.63L87.15,11a14.21,14.21 0,0 1,17.61 0.12l73.81,58.94a14.53,14.53 0,0 1,4.8 15.57l-28.48,88.18A14.32,14.32 0,0 1,141.22 184H50.84A14.33,14.33 0,0 1,37.14 173.74Z"/>
-    <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
-        <background android:drawable="@color/colorAccessibilityMenuIcon" />
-        <foreground>
-            <inset
-                android:drawable="@drawable/ic_a11y_menu_round"
-                android:inset="21.88%" />
-        </foreground>
-    </adaptive-icon>
-</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_app.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_app.xml
new file mode 100644
index 0000000..31fe99e1f
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_app.xml
@@ -0,0 +1,8 @@
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@color/colorAccessibilityMenuIcon" />
+    <foreground>
+        <inset
+            android:drawable="@drawable/ic_logo_app_foreground"
+            android:inset="21.88%" />
+    </foreground>
+</adaptive-icon>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_a11y_menu_round.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_app_foreground.xml
similarity index 100%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_a11y_menu_round.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_app_foreground.xml
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
index 76139c6..1d0becd 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
@@ -22,19 +22,28 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
+import android.hardware.display.BrightnessInfo;
 import android.hardware.display.DisplayManager;
+import android.media.AudioManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.view.Display;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 
+import com.android.settingslib.display.BrightnessUtils;
+import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut.ShortcutId;
 import com.android.systemui.accessibility.accessibilitymenu.view.A11yMenuOverlayLayout;
 
+import java.util.List;
+
 /** @hide */
 public class AccessibilityMenuService extends AccessibilityService
         implements View.OnTouchListener {
@@ -42,6 +51,11 @@
 
     private static final long BUFFER_MILLISECONDS_TO_PREVENT_UPDATE_FAILURE = 100L;
 
+    private static final int BRIGHTNESS_UP_INCREMENT_GAMMA =
+            (int) Math.ceil(BrightnessUtils.GAMMA_SPACE_MAX * 0.11f);
+    private static final int BRIGHTNESS_DOWN_INCREMENT_GAMMA =
+            (int) -Math.ceil(BrightnessUtils.GAMMA_SPACE_MAX * 0.11f);
+
     private long mLastTimeTouchedOutside = 0L;
     // Timeout used to ignore the A11y button onClick() when ACTION_OUTSIDE is also received on
     // clicking on the A11y button.
@@ -51,6 +65,8 @@
 
     private static boolean sInitialized = false;
 
+    private AudioManager mAudioManager;
+
     // TODO(b/136716947): Support multi-display once a11y framework side is ready.
     private DisplayManager mDisplayManager;
     final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() {
@@ -94,6 +110,7 @@
     @Override
     public void onCreate() {
         super.onCreate();
+        setTheme(R.style.ServiceTheme);
 
         getAccessibilityButtonController().registerAccessibilityButtonCallback(
                 new AccessibilityButtonController.AccessibilityButtonCallback() {
@@ -140,6 +157,7 @@
 
         mDisplayManager = getSystemService(DisplayManager.class);
         mDisplayManager.registerDisplayListener(mDisplayListener, null);
+        mAudioManager = getSystemService(AudioManager.class);
 
         sInitialized = true;
     }
@@ -170,9 +188,100 @@
      * @param view the shortcut button being clicked.
      */
     public void handleClick(View view) {
+        // Shortcuts are repeatable in a11y menu rather than unique, so use tag ID to handle.
+        int viewTag = (int) view.getTag();
+
+        if (viewTag == ShortcutId.ID_ASSISTANT_VALUE.ordinal()) {
+            // Always restart the voice command activity, so that the UI is reloaded.
+            startActivityIfIntentIsSafe(
+                    new Intent(Intent.ACTION_VOICE_COMMAND),
+                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        } else if (viewTag == ShortcutId.ID_A11YSETTING_VALUE.ordinal()) {
+            startActivityIfIntentIsSafe(
+                    new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS),
+                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        } else if (viewTag == ShortcutId.ID_POWER_VALUE.ordinal()) {
+            performGlobalAction(GLOBAL_ACTION_POWER_DIALOG);
+        } else if (viewTag == ShortcutId.ID_RECENT_VALUE.ordinal()) {
+            performGlobalAction(GLOBAL_ACTION_RECENTS);
+        } else if (viewTag == ShortcutId.ID_LOCKSCREEN_VALUE.ordinal()) {
+            performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN);
+        } else if (viewTag == ShortcutId.ID_QUICKSETTING_VALUE.ordinal()) {
+            performGlobalAction(GLOBAL_ACTION_QUICK_SETTINGS);
+        } else if (viewTag == ShortcutId.ID_NOTIFICATION_VALUE.ordinal()) {
+            performGlobalAction(GLOBAL_ACTION_NOTIFICATIONS);
+        } else if (viewTag == ShortcutId.ID_SCREENSHOT_VALUE.ordinal()) {
+            performGlobalAction(GLOBAL_ACTION_TAKE_SCREENSHOT);
+        } else if (viewTag == ShortcutId.ID_BRIGHTNESS_UP_VALUE.ordinal()) {
+            adjustBrightness(BRIGHTNESS_UP_INCREMENT_GAMMA);
+            return;
+        } else if (viewTag == ShortcutId.ID_BRIGHTNESS_DOWN_VALUE.ordinal()) {
+            adjustBrightness(BRIGHTNESS_DOWN_INCREMENT_GAMMA);
+            return;
+        } else if (viewTag == ShortcutId.ID_VOLUME_UP_VALUE.ordinal()) {
+            adjustVolume(AudioManager.ADJUST_RAISE);
+            return;
+        } else if (viewTag == ShortcutId.ID_VOLUME_DOWN_VALUE.ordinal()) {
+            adjustVolume(AudioManager.ADJUST_LOWER);
+            return;
+        }
+
         mA11yMenuLayout.hideMenu();
     }
 
+    /**
+     * Adjusts brightness using the same logic and utils class as the SystemUI brightness slider.
+     *
+     * @see BrightnessUtils
+     * @see com.android.systemui.settings.brightness.BrightnessController
+     * @param increment The increment amount in gamma-space
+     */
+    private void adjustBrightness(int increment) {
+        BrightnessInfo info = getDisplay().getBrightnessInfo();
+        int gamma = BrightnessUtils.convertLinearToGammaFloat(
+                info.brightness,
+                info.brightnessMinimum,
+                info.brightnessMaximum
+        );
+        gamma = Math.max(
+                BrightnessUtils.GAMMA_SPACE_MIN,
+                Math.min(BrightnessUtils.GAMMA_SPACE_MAX, gamma + increment));
+
+        float brightness = BrightnessUtils.convertGammaToLinearFloat(
+                gamma,
+                info.brightnessMinimum,
+                info.brightnessMaximum
+        );
+        mDisplayManager.setTemporaryBrightness(getDisplayId(), brightness);
+        mDisplayManager.setBrightness(getDisplayId(), brightness);
+        mA11yMenuLayout.showSnackbar(
+                getString(R.string.brightness_percentage_label,
+                        (gamma / (BrightnessUtils.GAMMA_SPACE_MAX / 100))));
+    }
+
+    private void adjustVolume(int direction) {
+        mAudioManager.adjustStreamVolume(
+                AudioManager.STREAM_MUSIC, direction,
+                AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
+        final int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        final int volume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+        mA11yMenuLayout.showSnackbar(
+                getString(
+                        R.string.music_volume_percentage_label,
+                        (int) (100.0 / maxVolume * volume))
+        );
+    }
+
+    private void startActivityIfIntentIsSafe(Intent intent, int flag) {
+        PackageManager packageManager = getPackageManager();
+        List<ResolveInfo> activities =
+                packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+        if (!activities.isEmpty()) {
+            intent.setFlags(flag);
+            startActivity(intent);
+        }
+    }
+
     @Override
     public void onInterrupt() {
     }
diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp
index 8acc2f8..978ab5d 100644
--- a/packages/SystemUI/animation/Android.bp
+++ b/packages/SystemUI/animation/Android.bp
@@ -35,7 +35,6 @@
     ],
 
     static_libs: [
-        "PluginCoreLib",
         "androidx.core_core-animation-nodeps",
         "androidx.core_core-ktx",
         "androidx.annotation_annotation",
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index b8d78fb..5aa7769 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -304,10 +304,16 @@
     ) {
         val view =
             openedDialogs.firstOrNull { it.dialog == animateFrom }?.dialogContentWithBackground
-                ?: throw IllegalStateException(
-                    "The animateFrom dialog was not animated using " +
-                        "DialogLaunchAnimator.showFrom(View|Dialog)"
-                )
+        if (view == null) {
+            Log.w(
+                TAG,
+                "Showing dialog $dialog normally as the dialog it is shown from was not shown " +
+                    "using DialogLaunchAnimator"
+            )
+            dialog.show()
+            return
+        }
+
         showFromView(
             dialog,
             view,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
index 7897934..442c6fa 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
@@ -66,11 +66,28 @@
     fun isPlaying(): Boolean = animator.isRunning
 
     private fun applyConfigToShader() {
-        rippleShader.setCenter(config.centerX, config.centerY)
-        rippleShader.setMaxSize(config.maxWidth, config.maxHeight)
-        rippleShader.rippleFill = config.shouldFillRipple
-        rippleShader.pixelDensity = config.pixelDensity
-        rippleShader.color = ColorUtils.setAlphaComponent(config.color, config.opacity)
-        rippleShader.sparkleStrength = config.sparkleStrength
+        with(rippleShader) {
+            setCenter(config.centerX, config.centerY)
+            setMaxSize(config.maxWidth, config.maxHeight)
+            pixelDensity = config.pixelDensity
+            color = ColorUtils.setAlphaComponent(config.color, config.opacity)
+            sparkleStrength = config.sparkleStrength
+
+            assignFadeParams(baseRingFadeParams, config.baseRingFadeParams)
+            assignFadeParams(sparkleRingFadeParams, config.sparkleRingFadeParams)
+            assignFadeParams(centerFillFadeParams, config.centerFillFadeParams)
+        }
+    }
+
+    private fun assignFadeParams(
+        destFadeParams: RippleShader.FadeParams,
+        srcFadeParams: RippleShader.FadeParams?
+    ) {
+        srcFadeParams?.let {
+            destFadeParams.fadeInStart = it.fadeInStart
+            destFadeParams.fadeInEnd = it.fadeInEnd
+            destFadeParams.fadeOutStart = it.fadeOutStart
+            destFadeParams.fadeOutEnd = it.fadeOutEnd
+        }
     }
 }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
index 773ac55..1786d13 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
@@ -20,8 +20,11 @@
     val pixelDensity: Float = 1f,
     var color: Int = Color.WHITE,
     val opacity: Int = RIPPLE_DEFAULT_ALPHA,
-    val shouldFillRipple: Boolean = false,
     val sparkleStrength: Float = RIPPLE_SPARKLE_STRENGTH,
+    // Null means it uses default fade parameter values.
+    val baseRingFadeParams: RippleShader.FadeParams? = null,
+    val sparkleRingFadeParams: RippleShader.FadeParams? = null,
+    val centerFillFadeParams: RippleShader.FadeParams? = null,
     val shouldDistort: Boolean = true
 ) {
     companion object {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index 4322d53..61ca90a 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -44,6 +44,20 @@
     }
     // language=AGSL
     companion object {
+        // Default fade in/ out values. The value range is [0,1].
+        const val DEFAULT_FADE_IN_START = 0f
+        const val DEFAULT_FADE_OUT_END = 1f
+
+        const val DEFAULT_BASE_RING_FADE_IN_END = 0.1f
+        const val DEFAULT_BASE_RING_FADE_OUT_START = 0.3f
+
+        const val DEFAULT_SPARKLE_RING_FADE_IN_END = 0.1f
+        const val DEFAULT_SPARKLE_RING_FADE_OUT_START = 0.4f
+
+        const val DEFAULT_CENTER_FILL_FADE_IN_END = 0f
+        const val DEFAULT_CENTER_FILL_FADE_OUT_START = 0f
+        const val DEFAULT_CENTER_FILL_FADE_OUT_END = 0.6f
+
         private const val SHADER_UNIFORMS =
             """
             uniform vec2 in_center;
@@ -68,7 +82,7 @@
                 vec2 p_distorted = distort(p, in_time, in_distort_radial, in_distort_xy);
                 float radius = in_size.x * 0.5;
                 float sparkleRing = soften(circleRing(p_distorted-in_center, radius), in_blur);
-                float inside = soften(sdCircle(p_distorted-in_center, radius * 1.2), in_blur);
+                float inside = soften(sdCircle(p_distorted-in_center, radius * 1.25), in_blur);
                 float sparkle = sparkles(p - mod(p, in_pixelDensity * 0.8), in_time * 0.00175)
                     * (1.-sparkleRing) * in_fadeSparkle;
 
@@ -143,11 +157,26 @@
             }
 
         private fun subProgress(start: Float, end: Float, progress: Float): Float {
+            // Avoid division by 0.
+            if (start == end) {
+                // If start and end are the same and progress has exceeded the start/ end point,
+                // treat it as 1, otherwise 0.
+                return if (progress > start) 1f else 0f
+            }
+
             val min = Math.min(start, end)
             val max = Math.max(start, end)
             val sub = Math.min(Math.max(progress, min), max)
             return (sub - start) / (end - start)
         }
+
+        private fun getFade(fadeParams: FadeParams, rawProgress: Float): Float {
+            val fadeIn = subProgress(fadeParams.fadeInStart, fadeParams.fadeInEnd, rawProgress)
+            val fadeOut =
+                1f - subProgress(fadeParams.fadeOutStart, fadeParams.fadeOutEnd, rawProgress)
+
+            return Math.min(fadeIn, fadeOut)
+        }
     }
 
     /** Sets the center position of the ripple. */
@@ -172,17 +201,9 @@
             field = value
             progress = Interpolators.STANDARD.getInterpolation(value)
 
-            val fadeIn = subProgress(0f, 0.1f, value)
-            val fadeOutNoise = subProgress(0.4f, 1f, value)
-            var fadeOutRipple = 0f
-            var fadeFill = 0f
-            if (!rippleFill) {
-                fadeFill = subProgress(0f, 0.6f, value)
-                fadeOutRipple = subProgress(0.3f, 1f, value)
-            }
-            setFloatUniform("in_fadeSparkle", Math.min(fadeIn, 1 - fadeOutNoise))
-            setFloatUniform("in_fadeFill", 1 - fadeFill)
-            setFloatUniform("in_fadeRing", Math.min(fadeIn, 1 - fadeOutRipple))
+            setFloatUniform("in_fadeSparkle", getFade(sparkleRingFadeParams, value))
+            setFloatUniform("in_fadeRing", getFade(baseRingFadeParams, value))
+            setFloatUniform("in_fadeFill", getFade(centerFillFadeParams, value))
         }
 
     /** Progress with Standard easing curve applied. */
@@ -232,21 +253,93 @@
             setFloatUniform("in_distort_xy", 75 * value)
         }
 
+    /**
+     * Pixel density of the screen that the effects are rendered to.
+     *
+     * <p>This value should come from [resources.displayMetrics.density].
+     */
     var pixelDensity: Float = 1.0f
         set(value) {
             field = value
             setFloatUniform("in_pixelDensity", value)
         }
 
-    /**
-     * True if the ripple should stayed filled in as it expands to give a filled-in circle effect.
-     * False for a ring effect.
-     */
-    var rippleFill: Boolean = false
-
     var currentWidth: Float = 0f
         private set
 
     var currentHeight: Float = 0f
         private set
+
+    /** Parameters that are used to fade in/ out of the sparkle ring. */
+    val sparkleRingFadeParams =
+        FadeParams(
+            DEFAULT_FADE_IN_START,
+            DEFAULT_SPARKLE_RING_FADE_IN_END,
+            DEFAULT_SPARKLE_RING_FADE_OUT_START,
+            DEFAULT_FADE_OUT_END
+        )
+
+    /**
+     * Parameters that are used to fade in/ out of the base ring.
+     *
+     * <p>Note that the shader draws the sparkle ring on top of the base ring.
+     */
+    val baseRingFadeParams =
+        FadeParams(
+            DEFAULT_FADE_IN_START,
+            DEFAULT_BASE_RING_FADE_IN_END,
+            DEFAULT_BASE_RING_FADE_OUT_START,
+            DEFAULT_FADE_OUT_END
+        )
+
+    /** Parameters that are used to fade in/ out of the center fill. */
+    val centerFillFadeParams =
+        FadeParams(
+            DEFAULT_FADE_IN_START,
+            DEFAULT_CENTER_FILL_FADE_IN_END,
+            DEFAULT_CENTER_FILL_FADE_OUT_START,
+            DEFAULT_CENTER_FILL_FADE_OUT_END
+        )
+
+    /**
+     * Parameters used for fade in and outs of the ripple.
+     *
+     * <p>Note that all the fade in/ outs are "linear" progression.
+     * ```
+     *          (opacity)
+     *          1
+     *          │
+     * maxAlpha ←       ――――――――――――
+     *          │      /            \
+     *          │     /              \
+     * minAlpha ←――――/                \―――― (alpha change)
+     *          │
+     *          │
+     *          0 ―――↑―――↑―――――――――↑―――↑――――1 (progress)
+     *               fadeIn        fadeOut
+     *               Start & End   Start & End
+     * ```
+     * <p>If no fade in/ out is needed, set [fadeInStart] and [fadeInEnd] to 0; [fadeOutStart] and
+     * [fadeOutEnd] to 1.
+     */
+    data class FadeParams(
+        /**
+         * The starting point of the fade out which ends at [fadeInEnd], given that the animation
+         * goes from 0 to 1.
+         */
+        var fadeInStart: Float = DEFAULT_FADE_IN_START,
+        /**
+         * The endpoint of the fade in when the fade in starts at [fadeInStart], given that the
+         * animation goes from 0 to 1.
+         */
+        var fadeInEnd: Float,
+        /**
+         * The starting point of the fade out which ends at 1, given that the animation goes from 0
+         * to 1.
+         */
+        var fadeOutStart: Float,
+
+        /** The endpoint of the fade out, given that the animation goes from 0 to 1. */
+        var fadeOutEnd: Float = DEFAULT_FADE_OUT_END,
+    )
 }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
index bc4796a..3c9328c 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
@@ -117,15 +117,6 @@
         rippleShader.color = ColorUtils.setAlphaComponent(color, alpha)
     }
 
-    /**
-     * Set whether the ripple should remain filled as the ripple expands.
-     *
-     * See [RippleShader.rippleFill].
-     */
-    fun setRippleFill(rippleFill: Boolean) {
-        rippleShader.rippleFill = rippleFill
-    }
-
     /** Set the intensity of the sparkles. */
     fun setSparkleStrength(strength: Float) {
         rippleShader.sparkleStrength = strength
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 59b4848..a523cf1 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
@@ -21,15 +21,14 @@
 import android.provider.Settings
 import android.util.Log
 import androidx.annotation.OpenForTesting
-import com.android.internal.annotations.Keep
 import com.android.systemui.plugins.ClockController
 import com.android.systemui.plugins.ClockId
 import com.android.systemui.plugins.ClockMetadata
 import com.android.systemui.plugins.ClockProvider
 import com.android.systemui.plugins.ClockProviderPlugin
+import com.android.systemui.plugins.ClockSettings
 import com.android.systemui.plugins.PluginListener
 import com.android.systemui.plugins.PluginManager
-import org.json.JSONObject
 
 private val TAG = ClockRegistry::class.simpleName
 private const val DEBUG = true
@@ -64,34 +63,54 @@
             disconnectClocks(plugin)
     }
 
-    open var currentClockId: ClockId
+    open var settings: ClockSettings?
         get() {
-            return try {
+            try {
                 val json = Settings.Secure.getString(
                     context.contentResolver,
                     Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE
                 )
                 if (json == null || json.isEmpty()) {
-                    return fallbackClockId
+                    return null
                 }
-                ClockSetting.deserialize(json).clockId
+                return ClockSettings.deserialize(json)
             } catch (ex: Exception) {
-                Log.e(TAG, "Failed to parse clock setting", ex)
-                fallbackClockId
+                Log.e(TAG, "Failed to parse clock settings", ex)
+                return null
             }
         }
-        set(value) {
+        protected set(value) {
             try {
-                val json = ClockSetting.serialize(ClockSetting(value, System.currentTimeMillis()))
+                val json = if (value != null) {
+                    value._applied_timestamp = System.currentTimeMillis()
+                    ClockSettings.serialize(value)
+                } else {
+                    ""
+                }
+
                 Settings.Secure.putString(
                     context.contentResolver,
                     Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, json
                 )
             } catch (ex: Exception) {
-                Log.e(TAG, "Failed to set clock setting", ex)
+                Log.e(TAG, "Failed to set clock settings", ex)
             }
         }
 
+    private fun mutateSetting(mutator: (ClockSettings) -> Unit) {
+        val settings = this.settings ?: ClockSettings()
+        mutator(settings)
+        this.settings = settings
+    }
+
+    var currentClockId: ClockId
+        get() = settings?.clockId ?: fallbackClockId
+        set(value) { mutateSetting { it.clockId = value } }
+
+    var seedColor: Int?
+        get() = settings?.seedColor
+        set(value) { mutateSetting { it.seedColor = value } }
+
     init {
         connectClocks(defaultClockProvider)
         if (!availableClocks.containsKey(DEFAULT_CLOCK_ID)) {
@@ -194,36 +213,16 @@
         return createClock(DEFAULT_CLOCK_ID)!!
     }
 
-    private fun createClock(clockId: ClockId): ClockController? =
-        availableClocks[clockId]?.provider?.createClock(clockId)
+    private fun createClock(clockId: ClockId): ClockController? {
+        val settings = this.settings ?: ClockSettings()
+        if (clockId != settings.clockId) {
+            settings.clockId = clockId
+        }
+        return availableClocks[clockId]?.provider?.createClock(settings)
+    }
 
     private data class ClockInfo(
         val metadata: ClockMetadata,
         val provider: ClockProvider
     )
-
-    @Keep
-    data class ClockSetting(
-        val clockId: ClockId,
-        val _applied_timestamp: Long?
-    ) {
-        companion object {
-            private val KEY_CLOCK_ID = "clockId"
-            private val KEY_TIMESTAMP = "_applied_timestamp"
-
-            fun serialize(setting: ClockSetting): String {
-                return JSONObject()
-                    .put(KEY_CLOCK_ID, setting.clockId)
-                    .put(KEY_TIMESTAMP, setting._applied_timestamp)
-                    .toString()
-            }
-
-            fun deserialize(jsonStr: String): ClockSetting {
-                val json = JSONObject(jsonStr)
-                return ClockSetting(
-                    json.getString(KEY_CLOCK_ID),
-                    if (!json.isNull(KEY_TIMESTAMP)) json.getLong(KEY_TIMESTAMP) else null)
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 7645dec..2a40f5c 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -29,6 +29,7 @@
 import com.android.systemui.plugins.ClockEvents
 import com.android.systemui.plugins.ClockFaceController
 import com.android.systemui.plugins.ClockFaceEvents
+import com.android.systemui.plugins.ClockSettings
 import com.android.systemui.plugins.log.LogBuffer
 import java.io.PrintWriter
 import java.util.Locale
@@ -46,6 +47,7 @@
     ctx: Context,
     private val layoutInflater: LayoutInflater,
     private val resources: Resources,
+    private val settings: ClockSettings?,
 ) : ClockController {
     override val smallClock: DefaultClockFaceController
     override val largeClock: LargeClockFaceController
@@ -66,12 +68,14 @@
         smallClock =
             DefaultClockFaceController(
                 layoutInflater.inflate(R.layout.clock_default_small, parent, false)
-                    as AnimatableClockView
+                    as AnimatableClockView,
+                settings?.seedColor
             )
         largeClock =
             LargeClockFaceController(
                 layoutInflater.inflate(R.layout.clock_default_large, parent, false)
-                    as AnimatableClockView
+                    as AnimatableClockView,
+                settings?.seedColor
             )
         clocks = listOf(smallClock.view, largeClock.view)
 
@@ -85,11 +89,13 @@
         animations = DefaultClockAnimations(dozeFraction, foldFraction)
         events.onColorPaletteChanged(resources)
         events.onTimeZoneChanged(TimeZone.getDefault())
-        events.onTimeTick()
+        smallClock.events.onTimeTick()
+        largeClock.events.onTimeTick()
     }
 
     open inner class DefaultClockFaceController(
         override val view: AnimatableClockView,
+        val seedColor: Int?,
     ) : ClockFaceController {
 
         // MAGENTA is a placeholder, and will be assigned correctly in initialize
@@ -104,11 +110,16 @@
             }
 
         init {
+            if (seedColor != null) {
+                currentColor = seedColor
+            }
             view.setColors(currentColor, currentColor)
         }
 
         override val events =
             object : ClockFaceEvents {
+                override fun onTimeTick() = view.refreshTime()
+
                 override fun onRegionDarknessChanged(isRegionDark: Boolean) {
                     this@DefaultClockFaceController.isRegionDark = isRegionDark
                     updateColor()
@@ -129,7 +140,9 @@
 
         fun updateColor() {
             val color =
-                if (isRegionDark) {
+                if (seedColor != null) {
+                    seedColor
+                } else if (isRegionDark) {
                     resources.getColor(android.R.color.system_accent1_100)
                 } else {
                     resources.getColor(android.R.color.system_accent2_600)
@@ -149,7 +162,8 @@
 
     inner class LargeClockFaceController(
         view: AnimatableClockView,
-    ) : DefaultClockFaceController(view) {
+        seedColor: Int?,
+    ) : DefaultClockFaceController(view, seedColor) {
         override fun recomputePadding(targetRegion: Rect?) {
             // We center the view within the targetRegion instead of within the parent
             // view by computing the difference and adding that to the padding.
@@ -169,8 +183,6 @@
     }
 
     inner class DefaultClockEvents : ClockEvents {
-        override fun onTimeTick() = clocks.forEach { it.refreshTime() }
-
         override fun onTimeFormatChanged(is24Hr: Boolean) =
             clocks.forEach { it.refreshFormat(is24Hr) }
 
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index 4c0504b..0fd1b49 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.plugins.ClockId
 import com.android.systemui.plugins.ClockMetadata
 import com.android.systemui.plugins.ClockProvider
+import com.android.systemui.plugins.ClockSettings
 
 private val TAG = DefaultClockProvider::class.simpleName
 const val DEFAULT_CLOCK_NAME = "Default Clock"
@@ -36,12 +37,12 @@
     override fun getClocks(): List<ClockMetadata> =
         listOf(ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME))
 
-    override fun createClock(id: ClockId): ClockController {
-        if (id != DEFAULT_CLOCK_ID) {
-            throw IllegalArgumentException("$id is unsupported by $TAG")
+    override fun createClock(settings: ClockSettings): ClockController {
+        if (settings.clockId != DEFAULT_CLOCK_ID) {
+            throw IllegalArgumentException("${settings.clockId} is unsupported by $TAG")
         }
 
-        return DefaultClockController(ctx, layoutInflater, resources)
+        return DefaultClockController(ctx, layoutInflater, resources, settings)
     }
 
     override fun getClockThumbnail(id: ClockId): Drawable? {
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 e4e9c46..c120876 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
@@ -181,6 +181,9 @@
         /** Flag denoting whether the Wallpaper preview should use the full screen UI. */
         const val FLAG_NAME_WALLPAPER_FULLSCREEN_PREVIEW = "wallpaper_fullscreen_preview"
 
+        /** Flag denoting whether the Monochromatic Theme is enabled. */
+        const val FLAG_NAME_MONOCHROMATIC_THEME = "is_monochromatic_theme_enabled"
+
         object Columns {
             /** String. Unique ID for the flag. */
             const val NAME = "name"
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/README.md b/packages/SystemUI/monet/src/com/android/systemui/monet/README.md
new file mode 100644
index 0000000..e4818f9
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/README.md
@@ -0,0 +1,26 @@
+Subpackages, i.e. folders, in this directory have their source of truth in the internal Google
+source code repository.
+
+The code is manually copied because:
+
+- Alternatives are automatically syncing Material Color Utilities from the internal Google source
+  repository, or GitHub.
+- Having Android's core automatically taking updates from code that changes regularly, and can
+  easily affect design, is undesirable.
+
+To update the code:
+
+1. Copy Material Color Utilities (libmonet internally) from the internal Google source repository to
+   this directory.
+2. Replace package definitions. Use Find and Replace in directory, replace
+   com.google.ux.material.libmonet with com.android.systemui.monet.
+3. Remove @CanIgnoreReturnValue and @CheckReturnValue, both usage and imports. Currently only in
+   Scheme.java. Chose removal because only Android /external libraries depend on the library with
+   these annotations.
+4. Copy tests for Material Color Utilities to
+   frameworks/base/packages/SystemUI/tests/src/com/android/systemui/monet/
+5. Remove HctRoundTripTest (~3 minutes to run) and QuantizerCelebiTest (depends on internal source
+   repository code for handling images)
+6. Reformat regular and test code to Android bracing/spacing style.
+   In Android Studio, right click on the package, and choose Reformat Code.
+7. Change tests to subclass SysuiTestCase and use an annotation such as @SmallTest / @MediumTest.
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/blend/Blend.java b/packages/SystemUI/monet/src/com/android/systemui/monet/blend/Blend.java
new file mode 100644
index 0000000..927417a
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/blend/Blend.java
@@ -0,0 +1,92 @@
+/*
+ * 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.monet.blend;
+
+import com.android.systemui.monet.hct.Cam16;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.utils.ColorUtils;
+import com.android.systemui.monet.utils.MathUtils;
+
+/** Functions for blending in HCT and CAM16. */
+public class Blend {
+    private Blend() {
+    }
+
+    /**
+     * Blend the design color's HCT hue towards the key color's HCT hue, in a way that leaves the
+     * original color recognizable and recognizably shifted towards the key color.
+     *
+     * @param designColor ARGB representation of an arbitrary color.
+     * @param sourceColor ARGB representation of the main theme color.
+     * @return The design color with a hue shifted towards the system's color, a slightly
+     * warmer/cooler variant of the design color's hue.
+     */
+    public static int harmonize(int designColor, int sourceColor) {
+        Hct fromHct = Hct.fromInt(designColor);
+        Hct toHct = Hct.fromInt(sourceColor);
+        double differenceDegrees = MathUtils.differenceDegrees(fromHct.getHue(), toHct.getHue());
+        double rotationDegrees = Math.min(differenceDegrees * 0.5, 15.0);
+        double outputHue =
+                MathUtils.sanitizeDegreesDouble(
+                        fromHct.getHue()
+                                + rotationDegrees * MathUtils.rotationDirection(fromHct.getHue(),
+                                toHct.getHue()));
+        return Hct.from(outputHue, fromHct.getChroma(), fromHct.getTone()).toInt();
+    }
+
+    /**
+     * Blends hue from one color into another. The chroma and tone of the original color are
+     * maintained.
+     *
+     * @param from   ARGB representation of color
+     * @param to     ARGB representation of color
+     * @param amount how much blending to perform; 0.0 >= and <= 1.0
+     * @return from, with a hue blended towards to. Chroma and tone are constant.
+     */
+    public static int hctHue(int from, int to, double amount) {
+        int ucs = cam16Ucs(from, to, amount);
+        Cam16 ucsCam = Cam16.fromInt(ucs);
+        Cam16 fromCam = Cam16.fromInt(from);
+        Hct blended = Hct.from(ucsCam.getHue(), fromCam.getChroma(),
+                ColorUtils.lstarFromArgb(from));
+        return blended.toInt();
+    }
+
+    /**
+     * Blend in CAM16-UCS space.
+     *
+     * @param from   ARGB representation of color
+     * @param to     ARGB representation of color
+     * @param amount how much blending to perform; 0.0 >= and <= 1.0
+     * @return from, blended towards to. Hue, chroma, and tone will change.
+     */
+    public static int cam16Ucs(int from, int to, double amount) {
+        Cam16 fromCam = Cam16.fromInt(from);
+        Cam16 toCam = Cam16.fromInt(to);
+        double fromJ = fromCam.getJstar();
+        double fromA = fromCam.getAstar();
+        double fromB = fromCam.getBstar();
+        double toJ = toCam.getJstar();
+        double toA = toCam.getAstar();
+        double toB = toCam.getBstar();
+        double jstar = fromJ + (toJ - fromJ) * amount;
+        double astar = fromA + (toA - fromA) * amount;
+        double bstar = fromB + (toB - fromB) * amount;
+        return Cam16.fromUcs(jstar, astar, bstar).toInt();
+    }
+}
+
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/contrast/Contrast.java b/packages/SystemUI/monet/src/com/android/systemui/monet/contrast/Contrast.java
new file mode 100644
index 0000000..ada8ced
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/contrast/Contrast.java
@@ -0,0 +1,215 @@
+/*
+ * 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.monet.contrast;
+
+
+import static java.lang.Math.max;
+
+import com.android.systemui.monet.utils.ColorUtils;
+
+/**
+ * Color science for contrast utilities.
+ *
+ * <p>Utility methods for calculating contrast given two colors, or calculating a color given one
+ * color and a contrast ratio.
+ *
+ * <p>Contrast ratio is calculated using XYZ's Y. When linearized to match human perception, Y
+ * becomes HCT's tone and L*a*b*'s' L*.
+ */
+public final class Contrast {
+    // The minimum contrast ratio of two colors.
+    // Contrast ratio equation = lighter + 5 / darker + 5, if lighter == darker, ratio == 1.
+    public static final double RATIO_MIN = 1.0;
+
+    // The maximum contrast ratio of two colors.
+    // Contrast ratio equation = lighter + 5 / darker + 5. Lighter and darker scale from 0 to 100.
+    // If lighter == 100, darker = 0, ratio == 21.
+    public static final double RATIO_MAX = 21.0;
+    public static final double RATIO_30 = 3.0;
+    public static final double RATIO_45 = 4.5;
+    public static final double RATIO_70 = 7.0;
+
+    // Given a color and a contrast ratio to reach, the luminance of a color that reaches that ratio
+    // with the color can be calculated. However, that luminance may not contrast as desired, i.e.
+    // the contrast ratio of the input color and the returned luminance may not reach the contrast
+    // ratio asked for.
+    //
+    // When the desired contrast ratio and the result contrast ratio differ by more than this
+    // amount, an error value should be returned, or the method should be documented as 'unsafe',
+    // meaning, it will return a valid luminance but that luminance may not meet the requested
+    // contrast ratio.
+    //
+    // 0.04 selected because it ensures the resulting ratio rounds to the same tenth.
+    private static final double CONTRAST_RATIO_EPSILON = 0.04;
+
+    // Color spaces that measure luminance, such as Y in XYZ, L* in L*a*b*, or T in HCT, are
+    // known as perceptually accurate color spaces.
+    //
+    // To be displayed, they must gamut map to a "display space", one that has a defined limit on
+    // the number of colors. Display spaces include sRGB, more commonly understood as RGB/HSL/HSV.
+    //
+    // Gamut mapping is undefined and not defined by the color space. Any gamut mapping algorithm
+    // must choose how to sacrifice accuracy in hue, saturation, and/or lightness.
+    //
+    // A principled solution is to maintain lightness, thus maintaining contrast/a11y, maintain hue,
+    // thus maintaining aesthetic intent, and reduce chroma until the color is in gamut.
+    //
+    // HCT chooses this solution, but, that doesn't mean it will _exactly_ matched desired
+    // lightness, if only because RGB is quantized: RGB is expressed as a set of integers: there may
+    // be an RGB color with, for example, 47.892 lightness, but not 47.891.
+    //
+    // To allow for this inherent incompatibility between perceptually accurate color spaces and
+    // display color spaces, methods that take a contrast ratio and luminance, and return a
+    // luminance that reaches that contrast ratio for the input luminance, purposefully
+    // darken/lighten their result such that the desired contrast ratio will be reached even if
+    // inaccuracy is introduced.
+    //
+    // 0.4 is generous, ex. HCT requires much less delta. It was chosen because it provides a rough
+    // guarantee that as long as a percetual color space gamut maps lightness such that the
+    // resulting lightness rounds to the same as the requested, the desired contrast ratio will be
+    // reached.
+    private static final double LUMINANCE_GAMUT_MAP_TOLERANCE = 0.4;
+
+    private Contrast() {
+    }
+
+    /**
+     * Contrast ratio is a measure of legibility, its used to compare the lightness of two colors.
+     * This method is used commonly in industry due to its use by WCAG.
+     *
+     * <p>To compare lightness, the colors are expressed in the XYZ color space, where Y is
+     * lightness,
+     * also known as relative luminance.
+     *
+     * <p>The equation is ratio = lighter Y + 5 / darker Y + 5.
+     */
+    public static double ratioOfYs(double y1, double y2) {
+        final double lighter = max(y1, y2);
+        final double darker = (lighter == y2) ? y1 : y2;
+        return (lighter + 5.0) / (darker + 5.0);
+    }
+
+    /**
+     * Contrast ratio of two tones. T in HCT, L* in L*a*b*. Also known as luminance or perpectual
+     * luminance.
+     *
+     * <p>Contrast ratio is defined using Y in XYZ, relative luminance. However, relative luminance
+     * is linear to number of photons, not to perception of lightness. Perceptual luminance, L* in
+     * L*a*b*, T in HCT, is. Designers prefer color spaces with perceptual luminance since they're
+     * accurate to the eye.
+     *
+     * <p>Y and L* are pure functions of each other, so it possible to use perceptually accurate
+     * color spaces, and measure contrast, and measure contrast in a much more understandable way:
+     * instead of a ratio, a linear difference. This allows a designer to determine what they need
+     * to adjust a color's lightness to in order to reach their desired contrast, instead of
+     * guessing & checking with hex codes.
+     */
+    public static double ratioOfTones(double t1, double t2) {
+        return ratioOfYs(ColorUtils.yFromLstar(t1), ColorUtils.yFromLstar(t2));
+    }
+
+    /**
+     * Returns T in HCT, L* in L*a*b* >= tone parameter that ensures ratio with input T/L*. Returns
+     * -1 if ratio cannot be achieved.
+     *
+     * @param tone  Tone return value must contrast with.
+     * @param ratio Desired contrast ratio of return value and tone parameter.
+     */
+    public static double lighter(double tone, double ratio) {
+        if (tone < 0.0 || tone > 100.0) {
+            return -1.0;
+        }
+        // Invert the contrast ratio equation to determine lighter Y given a ratio and darker Y.
+        final double darkY = ColorUtils.yFromLstar(tone);
+        final double lightY = ratio * (darkY + 5.0) - 5.0;
+        if (lightY < 0.0 || lightY > 100.0) {
+            return -1.0;
+        }
+        final double realContrast = ratioOfYs(lightY, darkY);
+        final double delta = Math.abs(realContrast - ratio);
+        if (realContrast < ratio && delta > CONTRAST_RATIO_EPSILON) {
+            return -1.0;
+        }
+
+        final double returnValue = ColorUtils.lstarFromY(lightY) + LUMINANCE_GAMUT_MAP_TOLERANCE;
+        // NOMUTANTS--important validation step; functions it is calling may change implementation.
+        if (returnValue < 0 || returnValue > 100) {
+            return -1.0;
+        }
+        return returnValue;
+    }
+
+    /**
+     * Tone >= tone parameter that ensures ratio. 100 if ratio cannot be achieved.
+     *
+     * <p>This method is unsafe because the returned value is guaranteed to be in bounds, but, the
+     * in bounds return value may not reach the desired ratio.
+     *
+     * @param tone  Tone return value must contrast with.
+     * @param ratio Desired contrast ratio of return value and tone parameter.
+     */
+    public static double lighterUnsafe(double tone, double ratio) {
+        double lighterSafe = lighter(tone, ratio);
+        return lighterSafe < 0.0 ? 100.0 : lighterSafe;
+    }
+
+    /**
+     * Returns T in HCT, L* in L*a*b* <= tone parameter that ensures ratio with input T/L*. Returns
+     * -1 if ratio cannot be achieved.
+     *
+     * @param tone  Tone return value must contrast with.
+     * @param ratio Desired contrast ratio of return value and tone parameter.
+     */
+    public static double darker(double tone, double ratio) {
+        if (tone < 0.0 || tone > 100.0) {
+            return -1.0;
+        }
+        // Invert the contrast ratio equation to determine darker Y given a ratio and lighter Y.
+        final double lightY = ColorUtils.yFromLstar(tone);
+        final double darkY = ((lightY + 5.0) / ratio) - 5.0;
+        if (darkY < 0.0 || darkY > 100.0) {
+            return -1.0;
+        }
+        final double realContrast = ratioOfYs(lightY, darkY);
+        final double delta = Math.abs(realContrast - ratio);
+        if (realContrast < ratio && delta > CONTRAST_RATIO_EPSILON) {
+            return -1.0;
+        }
+
+        // For information on 0.4 constant, see comment in lighter(tone, ratio).
+        final double returnValue = ColorUtils.lstarFromY(darkY) - LUMINANCE_GAMUT_MAP_TOLERANCE;
+        // NOMUTANTS--important validation step; functions it is calling may change implementation.
+        if (returnValue < 0 || returnValue > 100) {
+            return -1.0;
+        }
+        return returnValue;
+    }
+
+    /**
+     * Tone <= tone parameter that ensures ratio. 0 if ratio cannot be achieved.
+     *
+     * <p>This method is unsafe because the returned value is guaranteed to be in bounds, but, the
+     * in bounds return value may not reach the desired ratio.
+     *
+     * @param tone  Tone return value must contrast with.
+     * @param ratio Desired contrast ratio of return value and tone parameter.
+     */
+    public static double darkerUnsafe(double tone, double ratio) {
+        double darkerSafe = darker(tone, ratio);
+        return max(0.0, darkerSafe);
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dislike/DislikeAnalyzer.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dislike/DislikeAnalyzer.java
new file mode 100644
index 0000000..31feee3
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dislike/DislikeAnalyzer.java
@@ -0,0 +1,58 @@
+/*
+ * 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.monet.dislike;
+
+import com.android.systemui.monet.hct.Hct;
+
+/**
+ * Check and/or fix universally disliked colors.
+ *
+ * <p>Color science studies of color preference indicate universal distaste for dark yellow-greens,
+ * and also show this is correlated to distate for biological waste and rotting food.
+ *
+ * <p>See Palmer and Schloss, 2010 or Schloss and Palmer's Chapter 21 in Handbook of Color
+ * Psychology (2015).
+ */
+public final class DislikeAnalyzer {
+
+    private DislikeAnalyzer() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns true if color is disliked.
+     *
+     * <p>Disliked is defined as a dark yellow-green that is not neutral.
+     */
+    public static boolean isDisliked(Hct hct) {
+        final boolean huePasses = Math.round(hct.getHue()) >= 90.0 && Math.round(hct.getHue())
+                <= 111.0;
+        final boolean chromaPasses = Math.round(hct.getChroma()) > 16.0;
+        final boolean tonePasses = Math.round(hct.getTone()) < 70.0;
+
+        return huePasses && chromaPasses && tonePasses;
+    }
+
+    /** If color is disliked, lighten it to make it likable. */
+    public static Hct fixIfDisliked(Hct hct) {
+        if (isDisliked(hct)) {
+            return Hct.from(hct.getHue(), hct.getChroma(), 70.0);
+        }
+
+        return hct;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
new file mode 100644
index 0000000..3a6b362
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
@@ -0,0 +1,646 @@
+/*
+ * 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.monet.dynamiccolor;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+import com.android.systemui.monet.contrast.Contrast;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+import com.android.systemui.monet.scheme.DynamicScheme;
+import com.android.systemui.monet.utils.MathUtils;
+
+import java.util.HashMap;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * A color that adjusts itself based on UI state, represented by DynamicScheme.
+ *
+ * <p>This color automatically adjusts to accommodate a desired contrast level, or other adjustments
+ * such as differing in light mode versus dark mode, or what the theme is, or what the color that
+ * produced the theme is, etc.
+ *
+ * <p>Colors without backgrounds do not change tone when contrast changes. Colors with backgrounds
+ * become closer to their background as contrast lowers, and further when contrast increases.
+ *
+ * <p>Prefer the static constructors. They provide a much more simple interface, such as requiring
+ * just a hexcode, or just a hexcode and a background.
+ *
+ * <p>Ultimately, each component necessary for calculating a color, adjusting it for a desired
+ * contrast level, and ensuring it has a certain lightness/tone difference from another color, is
+ * provided by a function that takes a DynamicScheme and returns a value. This ensures ultimate
+ * flexibility, any desired behavior of a color for any design system, but it usually unnecessary.
+ * See the default constructor for more information.
+ */
+// Prevent lint for Function.apply not being available on Android before API level 14 (4.0.1).
+// "AndroidJdkLibsChecker" for Function, "NewApi" for Function.apply().
+// A java_library Bazel rule with an Android constraint cannot skip these warnings without this
+// annotation; another solution would be to create an android_library rule and supply
+// AndroidManifest with an SDK set higher than 14.
+@SuppressWarnings({"AndroidJdkLibsChecker", "NewApi"})
+public final class DynamicColor {
+    public final Function<DynamicScheme, Double> hue;
+    public final Function<DynamicScheme, Double> chroma;
+    public final Function<DynamicScheme, Double> tone;
+    public final Function<DynamicScheme, Double> opacity;
+
+    public final Function<DynamicScheme, DynamicColor> background;
+    public final Function<DynamicScheme, Double> toneMinContrast;
+    public final Function<DynamicScheme, Double> toneMaxContrast;
+    public final Function<DynamicScheme, ToneDeltaConstraint> toneDeltaConstraint;
+
+    private final HashMap<DynamicScheme, Hct> hctCache = new HashMap<>();
+
+    /**
+     * The base constructor for DynamicColor.
+     *
+     * <p>Functional arguments allow overriding without risks that come with subclasses. _Strongly_
+     * prefer using one of the static convenience constructors. This class is arguably too flexible
+     * to
+     * ensure it can support any scenario.
+     *
+     * <p>For example, the default behavior of adjust tone at max contrast to be at a 7.0 ratio
+     * with
+     * its background is principled and matches a11y guidance. That does not mean it's the desired
+     * approach for _every_ design system, and every color pairing, always, in every case.
+     *
+     * @param hue                 given DynamicScheme, return the hue in HCT of the output color.
+     * @param chroma              given DynamicScheme, return chroma in HCT of the output color.
+     * @param tone                given DynamicScheme, return tone in HCT of the output color.
+     * @param background          given DynamicScheme, return the DynamicColor that is the
+     *                            background of this
+     *                            DynamicColor. When this is provided, automated adjustments to
+     *                            lower and raise contrast are
+     *                            made.
+     * @param toneMinContrast     given DynamicScheme, return tone in HCT/L* in L*a*b* this color
+     *                            should
+     *                            be at minimum contrast. See toneMinContrastDefault for the default
+     *                            behavior, and strongly
+     *                            consider using it unless you have strong opinions on a11y. The
+     *                            static constructors use it.
+     * @param toneMaxContrast     given DynamicScheme, return tone in HCT/L* in L*a*b* this color
+     *                            should
+     *                            be at maximum contrast. See toneMaxContrastDefault for the default
+     *                            behavior, and strongly
+     *                            consider using it unless you have strong opinions on a11y. The
+     *                            static constructors use it.
+     * @param toneDeltaConstraint given DynamicScheme, return a ToneDeltaConstraint instance that
+     *                            describes a requirement that this DynamicColor must always have
+     *                            some difference in tone/L*
+     *                            from another DynamicColor.<br>
+     *                            Unlikely to be useful unless a design system has some distortions
+     *                            where colors that don't
+     *                            have a background/foreground relationship must have _some_
+     *                            difference in tone, yet, not
+     *                            enough difference to create meaningful contrast.
+     */
+    public DynamicColor(
+            Function<DynamicScheme, Double> hue,
+            Function<DynamicScheme, Double> chroma,
+            Function<DynamicScheme, Double> tone,
+            Function<DynamicScheme, Double> opacity,
+            Function<DynamicScheme, DynamicColor> background,
+            Function<DynamicScheme, Double> toneMinContrast,
+            Function<DynamicScheme, Double> toneMaxContrast,
+            Function<DynamicScheme, ToneDeltaConstraint> toneDeltaConstraint) {
+        this.hue = hue;
+        this.chroma = chroma;
+        this.tone = tone;
+        this.opacity = opacity;
+        this.background = background;
+        this.toneMinContrast = toneMinContrast;
+        this.toneMaxContrast = toneMaxContrast;
+        this.toneDeltaConstraint = toneDeltaConstraint;
+    }
+
+    /**
+     * Create a DynamicColor from a hex code.
+     *
+     * <p>Result has no background; thus no support for increasing/decreasing contrast for a11y.
+     */
+    public static DynamicColor fromArgb(int argb) {
+        final Hct hct = Hct.fromInt(argb);
+        final TonalPalette palette = TonalPalette.fromInt(argb);
+        return DynamicColor.fromPalette((s) -> palette, (s) -> hct.getTone());
+    }
+
+    /**
+     * Create a DynamicColor from just a hex code.
+     *
+     * <p>Result has no background; thus cannot support increasing/decreasing contrast for a11y.
+     *
+     * @param argb A hex code.
+     * @param tone Function that provides a tone given DynamicScheme. Useful for adjusting for dark
+     *             vs. light mode.
+     */
+    public static DynamicColor fromArgb(int argb, Function<DynamicScheme, Double> tone) {
+        return DynamicColor.fromPalette((s) -> TonalPalette.fromInt(argb), tone);
+    }
+
+    /**
+     * Create a DynamicColor.
+     *
+     * <p>If you don't understand HCT fully, or your design team doesn't, but wants support for
+     * automated contrast adjustment, this method is _extremely_ useful: you can take a standard
+     * design system expressed as hex codes, create DynamicColors corresponding to each color, and
+     * then wire up backgrounds.
+     *
+     * <p>If the design system uses the same hex code on multiple backgrounds, define that in
+     * multiple
+     * DynamicColors so that the background is accurate for each one. If you define a DynamicColor
+     * with one background, and actually use it on another, DynamicColor can't guarantee contrast.
+     * For
+     * example, if you use a color on both black and white, increasing the contrast on one
+     * necessarily
+     * decreases contrast of the other.
+     *
+     * @param argb       A hex code.
+     * @param tone       Function that provides a tone given DynamicScheme. (useful for dark vs.
+     *                   light mode)
+     * @param background Function that provides background DynamicColor given DynamicScheme. Useful
+     *                   for contrast, given a background, colors can adjust to increase/decrease
+     *                   contrast.
+     */
+    public static DynamicColor fromArgb(
+            int argb,
+            Function<DynamicScheme, Double> tone,
+            Function<DynamicScheme, DynamicColor> background) {
+        return DynamicColor.fromPalette((s) -> TonalPalette.fromInt(argb), tone, background);
+    }
+
+    /**
+     * Create a DynamicColor from:
+     *
+     * @param argb                A hex code.
+     * @param tone                Function that provides a tone given DynamicScheme. (useful for
+     *                            dark vs. light mode)
+     * @param background          Function that provides background DynamicColor given
+     *                            DynamicScheme. Useful
+     *                            for contrast, given a background, colors can adjust to
+     *                            increase/decrease contrast.
+     * @param toneDeltaConstraint Function that provides a ToneDeltaConstraint given DynamicScheme.
+     *                            Useful for ensuring lightness difference between colors that don't
+     *                            _require_ contrast or
+     *                            have a formal background/foreground relationship.
+     */
+    public static DynamicColor fromArgb(
+            int argb,
+            Function<DynamicScheme, Double> tone,
+            Function<DynamicScheme, DynamicColor> background,
+            Function<DynamicScheme, ToneDeltaConstraint> toneDeltaConstraint) {
+        return DynamicColor.fromPalette(
+                (s) -> TonalPalette.fromInt(argb), tone, background, toneDeltaConstraint);
+    }
+
+    /**
+     * Create a DynamicColor.
+     *
+     * @param palette Function that provides a TonalPalette given DynamicScheme. A TonalPalette is
+     *                defined by a hue and chroma, so this replaces the need to specify hue/chroma.
+     *                By providing
+     *                a tonal palette, when contrast adjustments are made, intended chroma can be
+     *                preserved. For
+     *                example, at T/L* 90, there is a significant limit to the amount of chroma.
+     *                There is no
+     *                colorful red, a red that light is pink. By preserving the _intended_ chroma if
+     *                lightness
+     *                lowers for contrast adjustments, the intended chroma is restored.
+     * @param tone    Function that provides a tone given DynamicScheme. (useful for dark vs. light
+     *                mode)
+     */
+    public static DynamicColor fromPalette(
+            Function<DynamicScheme, TonalPalette> palette, Function<DynamicScheme, Double> tone) {
+        return fromPalette(palette, tone, null, null);
+    }
+
+    /**
+     * Create a DynamicColor.
+     *
+     * @param palette    Function that provides a TonalPalette given DynamicScheme. A TonalPalette
+     *                   is
+     *                   defined by a hue and chroma, so this replaces the need to specify
+     *                   hue/chroma. By providing
+     *                   a tonal palette, when contrast adjustments are made, intended chroma can be
+     *                   preserved. For
+     *                   example, at T/L* 90, there is a significant limit to the amount of chroma.
+     *                   There is no
+     *                   colorful red, a red that light is pink. By preserving the _intended_ chroma
+     *                   if lightness
+     *                   lowers for contrast adjustments, the intended chroma is restored.
+     * @param tone       Function that provides a tone given DynamicScheme. (useful for dark vs.
+     *                   light mode)
+     * @param background Function that provides background DynamicColor given DynamicScheme. Useful
+     *                   for contrast, given a background, colors can adjust to increase/decrease
+     *                   contrast.
+     */
+    public static DynamicColor fromPalette(
+            Function<DynamicScheme, TonalPalette> palette,
+            Function<DynamicScheme, Double> tone,
+            Function<DynamicScheme, DynamicColor> background) {
+        return fromPalette(palette, tone, background, null);
+    }
+
+    /**
+     * Create a DynamicColor.
+     *
+     * @param palette             Function that provides a TonalPalette given DynamicScheme. A
+     *                            TonalPalette is
+     *                            defined by a hue and chroma, so this replaces the need to specify
+     *                            hue/chroma. By providing
+     *                            a tonal palette, when contrast adjustments are made, intended
+     *                            chroma can be preserved. For
+     *                            example, at T/L* 90, there is a significant limit to the amount of
+     *                            chroma. There is no
+     *                            colorful red, a red that light is pink. By preserving the
+     *                            _intended_ chroma if lightness
+     *                            lowers for contrast adjustments, the intended chroma is restored.
+     * @param tone                Function that provides a tone given DynamicScheme. (useful for
+     *                            dark vs. light mode)
+     * @param background          Function that provides background DynamicColor given
+     *                            DynamicScheme. Useful
+     *                            for contrast, given a background, colors can adjust to
+     *                            increase/decrease contrast.
+     * @param toneDeltaConstraint Function that provides a ToneDeltaConstraint given DynamicScheme.
+     *                            Useful for ensuring lightness difference between colors that don't
+     *                            _require_ contrast or
+     *                            have a formal background/foreground relationship.
+     */
+    public static DynamicColor fromPalette(
+            Function<DynamicScheme, TonalPalette> palette,
+            Function<DynamicScheme, Double> tone,
+            Function<DynamicScheme, DynamicColor> background,
+            Function<DynamicScheme, ToneDeltaConstraint> toneDeltaConstraint) {
+        return new DynamicColor(
+                scheme -> palette.apply(scheme).getHue(),
+                scheme -> palette.apply(scheme).getChroma(),
+                tone,
+                null,
+                background,
+                scheme -> toneMinContrastDefault(tone, background, scheme, toneDeltaConstraint),
+                scheme -> toneMaxContrastDefault(tone, background, scheme, toneDeltaConstraint),
+                toneDeltaConstraint);
+    }
+
+    /** Returns the ARGB (i.e. hex code) representation of the resolved color given scheme. */
+    public int getArgb(DynamicScheme scheme) {
+        final int argb = getHct(scheme).toInt();
+        if (opacity == null) {
+            return argb;
+        }
+        final double percentage = opacity.apply(scheme);
+        final int alpha = MathUtils.clampInt(0, 255, (int) Math.round(percentage * 255));
+        return (argb & 0x00ffffff) | (alpha << 24);
+    }
+
+    /** Returns the HCT representation of the resolved color given scheme. */
+    public Hct getHct(DynamicScheme scheme) {
+        final Hct cachedAnswer = hctCache.get(scheme);
+        if (cachedAnswer != null) {
+            return cachedAnswer;
+        }
+        // This is crucial for aesthetics: we aren't simply the taking the standard color
+        // and changing its tone for contrast. Rather, we find the tone for contrast, then
+        // use the specified chroma from the palette to construct a new color.
+        //
+        // For example, this enables colors with standard tone of T90, which has limited chroma, to
+        // "recover" intended chroma as contrast increases.
+        final Hct answer = Hct.from(hue.apply(scheme), chroma.apply(scheme), getTone(scheme));
+        // NOMUTANTS--trivial test with onerous dependency injection requirement.
+        if (hctCache.size() > 4) {
+            hctCache.clear();
+        }
+        // NOMUTANTS--trivial test with onerous dependency injection requirement.
+        hctCache.put(scheme, answer);
+        return answer;
+    }
+
+    /** Returns the tone in HCT, ranging from 0 to 100, of the resolved color given scheme. */
+    public double getTone(DynamicScheme scheme) {
+        double answer = tone.apply(scheme);
+
+        final boolean decreasingContrast = scheme.contrastLevel < 0.0;
+        if (scheme.contrastLevel != 0.0) {
+            final double startTone = tone.apply(scheme);
+            final double endTone =
+                    decreasingContrast ? toneMinContrast.apply(scheme) : toneMaxContrast.apply(
+                            scheme);
+            final double delta = (endTone - startTone) * Math.abs(scheme.contrastLevel);
+            answer = delta + startTone;
+        }
+
+        final DynamicColor bgDynamicColor = background == null ? null : background.apply(scheme);
+        double minRatio = Contrast.RATIO_MIN;
+        double maxRatio = Contrast.RATIO_MAX;
+        if (bgDynamicColor != null) {
+            final boolean bgHasBg =
+                    bgDynamicColor.background != null && bgDynamicColor.background.apply(scheme)
+                            == null;
+            final double standardRatio =
+                    Contrast.ratioOfTones(tone.apply(scheme), bgDynamicColor.tone.apply(scheme));
+            if (decreasingContrast) {
+                final double minContrastRatio =
+                        Contrast.ratioOfTones(
+                                toneMinContrast.apply(scheme),
+                                bgDynamicColor.toneMinContrast.apply(scheme));
+                minRatio = bgHasBg ? 1.0 : minContrastRatio;
+                maxRatio = standardRatio;
+            } else {
+                final double maxContrastRatio =
+                        Contrast.ratioOfTones(
+                                toneMaxContrast.apply(scheme),
+                                bgDynamicColor.toneMaxContrast.apply(scheme));
+                minRatio = !bgHasBg ? 1.0 : min(maxContrastRatio, standardRatio);
+                maxRatio = !bgHasBg ? 21.0 : max(maxContrastRatio, standardRatio);
+            }
+        }
+
+        final double finalMinRatio = minRatio;
+        final double finalMaxRatio = maxRatio;
+        final double finalAnswer = answer;
+        answer =
+                calculateDynamicTone(
+                        scheme,
+                        this.tone,
+                        (dynamicColor) -> dynamicColor.getTone(scheme),
+                        (a, b) -> finalAnswer,
+                        (s) -> bgDynamicColor,
+                        toneDeltaConstraint,
+                        (s) -> finalMinRatio,
+                        (s) -> finalMaxRatio);
+
+        return answer;
+    }
+
+    /**
+     * The default algorithm for calculating the tone of a color at minimum contrast.<br>
+     * If the original contrast ratio was >= 7.0, reach contrast 4.5.<br>
+     * If the original contrast ratio was >= 3.0, reach contrast 3.0.<br>
+     * If the original contrast ratio was < 3.0, reach that ratio.
+     */
+    public static double toneMinContrastDefault(
+            Function<DynamicScheme, Double> tone,
+            Function<DynamicScheme, DynamicColor> background,
+            DynamicScheme scheme,
+            Function<DynamicScheme, ToneDeltaConstraint> toneDeltaConstraint) {
+        return DynamicColor.calculateDynamicTone(
+                scheme,
+                tone,
+                c -> c.toneMinContrast.apply(scheme),
+                (stdRatio, bgTone) -> {
+                    double answer = tone.apply(scheme);
+                    if (stdRatio >= Contrast.RATIO_70) {
+                        answer = contrastingTone(bgTone, Contrast.RATIO_45);
+                    } else if (stdRatio >= Contrast.RATIO_30) {
+                        answer = contrastingTone(bgTone, Contrast.RATIO_30);
+                    } else {
+                        final boolean backgroundHasBackground =
+                                background != null
+                                        && background.apply(scheme) != null
+                                        && background.apply(scheme).background != null
+                                        && background.apply(scheme).background.apply(scheme)
+                                        != null;
+                        if (backgroundHasBackground) {
+                            answer = contrastingTone(bgTone, stdRatio);
+                        }
+                    }
+                    return answer;
+                },
+                background,
+                toneDeltaConstraint,
+                null,
+                standardRatio -> standardRatio);
+    }
+
+    /**
+     * The default algorithm for calculating the tone of a color at maximum contrast.<br>
+     * If the color's background has a background, reach contrast 7.0.<br>
+     * If it doesn't, maintain the original contrast ratio.<br>
+     *
+     * <p>This ensures text on surfaces maintains its original, often detrimentally excessive,
+     * contrast ratio. But, text on buttons can soften to not have excessive contrast.
+     *
+     * <p>Historically, digital design uses pure whites and black for text and surfaces. It's too
+     * much
+     * of a jump at this point in history to introduce a dynamic contrast system _and_ insist that
+     * text always had excessive contrast and should reach 7.0, it would deterimentally affect
+     * desire
+     * to understand and use dynamic contrast.
+     */
+    public static double toneMaxContrastDefault(
+            Function<DynamicScheme, Double> tone,
+            Function<DynamicScheme, DynamicColor> background,
+            DynamicScheme scheme,
+            Function<DynamicScheme, ToneDeltaConstraint> toneDeltaConstraint) {
+        return DynamicColor.calculateDynamicTone(
+                scheme,
+                tone,
+                c -> c.toneMaxContrast.apply(scheme),
+                (stdRatio, bgTone) -> {
+                    final boolean backgroundHasBackground =
+                            background != null
+                                    && background.apply(scheme) != null
+                                    && background.apply(scheme).background != null
+                                    && background.apply(scheme).background.apply(scheme) != null;
+                    if (backgroundHasBackground) {
+                        return contrastingTone(bgTone, Contrast.RATIO_70);
+                    } else {
+                        return contrastingTone(bgTone, max(Contrast.RATIO_70, stdRatio));
+                    }
+                },
+                background,
+                toneDeltaConstraint,
+                null,
+                null);
+    }
+
+    /**
+     * Core method for calculating a tone for under dynamic contrast.
+     *
+     * <p>It enforces important properties:<br>
+     * #1. Desired contrast ratio is reached.<br>
+     * As contrast increases from standard to max, the tones involved should always be at least the
+     * standard ratio. For example, if a button is T90, and button text is T0, and the button is T0
+     * at
+     * max contrast, the button text cannot simply linearly interpolate from T0 to T100, or at some
+     * point they'll both be at the same tone.
+     *
+     * <p>#2. Enable light foregrounds on midtones.<br>
+     * The eye prefers light foregrounds on T50 to T60, possibly up to T70, but, contrast ratio 4.5
+     * can't be reached with T100 unless the foreground is T50. Contrast ratio 4.5 is crucial, it
+     * represents 'readable text', i.e. text smaller than ~40 dp / 1/4". So, if a tone is between
+     * T50
+     * and T60, it is proactively changed to T49 to enable light foregrounds.
+     *
+     * <p>#3. Ensure tone delta with another color.<br>
+     * In design systems, there may be colors that don't have a pure background/foreground
+     * relationship, but, do require different tones for visual differentiation.
+     * ToneDeltaConstraint
+     * models this requirement, and DynamicColor enforces it.
+     */
+    public static double calculateDynamicTone(
+            DynamicScheme scheme,
+            Function<DynamicScheme, Double> toneStandard,
+            Function<DynamicColor, Double> toneToJudge,
+            BiFunction<Double, Double, Double> desiredTone,
+            Function<DynamicScheme, DynamicColor> background,
+            Function<DynamicScheme, ToneDeltaConstraint> toneDeltaConstraint,
+            Function<Double, Double> minRatio,
+            Function<Double, Double> maxRatio) {
+        // Start with the tone with no adjustment for contrast.
+        // If there is no background, don't perform any adjustment, return immediately.
+        final double toneStd = toneStandard.apply(scheme);
+        double answer = toneStd;
+        final DynamicColor bgDynamic = background == null ? null : background.apply(scheme);
+        if (bgDynamic == null) {
+            return answer;
+        }
+        final double bgToneStd = bgDynamic.tone.apply(scheme);
+        final double stdRatio = Contrast.ratioOfTones(toneStd, bgToneStd);
+
+        // If there is a background, determine its tone after contrast adjustment.
+        // Then, calculate the foreground tone that ensures the caller's desired contrast ratio
+        // is met.
+        final double bgTone = toneToJudge.apply(bgDynamic);
+        final double myDesiredTone = desiredTone.apply(stdRatio, bgTone);
+        final double currentRatio = Contrast.ratioOfTones(bgTone, myDesiredTone);
+        final double minRatioRealized =
+                minRatio == null
+                        ? Contrast.RATIO_MIN
+                        : minRatio.apply(stdRatio) == null ? Contrast.RATIO_MIN : minRatio.apply(
+                                stdRatio);
+        final double maxRatioRealized =
+                maxRatio == null
+                        ? Contrast.RATIO_MAX
+                        : maxRatio.apply(stdRatio) == null ? Contrast.RATIO_MAX : maxRatio.apply(
+                                stdRatio);
+        final double desiredRatio =
+                MathUtils.clampDouble(minRatioRealized, maxRatioRealized, currentRatio);
+        if (desiredRatio == currentRatio) {
+            answer = myDesiredTone;
+        } else {
+            answer = DynamicColor.contrastingTone(bgTone, desiredRatio);
+        }
+
+        // If the background has no background,  adjust the foreground tone to ensure that
+        // it is dark enough to have a light foreground.
+        if (bgDynamic.background == null || bgDynamic.background.apply(scheme) == null) {
+            answer = DynamicColor.enableLightForeground(answer);
+        }
+
+        // If the caller has specified a constraint where it must have a certain  tone distance from
+        // another color, enforce that constraint.
+        answer = ensureToneDelta(answer, toneStd, scheme, toneDeltaConstraint, toneToJudge);
+
+        return answer;
+    }
+
+    static double ensureToneDelta(
+            double tone,
+            double toneStandard,
+            DynamicScheme scheme,
+            Function<DynamicScheme, ToneDeltaConstraint> toneDeltaConstraint,
+            Function<DynamicColor, Double> toneToDistanceFrom) {
+        final ToneDeltaConstraint constraint =
+                (toneDeltaConstraint == null ? null : toneDeltaConstraint.apply(scheme));
+        if (constraint == null) {
+            return tone;
+        }
+
+        final double requiredDelta = constraint.delta;
+        final double keepAwayTone = toneToDistanceFrom.apply(constraint.keepAway);
+        final double delta = Math.abs(tone - keepAwayTone);
+        if (delta >= requiredDelta) {
+            return tone;
+        }
+        switch (constraint.keepAwayPolarity) {
+            case DARKER:
+                return MathUtils.clampDouble(0, 100, keepAwayTone + requiredDelta);
+            case LIGHTER:
+                return MathUtils.clampDouble(0, 100, keepAwayTone - requiredDelta);
+            case NO_PREFERENCE:
+                final double keepAwayToneStandard = constraint.keepAway.tone.apply(scheme);
+                final boolean preferLighten = toneStandard > keepAwayToneStandard;
+                final double alterAmount = Math.abs(delta - requiredDelta);
+                final boolean lighten =
+                        preferLighten ? (tone + alterAmount <= 100.0) : tone < alterAmount;
+                return lighten ? tone + alterAmount : tone - alterAmount;
+        }
+        return tone;
+    }
+
+    /**
+     * Given a background tone, find a foreground tone, while ensuring they reach a contrast ratio
+     * that is as close to ratio as possible.
+     */
+    public static double contrastingTone(double bgTone, double ratio) {
+        final double lighterTone = Contrast.lighterUnsafe(bgTone, ratio);
+        final double darkerTone = Contrast.darkerUnsafe(bgTone, ratio);
+        final double lighterRatio = Contrast.ratioOfTones(lighterTone, bgTone);
+        final double darkerRatio = Contrast.ratioOfTones(darkerTone, bgTone);
+        final boolean preferLighter = tonePrefersLightForeground(bgTone);
+
+        if (preferLighter) {
+            // "Negligible difference" handles an edge case where the initial contrast ratio is high
+            // (ex. 13.0), and the ratio passed to the function is that high ratio, and both the
+            // lighter and darker ratio fails to pass that ratio.
+            //
+            // This was observed with Tonal Spot's On Primary Container turning black momentarily
+            // between high and max contrast in light mode. PC's standard tone was T90, OPC's was
+            // T10, it was light mode, and the contrast level was 0.6568521221032331.
+            final boolean negligibleDifference =
+                    Math.abs(lighterRatio - darkerRatio) < 0.1 && lighterRatio < ratio
+                            && darkerRatio < ratio;
+            if (lighterRatio >= ratio || lighterRatio >= darkerRatio || negligibleDifference) {
+                return lighterTone;
+            } else {
+                return darkerTone;
+            }
+        } else {
+            return darkerRatio >= ratio || darkerRatio >= lighterRatio ? darkerTone : lighterTone;
+        }
+    }
+
+    /**
+     * Adjust a tone down such that white has 4.5 contrast, if the tone is reasonably close to
+     * supporting it.
+     */
+    public static double enableLightForeground(double tone) {
+        if (tonePrefersLightForeground(tone) && !toneAllowsLightForeground(tone)) {
+            return 49.0;
+        }
+        return tone;
+    }
+
+    /**
+     * People prefer white foregrounds on ~T60-70. Observed over time, and also by Andrew Somers
+     * during research for APCA.
+     *
+     * <p>T60 used as to create the smallest discontinuity possible when skipping down to T49 in
+     * order
+     * to ensure light foregrounds.
+     */
+    public static boolean tonePrefersLightForeground(double tone) {
+        return Math.round(tone) <= 60;
+    }
+
+    /** Tones less than ~T50 always permit white at 4.5 contrast. */
+    public static boolean toneAllowsLightForeground(double tone) {
+        return Math.round(tone) <= 49;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
new file mode 100644
index 0000000..91f3309
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
@@ -0,0 +1,436 @@
+/*
+ * 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.monet.dynamiccolor;
+
+import com.android.systemui.monet.dislike.DislikeAnalyzer;
+import com.android.systemui.monet.dynamiccolor.DynamicColor;
+import com.android.systemui.monet.dynamiccolor.ToneDeltaConstraint;
+import com.android.systemui.monet.dynamiccolor.TonePolarity;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.hct.ViewingConditions;
+import com.android.systemui.monet.scheme.DynamicScheme;
+import com.android.systemui.monet.scheme.Variant;
+
+/** Named colors, otherwise known as tokens, or roles, in the Material Design system. */
+public final class MaterialDynamicColors {
+    private static final double CONTAINER_ACCENT_TONE_DELTA = 15.0;
+
+
+    private MaterialDynamicColors() {
+    }
+
+    /** In light mode, the darkest surface. In dark mode, the lightest surface. */
+    public static DynamicColor highestSurface(DynamicScheme s) {
+        return s.isDark ? surfaceBright : surfaceDim;
+    }
+
+    public static final DynamicColor background =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0);
+
+    public static final DynamicColor onBackground =
+            DynamicColor.fromPalette(
+                    (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> background);
+
+    public static final DynamicColor surface =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0);
+
+    public static final DynamicColor surfaceInverse =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 20.0);
+
+    public static final DynamicColor surfaceBright =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 24.0 : 98.0);
+
+    public static final DynamicColor surfaceDim =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 87.0);
+
+    public static final DynamicColor surfaceContainerLowest =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 4.0 : 100.0);
+
+    public static final DynamicColor surfaceContainerLow =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 96.0);
+
+    public static final DynamicColor surfaceContainer =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 12.0 : 94.0);
+
+    public static final DynamicColor surfaceContainerHigh =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 17.0 : 92.0);
+
+    public static final DynamicColor surfaceContainerHighest =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 22.0 : 90.0);
+
+    public static final DynamicColor onSurface =
+            DynamicColor.fromPalette(
+                    (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0,
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor onSurfaceInverse =
+            DynamicColor.fromPalette(
+                    (s) -> s.neutralPalette, (s) -> s.isDark ? 20.0 : 95.0, (s) -> surfaceInverse);
+
+    public static final DynamicColor surfaceVariant =
+            DynamicColor.fromPalette((s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 90.0);
+
+    public static final DynamicColor onSurfaceVariant =
+            DynamicColor.fromPalette(
+                    (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 80.0 : 30.0,
+                    (s) -> surfaceVariant);
+
+    public static final DynamicColor outline =
+            DynamicColor.fromPalette(
+                    (s) -> s.neutralVariantPalette, (s) -> 50.0, (s) -> highestSurface(s));
+
+    public static final DynamicColor outlineVariant =
+            DynamicColor.fromPalette(
+                    (s) -> s.neutralVariantPalette, (s) -> 80.0, (s) -> highestSurface(s));
+
+    public static final DynamicColor primaryContainer =
+            DynamicColor.fromPalette(
+                    (s) -> s.primaryPalette,
+                    (s) -> {
+                        if (!isFidelity(s)) {
+                            return s.isDark ? 30.0 : 90.0;
+                        }
+                        return performAlbers(s.sourceColorHct, s);
+                    },
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor onPrimaryContainer =
+            DynamicColor.fromPalette(
+                    (s) -> s.primaryPalette,
+                    (s) -> {
+                        if (!isFidelity(s)) {
+                            return s.isDark ? 90.0 : 10.0;
+                        }
+                        return DynamicColor.contrastingTone(primaryContainer.getTone(s), 4.5);
+                    },
+                    (s) -> primaryContainer,
+                    null);
+
+    public static final DynamicColor primary =
+            DynamicColor.fromPalette(
+                    (s) -> s.primaryPalette,
+                    (s) -> s.isDark ? 80.0 : 40.0,
+                    (s) -> highestSurface(s),
+                    (s) ->
+                            new ToneDeltaConstraint(
+                                    CONTAINER_ACCENT_TONE_DELTA,
+                                    primaryContainer,
+                                    s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
+
+    public static final DynamicColor primaryInverse =
+            DynamicColor.fromPalette(
+                    (s) -> s.primaryPalette, (s) -> s.isDark ? 40.0 : 80.0, (s) -> surfaceInverse);
+
+    public static final DynamicColor onPrimary =
+            DynamicColor.fromPalette(
+                    (s) -> s.primaryPalette, (s) -> s.isDark ? 20.0 : 100.0, (s) -> primary);
+
+    public static final DynamicColor secondaryContainer =
+            DynamicColor.fromPalette(
+                    (s) -> s.secondaryPalette,
+                    (s) -> {
+                        final double initialTone = s.isDark ? 30.0 : 90.0;
+                        if (!isFidelity(s)) {
+                            return initialTone;
+                        }
+                        double answer =
+                                findDesiredChromaByTone(
+                                        s.secondaryPalette.getHue(),
+                                        s.secondaryPalette.getChroma(),
+                                        initialTone,
+                                        !s.isDark);
+                        answer = performAlbers(s.secondaryPalette.getHct(answer), s);
+                        return answer;
+                    },
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor onSecondaryContainer =
+            DynamicColor.fromPalette(
+                    (s) -> s.secondaryPalette,
+                    (s) -> {
+                        if (!isFidelity(s)) {
+                            return s.isDark ? 90.0 : 10.0;
+                        }
+                        return DynamicColor.contrastingTone(secondaryContainer.getTone(s), 4.5);
+                    },
+                    (s) -> secondaryContainer);
+
+    public static final DynamicColor secondary =
+            DynamicColor.fromPalette(
+                    (s) -> s.secondaryPalette,
+                    (s) -> s.isDark ? 80.0 : 40.0,
+                    (s) -> highestSurface(s),
+                    (s) ->
+                            new ToneDeltaConstraint(
+                                    CONTAINER_ACCENT_TONE_DELTA,
+                                    secondaryContainer,
+                                    s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
+
+    public static final DynamicColor onSecondary =
+            DynamicColor.fromPalette(
+                    (s) -> s.secondaryPalette, (s) -> s.isDark ? 20.0 : 100.0, (s) -> secondary);
+
+    public static final DynamicColor tertiaryContainer =
+            DynamicColor.fromPalette(
+                    (s) -> s.tertiaryPalette,
+                    (s) -> {
+                        if (!isFidelity(s)) {
+                            return s.isDark ? 30.0 : 90.0;
+                        }
+                        final double albersTone =
+                                performAlbers(s.tertiaryPalette.getHct(s.sourceColorHct.getTone()),
+                                        s);
+                        final Hct proposedHct = s.tertiaryPalette.getHct(albersTone);
+                        return DislikeAnalyzer.fixIfDisliked(proposedHct).getTone();
+                    },
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor onTertiaryContainer =
+            DynamicColor.fromPalette(
+                    (s) -> s.tertiaryPalette,
+                    (s) -> {
+                        if (!isFidelity(s)) {
+                            return s.isDark ? 90.0 : 10.0;
+                        }
+                        return DynamicColor.contrastingTone(tertiaryContainer.getTone(s), 4.5);
+                    },
+                    (s) -> tertiaryContainer);
+
+    public static final DynamicColor tertiary =
+            DynamicColor.fromPalette(
+                    (s) -> s.tertiaryPalette,
+                    (s) -> s.isDark ? 80.0 : 40.0,
+                    (s) -> highestSurface(s),
+                    (s) ->
+                            new ToneDeltaConstraint(
+                                    CONTAINER_ACCENT_TONE_DELTA,
+                                    tertiaryContainer,
+                                    s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
+
+    public static final DynamicColor onTertiary =
+            DynamicColor.fromPalette(
+                    (s) -> s.tertiaryPalette, (s) -> s.isDark ? 20.0 : 100.0, (s) -> tertiary);
+
+    public static final DynamicColor errorContainer =
+            DynamicColor.fromPalette(
+                    (s) -> s.errorPalette, (s) -> s.isDark ? 30.0 : 90.0, (s) -> highestSurface(s));
+
+    public static final DynamicColor onErrorContainer =
+            DynamicColor.fromPalette(
+                    (s) -> s.errorPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> errorContainer);
+
+    public static final DynamicColor error =
+            DynamicColor.fromPalette(
+                    (s) -> s.errorPalette,
+                    (s) -> s.isDark ? 80.0 : 40.0,
+                    (s) -> highestSurface(s),
+                    (s) ->
+                            new ToneDeltaConstraint(
+                                    CONTAINER_ACCENT_TONE_DELTA,
+                                    errorContainer,
+                                    s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
+
+    public static final DynamicColor onError =
+            DynamicColor.fromPalette((s) -> s.errorPalette, (s) -> s.isDark ? 20.0 : 100.0,
+                    (s) -> error);
+
+    public static final DynamicColor primaryFixed =
+            DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 90.0,
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor primaryFixedDarker =
+            DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 80.0,
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor onPrimaryFixed =
+            DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 10.0,
+                    (s) -> primaryFixedDarker);
+
+    public static final DynamicColor onPrimaryFixedVariant =
+            DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 30.0,
+                    (s) -> primaryFixedDarker);
+
+    public static final DynamicColor secondaryFixed =
+            DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 90.0,
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor secondaryFixedDarker =
+            DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 80.0,
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor onSecondaryFixed =
+            DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 10.0,
+                    (s) -> secondaryFixedDarker);
+
+    public static final DynamicColor onSecondaryFixedVariant =
+            DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 30.0,
+                    (s) -> secondaryFixedDarker);
+
+    public static final DynamicColor tertiaryFixed =
+            DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 90.0,
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor tertiaryFixedDarker =
+            DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 80.0,
+                    (s) -> highestSurface(s));
+
+    public static final DynamicColor onTertiaryFixed =
+            DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 10.0,
+                    (s) -> tertiaryFixedDarker);
+
+    public static final DynamicColor onTertiaryFixedVariant =
+            DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 30.0,
+                    (s) -> tertiaryFixedDarker);
+
+    /**
+     * These colors were present in Android framework before Android U, and used by MDC controls.
+     * They
+     * should be avoided, if possible. It's unclear if they're used on multiple backgrounds, and if
+     * they are, they can't be adjusted for contrast.* For now, they will be set with no
+     * background,
+     * and those won't adjust for contrast, avoiding issues.
+     *
+     * <p>* For example, if the same color is on a white background _and_ black background, there's
+     * no
+     * way to increase contrast with either without losing contrast with the other.
+     */
+    // colorControlActivated documented as colorAccent in M3 & GM3.
+    // colorAccent documented as colorSecondary in M3 and colorPrimary in GM3.
+    // Android used Material's Container as Primary/Secondary/Tertiary at launch.
+    // Therefore, this is a duplicated version of Primary Container.
+    public static final DynamicColor controlActivated =
+            DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> s.isDark ? 30.0 : 90.0, null);
+
+    // colorControlNormal documented as textColorSecondary in M3 & GM3.
+    // In Material, textColorSecondary points to onSurfaceVariant in the non-disabled state,
+    // which is Neutral Variant T30/80 in light/dark.
+    public static final DynamicColor controlNormal =
+            DynamicColor.fromPalette((s) -> s.neutralVariantPalette, (s) -> s.isDark ? 80.0 : 30.0);
+
+    // colorControlHighlight documented, in both M3 & GM3:
+    // Light mode: #1f000000 dark mode: #33ffffff.
+    // These are black and white with some alpha.
+    // 1F hex = 31 decimal; 31 / 255 = 12% alpha.
+    // 33 hex = 51 decimal; 51 / 255 = 20% alpha.
+    // DynamicColors do not support alpha currently, and _may_ not need it for this use case,
+    // depending on how MDC resolved alpha for the other cases.
+    // Returning black in dark mode, white in light mode.
+    public static final DynamicColor controlHighlight =
+            new DynamicColor(
+                    s -> 0.0,
+                    s -> 0.0,
+                    s -> s.isDark ? 100.0 : 0.0,
+                    s -> s.isDark ? 0.20 : 0.12,
+                    null,
+                    scheme ->
+                            DynamicColor.toneMinContrastDefault(
+                                    (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
+                    scheme ->
+                            DynamicColor.toneMaxContrastDefault(
+                                    (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
+                    null);
+
+    // textColorPrimaryInverse documented, in both M3 & GM3, documented as N10/N90.
+    public static final DynamicColor textPrimaryInverse =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+
+    // textColorSecondaryInverse and textColorTertiaryInverse both documented, in both M3 & GM3, as
+    // NV30/NV80
+    public static final DynamicColor textSecondaryAndTertiaryInverse =
+            DynamicColor.fromPalette((s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 80.0);
+
+    // textColorPrimaryInverseDisableOnly documented, in both M3 & GM3, as N10/N90
+    public static final DynamicColor textPrimaryInverseDisableOnly =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+
+    // textColorSecondaryInverse and textColorTertiaryInverse in disabled state both documented,
+    // in both M3 & GM3, as N10/N90
+    public static final DynamicColor textSecondaryAndTertiaryInverseDisabled =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+
+    // textColorHintInverse documented, in both M3 & GM3, as N10/N90
+    public static final DynamicColor textHintInverse =
+            DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+
+    public static final DynamicColor primaryPaletteKeyColor =
+            DynamicColor.fromPalette(
+                    (s) -> s.primaryPalette, (s) -> s.primaryPalette.getKeyColor().getTone());
+
+    public static final DynamicColor secondaryPaletteKeyColor =
+            DynamicColor.fromPalette(
+                    (s) -> s.secondaryPalette, (s) -> s.secondaryPalette.getKeyColor().getTone());
+
+    public static final DynamicColor tertiaryPaletteKeyColor =
+            DynamicColor.fromPalette(
+                    (s) -> s.tertiaryPalette, (s) -> s.tertiaryPalette.getKeyColor().getTone());
+
+    public static final DynamicColor neutralPaletteKeyColor =
+            DynamicColor.fromPalette(
+                    (s) -> s.neutralPalette, (s) -> s.neutralPalette.getKeyColor().getTone());
+
+    public static final DynamicColor neutralVariantPaletteKeyColor =
+            DynamicColor.fromPalette(
+                    (s) -> s.neutralVariantPalette,
+                    (s) -> s.neutralVariantPalette.getKeyColor().getTone());
+
+    private static ViewingConditions viewingConditionsForAlbers(DynamicScheme scheme) {
+        return ViewingConditions.defaultWithBackgroundLstar(scheme.isDark ? 30.0 : 80.0);
+    }
+
+    private static boolean isFidelity(DynamicScheme scheme) {
+        return scheme.variant == Variant.FIDELITY || scheme.variant == Variant.CONTENT;
+    }
+
+    static double findDesiredChromaByTone(
+            double hue, double chroma, double tone, boolean byDecreasingTone) {
+        double answer = tone;
+
+        Hct closestToChroma = Hct.from(hue, chroma, tone);
+        if (closestToChroma.getChroma() < chroma) {
+            double chromaPeak = closestToChroma.getChroma();
+            while (closestToChroma.getChroma() < chroma) {
+                answer += byDecreasingTone ? -1.0 : 1.0;
+                Hct potentialSolution = Hct.from(hue, chroma, answer);
+                if (chromaPeak > potentialSolution.getChroma()) {
+                    break;
+                }
+                if (Math.abs(potentialSolution.getChroma() - chroma) < 0.4) {
+                    break;
+                }
+
+                double potentialDelta = Math.abs(potentialSolution.getChroma() - chroma);
+                double currentDelta = Math.abs(closestToChroma.getChroma() - chroma);
+                if (potentialDelta < currentDelta) {
+                    closestToChroma = potentialSolution;
+                }
+                chromaPeak = Math.max(chromaPeak, potentialSolution.getChroma());
+            }
+        }
+
+        return answer;
+    }
+
+    static double performAlbers(Hct prealbers, DynamicScheme scheme) {
+        final Hct albersd = prealbers.inViewingConditions(viewingConditionsForAlbers(scheme));
+        if (DynamicColor.tonePrefersLightForeground(prealbers.getTone())
+                && !DynamicColor.toneAllowsLightForeground(albersd.getTone())) {
+            return DynamicColor.enableLightForeground(prealbers.getTone());
+        } else {
+            return DynamicColor.enableLightForeground(albersd.getTone());
+        }
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/ToneDeltaConstraint.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/ToneDeltaConstraint.java
new file mode 100644
index 0000000..5fd1210
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/ToneDeltaConstraint.java
@@ -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.monet.dynamiccolor;
+
+/**
+ * Documents a constraint between two DynamicColors, in which their tones must have a certain
+ * distance from each other.
+ */
+public final class ToneDeltaConstraint {
+    public final double delta;
+    public final DynamicColor keepAway;
+    public final TonePolarity keepAwayPolarity;
+
+    /**
+     * @param delta            the difference in tone required
+     * @param keepAway         the color to distance in tone from
+     * @param keepAwayPolarity whether the color to keep away from must be lighter, darker, or no
+     *                         preference, in which case it should
+     */
+    public ToneDeltaConstraint(double delta, DynamicColor keepAway, TonePolarity keepAwayPolarity) {
+        this.delta = delta;
+        this.keepAway = keepAway;
+        this.keepAwayPolarity = keepAwayPolarity;
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/TonePolarity.java
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/TonePolarity.java
index 497c272..bb5649c 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/TonePolarity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package com.android.systemui.monet.dynamiccolor;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+/** Describes the relationship in lightness between two colors. */
+public enum TonePolarity {
+    DARKER,
+    LIGHTER,
+    NO_PREFERENCE;
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/hct/Cam16.java b/packages/SystemUI/monet/src/com/android/systemui/monet/hct/Cam16.java
new file mode 100644
index 0000000..9ccc503
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/hct/Cam16.java
@@ -0,0 +1,454 @@
+/*
+ * 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.monet.hct;
+
+import static java.lang.Math.max;
+
+import com.android.systemui.monet.utils.ColorUtils;
+
+/**
+ * CAM16, a color appearance model. Colors are not just defined by their hex code, but rather, a hex
+ * code and viewing conditions.
+ *
+ * <p>CAM16 instances also have coordinates in the CAM16-UCS space, called J*, a*, b*, or jstar,
+ * astar, bstar in code. CAM16-UCS is included in the CAM16 specification, and should be used when
+ * measuring distances between colors.
+ *
+ * <p>In traditional color spaces, a color can be identified solely by the observer's measurement of
+ * the color. Color appearance models such as CAM16 also use information about the environment where
+ * the color was observed, known as the viewing conditions.
+ *
+ * <p>For example, white under the traditional assumption of a midday sun white point is accurately
+ * measured as a slightly chromatic blue by CAM16. (roughly, hue 203, chroma 3, lightness 100)
+ */
+public final class Cam16 {
+    // Transforms XYZ color space coordinates to 'cone'/'RGB' responses in CAM16.
+    static final double[][] XYZ_TO_CAM16RGB = {
+            {0.401288, 0.650173, -0.051461},
+            {-0.250268, 1.204414, 0.045854},
+            {-0.002079, 0.048952, 0.953127}
+    };
+
+    // Transforms 'cone'/'RGB' responses in CAM16 to XYZ color space coordinates.
+    static final double[][] CAM16RGB_TO_XYZ = {
+            {1.8620678, -1.0112547, 0.14918678},
+            {0.38752654, 0.62144744, -0.00897398},
+            {-0.01584150, -0.03412294, 1.0499644}
+    };
+
+    // CAM16 color dimensions, see getters for documentation.
+    private final double hue;
+    private final double chroma;
+    private final double j;
+    private final double q;
+    private final double m;
+    private final double s;
+
+    // Coordinates in UCS space. Used to determine color distance, like delta E equations in L*a*b*.
+    private final double jstar;
+    private final double astar;
+    private final double bstar;
+
+    // Avoid allocations during conversion by pre-allocating an array.
+    private final double[] tempArray = new double[]{0.0, 0.0, 0.0};
+
+    /**
+     * CAM16 instances also have coordinates in the CAM16-UCS space, called J*, a*, b*, or jstar,
+     * astar, bstar in code. CAM16-UCS is included in the CAM16 specification, and is used to
+     * measure
+     * distances between colors.
+     */
+    double distance(Cam16 other) {
+        double dJ = getJstar() - other.getJstar();
+        double dA = getAstar() - other.getAstar();
+        double dB = getBstar() - other.getBstar();
+        double dEPrime = Math.sqrt(dJ * dJ + dA * dA + dB * dB);
+        double dE = 1.41 * Math.pow(dEPrime, 0.63);
+        return dE;
+    }
+
+    /** Hue in CAM16 */
+    public double getHue() {
+        return hue;
+    }
+
+    /** Chroma in CAM16 */
+    public double getChroma() {
+        return chroma;
+    }
+
+    /** Lightness in CAM16 */
+    public double getJ() {
+        return j;
+    }
+
+    /**
+     * Brightness in CAM16.
+     *
+     * <p>Prefer lightness, brightness is an absolute quantity. For example, a sheet of white paper
+     * is
+     * much brighter viewed in sunlight than in indoor light, but it is the lightest object under
+     * any
+     * lighting.
+     */
+    public double getQ() {
+        return q;
+    }
+
+    /**
+     * Colorfulness in CAM16.
+     *
+     * <p>Prefer chroma, colorfulness is an absolute quantity. For example, a yellow toy car is much
+     * more colorful outside than inside, but it has the same chroma in both environments.
+     */
+    public double getM() {
+        return m;
+    }
+
+    /**
+     * Saturation in CAM16.
+     *
+     * <p>Colorfulness in proportion to brightness. Prefer chroma, saturation measures colorfulness
+     * relative to the color's own brightness, where chroma is colorfulness relative to white.
+     */
+    public double getS() {
+        return s;
+    }
+
+    /** Lightness coordinate in CAM16-UCS */
+    public double getJstar() {
+        return jstar;
+    }
+
+    /** a* coordinate in CAM16-UCS */
+    public double getAstar() {
+        return astar;
+    }
+
+    /** b* coordinate in CAM16-UCS */
+    public double getBstar() {
+        return bstar;
+    }
+
+    /**
+     * All of the CAM16 dimensions can be calculated from 3 of the dimensions, in the following
+     * combinations: - {j or q} and {c, m, or s} and hue - jstar, astar, bstar Prefer using a static
+     * method that constructs from 3 of those dimensions. This constructor is intended for those
+     * methods to use to return all possible dimensions.
+     *
+     * @param hue    for example, red, orange, yellow, green, etc.
+     * @param chroma informally, colorfulness / color intensity. like saturation in HSL, except
+     *               perceptually accurate.
+     * @param j      lightness
+     * @param q      brightness; ratio of lightness to white point's lightness
+     * @param m      colorfulness
+     * @param s      saturation; ratio of chroma to white point's chroma
+     * @param jstar  CAM16-UCS J coordinate
+     * @param astar  CAM16-UCS a coordinate
+     * @param bstar  CAM16-UCS b coordinate
+     */
+    private Cam16(
+            double hue,
+            double chroma,
+            double j,
+            double q,
+            double m,
+            double s,
+            double jstar,
+            double astar,
+            double bstar) {
+        this.hue = hue;
+        this.chroma = chroma;
+        this.j = j;
+        this.q = q;
+        this.m = m;
+        this.s = s;
+        this.jstar = jstar;
+        this.astar = astar;
+        this.bstar = bstar;
+    }
+
+    /**
+     * Create a CAM16 color from a color, assuming the color was viewed in default viewing
+     * conditions.
+     *
+     * @param argb ARGB representation of a color.
+     */
+    public static Cam16 fromInt(int argb) {
+        return fromIntInViewingConditions(argb, ViewingConditions.DEFAULT);
+    }
+
+    /**
+     * Create a CAM16 color from a color in defined viewing conditions.
+     *
+     * @param argb              ARGB representation of a color.
+     * @param viewingConditions Information about the environment where the color was observed.
+     */
+    // The RGB => XYZ conversion matrix elements are derived scientific constants. While the values
+    // may differ at runtime due to floating point imprecision, keeping the values the same, and
+    // accurate, across implementations takes precedence.
+    @SuppressWarnings("FloatingPointLiteralPrecision")
+    static Cam16 fromIntInViewingConditions(int argb, ViewingConditions viewingConditions) {
+        // Transform ARGB int to XYZ
+        int red = (argb & 0x00ff0000) >> 16;
+        int green = (argb & 0x0000ff00) >> 8;
+        int blue = (argb & 0x000000ff);
+        double redL = ColorUtils.linearized(red);
+        double greenL = ColorUtils.linearized(green);
+        double blueL = ColorUtils.linearized(blue);
+        double x = 0.41233895 * redL + 0.35762064 * greenL + 0.18051042 * blueL;
+        double y = 0.2126 * redL + 0.7152 * greenL + 0.0722 * blueL;
+        double z = 0.01932141 * redL + 0.11916382 * greenL + 0.95034478 * blueL;
+
+        return fromXyzInViewingConditions(x, y, z, viewingConditions);
+    }
+
+    static Cam16 fromXyzInViewingConditions(
+            double x, double y, double z, ViewingConditions viewingConditions) {
+        // Transform XYZ to 'cone'/'rgb' responses
+        double[][] matrix = XYZ_TO_CAM16RGB;
+        double rT = (x * matrix[0][0]) + (y * matrix[0][1]) + (z * matrix[0][2]);
+        double gT = (x * matrix[1][0]) + (y * matrix[1][1]) + (z * matrix[1][2]);
+        double bT = (x * matrix[2][0]) + (y * matrix[2][1]) + (z * matrix[2][2]);
+
+        // Discount illuminant
+        double rD = viewingConditions.getRgbD()[0] * rT;
+        double gD = viewingConditions.getRgbD()[1] * gT;
+        double bD = viewingConditions.getRgbD()[2] * bT;
+
+        // Chromatic adaptation
+        double rAF = Math.pow(viewingConditions.getFl() * Math.abs(rD) / 100.0, 0.42);
+        double gAF = Math.pow(viewingConditions.getFl() * Math.abs(gD) / 100.0, 0.42);
+        double bAF = Math.pow(viewingConditions.getFl() * Math.abs(bD) / 100.0, 0.42);
+        double rA = Math.signum(rD) * 400.0 * rAF / (rAF + 27.13);
+        double gA = Math.signum(gD) * 400.0 * gAF / (gAF + 27.13);
+        double bA = Math.signum(bD) * 400.0 * bAF / (bAF + 27.13);
+
+        // redness-greenness
+        double a = (11.0 * rA + -12.0 * gA + bA) / 11.0;
+        // yellowness-blueness
+        double b = (rA + gA - 2.0 * bA) / 9.0;
+
+        // auxiliary components
+        double u = (20.0 * rA + 20.0 * gA + 21.0 * bA) / 20.0;
+        double p2 = (40.0 * rA + 20.0 * gA + bA) / 20.0;
+
+        // hue
+        double atan2 = Math.atan2(b, a);
+        double atanDegrees = Math.toDegrees(atan2);
+        double hue =
+                atanDegrees < 0
+                        ? atanDegrees + 360.0
+                        : atanDegrees >= 360 ? atanDegrees - 360.0 : atanDegrees;
+        double hueRadians = Math.toRadians(hue);
+
+        // achromatic response to color
+        double ac = p2 * viewingConditions.getNbb();
+
+        // CAM16 lightness and brightness
+        double j =
+                100.0
+                        * Math.pow(
+                        ac / viewingConditions.getAw(),
+                        viewingConditions.getC() * viewingConditions.getZ());
+        double q =
+                4.0
+                        / viewingConditions.getC()
+                        * Math.sqrt(j / 100.0)
+                        * (viewingConditions.getAw() + 4.0)
+                        * viewingConditions.getFlRoot();
+
+        // CAM16 chroma, colorfulness, and saturation.
+        double huePrime = (hue < 20.14) ? hue + 360 : hue;
+        double eHue = 0.25 * (Math.cos(Math.toRadians(huePrime) + 2.0) + 3.8);
+        double p1 = 50000.0 / 13.0 * eHue * viewingConditions.getNc() * viewingConditions.getNcb();
+        double t = p1 * Math.hypot(a, b) / (u + 0.305);
+        double alpha =
+                Math.pow(1.64 - Math.pow(0.29, viewingConditions.getN()), 0.73) * Math.pow(t, 0.9);
+        // CAM16 chroma, colorfulness, saturation
+        double c = alpha * Math.sqrt(j / 100.0);
+        double m = c * viewingConditions.getFlRoot();
+        double s =
+                50.0 * Math.sqrt(
+                        (alpha * viewingConditions.getC()) / (viewingConditions.getAw() + 4.0));
+
+        // CAM16-UCS components
+        double jstar = (1.0 + 100.0 * 0.007) * j / (1.0 + 0.007 * j);
+        double mstar = 1.0 / 0.0228 * Math.log1p(0.0228 * m);
+        double astar = mstar * Math.cos(hueRadians);
+        double bstar = mstar * Math.sin(hueRadians);
+
+        return new Cam16(hue, c, j, q, m, s, jstar, astar, bstar);
+    }
+
+    /**
+     * @param j CAM16 lightness
+     * @param c CAM16 chroma
+     * @param h CAM16 hue
+     */
+    static Cam16 fromJch(double j, double c, double h) {
+        return fromJchInViewingConditions(j, c, h, ViewingConditions.DEFAULT);
+    }
+
+    /**
+     * @param j                 CAM16 lightness
+     * @param c                 CAM16 chroma
+     * @param h                 CAM16 hue
+     * @param viewingConditions Information about the environment where the color was observed.
+     */
+    private static Cam16 fromJchInViewingConditions(
+            double j, double c, double h, ViewingConditions viewingConditions) {
+        double q =
+                4.0
+                        / viewingConditions.getC()
+                        * Math.sqrt(j / 100.0)
+                        * (viewingConditions.getAw() + 4.0)
+                        * viewingConditions.getFlRoot();
+        double m = c * viewingConditions.getFlRoot();
+        double alpha = c / Math.sqrt(j / 100.0);
+        double s =
+                50.0 * Math.sqrt(
+                        (alpha * viewingConditions.getC()) / (viewingConditions.getAw() + 4.0));
+
+        double hueRadians = Math.toRadians(h);
+        double jstar = (1.0 + 100.0 * 0.007) * j / (1.0 + 0.007 * j);
+        double mstar = 1.0 / 0.0228 * Math.log1p(0.0228 * m);
+        double astar = mstar * Math.cos(hueRadians);
+        double bstar = mstar * Math.sin(hueRadians);
+        return new Cam16(h, c, j, q, m, s, jstar, astar, bstar);
+    }
+
+    /**
+     * Create a CAM16 color from CAM16-UCS coordinates.
+     *
+     * @param jstar CAM16-UCS lightness.
+     * @param astar CAM16-UCS a dimension. Like a* in L*a*b*, it is a Cartesian coordinate on the Y
+     *              axis.
+     * @param bstar CAM16-UCS b dimension. Like a* in L*a*b*, it is a Cartesian coordinate on the X
+     *              axis.
+     */
+    public static Cam16 fromUcs(double jstar, double astar, double bstar) {
+
+        return fromUcsInViewingConditions(jstar, astar, bstar, ViewingConditions.DEFAULT);
+    }
+
+    /**
+     * Create a CAM16 color from CAM16-UCS coordinates in defined viewing conditions.
+     *
+     * @param jstar             CAM16-UCS lightness.
+     * @param astar             CAM16-UCS a dimension. Like a* in L*a*b*, it is a Cartesian
+     *                          coordinate on the Y
+     *                          axis.
+     * @param bstar             CAM16-UCS b dimension. Like a* in L*a*b*, it is a Cartesian
+     *                          coordinate on the X
+     *                          axis.
+     * @param viewingConditions Information about the environment where the color was observed.
+     */
+    public static Cam16 fromUcsInViewingConditions(
+            double jstar, double astar, double bstar, ViewingConditions viewingConditions) {
+
+        double m = Math.hypot(astar, bstar);
+        double m2 = Math.expm1(m * 0.0228) / 0.0228;
+        double c = m2 / viewingConditions.getFlRoot();
+        double h = Math.atan2(bstar, astar) * (180.0 / Math.PI);
+        if (h < 0.0) {
+            h += 360.0;
+        }
+        double j = jstar / (1. - (jstar - 100.) * 0.007);
+        return fromJchInViewingConditions(j, c, h, viewingConditions);
+    }
+
+    /**
+     * ARGB representation of the color. Assumes the color was viewed in default viewing conditions,
+     * which are near-identical to the default viewing conditions for sRGB.
+     */
+    public int toInt() {
+        return viewed(ViewingConditions.DEFAULT);
+    }
+
+    /**
+     * ARGB representation of the color, in defined viewing conditions.
+     *
+     * @param viewingConditions Information about the environment where the color will be viewed.
+     * @return ARGB representation of color
+     */
+    int viewed(ViewingConditions viewingConditions) {
+        double[] xyz = xyzInViewingConditions(viewingConditions, tempArray);
+        return ColorUtils.argbFromXyz(xyz[0], xyz[1], xyz[2]);
+    }
+
+    double[] xyzInViewingConditions(ViewingConditions viewingConditions, double[] returnArray) {
+        double alpha =
+                (getChroma() == 0.0 || getJ() == 0.0) ? 0.0 : getChroma() / Math.sqrt(
+                        getJ() / 100.0);
+
+        double t =
+                Math.pow(
+                        alpha / Math.pow(1.64 - Math.pow(0.29, viewingConditions.getN()), 0.73),
+                        1.0 / 0.9);
+        double hRad = Math.toRadians(getHue());
+
+        double eHue = 0.25 * (Math.cos(hRad + 2.0) + 3.8);
+        double ac =
+                viewingConditions.getAw()
+                        * Math.pow(getJ() / 100.0,
+                        1.0 / viewingConditions.getC() / viewingConditions.getZ());
+        double p1 =
+                eHue * (50000.0 / 13.0) * viewingConditions.getNc() * viewingConditions.getNcb();
+        double p2 = (ac / viewingConditions.getNbb());
+
+        double hSin = Math.sin(hRad);
+        double hCos = Math.cos(hRad);
+
+        double gamma = 23.0 * (p2 + 0.305) * t / (23.0 * p1 + 11.0 * t * hCos + 108.0 * t * hSin);
+        double a = gamma * hCos;
+        double b = gamma * hSin;
+        double rA = (460.0 * p2 + 451.0 * a + 288.0 * b) / 1403.0;
+        double gA = (460.0 * p2 - 891.0 * a - 261.0 * b) / 1403.0;
+        double bA = (460.0 * p2 - 220.0 * a - 6300.0 * b) / 1403.0;
+
+        double rCBase = max(0, (27.13 * Math.abs(rA)) / (400.0 - Math.abs(rA)));
+        double rC =
+                Math.signum(rA) * (100.0 / viewingConditions.getFl()) * Math.pow(rCBase,
+                        1.0 / 0.42);
+        double gCBase = max(0, (27.13 * Math.abs(gA)) / (400.0 - Math.abs(gA)));
+        double gC =
+                Math.signum(gA) * (100.0 / viewingConditions.getFl()) * Math.pow(gCBase,
+                        1.0 / 0.42);
+        double bCBase = max(0, (27.13 * Math.abs(bA)) / (400.0 - Math.abs(bA)));
+        double bC =
+                Math.signum(bA) * (100.0 / viewingConditions.getFl()) * Math.pow(bCBase,
+                        1.0 / 0.42);
+        double rF = rC / viewingConditions.getRgbD()[0];
+        double gF = gC / viewingConditions.getRgbD()[1];
+        double bF = bC / viewingConditions.getRgbD()[2];
+
+        double[][] matrix = CAM16RGB_TO_XYZ;
+        double x = (rF * matrix[0][0]) + (gF * matrix[0][1]) + (bF * matrix[0][2]);
+        double y = (rF * matrix[1][0]) + (gF * matrix[1][1]) + (bF * matrix[1][2]);
+        double z = (rF * matrix[2][0]) + (gF * matrix[2][1]) + (bF * matrix[2][2]);
+
+        if (returnArray != null) {
+            returnArray[0] = x;
+            returnArray[1] = y;
+            returnArray[2] = z;
+            return returnArray;
+        } else {
+            return new double[]{x, y, z};
+        }
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/hct/Hct.java b/packages/SystemUI/monet/src/com/android/systemui/monet/hct/Hct.java
new file mode 100644
index 0000000..6cff99e
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/hct/Hct.java
@@ -0,0 +1,164 @@
+/*
+ * 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.monet.hct;
+
+import com.android.systemui.monet.utils.ColorUtils;
+
+/**
+ * A color system built using CAM16 hue and chroma, and L* from L*a*b*.
+ *
+ * <p>Using L* creates a link between the color system, contrast, and thus accessibility. Contrast
+ * ratio depends on relative luminance, or Y in the XYZ color space. L*, or perceptual luminance can
+ * be calculated from Y.
+ *
+ * <p>Unlike Y, L* is linear to human perception, allowing trivial creation of accurate color tones.
+ *
+ * <p>Unlike contrast ratio, measuring contrast in L* is linear, and simple to calculate. A
+ * difference of 40 in HCT tone guarantees a contrast ratio >= 3.0, and a difference of 50
+ * guarantees a contrast ratio >= 4.5.
+ */
+
+/**
+ * HCT, hue, chroma, and tone. A color system that provides a perceptually accurate color
+ * measurement system that can also accurately render what colors will appear as in different
+ * lighting environments.
+ */
+public final class Hct {
+    private double hue;
+    private double chroma;
+    private double tone;
+    private int argb;
+
+    /**
+     * Create an HCT color from hue, chroma, and tone.
+     *
+     * @param hue    0 <= hue < 360; invalid values are corrected.
+     * @param chroma 0 <= chroma < ?; Informally, colorfulness. The color returned may be lower
+     *               than
+     *               the requested chroma. Chroma has a different maximum for any given hue and
+     *               tone.
+     * @param tone   0 <= tone <= 100; invalid values are corrected.
+     * @return HCT representation of a color in default viewing conditions.
+     */
+    public static Hct from(double hue, double chroma, double tone) {
+        int argb = HctSolver.solveToInt(hue, chroma, tone);
+        return new Hct(argb);
+    }
+
+    /**
+     * Create an HCT color from a color.
+     *
+     * @param argb ARGB representation of a color.
+     * @return HCT representation of a color in default viewing conditions
+     */
+    public static Hct fromInt(int argb) {
+        return new Hct(argb);
+    }
+
+    private Hct(int argb) {
+        setInternalState(argb);
+    }
+
+    public double getHue() {
+        return hue;
+    }
+
+    public double getChroma() {
+        return chroma;
+    }
+
+    public double getTone() {
+        return tone;
+    }
+
+    /** This color converted to ARGB, i.e. a hex code. */
+    public int toInt() {
+        return argb;
+    }
+
+    /**
+     * Set the hue of this color. Chroma may decrease because chroma has a different maximum for any
+     * given hue and tone.
+     *
+     * @param newHue 0 <= newHue < 360; invalid values are corrected.
+     */
+    public void setHue(double newHue) {
+        setInternalState(HctSolver.solveToInt(newHue, chroma, tone));
+    }
+
+    /**
+     * Set the chroma of this color. Chroma may decrease because chroma has a different maximum for
+     * any given hue and tone.
+     *
+     * @param newChroma 0 <= newChroma < ?
+     */
+    public void setChroma(double newChroma) {
+        setInternalState(HctSolver.solveToInt(hue, newChroma, tone));
+    }
+
+    /**
+     * Set the tone of this color. Chroma may decrease because chroma has a different maximum for
+     * any
+     * given hue and tone.
+     *
+     * @param newTone 0 <= newTone <= 100; invalid valids are corrected.
+     */
+    public void setTone(double newTone) {
+        setInternalState(HctSolver.solveToInt(hue, chroma, newTone));
+    }
+
+    /**
+     * Translate a color into different ViewingConditions.
+     *
+     * <p>Colors change appearance. They look different with lights on versus off, the same color,
+     * as
+     * in hex code, on white looks different when on black. This is called color relativity, most
+     * famously explicated by Josef Albers in Interaction of Color.
+     *
+     * <p>In color science, color appearance models can account for this and calculate the
+     * appearance
+     * of a color in different settings. HCT is based on CAM16, a color appearance model, and uses
+     * it
+     * to make these calculations.
+     *
+     * <p>See ViewingConditions.make for parameters affecting color appearance.
+     */
+    public Hct inViewingConditions(ViewingConditions vc) {
+        // 1. Use CAM16 to find XYZ coordinates of color in specified VC.
+        Cam16 cam16 = Cam16.fromInt(toInt());
+        double[] viewedInVc = cam16.xyzInViewingConditions(vc, null);
+
+        // 2. Create CAM16 of those XYZ coordinates in default VC.
+        Cam16 recastInVc =
+                Cam16.fromXyzInViewingConditions(
+                        viewedInVc[0], viewedInVc[1], viewedInVc[2], ViewingConditions.DEFAULT);
+
+        // 3. Create HCT from:
+        // - CAM16 using default VC with XYZ coordinates in specified VC.
+        // - L* converted from Y in XYZ coordinates in specified VC.
+        return Hct.from(
+                recastInVc.getHue(), recastInVc.getChroma(), ColorUtils.lstarFromY(viewedInVc[1]));
+    }
+
+    private void setInternalState(int argb) {
+        this.argb = argb;
+        Cam16 cam = Cam16.fromInt(argb);
+        hue = cam.getHue();
+        chroma = cam.getChroma();
+        this.tone = ColorUtils.lstarFromArgb(argb);
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/hct/HctSolver.java b/packages/SystemUI/monet/src/com/android/systemui/monet/hct/HctSolver.java
new file mode 100644
index 0000000..7083222
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/hct/HctSolver.java
@@ -0,0 +1,677 @@
+/*
+ * 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.monet.hct;
+
+import com.android.systemui.monet.utils.ColorUtils;
+import com.android.systemui.monet.utils.MathUtils;
+
+/** A class that solves the HCT equation. */
+public class HctSolver {
+    private HctSolver() {
+    }
+
+    static final double[][] SCALED_DISCOUNT_FROM_LINRGB =
+            new double[][]{
+                    new double[]{
+                            0.001200833568784504, 0.002389694492170889, 0.0002795742885861124,
+                    },
+                    new double[]{
+                            0.0005891086651375999, 0.0029785502573438758, 0.0003270666104008398,
+                    },
+                    new double[]{
+                            0.00010146692491640572, 0.0005364214359186694, 0.0032979401770712076,
+                    },
+            };
+
+    static final double[][] LINRGB_FROM_SCALED_DISCOUNT =
+            new double[][]{
+                    new double[]{
+                            1373.2198709594231, -1100.4251190754821, -7.278681089101213,
+                    },
+                    new double[]{
+                            -271.815969077903, 559.6580465940733, -32.46047482791194,
+                    },
+                    new double[]{
+                            1.9622899599665666, -57.173814538844006, 308.7233197812385,
+                    },
+            };
+
+    static final double[] Y_FROM_LINRGB = new double[]{0.2126, 0.7152, 0.0722};
+
+    static final double[] CRITICAL_PLANES =
+            new double[]{
+                    0.015176349177441876,
+                    0.045529047532325624,
+                    0.07588174588720938,
+                    0.10623444424209313,
+                    0.13658714259697685,
+                    0.16693984095186062,
+                    0.19729253930674434,
+                    0.2276452376616281,
+                    0.2579979360165119,
+                    0.28835063437139563,
+                    0.3188300904430532,
+                    0.350925934958123,
+                    0.3848314933096426,
+                    0.42057480301049466,
+                    0.458183274052838,
+                    0.4976837250274023,
+                    0.5391024159806381,
+                    0.5824650784040898,
+                    0.6277969426914107,
+                    0.6751227633498623,
+                    0.7244668422128921,
+                    0.775853049866786,
+                    0.829304845476233,
+                    0.8848452951698498,
+                    0.942497089126609,
+                    1.0022825574869039,
+                    1.0642236851973577,
+                    1.1283421258858297,
+                    1.1946592148522128,
+                    1.2631959812511864,
+                    1.3339731595349034,
+                    1.407011200216447,
+                    1.4823302800086415,
+                    1.5599503113873272,
+                    1.6398909516233677,
+                    1.7221716113234105,
+                    1.8068114625156377,
+                    1.8938294463134073,
+                    1.9832442801866852,
+                    2.075074464868551,
+                    2.1693382909216234,
+                    2.2660538449872063,
+                    2.36523901573795,
+                    2.4669114995532007,
+                    2.5710888059345764,
+                    2.6777882626779785,
+                    2.7870270208169257,
+                    2.898822059350997,
+                    3.0131901897720907,
+                    3.1301480604002863,
+                    3.2497121605402226,
+                    3.3718988244681087,
+                    3.4967242352587946,
+                    3.624204428461639,
+                    3.754355295633311,
+                    3.887192587735158,
+                    4.022731918402185,
+                    4.160988767090289,
+                    4.301978482107941,
+                    4.445716283538092,
+                    4.592217266055746,
+                    4.741496401646282,
+                    4.893568542229298,
+                    5.048448422192488,
+                    5.20615066083972,
+                    5.3666897647573375,
+                    5.5300801301023865,
+                    5.696336044816294,
+                    5.865471690767354,
+                    6.037501145825082,
+                    6.212438385869475,
+                    6.390297286737924,
+                    6.571091626112461,
+                    6.7548350853498045,
+                    6.941541251256611,
+                    7.131223617812143,
+                    7.323895587840543,
+                    7.5195704746346665,
+                    7.7182615035334345,
+                    7.919981813454504,
+                    8.124744458384042,
+                    8.332562408825165,
+                    8.543448553206703,
+                    8.757415699253682,
+                    8.974476575321063,
+                    9.194643831691977,
+                    9.417930041841839,
+                    9.644347703669503,
+                    9.873909240696694,
+                    10.106627003236781,
+                    10.342513269534024,
+                    10.58158024687427,
+                    10.8238400726681,
+                    11.069304815507364,
+                    11.317986476196008,
+                    11.569896988756009,
+                    11.825048221409341,
+                    12.083451977536606,
+                    12.345119996613247,
+                    12.610063955123938,
+                    12.878295467455942,
+                    13.149826086772048,
+                    13.42466730586372,
+                    13.702830557985108,
+                    13.984327217668513,
+                    14.269168601521828,
+                    14.55736596900856,
+                    14.848930523210871,
+                    15.143873411576273,
+                    15.44220572664832,
+                    15.743938506781891,
+                    16.04908273684337,
+                    16.35764934889634,
+                    16.66964922287304,
+                    16.985093187232053,
+                    17.30399201960269,
+                    17.62635644741625,
+                    17.95219714852476,
+                    18.281524751807332,
+                    18.614349837764564,
+                    18.95068293910138,
+                    19.290534541298456,
+                    19.633915083172692,
+                    19.98083495742689,
+                    20.331304511189067,
+                    20.685334046541502,
+                    21.042933821039977,
+                    21.404114048223256,
+                    21.76888489811322,
+                    22.137256497705877,
+                    22.50923893145328,
+                    22.884842241736916,
+                    23.264076429332462,
+                    23.6469514538663,
+                    24.033477234264016,
+                    24.42366364919083,
+                    24.817520537484558,
+                    25.21505769858089,
+                    25.61628489293138,
+                    26.021211842414342,
+                    26.429848230738664,
+                    26.842203703840827,
+                    27.258287870275353,
+                    27.678110301598522,
+                    28.10168053274597,
+                    28.529008062403893,
+                    28.96010235337422,
+                    29.39497283293396,
+                    29.83362889318845,
+                    30.276079891419332,
+                    30.722335150426627,
+                    31.172403958865512,
+                    31.62629557157785,
+                    32.08401920991837,
+                    32.54558406207592,
+                    33.010999283389665,
+                    33.4802739966603,
+                    33.953417292456834,
+                    34.430438229418264,
+                    34.911345834551085,
+                    35.39614910352207,
+                    35.88485700094671,
+                    36.37747846067349,
+                    36.87402238606382,
+                    37.37449765026789,
+                    37.87891309649659,
+                    38.38727753828926,
+                    38.89959975977785,
+                    39.41588851594697,
+                    39.93615253289054,
+                    40.460400508064545,
+                    40.98864111053629,
+                    41.520882981230194,
+                    42.05713473317016,
+                    42.597404951718396,
+                    43.141702194811224,
+                    43.6900349931913,
+                    44.24241185063697,
+                    44.798841244188324,
+                    45.35933162437017,
+                    45.92389141541209,
+                    46.49252901546552,
+                    47.065252796817916,
+                    47.64207110610409,
+                    48.22299226451468,
+                    48.808024568002054,
+                    49.3971762874833,
+                    49.9904556690408,
+                    50.587870934119984,
+                    51.189430279724725,
+                    51.79514187861014,
+                    52.40501387947288,
+                    53.0190544071392,
+                    53.637271562750364,
+                    54.259673423945976,
+                    54.88626804504493,
+                    55.517063457223934,
+                    56.15206766869424,
+                    56.79128866487574,
+                    57.43473440856916,
+                    58.08241284012621,
+                    58.734331877617365,
+                    59.39049941699807,
+                    60.05092333227251,
+                    60.715611475655585,
+                    61.38457167773311,
+                    62.057811747619894,
+                    62.7353394731159,
+                    63.417162620860914,
+                    64.10328893648692,
+                    64.79372614476921,
+                    65.48848194977529,
+                    66.18756403501224,
+                    66.89098006357258,
+                    67.59873767827808,
+                    68.31084450182222,
+                    69.02730813691093,
+                    69.74813616640164,
+                    70.47333615344107,
+                    71.20291564160104,
+                    71.93688215501312,
+                    72.67524319850172,
+                    73.41800625771542,
+                    74.16517879925733,
+                    74.9167682708136,
+                    75.67278210128072,
+                    76.43322770089146,
+                    77.1981124613393,
+                    77.96744375590167,
+                    78.74122893956174,
+                    79.51947534912904,
+                    80.30219030335869,
+                    81.08938110306934,
+                    81.88105503125999,
+                    82.67721935322541,
+                    83.4778813166706,
+                    84.28304815182372,
+                    85.09272707154808,
+                    85.90692527145302,
+                    86.72564993000343,
+                    87.54890820862819,
+                    88.3767072518277,
+                    89.2090541872801,
+                    90.04595612594655,
+                    90.88742016217518,
+                    91.73345337380438,
+                    92.58406282226491,
+                    93.43925555268066,
+                    94.29903859396902,
+                    95.16341895893969,
+                    96.03240364439274,
+                    96.9059996312159,
+                    97.78421388448044,
+                    98.6670533535366,
+                    99.55452497210776,
+            };
+
+    /**
+     * Sanitizes a small enough angle in radians.
+     *
+     * @param angle An angle in radians; must not deviate too much from 0.
+     * @return A coterminal angle between 0 and 2pi.
+     */
+    static double sanitizeRadians(double angle) {
+        return (angle + Math.PI * 8) % (Math.PI * 2);
+    }
+
+    /**
+     * Delinearizes an RGB component, returning a floating-point number.
+     *
+     * @param rgbComponent 0.0 <= rgb_component <= 100.0, represents linear R/G/B channel
+     * @return 0.0 <= output <= 255.0, color channel converted to regular RGB space
+     */
+    static double trueDelinearized(double rgbComponent) {
+        double normalized = rgbComponent / 100.0;
+        double delinearized = 0.0;
+        if (normalized <= 0.0031308) {
+            delinearized = normalized * 12.92;
+        } else {
+            delinearized = 1.055 * Math.pow(normalized, 1.0 / 2.4) - 0.055;
+        }
+        return delinearized * 255.0;
+    }
+
+    static double chromaticAdaptation(double component) {
+        double af = Math.pow(Math.abs(component), 0.42);
+        return MathUtils.signum(component) * 400.0 * af / (af + 27.13);
+    }
+
+    /**
+     * Returns the hue of a linear RGB color in CAM16.
+     *
+     * @param linrgb The linear RGB coordinates of a color.
+     * @return The hue of the color in CAM16, in radians.
+     */
+    static double hueOf(double[] linrgb) {
+        double[] scaledDiscount = MathUtils.matrixMultiply(linrgb, SCALED_DISCOUNT_FROM_LINRGB);
+        double rA = chromaticAdaptation(scaledDiscount[0]);
+        double gA = chromaticAdaptation(scaledDiscount[1]);
+        double bA = chromaticAdaptation(scaledDiscount[2]);
+        // redness-greenness
+        double a = (11.0 * rA + -12.0 * gA + bA) / 11.0;
+        // yellowness-blueness
+        double b = (rA + gA - 2.0 * bA) / 9.0;
+        return Math.atan2(b, a);
+    }
+
+    static boolean areInCyclicOrder(double a, double b, double c) {
+        double deltaAB = sanitizeRadians(b - a);
+        double deltaAC = sanitizeRadians(c - a);
+        return deltaAB < deltaAC;
+    }
+
+    /**
+     * Solves the lerp equation.
+     *
+     * @param source The starting number.
+     * @param mid    The number in the middle.
+     * @param target The ending number.
+     * @return A number t such that lerp(source, target, t) = mid.
+     */
+    static double intercept(double source, double mid, double target) {
+        return (mid - source) / (target - source);
+    }
+
+    static double[] lerpPoint(double[] source, double t, double[] target) {
+        return new double[]{
+                source[0] + (target[0] - source[0]) * t,
+                source[1] + (target[1] - source[1]) * t,
+                source[2] + (target[2] - source[2]) * t,
+        };
+    }
+
+    /**
+     * Intersects a segment with a plane.
+     *
+     * @param source     The coordinates of point A.
+     * @param coordinate The R-, G-, or B-coordinate of the plane.
+     * @param target     The coordinates of point B.
+     * @param axis       The axis the plane is perpendicular with. (0: R, 1: G, 2: B)
+     * @return The intersection point of the segment AB with the plane R=coordinate,
+     * G=coordinate, or
+     * B=coordinate
+     */
+    static double[] setCoordinate(double[] source, double coordinate, double[] target, int axis) {
+        double t = intercept(source[axis], coordinate, target[axis]);
+        return lerpPoint(source, t, target);
+    }
+
+    static boolean isBounded(double x) {
+        return 0.0 <= x && x <= 100.0;
+    }
+
+    /**
+     * Returns the nth possible vertex of the polygonal intersection.
+     *
+     * @param y The Y value of the plane.
+     * @param n The zero-based index of the point. 0 <= n <= 11.
+     * @return The nth possible vertex of the polygonal intersection of the y plane and the RGB
+     * cube,
+     * in linear RGB coordinates, if it exists. If this possible vertex lies outside of the cube,
+     * [-1.0, -1.0, -1.0] is returned.
+     */
+    static double[] nthVertex(double y, int n) {
+        double kR = Y_FROM_LINRGB[0];
+        double kG = Y_FROM_LINRGB[1];
+        double kB = Y_FROM_LINRGB[2];
+        double coordA = n % 4 <= 1 ? 0.0 : 100.0;
+        double coordB = n % 2 == 0 ? 0.0 : 100.0;
+        if (n < 4) {
+            double g = coordA;
+            double b = coordB;
+            double r = (y - g * kG - b * kB) / kR;
+            if (isBounded(r)) {
+                return new double[]{r, g, b};
+            } else {
+                return new double[]{-1.0, -1.0, -1.0};
+            }
+        } else if (n < 8) {
+            double b = coordA;
+            double r = coordB;
+            double g = (y - r * kR - b * kB) / kG;
+            if (isBounded(g)) {
+                return new double[]{r, g, b};
+            } else {
+                return new double[]{-1.0, -1.0, -1.0};
+            }
+        } else {
+            double r = coordA;
+            double g = coordB;
+            double b = (y - r * kR - g * kG) / kB;
+            if (isBounded(b)) {
+                return new double[]{r, g, b};
+            } else {
+                return new double[]{-1.0, -1.0, -1.0};
+            }
+        }
+    }
+
+    /**
+     * Finds the segment containing the desired color.
+     *
+     * @param y         The Y value of the color.
+     * @param targetHue The hue of the color.
+     * @return A list of two sets of linear RGB coordinates, each corresponding to an endpoint of
+     * the
+     * segment containing the desired color.
+     */
+    static double[][] bisectToSegment(double y, double targetHue) {
+        double[] left = new double[]{-1.0, -1.0, -1.0};
+        double[] right = left;
+        double leftHue = 0.0;
+        double rightHue = 0.0;
+        boolean initialized = false;
+        boolean uncut = true;
+        for (int n = 0; n < 12; n++) {
+            double[] mid = nthVertex(y, n);
+            if (mid[0] < 0) {
+                continue;
+            }
+            double midHue = hueOf(mid);
+            if (!initialized) {
+                left = mid;
+                right = mid;
+                leftHue = midHue;
+                rightHue = midHue;
+                initialized = true;
+                continue;
+            }
+            if (uncut || areInCyclicOrder(leftHue, midHue, rightHue)) {
+                uncut = false;
+                if (areInCyclicOrder(leftHue, targetHue, midHue)) {
+                    right = mid;
+                    rightHue = midHue;
+                } else {
+                    left = mid;
+                    leftHue = midHue;
+                }
+            }
+        }
+        return new double[][]{left, right};
+    }
+
+    static double[] midpoint(double[] a, double[] b) {
+        return new double[]{
+                (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2,
+        };
+    }
+
+    static int criticalPlaneBelow(double x) {
+        return (int) Math.floor(x - 0.5);
+    }
+
+    static int criticalPlaneAbove(double x) {
+        return (int) Math.ceil(x - 0.5);
+    }
+
+    /**
+     * Finds a color with the given Y and hue on the boundary of the cube.
+     *
+     * @param y         The Y value of the color.
+     * @param targetHue The hue of the color.
+     * @return The desired color, in linear RGB coordinates.
+     */
+    static double[] bisectToLimit(double y, double targetHue) {
+        double[][] segment = bisectToSegment(y, targetHue);
+        double[] left = segment[0];
+        double leftHue = hueOf(left);
+        double[] right = segment[1];
+        for (int axis = 0; axis < 3; axis++) {
+            if (left[axis] != right[axis]) {
+                int lPlane = -1;
+                int rPlane = 255;
+                if (left[axis] < right[axis]) {
+                    lPlane = criticalPlaneBelow(trueDelinearized(left[axis]));
+                    rPlane = criticalPlaneAbove(trueDelinearized(right[axis]));
+                } else {
+                    lPlane = criticalPlaneAbove(trueDelinearized(left[axis]));
+                    rPlane = criticalPlaneBelow(trueDelinearized(right[axis]));
+                }
+                for (int i = 0; i < 8; i++) {
+                    if (Math.abs(rPlane - lPlane) <= 1) {
+                        break;
+                    } else {
+                        int mPlane = (int) Math.floor((lPlane + rPlane) / 2.0);
+                        double midPlaneCoordinate = CRITICAL_PLANES[mPlane];
+                        double[] mid = setCoordinate(left, midPlaneCoordinate, right, axis);
+                        double midHue = hueOf(mid);
+                        if (areInCyclicOrder(leftHue, targetHue, midHue)) {
+                            right = mid;
+                            rPlane = mPlane;
+                        } else {
+                            left = mid;
+                            leftHue = midHue;
+                            lPlane = mPlane;
+                        }
+                    }
+                }
+            }
+        }
+        return midpoint(left, right);
+    }
+
+    static double inverseChromaticAdaptation(double adapted) {
+        double adaptedAbs = Math.abs(adapted);
+        double base = Math.max(0, 27.13 * adaptedAbs / (400.0 - adaptedAbs));
+        return MathUtils.signum(adapted) * Math.pow(base, 1.0 / 0.42);
+    }
+
+    /**
+     * Finds a color with the given hue, chroma, and Y.
+     *
+     * @param hueRadians The desired hue in radians.
+     * @param chroma     The desired chroma.
+     * @param y          The desired Y.
+     * @return The desired color as a hexadecimal integer, if found; 0 otherwise.
+     */
+    static int findResultByJ(double hueRadians, double chroma, double y) {
+        // Initial estimate of j.
+        double j = Math.sqrt(y) * 11.0;
+        // ===========================================================
+        // Operations inlined from Cam16 to avoid repeated calculation
+        // ===========================================================
+        ViewingConditions viewingConditions = ViewingConditions.DEFAULT;
+        double tInnerCoeff = 1 / Math.pow(1.64 - Math.pow(0.29, viewingConditions.getN()), 0.73);
+        double eHue = 0.25 * (Math.cos(hueRadians + 2.0) + 3.8);
+        double p1 =
+                eHue * (50000.0 / 13.0) * viewingConditions.getNc() * viewingConditions.getNcb();
+        double hSin = Math.sin(hueRadians);
+        double hCos = Math.cos(hueRadians);
+        for (int iterationRound = 0; iterationRound < 5; iterationRound++) {
+            // ===========================================================
+            // Operations inlined from Cam16 to avoid repeated calculation
+            // ===========================================================
+            double jNormalized = j / 100.0;
+            double alpha = chroma == 0.0 || j == 0.0 ? 0.0 : chroma / Math.sqrt(jNormalized);
+            double t = Math.pow(alpha * tInnerCoeff, 1.0 / 0.9);
+            double ac =
+                    viewingConditions.getAw()
+                            * Math.pow(jNormalized,
+                            1.0 / viewingConditions.getC() / viewingConditions.getZ());
+            double p2 = ac / viewingConditions.getNbb();
+            double gamma = 23.0 * (p2 + 0.305) * t / (23.0 * p1 + 11 * t * hCos + 108.0 * t * hSin);
+            double a = gamma * hCos;
+            double b = gamma * hSin;
+            double rA = (460.0 * p2 + 451.0 * a + 288.0 * b) / 1403.0;
+            double gA = (460.0 * p2 - 891.0 * a - 261.0 * b) / 1403.0;
+            double bA = (460.0 * p2 - 220.0 * a - 6300.0 * b) / 1403.0;
+            double rCScaled = inverseChromaticAdaptation(rA);
+            double gCScaled = inverseChromaticAdaptation(gA);
+            double bCScaled = inverseChromaticAdaptation(bA);
+            double[] linrgb =
+                    MathUtils.matrixMultiply(
+                            new double[]{rCScaled, gCScaled, bCScaled},
+                            LINRGB_FROM_SCALED_DISCOUNT);
+            // ===========================================================
+            // Operations inlined from Cam16 to avoid repeated calculation
+            // ===========================================================
+            if (linrgb[0] < 0 || linrgb[1] < 0 || linrgb[2] < 0) {
+                return 0;
+            }
+            double kR = Y_FROM_LINRGB[0];
+            double kG = Y_FROM_LINRGB[1];
+            double kB = Y_FROM_LINRGB[2];
+            double fnj = kR * linrgb[0] + kG * linrgb[1] + kB * linrgb[2];
+            if (fnj <= 0) {
+                return 0;
+            }
+            if (iterationRound == 4 || Math.abs(fnj - y) < 0.002) {
+                if (linrgb[0] > 100.01 || linrgb[1] > 100.01 || linrgb[2] > 100.01) {
+                    return 0;
+                }
+                return ColorUtils.argbFromLinrgb(linrgb);
+            }
+            // Iterates with Newton method,
+            // Using 2 * fn(j) / j as the approximation of fn'(j)
+            j = j - (fnj - y) * j / (2 * fnj);
+        }
+        return 0;
+    }
+
+    /**
+     * Finds an sRGB color with the given hue, chroma, and L*, if possible.
+     *
+     * @param hueDegrees The desired hue, in degrees.
+     * @param chroma     The desired chroma.
+     * @param lstar      The desired L*.
+     * @return A hexadecimal representing the sRGB color. The color has sufficiently close hue,
+     * chroma, and L* to the desired values, if possible; otherwise, the hue and L* will be
+     * sufficiently close, and chroma will be maximized.
+     */
+    public static int solveToInt(double hueDegrees, double chroma, double lstar) {
+        if (chroma < 0.0001 || lstar < 0.0001 || lstar > 99.9999) {
+            return ColorUtils.argbFromLstar(lstar);
+        }
+        hueDegrees = MathUtils.sanitizeDegreesDouble(hueDegrees);
+        double hueRadians = hueDegrees / 180 * Math.PI;
+        double y = ColorUtils.yFromLstar(lstar);
+        int exactAnswer = findResultByJ(hueRadians, chroma, y);
+        if (exactAnswer != 0) {
+            return exactAnswer;
+        }
+        double[] linrgb = bisectToLimit(y, hueRadians);
+        return ColorUtils.argbFromLinrgb(linrgb);
+    }
+
+    /**
+     * Finds an sRGB color with the given hue, chroma, and L*, if possible.
+     *
+     * @param hueDegrees The desired hue, in degrees.
+     * @param chroma     The desired chroma.
+     * @param lstar      The desired L*.
+     * @return A CAM16 object representing the sRGB color. The color has sufficiently close hue,
+     * chroma, and L* to the desired values, if possible; otherwise, the hue and L* will be
+     * sufficiently close, and chroma will be maximized.
+     */
+    public static Cam16 solveToCam(double hueDegrees, double chroma, double lstar) {
+        return Cam16.fromInt(solveToInt(hueDegrees, chroma, lstar));
+    }
+}
+
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/hct/ViewingConditions.java b/packages/SystemUI/monet/src/com/android/systemui/monet/hct/ViewingConditions.java
new file mode 100644
index 0000000..a0ba7a6
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/hct/ViewingConditions.java
@@ -0,0 +1,218 @@
+/*
+ * 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.monet.hct;
+
+import com.android.systemui.monet.utils.ColorUtils;
+import com.android.systemui.monet.utils.MathUtils;
+
+/**
+ * In traditional color spaces, a color can be identified solely by the observer's measurement of
+ * the color. Color appearance models such as CAM16 also use information about the environment where
+ * the color was observed, known as the viewing conditions.
+ *
+ * <p>For example, white under the traditional assumption of a midday sun white point is accurately
+ * measured as a slightly chromatic blue by CAM16. (roughly, hue 203, chroma 3, lightness 100)
+ *
+ * <p>This class caches intermediate values of the CAM16 conversion process that depend only on
+ * viewing conditions, enabling speed ups.
+ */
+public final class ViewingConditions {
+    /** sRGB-like viewing conditions. */
+    public static final ViewingConditions DEFAULT =
+            ViewingConditions.defaultWithBackgroundLstar(50.0);
+
+    private final double aw;
+    private final double nbb;
+    private final double ncb;
+    private final double c;
+    private final double nc;
+    private final double n;
+    private final double[] rgbD;
+    private final double fl;
+    private final double flRoot;
+    private final double z;
+
+    public double getAw() {
+        return aw;
+    }
+
+    public double getN() {
+        return n;
+    }
+
+    public double getNbb() {
+        return nbb;
+    }
+
+    double getNcb() {
+        return ncb;
+    }
+
+    double getC() {
+        return c;
+    }
+
+    double getNc() {
+        return nc;
+    }
+
+    public double[] getRgbD() {
+        return rgbD;
+    }
+
+    double getFl() {
+        return fl;
+    }
+
+    public double getFlRoot() {
+        return flRoot;
+    }
+
+    double getZ() {
+        return z;
+    }
+
+    /**
+     * Create ViewingConditions from a simple, physically relevant, set of parameters.
+     *
+     * @param whitePoint            White point, measured in the XYZ color space. default = D65, or
+     *                              sunny day
+     *                              afternoon
+     * @param adaptingLuminance     The luminance of the adapting field. Informally, how bright it
+     *                              is in
+     *                              the room where the color is viewed. Can be calculated from lux
+     *                              by multiplying lux by
+     *                              0.0586. default = 11.72, or 200 lux.
+     * @param backgroundLstar       The lightness of the area surrounding the color. measured by L*
+     *                              in
+     *                              L*a*b*. default = 50.0
+     * @param surround              A general description of the lighting surrounding the color. 0
+     *                              is pitch dark,
+     *                              like watching a movie in a theater. 1.0 is a dimly light room,
+     *                              like watching TV at home at
+     *                              night. 2.0 means there is no difference between the lighting on
+     *                              the color and around it.
+     *                              default = 2.0
+     * @param discountingIlluminant Whether the eye accounts for the tint of the ambient lighting,
+     *                              such as knowing an apple is still red in green light. default =
+     *                              false, the eye does not
+     *                              perform this process on self-luminous objects like displays.
+     */
+    public static ViewingConditions make(
+            double[] whitePoint,
+            double adaptingLuminance,
+            double backgroundLstar,
+            double surround,
+            boolean discountingIlluminant) {
+        // A background of pure black is non-physical and leads to infinities that represent the
+        // idea
+        // that any color viewed in pure black can't be seen.
+        backgroundLstar = Math.max(0.1, backgroundLstar);
+        // Transform white point XYZ to 'cone'/'rgb' responses
+        double[][] matrix = Cam16.XYZ_TO_CAM16RGB;
+        double[] xyz = whitePoint;
+        double rW = (xyz[0] * matrix[0][0]) + (xyz[1] * matrix[0][1]) + (xyz[2] * matrix[0][2]);
+        double gW = (xyz[0] * matrix[1][0]) + (xyz[1] * matrix[1][1]) + (xyz[2] * matrix[1][2]);
+        double bW = (xyz[0] * matrix[2][0]) + (xyz[1] * matrix[2][1]) + (xyz[2] * matrix[2][2]);
+        double f = 0.8 + (surround / 10.0);
+        double c =
+                (f >= 0.9)
+                        ? MathUtils.lerp(0.59, 0.69, ((f - 0.9) * 10.0))
+                        : MathUtils.lerp(0.525, 0.59, ((f - 0.8) * 10.0));
+        double d =
+                discountingIlluminant
+                        ? 1.0
+                        : f * (1.0 - ((1.0 / 3.6) * Math.exp((-adaptingLuminance - 42.0) / 92.0)));
+        d = MathUtils.clampDouble(0.0, 1.0, d);
+        double nc = f;
+        double[] rgbD =
+                new double[]{
+                        d * (100.0 / rW) + 1.0 - d, d * (100.0 / gW) + 1.0 - d,
+                        d * (100.0 / bW) + 1.0 - d
+                };
+        double k = 1.0 / (5.0 * adaptingLuminance + 1.0);
+        double k4 = k * k * k * k;
+        double k4F = 1.0 - k4;
+        double fl = (k4 * adaptingLuminance) + (0.1 * k4F * k4F * Math.cbrt(
+                5.0 * adaptingLuminance));
+        double n = (ColorUtils.yFromLstar(backgroundLstar) / whitePoint[1]);
+        double z = 1.48 + Math.sqrt(n);
+        double nbb = 0.725 / Math.pow(n, 0.2);
+        double ncb = nbb;
+        double[] rgbAFactors =
+                new double[]{
+                        Math.pow(fl * rgbD[0] * rW / 100.0, 0.42),
+                        Math.pow(fl * rgbD[1] * gW / 100.0, 0.42),
+                        Math.pow(fl * rgbD[2] * bW / 100.0, 0.42)
+                };
+
+        double[] rgbA =
+                new double[]{
+                        (400.0 * rgbAFactors[0]) / (rgbAFactors[0] + 27.13),
+                        (400.0 * rgbAFactors[1]) / (rgbAFactors[1] + 27.13),
+                        (400.0 * rgbAFactors[2]) / (rgbAFactors[2] + 27.13)
+                };
+
+        double aw = ((2.0 * rgbA[0]) + rgbA[1] + (0.05 * rgbA[2])) * nbb;
+        return new ViewingConditions(n, aw, nbb, ncb, c, nc, rgbD, fl, Math.pow(fl, 0.25), z);
+    }
+
+    /**
+     * Create sRGB-like viewing conditions with a custom background lstar.
+     *
+     * <p>Default viewing conditions have a lstar of 50, midgray.
+     */
+    public static ViewingConditions defaultWithBackgroundLstar(double lstar) {
+        return ViewingConditions.make(
+                ColorUtils.whitePointD65(),
+                (200.0 / Math.PI * ColorUtils.yFromLstar(50.0) / 100.f),
+                lstar,
+                2.0,
+                false);
+    }
+
+    /**
+     * Parameters are intermediate values of the CAM16 conversion process. Their names are
+     * shorthand
+     * for technical color science terminology, this class would not benefit from documenting them
+     * individually. A brief overview is available in the CAM16 specification, and a complete
+     * overview
+     * requires a color science textbook, such as Fairchild's Color Appearance Models.
+     */
+    private ViewingConditions(
+            double n,
+            double aw,
+            double nbb,
+            double ncb,
+            double c,
+            double nc,
+            double[] rgbD,
+            double fl,
+            double flRoot,
+            double z) {
+        this.n = n;
+        this.aw = aw;
+        this.nbb = nbb;
+        this.ncb = ncb;
+        this.c = c;
+        this.nc = nc;
+        this.rgbD = rgbD;
+        this.fl = fl;
+        this.flRoot = flRoot;
+        this.z = z;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/palettes/CorePalette.java b/packages/SystemUI/monet/src/com/android/systemui/monet/palettes/CorePalette.java
new file mode 100644
index 0000000..37f6042
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/palettes/CorePalette.java
@@ -0,0 +1,73 @@
+/*
+ * 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.monet.palettes;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+import com.android.systemui.monet.hct.Hct;
+
+/**
+ * An intermediate concept between the key color for a UI theme, and a full color scheme. 5 sets of
+ * tones are generated, all except one use the same hue as the key color, and all vary in chroma.
+ */
+public final class CorePalette {
+    public TonalPalette a1;
+    public TonalPalette a2;
+    public TonalPalette a3;
+    public TonalPalette n1;
+    public TonalPalette n2;
+    public TonalPalette error;
+
+    /**
+     * Create key tones from a color.
+     *
+     * @param argb ARGB representation of a color
+     */
+    public static CorePalette of(int argb) {
+        return new CorePalette(argb, false);
+    }
+
+    /**
+     * Create content key tones from a color.
+     *
+     * @param argb ARGB representation of a color
+     */
+    public static CorePalette contentOf(int argb) {
+        return new CorePalette(argb, true);
+    }
+
+    private CorePalette(int argb, boolean isContent) {
+        Hct hct = Hct.fromInt(argb);
+        double hue = hct.getHue();
+        double chroma = hct.getChroma();
+        if (isContent) {
+            this.a1 = TonalPalette.fromHueAndChroma(hue, chroma);
+            this.a2 = TonalPalette.fromHueAndChroma(hue, chroma / 3.);
+            this.a3 = TonalPalette.fromHueAndChroma(hue + 60., chroma / 2.);
+            this.n1 = TonalPalette.fromHueAndChroma(hue, min(chroma / 12., 4.));
+            this.n2 = TonalPalette.fromHueAndChroma(hue, min(chroma / 6., 8.));
+        } else {
+            this.a1 = TonalPalette.fromHueAndChroma(hue, max(48., chroma));
+            this.a2 = TonalPalette.fromHueAndChroma(hue, 16.);
+            this.a3 = TonalPalette.fromHueAndChroma(hue + 60., 24.);
+            this.n1 = TonalPalette.fromHueAndChroma(hue, 4.);
+            this.n2 = TonalPalette.fromHueAndChroma(hue, 8.);
+        }
+        this.error = TonalPalette.fromHueAndChroma(25, 84.);
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/palettes/TonalPalette.java b/packages/SystemUI/monet/src/com/android/systemui/monet/palettes/TonalPalette.java
new file mode 100644
index 0000000..8e905ea
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/palettes/TonalPalette.java
@@ -0,0 +1,146 @@
+/*
+ * 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.monet.palettes;
+
+import com.android.systemui.monet.hct.Hct;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A convenience class for retrieving colors that are constant in hue and chroma, but vary in tone.
+ */
+public final class TonalPalette {
+    Map<Integer, Integer> cache;
+    Hct keyColor;
+    double hue;
+    double chroma;
+
+    /**
+     * Create tones using the HCT hue and chroma from a color.
+     *
+     * @param argb ARGB representation of a color
+     * @return Tones matching that color's hue and chroma.
+     */
+    public static TonalPalette fromInt(int argb) {
+        return fromHct(Hct.fromInt(argb));
+    }
+
+    /**
+     * Create tones using a HCT color.
+     *
+     * @param hct HCT representation of a color.
+     * @return Tones matching that color's hue and chroma.
+     */
+    public static TonalPalette fromHct(Hct hct) {
+        return new TonalPalette(hct.getHue(), hct.getChroma(), hct);
+    }
+
+    /**
+     * Create tones from a defined HCT hue and chroma.
+     *
+     * @param hue    HCT hue
+     * @param chroma HCT chroma
+     * @return Tones matching hue and chroma.
+     */
+    public static TonalPalette fromHueAndChroma(double hue, double chroma) {
+        return new TonalPalette(hue, chroma, createKeyColor(hue, chroma));
+    }
+
+    private TonalPalette(double hue, double chroma, Hct keyColor) {
+        cache = new HashMap<>();
+        this.hue = hue;
+        this.chroma = chroma;
+        this.keyColor = keyColor;
+    }
+
+    /** The key color is the first tone, starting from T50, matching the given hue and chroma. */
+    private static Hct createKeyColor(double hue, double chroma) {
+        double startTone = 50.0;
+        Hct smallestDeltaHct = Hct.from(hue, chroma, startTone);
+        double smallestDelta = Math.abs(smallestDeltaHct.getChroma() - chroma);
+        // Starting from T50, check T+/-delta to see if they match the requested
+        // chroma.
+        //
+        // Starts from T50 because T50 has the most chroma available, on
+        // average. Thus it is most likely to have a direct answer and minimize
+        // iteration.
+        for (double delta = 1.0; delta < 50.0; delta += 1.0) {
+            // Termination condition rounding instead of minimizing delta to avoid
+            // case where requested chroma is 16.51, and the closest chroma is 16.49.
+            // Error is minimized, but when rounded and displayed, requested chroma
+            // is 17, key color's chroma is 16.
+            if (Math.round(chroma) == Math.round(smallestDeltaHct.getChroma())) {
+                return smallestDeltaHct;
+            }
+
+            final Hct hctAdd = Hct.from(hue, chroma, startTone + delta);
+            final double hctAddDelta = Math.abs(hctAdd.getChroma() - chroma);
+            if (hctAddDelta < smallestDelta) {
+                smallestDelta = hctAddDelta;
+                smallestDeltaHct = hctAdd;
+            }
+
+            final Hct hctSubtract = Hct.from(hue, chroma, startTone - delta);
+            final double hctSubtractDelta = Math.abs(hctSubtract.getChroma() - chroma);
+            if (hctSubtractDelta < smallestDelta) {
+                smallestDelta = hctSubtractDelta;
+                smallestDeltaHct = hctSubtract;
+            }
+        }
+
+        return smallestDeltaHct;
+    }
+
+    /**
+     * Create an ARGB color with HCT hue and chroma of this Tones instance, and the provided HCT
+     * tone.
+     *
+     * @param tone HCT tone, measured from 0 to 100.
+     * @return ARGB representation of a color with that tone.
+     */
+    // AndroidJdkLibsChecker is higher priority than ComputeIfAbsentUseValue (b/119581923)
+    @SuppressWarnings("ComputeIfAbsentUseValue")
+    public int tone(int tone) {
+        Integer color = cache.get(tone);
+        if (color == null) {
+            color = Hct.from(this.hue, this.chroma, tone).toInt();
+            cache.put(tone, color);
+        }
+        return color;
+    }
+
+    /** Given a tone, use hue and chroma of palette to create a color, and return it as HCT. */
+    public Hct getHct(double tone) {
+        return Hct.from(this.hue, this.chroma, tone);
+    }
+
+    /** The chroma of the Tonal Palette, in HCT. Ranges from 0 to ~130 (for sRGB gamut). */
+    public double getChroma() {
+        return this.chroma;
+    }
+
+    /** The hue of the Tonal Palette, in HCT. Ranges from 0 to 360. */
+    public double getHue() {
+        return this.hue;
+    }
+
+    /** The key color is the first tone, starting from T50, that matches the palette's chroma. */
+    public Hct getKeyColor() {
+        return this.keyColor;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/PointProvider.java b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/PointProvider.java
new file mode 100644
index 0000000..99ee0d4
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/PointProvider.java
@@ -0,0 +1,32 @@
+/*
+ * 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.monet.quantize;
+
+/** An interface to allow use of different color spaces by quantizers. */
+public interface PointProvider {
+    /** The three components in the color space of an sRGB color. */
+    double[] fromInt(int argb);
+
+    /** The ARGB (i.e. hex code) representation of this color. */
+    int toInt(double[] point);
+
+    /**
+     * Squared distance between two colors.
+     * Distance is defined by scientific color spaces and referred to as delta E.
+     */
+    double distance(double[] a, double[] b);
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/PointProviderLab.java b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/PointProviderLab.java
new file mode 100644
index 0000000..e852d5a
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/PointProviderLab.java
@@ -0,0 +1,56 @@
+/*
+ * 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.monet.quantize;
+
+import com.android.systemui.monet.utils.ColorUtils;
+
+/**
+ * Provides conversions needed for K-Means quantization. Converting input to points, and converting
+ * the final state of the K-Means algorithm to colors.
+ */
+public final class PointProviderLab implements PointProvider {
+    /**
+     * Convert a color represented in ARGB to a 3-element array of L*a*b* coordinates of the color.
+     */
+    @Override
+    public double[] fromInt(int argb) {
+        double[] lab = ColorUtils.labFromArgb(argb);
+        return new double[]{lab[0], lab[1], lab[2]};
+    }
+
+    /** Convert a 3-element array to a color represented in ARGB. */
+    @Override
+    public int toInt(double[] lab) {
+        return ColorUtils.argbFromLab(lab[0], lab[1], lab[2]);
+    }
+
+    /**
+     * Standard CIE 1976 delta E formula also takes the square root, unneeded here. This method is
+     * used by quantization algorithms to compare distance, and the relative ordering is the same,
+     * with or without a square root.
+     *
+     * <p>This relatively minor optimization is helpful because this method is called at least once
+     * for each pixel in an image.
+     */
+    @Override
+    public double distance(double[] one, double[] two) {
+        double dL = (one[0] - two[0]);
+        double dA = (one[1] - two[1]);
+        double dB = (one[2] - two[2]);
+        return (dL * dL + dA * dA + dB * dB);
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/Quantizer.java
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to packages/SystemUI/monet/src/com/android/systemui/monet/quantize/Quantizer.java
index 497c272..136e5a5 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/Quantizer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package com.android.systemui.monet.quantize;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+interface Quantizer {
+    QuantizerResult quantize(int[] pixels, int maxColors);
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerCelebi.java b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerCelebi.java
new file mode 100644
index 0000000..d448dd0
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerCelebi.java
@@ -0,0 +1,61 @@
+/*
+ * 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.monet.quantize;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An image quantizer that improves on the quality of a standard K-Means algorithm by setting the
+ * K-Means initial state to the output of a Wu quantizer, instead of random centroids. Improves on
+ * speed by several optimizations, as implemented in Wsmeans, or Weighted Square Means, K-Means with
+ * those optimizations.
+ *
+ * <p>This algorithm was designed by M. Emre Celebi, and was found in their 2011 paper, Improving
+ * the Performance of K-Means for Color Quantization. https://arxiv.org/abs/1101.0395
+ */
+public final class QuantizerCelebi {
+    private QuantizerCelebi() {
+    }
+
+    /**
+     * Reduce the number of colors needed to represented the input, minimizing the difference
+     * between
+     * the original image and the recolored image.
+     *
+     * @param pixels    Colors in ARGB format.
+     * @param maxColors The number of colors to divide the image into. A lower number of colors may
+     *                  be
+     *                  returned.
+     * @return Map with keys of colors in ARGB format, and values of number of pixels in the
+     * original
+     * image that correspond to the color in the quantized image.
+     */
+    public static Map<Integer, Integer> quantize(int[] pixels, int maxColors) {
+        QuantizerWu wu = new QuantizerWu();
+        QuantizerResult wuResult = wu.quantize(pixels, maxColors);
+
+        Set<Integer> wuClustersAsObjects = wuResult.colorToCount.keySet();
+        int index = 0;
+        int[] wuClusters = new int[wuClustersAsObjects.size()];
+        for (Integer argb : wuClustersAsObjects) {
+            wuClusters[index++] = argb;
+        }
+
+        return QuantizerWsmeans.quantize(pixels, wuClusters, maxColors);
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerMap.java b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerMap.java
new file mode 100644
index 0000000..9dae8ff
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerMap.java
@@ -0,0 +1,41 @@
+/*
+ * 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.monet.quantize;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/** Creates a dictionary with keys of colors, and values of count of the color */
+public final class QuantizerMap implements Quantizer {
+    Map<Integer, Integer> colorToCount;
+
+    @Override
+    public QuantizerResult quantize(int[] pixels, int colorCount) {
+        final Map<Integer, Integer> pixelByCount = new LinkedHashMap<>();
+        for (int pixel : pixels) {
+            final Integer currentPixelCount = pixelByCount.get(pixel);
+            final int newPixelCount = currentPixelCount == null ? 1 : currentPixelCount + 1;
+            pixelByCount.put(pixel, newPixelCount);
+        }
+        colorToCount = pixelByCount;
+        return new QuantizerResult(pixelByCount);
+    }
+
+    public Map<Integer, Integer> getColorToCount() {
+        return colorToCount;
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerResult.java
similarity index 60%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerResult.java
index 497c272..a2d06af 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerResult.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package com.android.systemui.monet.quantize;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+import java.util.Map;
+
+/** Represents result of a quantizer run */
+public final class QuantizerResult {
+    public final Map<Integer, Integer> colorToCount;
+
+    QuantizerResult(Map<Integer, Integer> colorToCount) {
+        this.colorToCount = colorToCount;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerWsmeans.java b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerWsmeans.java
new file mode 100644
index 0000000..75dd75b
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerWsmeans.java
@@ -0,0 +1,233 @@
+/*
+ * 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.monet.quantize;
+
+import static java.lang.Math.min;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * An image quantizer that improves on the speed of a standard K-Means algorithm by implementing
+ * several optimizations, including deduping identical pixels and a triangle inequality rule that
+ * reduces the number of comparisons needed to identify which cluster a point should be moved to.
+ *
+ * <p>Wsmeans stands for Weighted Square Means.
+ *
+ * <p>This algorithm was designed by M. Emre Celebi, and was found in their 2011 paper, Improving
+ * the Performance of K-Means for Color Quantization. https://arxiv.org/abs/1101.0395
+ */
+public final class QuantizerWsmeans {
+    private QuantizerWsmeans() {
+    }
+
+    private static final class Distance implements Comparable<Distance> {
+        int index;
+        double distance;
+
+        Distance() {
+            this.index = -1;
+            this.distance = -1;
+        }
+
+        @Override
+        public int compareTo(Distance other) {
+            return ((Double) this.distance).compareTo(other.distance);
+        }
+    }
+
+    private static final int MAX_ITERATIONS = 10;
+    private static final double MIN_MOVEMENT_DISTANCE = 3.0;
+
+    /**
+     * Reduce the number of colors needed to represented the input, minimizing the difference
+     * between
+     * the original image and the recolored image.
+     *
+     * @param inputPixels      Colors in ARGB format.
+     * @param startingClusters Defines the initial state of the quantizer. Passing an empty array
+     *                         is
+     *                         fine, the implementation will create its own initial state that leads
+     *                         to reproducible
+     *                         results for the same inputs. Passing an array that is the result of
+     *                         Wu quantization leads
+     *                         to higher quality results.
+     * @param maxColors        The number of colors to divide the image into. A lower number of
+     *                         colors may be
+     *                         returned.
+     * @return Map with keys of colors in ARGB format, values of how many of the input pixels belong
+     * to the color.
+     */
+    public static Map<Integer, Integer> quantize(
+            int[] inputPixels, int[] startingClusters, int maxColors) {
+        // Uses a seeded random number generator to ensure consistent results.
+        Random random = new Random(0x42688);
+
+        Map<Integer, Integer> pixelToCount = new LinkedHashMap<>();
+        double[][] points = new double[inputPixels.length][];
+        int[] pixels = new int[inputPixels.length];
+        PointProvider pointProvider = new PointProviderLab();
+
+        int pointCount = 0;
+        for (int i = 0; i < inputPixels.length; i++) {
+            int inputPixel = inputPixels[i];
+            Integer pixelCount = pixelToCount.get(inputPixel);
+            if (pixelCount == null) {
+                points[pointCount] = pointProvider.fromInt(inputPixel);
+                pixels[pointCount] = inputPixel;
+                pointCount++;
+
+                pixelToCount.put(inputPixel, 1);
+            } else {
+                pixelToCount.put(inputPixel, pixelCount + 1);
+            }
+        }
+
+        int[] counts = new int[pointCount];
+        for (int i = 0; i < pointCount; i++) {
+            int pixel = pixels[i];
+            int count = pixelToCount.get(pixel);
+            counts[i] = count;
+        }
+
+        int clusterCount = min(maxColors, pointCount);
+        if (startingClusters.length != 0) {
+            clusterCount = min(clusterCount, startingClusters.length);
+        }
+
+        double[][] clusters = new double[clusterCount][];
+        for (int i = 0; i < startingClusters.length; i++) {
+            clusters[i] = pointProvider.fromInt(startingClusters[i]);
+        }
+
+        int[] clusterIndices = new int[pointCount];
+        for (int i = 0; i < pointCount; i++) {
+            clusterIndices[i] = random.nextInt(clusterCount);
+        }
+
+        int[][] indexMatrix = new int[clusterCount][];
+        for (int i = 0; i < clusterCount; i++) {
+            indexMatrix[i] = new int[clusterCount];
+        }
+
+        Distance[][] distanceToIndexMatrix = new Distance[clusterCount][];
+        for (int i = 0; i < clusterCount; i++) {
+            distanceToIndexMatrix[i] = new Distance[clusterCount];
+            for (int j = 0; j < clusterCount; j++) {
+                distanceToIndexMatrix[i][j] = new Distance();
+            }
+        }
+
+        int[] pixelCountSums = new int[clusterCount];
+        for (int iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
+            for (int i = 0; i < clusterCount; i++) {
+                for (int j = i + 1; j < clusterCount; j++) {
+                    double distance = pointProvider.distance(clusters[i], clusters[j]);
+                    distanceToIndexMatrix[j][i].distance = distance;
+                    distanceToIndexMatrix[j][i].index = i;
+                    distanceToIndexMatrix[i][j].distance = distance;
+                    distanceToIndexMatrix[i][j].index = j;
+                }
+                Arrays.sort(distanceToIndexMatrix[i]);
+                for (int j = 0; j < clusterCount; j++) {
+                    indexMatrix[i][j] = distanceToIndexMatrix[i][j].index;
+                }
+            }
+
+            int pointsMoved = 0;
+            for (int i = 0; i < pointCount; i++) {
+                double[] point = points[i];
+                int previousClusterIndex = clusterIndices[i];
+                double[] previousCluster = clusters[previousClusterIndex];
+                double previousDistance = pointProvider.distance(point, previousCluster);
+
+                double minimumDistance = previousDistance;
+                int newClusterIndex = -1;
+                for (int j = 0; j < clusterCount; j++) {
+                    if (distanceToIndexMatrix[previousClusterIndex][j].distance
+                            >= 4 * previousDistance) {
+                        continue;
+                    }
+                    double distance = pointProvider.distance(point, clusters[j]);
+                    if (distance < minimumDistance) {
+                        minimumDistance = distance;
+                        newClusterIndex = j;
+                    }
+                }
+                if (newClusterIndex != -1) {
+                    double distanceChange =
+                            Math.abs(Math.sqrt(minimumDistance) - Math.sqrt(previousDistance));
+                    if (distanceChange > MIN_MOVEMENT_DISTANCE) {
+                        pointsMoved++;
+                        clusterIndices[i] = newClusterIndex;
+                    }
+                }
+            }
+
+            if (pointsMoved == 0 && iteration != 0) {
+                break;
+            }
+
+            double[] componentASums = new double[clusterCount];
+            double[] componentBSums = new double[clusterCount];
+            double[] componentCSums = new double[clusterCount];
+            Arrays.fill(pixelCountSums, 0);
+            for (int i = 0; i < pointCount; i++) {
+                int clusterIndex = clusterIndices[i];
+                double[] point = points[i];
+                int count = counts[i];
+                pixelCountSums[clusterIndex] += count;
+                componentASums[clusterIndex] += (point[0] * count);
+                componentBSums[clusterIndex] += (point[1] * count);
+                componentCSums[clusterIndex] += (point[2] * count);
+            }
+
+            for (int i = 0; i < clusterCount; i++) {
+                int count = pixelCountSums[i];
+                if (count == 0) {
+                    clusters[i] = new double[]{0., 0., 0.};
+                    continue;
+                }
+                double a = componentASums[i] / count;
+                double b = componentBSums[i] / count;
+                double c = componentCSums[i] / count;
+                clusters[i][0] = a;
+                clusters[i][1] = b;
+                clusters[i][2] = c;
+            }
+        }
+
+        Map<Integer, Integer> argbToPopulation = new LinkedHashMap<>();
+        for (int i = 0; i < clusterCount; i++) {
+            int count = pixelCountSums[i];
+            if (count == 0) {
+                continue;
+            }
+
+            int possibleNewCluster = pointProvider.toInt(clusters[i]);
+            if (argbToPopulation.containsKey(possibleNewCluster)) {
+                continue;
+            }
+
+            argbToPopulation.put(possibleNewCluster, count);
+        }
+
+        return argbToPopulation;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerWu.java b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerWu.java
new file mode 100644
index 0000000..f788d45
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/quantize/QuantizerWu.java
@@ -0,0 +1,407 @@
+/*
+ * 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.monet.quantize;
+
+import com.android.systemui.monet.utils.ColorUtils;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An image quantizer that divides the image's pixels into clusters by recursively cutting an RGB
+ * cube, based on the weight of pixels in each area of the cube.
+ *
+ * <p>The algorithm was described by Xiaolin Wu in Graphic Gems II, published in 1991.
+ */
+public final class QuantizerWu implements Quantizer {
+    int[] weights;
+    int[] momentsR;
+    int[] momentsG;
+    int[] momentsB;
+    double[] moments;
+    Box[] cubes;
+
+    // A histogram of all the input colors is constructed. It has the shape of a
+    // cube. The cube would be too large if it contained all 16 million colors:
+    // historical best practice is to use 5 bits  of the 8 in each channel,
+    // reducing the histogram to a volume of ~32,000.
+    private static final int INDEX_BITS = 5;
+    private static final int INDEX_COUNT = 33; // ((1 << INDEX_BITS) + 1)
+    private static final int TOTAL_SIZE = 35937; // INDEX_COUNT * INDEX_COUNT * INDEX_COUNT
+
+    @Override
+    public QuantizerResult quantize(int[] pixels, int colorCount) {
+        QuantizerResult mapResult = new QuantizerMap().quantize(pixels, colorCount);
+        constructHistogram(mapResult.colorToCount);
+        createMoments();
+        CreateBoxesResult createBoxesResult = createBoxes(colorCount);
+        List<Integer> colors = createResult(createBoxesResult.resultCount);
+        Map<Integer, Integer> resultMap = new LinkedHashMap<>();
+        for (int color : colors) {
+            resultMap.put(color, 0);
+        }
+        return new QuantizerResult(resultMap);
+    }
+
+    static int getIndex(int r, int g, int b) {
+        return (r << (INDEX_BITS * 2)) + (r << (INDEX_BITS + 1)) + r + (g << INDEX_BITS) + g + b;
+    }
+
+    void constructHistogram(Map<Integer, Integer> pixels) {
+        weights = new int[TOTAL_SIZE];
+        momentsR = new int[TOTAL_SIZE];
+        momentsG = new int[TOTAL_SIZE];
+        momentsB = new int[TOTAL_SIZE];
+        moments = new double[TOTAL_SIZE];
+
+        for (Map.Entry<Integer, Integer> pair : pixels.entrySet()) {
+            int pixel = pair.getKey();
+            int count = pair.getValue();
+            int red = ColorUtils.redFromArgb(pixel);
+            int green = ColorUtils.greenFromArgb(pixel);
+            int blue = ColorUtils.blueFromArgb(pixel);
+            int bitsToRemove = 8 - INDEX_BITS;
+            int iR = (red >> bitsToRemove) + 1;
+            int iG = (green >> bitsToRemove) + 1;
+            int iB = (blue >> bitsToRemove) + 1;
+            int index = getIndex(iR, iG, iB);
+            weights[index] += count;
+            momentsR[index] += (red * count);
+            momentsG[index] += (green * count);
+            momentsB[index] += (blue * count);
+            moments[index] += (count * ((red * red) + (green * green) + (blue * blue)));
+        }
+    }
+
+    void createMoments() {
+        for (int r = 1; r < INDEX_COUNT; ++r) {
+            int[] area = new int[INDEX_COUNT];
+            int[] areaR = new int[INDEX_COUNT];
+            int[] areaG = new int[INDEX_COUNT];
+            int[] areaB = new int[INDEX_COUNT];
+            double[] area2 = new double[INDEX_COUNT];
+
+            for (int g = 1; g < INDEX_COUNT; ++g) {
+                int line = 0;
+                int lineR = 0;
+                int lineG = 0;
+                int lineB = 0;
+                double line2 = 0.0;
+                for (int b = 1; b < INDEX_COUNT; ++b) {
+                    int index = getIndex(r, g, b);
+                    line += weights[index];
+                    lineR += momentsR[index];
+                    lineG += momentsG[index];
+                    lineB += momentsB[index];
+                    line2 += moments[index];
+
+                    area[b] += line;
+                    areaR[b] += lineR;
+                    areaG[b] += lineG;
+                    areaB[b] += lineB;
+                    area2[b] += line2;
+
+                    int previousIndex = getIndex(r - 1, g, b);
+                    weights[index] = weights[previousIndex] + area[b];
+                    momentsR[index] = momentsR[previousIndex] + areaR[b];
+                    momentsG[index] = momentsG[previousIndex] + areaG[b];
+                    momentsB[index] = momentsB[previousIndex] + areaB[b];
+                    moments[index] = moments[previousIndex] + area2[b];
+                }
+            }
+        }
+    }
+
+    CreateBoxesResult createBoxes(int maxColorCount) {
+        cubes = new Box[maxColorCount];
+        for (int i = 0; i < maxColorCount; i++) {
+            cubes[i] = new Box();
+        }
+        double[] volumeVariance = new double[maxColorCount];
+        Box firstBox = cubes[0];
+        firstBox.r1 = INDEX_COUNT - 1;
+        firstBox.g1 = INDEX_COUNT - 1;
+        firstBox.b1 = INDEX_COUNT - 1;
+
+        int generatedColorCount = maxColorCount;
+        int next = 0;
+        for (int i = 1; i < maxColorCount; i++) {
+            if (cut(cubes[next], cubes[i])) {
+                volumeVariance[next] = (cubes[next].vol > 1) ? variance(cubes[next]) : 0.0;
+                volumeVariance[i] = (cubes[i].vol > 1) ? variance(cubes[i]) : 0.0;
+            } else {
+                volumeVariance[next] = 0.0;
+                i--;
+            }
+
+            next = 0;
+
+            double temp = volumeVariance[0];
+            for (int j = 1; j <= i; j++) {
+                if (volumeVariance[j] > temp) {
+                    temp = volumeVariance[j];
+                    next = j;
+                }
+            }
+            if (temp <= 0.0) {
+                generatedColorCount = i + 1;
+                break;
+            }
+        }
+
+        return new CreateBoxesResult(maxColorCount, generatedColorCount);
+    }
+
+    List<Integer> createResult(int colorCount) {
+        List<Integer> colors = new ArrayList<>();
+        for (int i = 0; i < colorCount; ++i) {
+            Box cube = cubes[i];
+            int weight = volume(cube, weights);
+            if (weight > 0) {
+                int r = volume(cube, momentsR) / weight;
+                int g = volume(cube, momentsG) / weight;
+                int b = volume(cube, momentsB) / weight;
+                int color = (255 << 24) | ((r & 0x0ff) << 16) | ((g & 0x0ff) << 8) | (b & 0x0ff);
+                colors.add(color);
+            }
+        }
+        return colors;
+    }
+
+    double variance(Box cube) {
+        int dr = volume(cube, momentsR);
+        int dg = volume(cube, momentsG);
+        int db = volume(cube, momentsB);
+        double xx =
+                moments[getIndex(cube.r1, cube.g1, cube.b1)]
+                        - moments[getIndex(cube.r1, cube.g1, cube.b0)]
+                        - moments[getIndex(cube.r1, cube.g0, cube.b1)]
+                        + moments[getIndex(cube.r1, cube.g0, cube.b0)]
+                        - moments[getIndex(cube.r0, cube.g1, cube.b1)]
+                        + moments[getIndex(cube.r0, cube.g1, cube.b0)]
+                        + moments[getIndex(cube.r0, cube.g0, cube.b1)]
+                        - moments[getIndex(cube.r0, cube.g0, cube.b0)];
+
+        int hypotenuse = dr * dr + dg * dg + db * db;
+        int volume = volume(cube, weights);
+        return xx - hypotenuse / ((double) volume);
+    }
+
+    Boolean cut(Box one, Box two) {
+        int wholeR = volume(one, momentsR);
+        int wholeG = volume(one, momentsG);
+        int wholeB = volume(one, momentsB);
+        int wholeW = volume(one, weights);
+
+        MaximizeResult maxRResult =
+                maximize(one, Direction.RED, one.r0 + 1, one.r1, wholeR, wholeG, wholeB, wholeW);
+        MaximizeResult maxGResult =
+                maximize(one, Direction.GREEN, one.g0 + 1, one.g1, wholeR, wholeG, wholeB, wholeW);
+        MaximizeResult maxBResult =
+                maximize(one, Direction.BLUE, one.b0 + 1, one.b1, wholeR, wholeG, wholeB, wholeW);
+        Direction cutDirection;
+        double maxR = maxRResult.maximum;
+        double maxG = maxGResult.maximum;
+        double maxB = maxBResult.maximum;
+        if (maxR >= maxG && maxR >= maxB) {
+            if (maxRResult.cutLocation < 0) {
+                return false;
+            }
+            cutDirection = Direction.RED;
+        } else if (maxG >= maxR && maxG >= maxB) {
+            cutDirection = Direction.GREEN;
+        } else {
+            cutDirection = Direction.BLUE;
+        }
+
+        two.r1 = one.r1;
+        two.g1 = one.g1;
+        two.b1 = one.b1;
+
+        switch (cutDirection) {
+            case RED:
+                one.r1 = maxRResult.cutLocation;
+                two.r0 = one.r1;
+                two.g0 = one.g0;
+                two.b0 = one.b0;
+                break;
+            case GREEN:
+                one.g1 = maxGResult.cutLocation;
+                two.r0 = one.r0;
+                two.g0 = one.g1;
+                two.b0 = one.b0;
+                break;
+            case BLUE:
+                one.b1 = maxBResult.cutLocation;
+                two.r0 = one.r0;
+                two.g0 = one.g0;
+                two.b0 = one.b1;
+                break;
+        }
+
+        one.vol = (one.r1 - one.r0) * (one.g1 - one.g0) * (one.b1 - one.b0);
+        two.vol = (two.r1 - two.r0) * (two.g1 - two.g0) * (two.b1 - two.b0);
+
+        return true;
+    }
+
+    MaximizeResult maximize(
+            Box cube,
+            Direction direction,
+            int first,
+            int last,
+            int wholeR,
+            int wholeG,
+            int wholeB,
+            int wholeW) {
+        int bottomR = bottom(cube, direction, momentsR);
+        int bottomG = bottom(cube, direction, momentsG);
+        int bottomB = bottom(cube, direction, momentsB);
+        int bottomW = bottom(cube, direction, weights);
+
+        double max = 0.0;
+        int cut = -1;
+
+        int halfR = 0;
+        int halfG = 0;
+        int halfB = 0;
+        int halfW = 0;
+        for (int i = first; i < last; i++) {
+            halfR = bottomR + top(cube, direction, i, momentsR);
+            halfG = bottomG + top(cube, direction, i, momentsG);
+            halfB = bottomB + top(cube, direction, i, momentsB);
+            halfW = bottomW + top(cube, direction, i, weights);
+            if (halfW == 0) {
+                continue;
+            }
+
+            double tempNumerator = halfR * halfR + halfG * halfG + halfB * halfB;
+            double tempDenominator = halfW;
+            double temp = tempNumerator / tempDenominator;
+
+            halfR = wholeR - halfR;
+            halfG = wholeG - halfG;
+            halfB = wholeB - halfB;
+            halfW = wholeW - halfW;
+            if (halfW == 0) {
+                continue;
+            }
+
+            tempNumerator = halfR * halfR + halfG * halfG + halfB * halfB;
+            tempDenominator = halfW;
+            temp += (tempNumerator / tempDenominator);
+
+            if (temp > max) {
+                max = temp;
+                cut = i;
+            }
+        }
+        return new MaximizeResult(cut, max);
+    }
+
+    static int volume(Box cube, int[] moment) {
+        return (moment[getIndex(cube.r1, cube.g1, cube.b1)]
+                - moment[getIndex(cube.r1, cube.g1, cube.b0)]
+                - moment[getIndex(cube.r1, cube.g0, cube.b1)]
+                + moment[getIndex(cube.r1, cube.g0, cube.b0)]
+                - moment[getIndex(cube.r0, cube.g1, cube.b1)]
+                + moment[getIndex(cube.r0, cube.g1, cube.b0)]
+                + moment[getIndex(cube.r0, cube.g0, cube.b1)]
+                - moment[getIndex(cube.r0, cube.g0, cube.b0)]);
+    }
+
+    static int bottom(Box cube, Direction direction, int[] moment) {
+        switch (direction) {
+            case RED:
+                return -moment[getIndex(cube.r0, cube.g1, cube.b1)]
+                        + moment[getIndex(cube.r0, cube.g1, cube.b0)]
+                        + moment[getIndex(cube.r0, cube.g0, cube.b1)]
+                        - moment[getIndex(cube.r0, cube.g0, cube.b0)];
+            case GREEN:
+                return -moment[getIndex(cube.r1, cube.g0, cube.b1)]
+                        + moment[getIndex(cube.r1, cube.g0, cube.b0)]
+                        + moment[getIndex(cube.r0, cube.g0, cube.b1)]
+                        - moment[getIndex(cube.r0, cube.g0, cube.b0)];
+            case BLUE:
+                return -moment[getIndex(cube.r1, cube.g1, cube.b0)]
+                        + moment[getIndex(cube.r1, cube.g0, cube.b0)]
+                        + moment[getIndex(cube.r0, cube.g1, cube.b0)]
+                        - moment[getIndex(cube.r0, cube.g0, cube.b0)];
+        }
+        throw new IllegalArgumentException("unexpected direction " + direction);
+    }
+
+    static int top(Box cube, Direction direction, int position, int[] moment) {
+        switch (direction) {
+            case RED:
+                return (moment[getIndex(position, cube.g1, cube.b1)]
+                        - moment[getIndex(position, cube.g1, cube.b0)]
+                        - moment[getIndex(position, cube.g0, cube.b1)]
+                        + moment[getIndex(position, cube.g0, cube.b0)]);
+            case GREEN:
+                return (moment[getIndex(cube.r1, position, cube.b1)]
+                        - moment[getIndex(cube.r1, position, cube.b0)]
+                        - moment[getIndex(cube.r0, position, cube.b1)]
+                        + moment[getIndex(cube.r0, position, cube.b0)]);
+            case BLUE:
+                return (moment[getIndex(cube.r1, cube.g1, position)]
+                        - moment[getIndex(cube.r1, cube.g0, position)]
+                        - moment[getIndex(cube.r0, cube.g1, position)]
+                        + moment[getIndex(cube.r0, cube.g0, position)]);
+        }
+        throw new IllegalArgumentException("unexpected direction " + direction);
+    }
+
+    private enum Direction {
+        RED,
+        GREEN,
+        BLUE
+    }
+
+    private static final class MaximizeResult {
+        // < 0 if cut impossible
+        int cutLocation;
+        double maximum;
+
+        MaximizeResult(int cut, double max) {
+            this.cutLocation = cut;
+            this.maximum = max;
+        }
+    }
+
+    private static final class CreateBoxesResult {
+        int requestedCount;
+        int resultCount;
+
+        CreateBoxesResult(int requestedCount, int resultCount) {
+            this.requestedCount = requestedCount;
+            this.resultCount = resultCount;
+        }
+    }
+
+    private static final class Box {
+        int r0 = 0;
+        int r1 = 0;
+        int g0 = 0;
+        int g1 = 0;
+        int b0 = 0;
+        int b1 = 0;
+        int vol = 0;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/DynamicScheme.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/DynamicScheme.java
new file mode 100644
index 0000000..e1cbfb1
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/DynamicScheme.java
@@ -0,0 +1,93 @@
+/*
+ * 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.monet.scheme;
+
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+import com.android.systemui.monet.utils.MathUtils;
+
+/**
+ * Provides important settings for creating colors dynamically, and 6 color palettes. Requires: 1. A
+ * color. (source color) 2. A theme. (Variant) 3. Whether or not its dark mode. 4. Contrast level.
+ * (-1 to 1, currently contrast ratio 3.0 and 7.0)
+ */
+public class DynamicScheme {
+    public final int sourceColorArgb;
+    public final Hct sourceColorHct;
+    public final Variant variant;
+    public final boolean isDark;
+    public final double contrastLevel;
+
+    public final TonalPalette primaryPalette;
+    public final TonalPalette secondaryPalette;
+    public final TonalPalette tertiaryPalette;
+    public final TonalPalette neutralPalette;
+    public final TonalPalette neutralVariantPalette;
+    public final TonalPalette errorPalette;
+
+    public DynamicScheme(
+            Hct sourceColorHct,
+            Variant variant,
+            boolean isDark,
+            double contrastLevel,
+            TonalPalette primaryPalette,
+            TonalPalette secondaryPalette,
+            TonalPalette tertiaryPalette,
+            TonalPalette neutralPalette,
+            TonalPalette neutralVariantPalette) {
+        this.sourceColorArgb = sourceColorHct.toInt();
+        this.sourceColorHct = sourceColorHct;
+        this.variant = variant;
+        this.isDark = isDark;
+        this.contrastLevel = contrastLevel;
+
+        this.primaryPalette = primaryPalette;
+        this.secondaryPalette = secondaryPalette;
+        this.tertiaryPalette = tertiaryPalette;
+        this.neutralPalette = neutralPalette;
+        this.neutralVariantPalette = neutralVariantPalette;
+        this.errorPalette = TonalPalette.fromHueAndChroma(25.0, 84.0);
+    }
+
+    /**
+     * Given a set of hues and set of hue rotations, locate which hues the source color's hue is
+     * between, apply the rotation at the same index as the first hue in the range, and return the
+     * rotated hue.
+     *
+     * @param sourceColorHct The color whose hue should be rotated.
+     * @param hues A set of hues.
+     * @param rotations A set of hue rotations.
+     * @return Color's hue with a rotation applied.
+     */
+    public static double getRotatedHue(Hct sourceColorHct, double[] hues, double[] rotations) {
+        final double sourceHue = sourceColorHct.getHue();
+        if (rotations.length == 1) {
+            return MathUtils.sanitizeDegreesDouble(sourceHue + rotations[0]);
+        }
+        final int size = hues.length;
+        for (int i = 0; i <= (size - 2); i++) {
+            final double thisHue = hues[i];
+            final double nextHue = hues[i + 1];
+            if (thisHue < sourceHue && sourceHue < nextHue) {
+                return MathUtils.sanitizeDegreesDouble(sourceHue + rotations[i]);
+            }
+        }
+        // If this statement executes, something is wrong, there should have been a rotation
+        // found using the arrays.
+        return sourceHue;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/Scheme.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/Scheme.java
new file mode 100644
index 0000000..fa736cc
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/Scheme.java
@@ -0,0 +1,784 @@
+/*
+ * 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.monet.scheme;
+
+import com.android.systemui.monet.palettes.CorePalette;
+
+/** Represents a Material color scheme, a mapping of color roles to colors. */
+public class Scheme {
+    private int primary;
+    private int onPrimary;
+    private int primaryContainer;
+    private int onPrimaryContainer;
+    private int secondary;
+    private int onSecondary;
+    private int secondaryContainer;
+    private int onSecondaryContainer;
+    private int tertiary;
+    private int onTertiary;
+    private int tertiaryContainer;
+    private int onTertiaryContainer;
+    private int error;
+    private int onError;
+    private int errorContainer;
+    private int onErrorContainer;
+    private int background;
+    private int onBackground;
+    private int surface;
+    private int onSurface;
+    private int surfaceVariant;
+    private int onSurfaceVariant;
+    private int outline;
+    private int outlineVariant;
+    private int shadow;
+    private int scrim;
+    private int inverseSurface;
+    private int inverseOnSurface;
+    private int inversePrimary;
+
+    public Scheme() {
+    }
+
+    public Scheme(
+            int primary,
+            int onPrimary,
+            int primaryContainer,
+            int onPrimaryContainer,
+            int secondary,
+            int onSecondary,
+            int secondaryContainer,
+            int onSecondaryContainer,
+            int tertiary,
+            int onTertiary,
+            int tertiaryContainer,
+            int onTertiaryContainer,
+            int error,
+            int onError,
+            int errorContainer,
+            int onErrorContainer,
+            int background,
+            int onBackground,
+            int surface,
+            int onSurface,
+            int surfaceVariant,
+            int onSurfaceVariant,
+            int outline,
+            int outlineVariant,
+            int shadow,
+            int scrim,
+            int inverseSurface,
+            int inverseOnSurface,
+            int inversePrimary) {
+        super();
+        this.primary = primary;
+        this.onPrimary = onPrimary;
+        this.primaryContainer = primaryContainer;
+        this.onPrimaryContainer = onPrimaryContainer;
+        this.secondary = secondary;
+        this.onSecondary = onSecondary;
+        this.secondaryContainer = secondaryContainer;
+        this.onSecondaryContainer = onSecondaryContainer;
+        this.tertiary = tertiary;
+        this.onTertiary = onTertiary;
+        this.tertiaryContainer = tertiaryContainer;
+        this.onTertiaryContainer = onTertiaryContainer;
+        this.error = error;
+        this.onError = onError;
+        this.errorContainer = errorContainer;
+        this.onErrorContainer = onErrorContainer;
+        this.background = background;
+        this.onBackground = onBackground;
+        this.surface = surface;
+        this.onSurface = onSurface;
+        this.surfaceVariant = surfaceVariant;
+        this.onSurfaceVariant = onSurfaceVariant;
+        this.outline = outline;
+        this.outlineVariant = outlineVariant;
+        this.shadow = shadow;
+        this.scrim = scrim;
+        this.inverseSurface = inverseSurface;
+        this.inverseOnSurface = inverseOnSurface;
+        this.inversePrimary = inversePrimary;
+    }
+
+    /** Create a light theme Scheme from a source color in ARGB, i.e. a hex code. */
+    public static Scheme light(int argb) {
+        return lightFromCorePalette(CorePalette.of(argb));
+    }
+
+    /** Create a dark theme Scheme from a source color in ARGB, i.e. a hex code. */
+    public static Scheme dark(int argb) {
+        return darkFromCorePalette(CorePalette.of(argb));
+    }
+
+    /** Create a light theme content-based Scheme from a source color in ARGB, i.e. a hex code. */
+    public static Scheme lightContent(int argb) {
+        return lightFromCorePalette(CorePalette.contentOf(argb));
+    }
+
+    /** Create a dark theme content-based Scheme from a source color in ARGB, i.e. a hex code. */
+    public static Scheme darkContent(int argb) {
+        return darkFromCorePalette(CorePalette.contentOf(argb));
+    }
+
+    private static Scheme lightFromCorePalette(CorePalette core) {
+        return new Scheme()
+                .withPrimary(core.a1.tone(40))
+                .withOnPrimary(core.a1.tone(100))
+                .withPrimaryContainer(core.a1.tone(90))
+                .withOnPrimaryContainer(core.a1.tone(10))
+                .withSecondary(core.a2.tone(40))
+                .withOnSecondary(core.a2.tone(100))
+                .withSecondaryContainer(core.a2.tone(90))
+                .withOnSecondaryContainer(core.a2.tone(10))
+                .withTertiary(core.a3.tone(40))
+                .withOnTertiary(core.a3.tone(100))
+                .withTertiaryContainer(core.a3.tone(90))
+                .withOnTertiaryContainer(core.a3.tone(10))
+                .withError(core.error.tone(40))
+                .withOnError(core.error.tone(100))
+                .withErrorContainer(core.error.tone(90))
+                .withOnErrorContainer(core.error.tone(10))
+                .withBackground(core.n1.tone(99))
+                .withOnBackground(core.n1.tone(10))
+                .withSurface(core.n1.tone(99))
+                .withOnSurface(core.n1.tone(10))
+                .withSurfaceVariant(core.n2.tone(90))
+                .withOnSurfaceVariant(core.n2.tone(30))
+                .withOutline(core.n2.tone(50))
+                .withOutlineVariant(core.n2.tone(80))
+                .withShadow(core.n1.tone(0))
+                .withScrim(core.n1.tone(0))
+                .withInverseSurface(core.n1.tone(20))
+                .withInverseOnSurface(core.n1.tone(95))
+                .withInversePrimary(core.a1.tone(80));
+    }
+
+    private static Scheme darkFromCorePalette(CorePalette core) {
+        return new Scheme()
+                .withPrimary(core.a1.tone(80))
+                .withOnPrimary(core.a1.tone(20))
+                .withPrimaryContainer(core.a1.tone(30))
+                .withOnPrimaryContainer(core.a1.tone(90))
+                .withSecondary(core.a2.tone(80))
+                .withOnSecondary(core.a2.tone(20))
+                .withSecondaryContainer(core.a2.tone(30))
+                .withOnSecondaryContainer(core.a2.tone(90))
+                .withTertiary(core.a3.tone(80))
+                .withOnTertiary(core.a3.tone(20))
+                .withTertiaryContainer(core.a3.tone(30))
+                .withOnTertiaryContainer(core.a3.tone(90))
+                .withError(core.error.tone(80))
+                .withOnError(core.error.tone(20))
+                .withErrorContainer(core.error.tone(30))
+                .withOnErrorContainer(core.error.tone(80))
+                .withBackground(core.n1.tone(10))
+                .withOnBackground(core.n1.tone(90))
+                .withSurface(core.n1.tone(10))
+                .withOnSurface(core.n1.tone(90))
+                .withSurfaceVariant(core.n2.tone(30))
+                .withOnSurfaceVariant(core.n2.tone(80))
+                .withOutline(core.n2.tone(60))
+                .withOutlineVariant(core.n2.tone(30))
+                .withShadow(core.n1.tone(0))
+                .withScrim(core.n1.tone(0))
+                .withInverseSurface(core.n1.tone(90))
+                .withInverseOnSurface(core.n1.tone(20))
+                .withInversePrimary(core.a1.tone(40));
+    }
+
+    public int getPrimary() {
+        return primary;
+    }
+
+    public void setPrimary(int primary) {
+        this.primary = primary;
+    }
+
+    public Scheme withPrimary(int primary) {
+        this.primary = primary;
+        return this;
+    }
+
+    public int getOnPrimary() {
+        return onPrimary;
+    }
+
+    public void setOnPrimary(int onPrimary) {
+        this.onPrimary = onPrimary;
+    }
+
+    public Scheme withOnPrimary(int onPrimary) {
+        this.onPrimary = onPrimary;
+        return this;
+    }
+
+    public int getPrimaryContainer() {
+        return primaryContainer;
+    }
+
+    public void setPrimaryContainer(int primaryContainer) {
+        this.primaryContainer = primaryContainer;
+    }
+
+    public Scheme withPrimaryContainer(int primaryContainer) {
+        this.primaryContainer = primaryContainer;
+        return this;
+    }
+
+    public int getOnPrimaryContainer() {
+        return onPrimaryContainer;
+    }
+
+    public void setOnPrimaryContainer(int onPrimaryContainer) {
+        this.onPrimaryContainer = onPrimaryContainer;
+    }
+
+    public Scheme withOnPrimaryContainer(int onPrimaryContainer) {
+        this.onPrimaryContainer = onPrimaryContainer;
+        return this;
+    }
+
+    public int getSecondary() {
+        return secondary;
+    }
+
+    public void setSecondary(int secondary) {
+        this.secondary = secondary;
+    }
+
+    public Scheme withSecondary(int secondary) {
+        this.secondary = secondary;
+        return this;
+    }
+
+    public int getOnSecondary() {
+        return onSecondary;
+    }
+
+    public void setOnSecondary(int onSecondary) {
+        this.onSecondary = onSecondary;
+    }
+
+    public Scheme withOnSecondary(int onSecondary) {
+        this.onSecondary = onSecondary;
+        return this;
+    }
+
+    public int getSecondaryContainer() {
+        return secondaryContainer;
+    }
+
+    public void setSecondaryContainer(int secondaryContainer) {
+        this.secondaryContainer = secondaryContainer;
+    }
+
+    public Scheme withSecondaryContainer(int secondaryContainer) {
+        this.secondaryContainer = secondaryContainer;
+        return this;
+    }
+
+    public int getOnSecondaryContainer() {
+        return onSecondaryContainer;
+    }
+
+    public void setOnSecondaryContainer(int onSecondaryContainer) {
+        this.onSecondaryContainer = onSecondaryContainer;
+    }
+
+    public Scheme withOnSecondaryContainer(int onSecondaryContainer) {
+        this.onSecondaryContainer = onSecondaryContainer;
+        return this;
+    }
+
+    public int getTertiary() {
+        return tertiary;
+    }
+
+    public void setTertiary(int tertiary) {
+        this.tertiary = tertiary;
+    }
+
+    public Scheme withTertiary(int tertiary) {
+        this.tertiary = tertiary;
+        return this;
+    }
+
+    public int getOnTertiary() {
+        return onTertiary;
+    }
+
+    public void setOnTertiary(int onTertiary) {
+        this.onTertiary = onTertiary;
+    }
+
+    public Scheme withOnTertiary(int onTertiary) {
+        this.onTertiary = onTertiary;
+        return this;
+    }
+
+    public int getTertiaryContainer() {
+        return tertiaryContainer;
+    }
+
+    public void setTertiaryContainer(int tertiaryContainer) {
+        this.tertiaryContainer = tertiaryContainer;
+    }
+
+    public Scheme withTertiaryContainer(int tertiaryContainer) {
+        this.tertiaryContainer = tertiaryContainer;
+        return this;
+    }
+
+    public int getOnTertiaryContainer() {
+        return onTertiaryContainer;
+    }
+
+    public void setOnTertiaryContainer(int onTertiaryContainer) {
+        this.onTertiaryContainer = onTertiaryContainer;
+    }
+
+    public Scheme withOnTertiaryContainer(int onTertiaryContainer) {
+        this.onTertiaryContainer = onTertiaryContainer;
+        return this;
+    }
+
+    public int getError() {
+        return error;
+    }
+
+    public void setError(int error) {
+        this.error = error;
+    }
+
+    public Scheme withError(int error) {
+        this.error = error;
+        return this;
+    }
+
+    public int getOnError() {
+        return onError;
+    }
+
+    public void setOnError(int onError) {
+        this.onError = onError;
+    }
+
+    public Scheme withOnError(int onError) {
+        this.onError = onError;
+        return this;
+    }
+
+    public int getErrorContainer() {
+        return errorContainer;
+    }
+
+    public void setErrorContainer(int errorContainer) {
+        this.errorContainer = errorContainer;
+    }
+
+    public Scheme withErrorContainer(int errorContainer) {
+        this.errorContainer = errorContainer;
+        return this;
+    }
+
+    public int getOnErrorContainer() {
+        return onErrorContainer;
+    }
+
+    public void setOnErrorContainer(int onErrorContainer) {
+        this.onErrorContainer = onErrorContainer;
+    }
+
+    public Scheme withOnErrorContainer(int onErrorContainer) {
+        this.onErrorContainer = onErrorContainer;
+        return this;
+    }
+
+    public int getBackground() {
+        return background;
+    }
+
+    public void setBackground(int background) {
+        this.background = background;
+    }
+
+    public Scheme withBackground(int background) {
+        this.background = background;
+        return this;
+    }
+
+    public int getOnBackground() {
+        return onBackground;
+    }
+
+    public void setOnBackground(int onBackground) {
+        this.onBackground = onBackground;
+    }
+
+    public Scheme withOnBackground(int onBackground) {
+        this.onBackground = onBackground;
+        return this;
+    }
+
+    public int getSurface() {
+        return surface;
+    }
+
+    public void setSurface(int surface) {
+        this.surface = surface;
+    }
+
+    public Scheme withSurface(int surface) {
+        this.surface = surface;
+        return this;
+    }
+
+    public int getOnSurface() {
+        return onSurface;
+    }
+
+    public void setOnSurface(int onSurface) {
+        this.onSurface = onSurface;
+    }
+
+    public Scheme withOnSurface(int onSurface) {
+        this.onSurface = onSurface;
+        return this;
+    }
+
+    public int getSurfaceVariant() {
+        return surfaceVariant;
+    }
+
+    public void setSurfaceVariant(int surfaceVariant) {
+        this.surfaceVariant = surfaceVariant;
+    }
+
+    public Scheme withSurfaceVariant(int surfaceVariant) {
+        this.surfaceVariant = surfaceVariant;
+        return this;
+    }
+
+    public int getOnSurfaceVariant() {
+        return onSurfaceVariant;
+    }
+
+    public void setOnSurfaceVariant(int onSurfaceVariant) {
+        this.onSurfaceVariant = onSurfaceVariant;
+    }
+
+    public Scheme withOnSurfaceVariant(int onSurfaceVariant) {
+        this.onSurfaceVariant = onSurfaceVariant;
+        return this;
+    }
+
+    public int getOutline() {
+        return outline;
+    }
+
+    public void setOutline(int outline) {
+        this.outline = outline;
+    }
+
+    public Scheme withOutline(int outline) {
+        this.outline = outline;
+        return this;
+    }
+
+    public int getOutlineVariant() {
+        return outlineVariant;
+    }
+
+    public void setOutlineVariant(int outlineVariant) {
+        this.outlineVariant = outlineVariant;
+    }
+
+    public Scheme withOutlineVariant(int outlineVariant) {
+        this.outlineVariant = outlineVariant;
+        return this;
+    }
+
+    public int getShadow() {
+        return shadow;
+    }
+
+    public void setShadow(int shadow) {
+        this.shadow = shadow;
+    }
+
+    public Scheme withShadow(int shadow) {
+        this.shadow = shadow;
+        return this;
+    }
+
+    public int getScrim() {
+        return scrim;
+    }
+
+    public void setScrim(int scrim) {
+        this.scrim = scrim;
+    }
+
+    public Scheme withScrim(int scrim) {
+        this.scrim = scrim;
+        return this;
+    }
+
+    public int getInverseSurface() {
+        return inverseSurface;
+    }
+
+    public void setInverseSurface(int inverseSurface) {
+        this.inverseSurface = inverseSurface;
+    }
+
+    public Scheme withInverseSurface(int inverseSurface) {
+        this.inverseSurface = inverseSurface;
+        return this;
+    }
+
+    public int getInverseOnSurface() {
+        return inverseOnSurface;
+    }
+
+    public void setInverseOnSurface(int inverseOnSurface) {
+        this.inverseOnSurface = inverseOnSurface;
+    }
+
+    public Scheme withInverseOnSurface(int inverseOnSurface) {
+        this.inverseOnSurface = inverseOnSurface;
+        return this;
+    }
+
+    public int getInversePrimary() {
+        return inversePrimary;
+    }
+
+    public void setInversePrimary(int inversePrimary) {
+        this.inversePrimary = inversePrimary;
+    }
+
+    public Scheme withInversePrimary(int inversePrimary) {
+        this.inversePrimary = inversePrimary;
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return "Scheme{"
+                + "primary="
+                + primary
+                + ", onPrimary="
+                + onPrimary
+                + ", primaryContainer="
+                + primaryContainer
+                + ", onPrimaryContainer="
+                + onPrimaryContainer
+                + ", secondary="
+                + secondary
+                + ", onSecondary="
+                + onSecondary
+                + ", secondaryContainer="
+                + secondaryContainer
+                + ", onSecondaryContainer="
+                + onSecondaryContainer
+                + ", tertiary="
+                + tertiary
+                + ", onTertiary="
+                + onTertiary
+                + ", tertiaryContainer="
+                + tertiaryContainer
+                + ", onTertiaryContainer="
+                + onTertiaryContainer
+                + ", error="
+                + error
+                + ", onError="
+                + onError
+                + ", errorContainer="
+                + errorContainer
+                + ", onErrorContainer="
+                + onErrorContainer
+                + ", background="
+                + background
+                + ", onBackground="
+                + onBackground
+                + ", surface="
+                + surface
+                + ", onSurface="
+                + onSurface
+                + ", surfaceVariant="
+                + surfaceVariant
+                + ", onSurfaceVariant="
+                + onSurfaceVariant
+                + ", outline="
+                + outline
+                + ", outlineVariant="
+                + outlineVariant
+                + ", shadow="
+                + shadow
+                + ", scrim="
+                + scrim
+                + ", inverseSurface="
+                + inverseSurface
+                + ", inverseOnSurface="
+                + inverseOnSurface
+                + ", inversePrimary="
+                + inversePrimary
+                + '}';
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (!(object instanceof Scheme)) {
+            return false;
+        }
+        if (!super.equals(object)) {
+            return false;
+        }
+
+        Scheme scheme = (Scheme) object;
+
+        if (primary != scheme.primary) {
+            return false;
+        }
+        if (onPrimary != scheme.onPrimary) {
+            return false;
+        }
+        if (primaryContainer != scheme.primaryContainer) {
+            return false;
+        }
+        if (onPrimaryContainer != scheme.onPrimaryContainer) {
+            return false;
+        }
+        if (secondary != scheme.secondary) {
+            return false;
+        }
+        if (onSecondary != scheme.onSecondary) {
+            return false;
+        }
+        if (secondaryContainer != scheme.secondaryContainer) {
+            return false;
+        }
+        if (onSecondaryContainer != scheme.onSecondaryContainer) {
+            return false;
+        }
+        if (tertiary != scheme.tertiary) {
+            return false;
+        }
+        if (onTertiary != scheme.onTertiary) {
+            return false;
+        }
+        if (tertiaryContainer != scheme.tertiaryContainer) {
+            return false;
+        }
+        if (onTertiaryContainer != scheme.onTertiaryContainer) {
+            return false;
+        }
+        if (error != scheme.error) {
+            return false;
+        }
+        if (onError != scheme.onError) {
+            return false;
+        }
+        if (errorContainer != scheme.errorContainer) {
+            return false;
+        }
+        if (onErrorContainer != scheme.onErrorContainer) {
+            return false;
+        }
+        if (background != scheme.background) {
+            return false;
+        }
+        if (onBackground != scheme.onBackground) {
+            return false;
+        }
+        if (surface != scheme.surface) {
+            return false;
+        }
+        if (onSurface != scheme.onSurface) {
+            return false;
+        }
+        if (surfaceVariant != scheme.surfaceVariant) {
+            return false;
+        }
+        if (onSurfaceVariant != scheme.onSurfaceVariant) {
+            return false;
+        }
+        if (outline != scheme.outline) {
+            return false;
+        }
+        if (outlineVariant != scheme.outlineVariant) {
+            return false;
+        }
+        if (shadow != scheme.shadow) {
+            return false;
+        }
+        if (scrim != scheme.scrim) {
+            return false;
+        }
+        if (inverseSurface != scheme.inverseSurface) {
+            return false;
+        }
+        if (inverseOnSurface != scheme.inverseOnSurface) {
+            return false;
+        }
+        if (inversePrimary != scheme.inversePrimary) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + primary;
+        result = 31 * result + onPrimary;
+        result = 31 * result + primaryContainer;
+        result = 31 * result + onPrimaryContainer;
+        result = 31 * result + secondary;
+        result = 31 * result + onSecondary;
+        result = 31 * result + secondaryContainer;
+        result = 31 * result + onSecondaryContainer;
+        result = 31 * result + tertiary;
+        result = 31 * result + onTertiary;
+        result = 31 * result + tertiaryContainer;
+        result = 31 * result + onTertiaryContainer;
+        result = 31 * result + error;
+        result = 31 * result + onError;
+        result = 31 * result + errorContainer;
+        result = 31 * result + onErrorContainer;
+        result = 31 * result + background;
+        result = 31 * result + onBackground;
+        result = 31 * result + surface;
+        result = 31 * result + onSurface;
+        result = 31 * result + surfaceVariant;
+        result = 31 * result + onSurfaceVariant;
+        result = 31 * result + outline;
+        result = 31 * result + outlineVariant;
+        result = 31 * result + shadow;
+        result = 31 * result + scrim;
+        result = 31 * result + inverseSurface;
+        result = 31 * result + inverseOnSurface;
+        result = 31 * result + inversePrimary;
+        return result;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeContent.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeContent.java
new file mode 100644
index 0000000..4c3c07c
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeContent.java
@@ -0,0 +1,59 @@
+/*
+ * 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.monet.scheme;
+
+import static java.lang.Math.max;
+
+import com.android.systemui.monet.dislike.DislikeAnalyzer;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+import com.android.systemui.monet.temperature.TemperatureCache;
+
+/**
+ * A scheme that places the source color in Scheme.primaryContainer.
+ *
+ * <p>Primary Container is the source color, adjusted for color relativity. It maintains constant
+ * appearance in light mode and dark mode. This adds ~5 tone in light mode, and subtracts ~5 tone in
+ * dark mode.
+ *
+ * <p>Tertiary Container is an analogous color, specifically, the analog of a color wheel divided
+ * into 6, and the precise analog is the one found by increasing hue. This is a scientifically
+ * grounded equivalent to rotating hue clockwise by 60 degrees. It also maintains constant
+ * appearance.
+ */
+public class SchemeContent extends DynamicScheme {
+    public SchemeContent(Hct sourceColorHct, boolean isDark, double contrastLevel) {
+        super(
+                sourceColorHct,
+                Variant.CONTENT,
+                isDark,
+                contrastLevel,
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), sourceColorHct.getChroma()),
+                TonalPalette.fromHueAndChroma(
+                        sourceColorHct.getHue(),
+                        max(sourceColorHct.getChroma() - 32.0, sourceColorHct.getChroma() * 0.5)),
+                TonalPalette.fromHct(
+                        DislikeAnalyzer.fixIfDisliked(
+                                new TemperatureCache(sourceColorHct)
+                                        .getAnalogousColors(/* count= */ 3, /* divisions= */ 6)
+                                        .get(2))),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(),
+                        sourceColorHct.getChroma() / 8.0),
+                TonalPalette.fromHueAndChroma(
+                        sourceColorHct.getHue(), (sourceColorHct.getChroma() / 8.0) + 4.0));
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeExpressive.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeExpressive.java
new file mode 100644
index 0000000..234826e
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeExpressive.java
@@ -0,0 +1,49 @@
+/*
+ * 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.monet.scheme;
+
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+import com.android.systemui.monet.utils.MathUtils;
+
+/** A playful theme - the source color's hue does not appear in the theme. */
+public class SchemeExpressive extends DynamicScheme {
+    // NOMUTANTS--arbitrary increments/decrements, correctly, still passes tests.
+    private static final double[] HUES = {0, 21, 51, 121, 151, 191, 271, 321, 360};
+    private static final double[] SECONDARY_ROTATIONS = {45, 95, 45, 20, 45, 90, 45, 45, 45};
+    private static final double[] TERTIARY_ROTATIONS = {120, 120, 20, 45, 20, 15, 20, 120, 120};
+
+    public SchemeExpressive(Hct sourceColorHct, boolean isDark, double contrastLevel) {
+        super(
+                sourceColorHct,
+                Variant.EXPRESSIVE,
+                isDark,
+                contrastLevel,
+                TonalPalette.fromHueAndChroma(
+                        MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 240.0), 40.0),
+                TonalPalette.fromHueAndChroma(
+                        DynamicScheme.getRotatedHue(sourceColorHct, HUES, SECONDARY_ROTATIONS),
+                        24.0),
+                TonalPalette.fromHueAndChroma(
+                        DynamicScheme.getRotatedHue(sourceColorHct, HUES, TERTIARY_ROTATIONS),
+                        32.0),
+                TonalPalette.fromHueAndChroma(
+                        MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 15.0), 8.0),
+                TonalPalette.fromHueAndChroma(
+                        MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 15.0), 12.0));
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeFidelity.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeFidelity.java
new file mode 100644
index 0000000..dfbf56d
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeFidelity.java
@@ -0,0 +1,54 @@
+/*
+ * 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.monet.scheme;
+
+import com.android.systemui.monet.dislike.DislikeAnalyzer;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+import com.android.systemui.monet.temperature.TemperatureCache;
+
+/**
+ * A scheme that places the source color in Scheme.primaryContainer.
+ *
+ * <p>Primary Container is the source color, adjusted for color relativity. It maintains constant
+ * appearance in light mode and dark mode. This adds ~5 tone in light mode, and subtracts ~5 tone in
+ * dark mode.
+ *
+ * <p>Tertiary Container is the complement to the source color, using TemperatureCache. It also
+ * maintains constant appearance.
+ */
+public class SchemeFidelity extends DynamicScheme {
+    public SchemeFidelity(Hct sourceColorHct, boolean isDark, double contrastLevel) {
+        super(
+                sourceColorHct,
+                Variant.FIDELITY,
+                isDark,
+                contrastLevel,
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), sourceColorHct.getChroma()),
+                TonalPalette.fromHueAndChroma(
+                        sourceColorHct.getHue(),
+                        Math.max(sourceColorHct.getChroma() - 32.0,
+                                sourceColorHct.getChroma() * 0.5)),
+                TonalPalette.fromHct(
+                        DislikeAnalyzer.fixIfDisliked(
+                                new TemperatureCache(sourceColorHct).getComplement())),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(),
+                        sourceColorHct.getChroma() / 8.0),
+                TonalPalette.fromHueAndChroma(
+                        sourceColorHct.getHue(), (sourceColorHct.getChroma() / 8.0) + 4.0));
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeFruitSalad.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeFruitSalad.java
new file mode 100644
index 0000000..aa2c979
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeFruitSalad.java
@@ -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.monet.scheme;
+
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+import com.android.systemui.monet.utils.MathUtils;
+
+/** A playful theme - the source color's hue does not appear in the theme. */
+public class SchemeFruitSalad extends DynamicScheme {
+    public SchemeFruitSalad(Hct sourceColorHct, boolean isDark, double contrastLevel) {
+        super(
+                sourceColorHct,
+                Variant.FRUIT_SALAD,
+                isDark,
+                contrastLevel,
+                TonalPalette.fromHueAndChroma(
+                        MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() - 50.0), 48.0),
+                TonalPalette.fromHueAndChroma(
+                        MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() - 50.0), 36.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 36.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 10.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 16.0));
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeMonochrome.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeMonochrome.java
new file mode 100644
index 0000000..509ea2a
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeMonochrome.java
@@ -0,0 +1,36 @@
+/*
+ * 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.monet.scheme;
+
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+
+/** A monochrome theme, colors are purely black / white / gray. */
+public class SchemeMonochrome extends DynamicScheme {
+    public SchemeMonochrome(Hct sourceColorHct, boolean isDark, double contrastLevel) {
+        super(
+                sourceColorHct,
+                Variant.MONOCHROME,
+                isDark,
+                contrastLevel,
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0));
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeNeutral.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeNeutral.java
new file mode 100644
index 0000000..fdbde9de
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeNeutral.java
@@ -0,0 +1,36 @@
+/*
+ * 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.monet.scheme;
+
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+
+/** A theme that's slightly more chromatic than monochrome, which is purely black / white / gray. */
+public class SchemeNeutral extends DynamicScheme {
+    public SchemeNeutral(Hct sourceColorHct, boolean isDark, double contrastLevel) {
+        super(
+                sourceColorHct,
+                Variant.NEUTRAL,
+                isDark,
+                contrastLevel,
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 12.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 8.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 16.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 2.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 2.0));
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeRainbow.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeRainbow.java
new file mode 100644
index 0000000..92eb27f
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeRainbow.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.monet.scheme;
+
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+import com.android.systemui.monet.utils.MathUtils;
+
+/** A playful theme - the source color's hue does not appear in the theme. */
+public class SchemeRainbow extends DynamicScheme {
+    public SchemeRainbow(Hct sourceColorHct, boolean isDark, double contrastLevel) {
+        super(
+                sourceColorHct,
+                Variant.RAINBOW,
+                isDark,
+                contrastLevel,
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 48.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 16.0),
+                TonalPalette.fromHueAndChroma(
+                        MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 60.0), 24.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0));
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeTonalSpot.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeTonalSpot.java
new file mode 100644
index 0000000..8480684
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeTonalSpot.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.monet.scheme;
+
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+import com.android.systemui.monet.utils.MathUtils;
+
+/** A calm theme, sedated colors that aren't particularly chromatic. */
+public class SchemeTonalSpot extends DynamicScheme {
+    public SchemeTonalSpot(Hct sourceColorHct, boolean isDark, double contrastLevel) {
+        super(
+                sourceColorHct,
+                Variant.TONAL_SPOT,
+                isDark,
+                contrastLevel,
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 36.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 16.0),
+                TonalPalette.fromHueAndChroma(
+                        MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 60.0), 24.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 4.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 8.0));
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeVibrant.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeVibrant.java
new file mode 100644
index 0000000..160fab7
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeVibrant.java
@@ -0,0 +1,44 @@
+/*
+ * 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.monet.scheme;
+
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.palettes.TonalPalette;
+
+/** A loud theme, colorfulness is maximum for Primary palette, increased for others. */
+public class SchemeVibrant extends DynamicScheme {
+    private static final double[] HUES = {0, 41, 61, 101, 131, 181, 251, 301, 360};
+    private static final double[] SECONDARY_ROTATIONS = {18, 15, 10, 12, 15, 18, 15, 12, 12};
+    private static final double[] TERTIARY_ROTATIONS = {35, 30, 20, 25, 30, 35, 30, 25, 25};
+
+    public SchemeVibrant(Hct sourceColorHct, boolean isDark, double contrastLevel) {
+        super(
+                sourceColorHct,
+                Variant.VIBRANT,
+                isDark,
+                contrastLevel,
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 200.0),
+                TonalPalette.fromHueAndChroma(
+                        DynamicScheme.getRotatedHue(sourceColorHct, HUES, SECONDARY_ROTATIONS),
+                        24.0),
+                TonalPalette.fromHueAndChroma(
+                        DynamicScheme.getRotatedHue(sourceColorHct, HUES, TERTIARY_ROTATIONS),
+                        32.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 10.0),
+                TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 12.0));
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/Variant.java
similarity index 64%
rename from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
rename to packages/SystemUI/monet/src/com/android/systemui/monet/scheme/Variant.java
index 497c272..99aa2de 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/Variant.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package com.android.systemui.monet.scheme;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+/** Themes for Dynamic Color. */
+public enum Variant {
+    MONOCHROME,
+    NEUTRAL,
+    TONAL_SPOT,
+    VIBRANT,
+    EXPRESSIVE,
+    FIDELITY,
+    CONTENT,
+    RAINBOW,
+    FRUIT_SALAD
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/score/Score.java b/packages/SystemUI/monet/src/com/android/systemui/monet/score/Score.java
new file mode 100644
index 0000000..09ea7a3
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/score/Score.java
@@ -0,0 +1,184 @@
+/*
+ * 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.monet.score;
+
+import com.android.systemui.monet.hct.Cam16;
+import com.android.systemui.monet.utils.ColorUtils;
+import com.android.systemui.monet.utils.MathUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Given a large set of colors, remove colors that are unsuitable for a UI theme, and rank the rest
+ * based on suitability.
+ *
+ * <p>Enables use of a high cluster count for image quantization, thus ensuring colors aren't
+ * muddied, while curating the high cluster count to a much smaller number of appropriate choices.
+ */
+public final class Score {
+    private static final double CUTOFF_CHROMA = 15.;
+    private static final double CUTOFF_EXCITED_PROPORTION = 0.01;
+    private static final double CUTOFF_TONE = 10.;
+    private static final double TARGET_CHROMA = 48.;
+    private static final double WEIGHT_PROPORTION = 0.7;
+    private static final double WEIGHT_CHROMA_ABOVE = 0.3;
+    private static final double WEIGHT_CHROMA_BELOW = 0.1;
+
+    private Score() {
+    }
+
+    /**
+     * Given a map with keys of colors and values of how often the color appears, rank the colors
+     * based on suitability for being used for a UI theme.
+     *
+     * @param colorsToPopulation map with keys of colors and values of how often the color appears,
+     *                           usually from a source image.
+     * @return Colors sorted by suitability for a UI theme. The most suitable color is the first
+     * item,
+     * the least suitable is the last. There will always be at least one color returned. If all
+     * the input colors were not suitable for a theme, a default fallback color will be provided.
+     */
+    public static List<Integer> score(Map<Integer, Integer> colorsToPopulation) {
+        // Determine the total count of all colors.
+        double populationSum = 0.;
+        for (Map.Entry<Integer, Integer> entry : colorsToPopulation.entrySet()) {
+            populationSum += entry.getValue();
+        }
+
+        // Turn the count of each color into a proportion by dividing by the total
+        // count. Also, fill a cache of CAM16 colors representing each color, and
+        // record the proportion of colors for each CAM16 hue.
+        Map<Integer, Cam16> colorsToCam = new HashMap<>();
+        double[] hueProportions = new double[361];
+        for (Map.Entry<Integer, Integer> entry : colorsToPopulation.entrySet()) {
+            int color = entry.getKey();
+            double population = entry.getValue();
+            double proportion = population / populationSum;
+
+            Cam16 cam = Cam16.fromInt(color);
+            colorsToCam.put(color, cam);
+
+            int hue = (int) Math.round(cam.getHue());
+            hueProportions[hue] += proportion;
+        }
+
+        // Determine the proportion of the colors around each color, by summing the
+        // proportions around each color's hue.
+        Map<Integer, Double> colorsToExcitedProportion = new HashMap<>();
+        for (Map.Entry<Integer, Cam16> entry : colorsToCam.entrySet()) {
+            int color = entry.getKey();
+            Cam16 cam = entry.getValue();
+            int hue = (int) Math.round(cam.getHue());
+
+            double excitedProportion = 0.;
+            for (int j = (hue - 15); j < (hue + 15); j++) {
+                int neighborHue = MathUtils.sanitizeDegreesInt(j);
+                excitedProportion += hueProportions[neighborHue];
+            }
+
+            colorsToExcitedProportion.put(color, excitedProportion);
+        }
+
+        // Score the colors by their proportion, as well as how chromatic they are.
+        Map<Integer, Double> colorsToScore = new HashMap<>();
+        for (Map.Entry<Integer, Cam16> entry : colorsToCam.entrySet()) {
+            int color = entry.getKey();
+            Cam16 cam = entry.getValue();
+
+            double proportion = colorsToExcitedProportion.get(color);
+            double proportionScore = proportion * 100.0 * WEIGHT_PROPORTION;
+
+            double chromaWeight =
+                    cam.getChroma() < TARGET_CHROMA ? WEIGHT_CHROMA_BELOW : WEIGHT_CHROMA_ABOVE;
+            double chromaScore = (cam.getChroma() - TARGET_CHROMA) * chromaWeight;
+
+            double score = proportionScore + chromaScore;
+            colorsToScore.put(color, score);
+        }
+
+        // Remove colors that are unsuitable, ex. very dark or unchromatic colors.
+        // Also, remove colors that are very similar in hue.
+        List<Integer> filteredColors = filter(colorsToExcitedProportion, colorsToCam);
+        Map<Integer, Double> filteredColorsToScore = new HashMap<>();
+        for (int color : filteredColors) {
+            filteredColorsToScore.put(color, colorsToScore.get(color));
+        }
+
+        // Ensure the list of colors returned is sorted such that the first in the
+        // list is the most suitable, and the last is the least suitable.
+        List<Map.Entry<Integer, Double>> entryList = new ArrayList<>(
+                filteredColorsToScore.entrySet());
+        Collections.sort(entryList, new ScoredComparator());
+        List<Integer> colorsByScoreDescending = new ArrayList<>();
+        for (Map.Entry<Integer, Double> entry : entryList) {
+            int color = entry.getKey();
+            Cam16 cam = colorsToCam.get(color);
+            boolean duplicateHue = false;
+
+            for (Integer alreadyChosenColor : colorsByScoreDescending) {
+                Cam16 alreadyChosenCam = colorsToCam.get(alreadyChosenColor);
+                if (MathUtils.differenceDegrees(cam.getHue(), alreadyChosenCam.getHue()) < 15) {
+                    duplicateHue = true;
+                    break;
+                }
+            }
+
+            if (duplicateHue) {
+                continue;
+            }
+            colorsByScoreDescending.add(entry.getKey());
+        }
+
+        // Ensure that at least one color is returned.
+        if (colorsByScoreDescending.isEmpty()) {
+            colorsByScoreDescending.add(0xff4285F4);
+        }
+        return colorsByScoreDescending;
+    }
+
+    private static List<Integer> filter(
+            Map<Integer, Double> colorsToExcitedProportion, Map<Integer, Cam16> colorsToCam) {
+        List<Integer> filtered = new ArrayList<>();
+        for (Map.Entry<Integer, Cam16> entry : colorsToCam.entrySet()) {
+            int color = entry.getKey();
+            Cam16 cam = entry.getValue();
+            double proportion = colorsToExcitedProportion.get(color);
+
+            if (cam.getChroma() >= CUTOFF_CHROMA
+                    && ColorUtils.lstarFromArgb(color) >= CUTOFF_TONE
+                    && proportion >= CUTOFF_EXCITED_PROPORTION) {
+                filtered.add(color);
+            }
+        }
+        return filtered;
+    }
+
+    static class ScoredComparator implements Comparator<Map.Entry<Integer, Double>> {
+        ScoredComparator() {
+        }
+
+        @Override
+        public int compare(Map.Entry<Integer, Double> entry1, Map.Entry<Integer, Double> entry2) {
+            return -entry1.getValue().compareTo(entry2.getValue());
+        }
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/temperature/TemperatureCache.java b/packages/SystemUI/monet/src/com/android/systemui/monet/temperature/TemperatureCache.java
new file mode 100644
index 0000000..2f2022b
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/temperature/TemperatureCache.java
@@ -0,0 +1,337 @@
+/*
+ * 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.monet.temperature;
+
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.utils.ColorUtils;
+import com.android.systemui.monet.utils.MathUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Design utilities using color temperature theory.
+ *
+ * <p>Analogous colors, complementary color, and cache to efficiently, lazily, generate data for
+ * calculations when needed.
+ */
+public final class TemperatureCache {
+    private final Hct input;
+
+    private Hct precomputedComplement;
+    private List<Hct> precomputedHctsByTemp;
+    private List<Hct> precomputedHctsByHue;
+    private Map<Hct, Double> precomputedTempsByHct;
+
+    private TemperatureCache() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Create a cache that allows calculation of ex. complementary and analogous colors.
+     *
+     * @param input Color to find complement/analogous colors of. Any colors will have the same
+     *              tone,
+     *              and chroma as the input color, modulo any restrictions due to the other hues
+     *              having lower
+     *              limits on chroma.
+     */
+    public TemperatureCache(Hct input) {
+        this.input = input;
+    }
+
+    /**
+     * A color that complements the input color aesthetically.
+     *
+     * <p>In art, this is usually described as being across the color wheel. History of this shows
+     * intent as a color that is just as cool-warm as the input color is warm-cool.
+     */
+    public Hct getComplement() {
+        if (precomputedComplement != null) {
+            return precomputedComplement;
+        }
+
+        double coldestHue = getColdest().getHue();
+        double coldestTemp = getTempsByHct().get(getColdest());
+
+        double warmestHue = getWarmest().getHue();
+        double warmestTemp = getTempsByHct().get(getWarmest());
+        double range = warmestTemp - coldestTemp;
+        boolean startHueIsColdestToWarmest = isBetween(input.getHue(), coldestHue, warmestHue);
+        double startHue = startHueIsColdestToWarmest ? warmestHue : coldestHue;
+        double endHue = startHueIsColdestToWarmest ? coldestHue : warmestHue;
+        double directionOfRotation = 1.;
+        double smallestError = 1000.;
+        Hct answer = getHctsByHue().get((int) Math.round(input.getHue()));
+
+        double complementRelativeTemp = (1. - getRelativeTemperature(input));
+        // Find the color in the other section, closest to the inverse percentile
+        // of the input color. This is the complement.
+        for (double hueAddend = 0.; hueAddend <= 360.; hueAddend += 1.) {
+            double hue = MathUtils.sanitizeDegreesDouble(
+                    startHue + directionOfRotation * hueAddend);
+            if (!isBetween(hue, startHue, endHue)) {
+                continue;
+            }
+            Hct possibleAnswer = getHctsByHue().get((int) Math.round(hue));
+            double relativeTemp =
+                    (getTempsByHct().get(possibleAnswer) - coldestTemp) / range;
+            double error = Math.abs(complementRelativeTemp - relativeTemp);
+            if (error < smallestError) {
+                smallestError = error;
+                answer = possibleAnswer;
+            }
+        }
+        precomputedComplement = answer;
+        return precomputedComplement;
+    }
+
+    /**
+     * 5 colors that pair well with the input color.
+     *
+     * <p>The colors are equidistant in temperature and adjacent in hue.
+     */
+    public List<Hct> getAnalogousColors() {
+        return getAnalogousColors(5, 12);
+    }
+
+    /**
+     * A set of colors with differing hues, equidistant in temperature.
+     *
+     * <p>In art, this is usually described as a set of 5 colors on a color wheel divided into 12
+     * sections. This method allows provision of either of those values.
+     *
+     * <p>Behavior is undefined when count or divisions is 0. When divisions < count, colors repeat.
+     *
+     * @param count     The number of colors to return, includes the input color.
+     * @param divisions The number of divisions on the color wheel.
+     */
+    public List<Hct> getAnalogousColors(int count, int divisions) {
+        // The starting hue is the hue of the input color.
+        int startHue = (int) Math.round(input.getHue());
+        Hct startHct = getHctsByHue().get(startHue);
+        double lastTemp = getRelativeTemperature(startHct);
+
+        List<Hct> allColors = new ArrayList<>();
+        allColors.add(startHct);
+
+        double absoluteTotalTempDelta = 0.f;
+        for (int i = 0; i < 360; i++) {
+            int hue = MathUtils.sanitizeDegreesInt(startHue + i);
+            Hct hct = getHctsByHue().get(hue);
+            double temp = getRelativeTemperature(hct);
+            double tempDelta = Math.abs(temp - lastTemp);
+            lastTemp = temp;
+            absoluteTotalTempDelta += tempDelta;
+        }
+
+        int hueAddend = 1;
+        double tempStep = absoluteTotalTempDelta / (double) divisions;
+        double totalTempDelta = 0.0;
+        lastTemp = getRelativeTemperature(startHct);
+        while (allColors.size() < divisions) {
+            int hue = MathUtils.sanitizeDegreesInt(startHue + hueAddend);
+            Hct hct = getHctsByHue().get(hue);
+            double temp = getRelativeTemperature(hct);
+            double tempDelta = Math.abs(temp - lastTemp);
+            totalTempDelta += tempDelta;
+
+            double desiredTotalTempDeltaForIndex = (allColors.size() * tempStep);
+            boolean indexSatisfied = totalTempDelta >= desiredTotalTempDeltaForIndex;
+            int indexAddend = 1;
+            // Keep adding this hue to the answers until its temperature is
+            // insufficient. This ensures consistent behavior when there aren't
+            // `divisions` discrete steps between 0 and 360 in hue with `tempStep`
+            // delta in temperature between them.
+            //
+            // For example, white and black have no analogues: there are no other
+            // colors at T100/T0. Therefore, they should just be added to the array
+            // as answers.
+            while (indexSatisfied && allColors.size() < divisions) {
+                allColors.add(hct);
+                desiredTotalTempDeltaForIndex = ((allColors.size() + indexAddend) * tempStep);
+                indexSatisfied = totalTempDelta >= desiredTotalTempDeltaForIndex;
+                indexAddend++;
+            }
+            lastTemp = temp;
+            hueAddend++;
+
+            if (hueAddend > 360) {
+                while (allColors.size() < divisions) {
+                    allColors.add(hct);
+                }
+                break;
+            }
+        }
+
+        List<Hct> answers = new ArrayList<>();
+        answers.add(input);
+
+        int ccwCount = (int) Math.floor(((double) count - 1.0) / 2.0);
+        for (int i = 1; i < (ccwCount + 1); i++) {
+            int index = 0 - i;
+            while (index < 0) {
+                index = allColors.size() + index;
+            }
+            if (index >= allColors.size()) {
+                index = index % allColors.size();
+            }
+            answers.add(0, allColors.get(index));
+        }
+
+        int cwCount = count - ccwCount - 1;
+        for (int i = 1; i < (cwCount + 1); i++) {
+            int index = i;
+            while (index < 0) {
+                index = allColors.size() + index;
+            }
+            if (index >= allColors.size()) {
+                index = index % allColors.size();
+            }
+            answers.add(allColors.get(index));
+        }
+
+        return answers;
+    }
+
+    /**
+     * Temperature relative to all colors with the same chroma and tone.
+     *
+     * @param hct HCT to find the relative temperature of.
+     * @return Value on a scale from 0 to 1.
+     */
+    public double getRelativeTemperature(Hct hct) {
+        double range = getTempsByHct().get(getWarmest()) - getTempsByHct().get(getColdest());
+        double differenceFromColdest =
+                getTempsByHct().get(hct) - getTempsByHct().get(getColdest());
+        // Handle when there's no difference in temperature between warmest and
+        // coldest: for example, at T100, only one color is available, white.
+        if (range == 0.) {
+            return 0.5;
+        }
+        return differenceFromColdest / range;
+    }
+
+    /**
+     * Value representing cool-warm factor of a color. Values below 0 are considered cool, above,
+     * warm.
+     *
+     * <p>Color science has researched emotion and harmony, which art uses to select colors.
+     * Warm-cool
+     * is the foundation of analogous and complementary colors. See: - Li-Chen Ou's Chapter 19 in
+     * Handbook of Color Psychology (2015). - Josef Albers' Interaction of Color chapters 19 and
+     * 21.
+     *
+     * <p>Implementation of Ou, Woodcock and Wright's algorithm, which uses Lab/LCH color space.
+     * Return value has these properties:<br>
+     * - Values below 0 are cool, above 0 are warm.<br>
+     * - Lower bound: -9.66. Chroma is infinite. Assuming max of Lab chroma 130.<br>
+     * - Upper bound: 8.61. Chroma is infinite. Assuming max of Lab chroma 130.
+     */
+    public static double rawTemperature(Hct color) {
+        double[] lab = ColorUtils.labFromArgb(color.toInt());
+        double hue = MathUtils.sanitizeDegreesDouble(Math.toDegrees(Math.atan2(lab[2], lab[1])));
+        double chroma = Math.hypot(lab[1], lab[2]);
+        return -0.5
+                + 0.02
+                * Math.pow(chroma, 1.07)
+                * Math.cos(Math.toRadians(MathUtils.sanitizeDegreesDouble(hue - 50.)));
+    }
+
+    /** Coldest color with same chroma and tone as input. */
+    private Hct getColdest() {
+        return getHctsByTemp().get(0);
+    }
+
+    /**
+     * HCTs for all colors with the same chroma/tone as the input.
+     *
+     * <p>Sorted by hue, ex. index 0 is hue 0.
+     */
+    private List<Hct> getHctsByHue() {
+        if (precomputedHctsByHue != null) {
+            return precomputedHctsByHue;
+        }
+        List<Hct> hcts = new ArrayList<>();
+        for (double hue = 0.; hue <= 360.; hue += 1.) {
+            Hct colorAtHue = Hct.from(hue, input.getChroma(), input.getTone());
+            hcts.add(colorAtHue);
+        }
+        precomputedHctsByHue = Collections.unmodifiableList(hcts);
+        return precomputedHctsByHue;
+    }
+
+    /**
+     * HCTs for all colors with the same chroma/tone as the input.
+     *
+     * <p>Sorted from coldest first to warmest last.
+     */
+    // Prevent lint for Comparator not being available on Android before API level 24, 7.0, 2016.
+    // "AndroidJdkLibsChecker" for one linter, "NewApi" for another.
+    // A java_library Bazel rule with an Android constraint cannot skip these warnings without this
+    // annotation; another solution would be to create an android_library rule and supply
+    // AndroidManifest with an SDK set higher than 23.
+    @SuppressWarnings({"AndroidJdkLibsChecker", "NewApi"})
+    private List<Hct> getHctsByTemp() {
+        if (precomputedHctsByTemp != null) {
+            return precomputedHctsByTemp;
+        }
+
+        List<Hct> hcts = new ArrayList<>(getHctsByHue());
+        hcts.add(input);
+        Comparator<Hct> temperaturesComparator =
+                Comparator.comparing((Hct arg) -> getTempsByHct().get(arg), Double::compareTo);
+        Collections.sort(hcts, temperaturesComparator);
+        precomputedHctsByTemp = hcts;
+        return precomputedHctsByTemp;
+    }
+
+    /** Keys of HCTs in getHctsByTemp, values of raw temperature. */
+    private Map<Hct, Double> getTempsByHct() {
+        if (precomputedTempsByHct != null) {
+            return precomputedTempsByHct;
+        }
+
+        List<Hct> allHcts = new ArrayList<>(getHctsByHue());
+        allHcts.add(input);
+
+        Map<Hct, Double> temperaturesByHct = new HashMap<>();
+        for (Hct hct : allHcts) {
+            temperaturesByHct.put(hct, rawTemperature(hct));
+        }
+
+        precomputedTempsByHct = temperaturesByHct;
+        return precomputedTempsByHct;
+    }
+
+    /** Warmest color with same chroma and tone as input. */
+    private Hct getWarmest() {
+        return getHctsByTemp().get(getHctsByTemp().size() - 1);
+    }
+
+    /** Determines if an angle is between two other angles, rotating clockwise. */
+    private static boolean isBetween(double angle, double a, double b) {
+        if (a < b) {
+            return a <= angle && angle <= b;
+        }
+        return a <= angle || angle <= b;
+    }
+}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/utils/ColorUtils.java b/packages/SystemUI/monet/src/com/android/systemui/monet/utils/ColorUtils.java
new file mode 100644
index 0000000..5a4ced0
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/utils/ColorUtils.java
@@ -0,0 +1,266 @@
+/*
+ * 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.monet.utils;
+
+/**
+ * Color science utilities.
+ *
+ * <p>Utility methods for color science constants and color space conversions that aren't HCT or
+ * CAM16.
+ */
+public class ColorUtils {
+    private ColorUtils() {
+    }
+
+    static final double[][] SRGB_TO_XYZ =
+            new double[][]{
+                    new double[]{0.41233895, 0.35762064, 0.18051042},
+                    new double[]{0.2126, 0.7152, 0.0722},
+                    new double[]{0.01932141, 0.11916382, 0.95034478},
+            };
+
+    static final double[][] XYZ_TO_SRGB =
+            new double[][]{
+                    new double[]{
+                            3.2413774792388685, -1.5376652402851851, -0.49885366846268053,
+                    },
+                    new double[]{
+                            -0.9691452513005321, 1.8758853451067872, 0.04156585616912061,
+                    },
+                    new double[]{
+                            0.05562093689691305, -0.20395524564742123, 1.0571799111220335,
+                    },
+            };
+
+    static final double[] WHITE_POINT_D65 = new double[]{95.047, 100.0, 108.883};
+
+    /** Converts a color from RGB components to ARGB format. */
+    public static int argbFromRgb(int red, int green, int blue) {
+        return (255 << 24) | ((red & 255) << 16) | ((green & 255) << 8) | (blue & 255);
+    }
+
+    /** Converts a color from linear RGB components to ARGB format. */
+    public static int argbFromLinrgb(double[] linrgb) {
+        int r = delinearized(linrgb[0]);
+        int g = delinearized(linrgb[1]);
+        int b = delinearized(linrgb[2]);
+        return argbFromRgb(r, g, b);
+    }
+
+    /** Returns the alpha component of a color in ARGB format. */
+    public static int alphaFromArgb(int argb) {
+        return (argb >> 24) & 255;
+    }
+
+    /** Returns the red component of a color in ARGB format. */
+    public static int redFromArgb(int argb) {
+        return (argb >> 16) & 255;
+    }
+
+    /** Returns the green component of a color in ARGB format. */
+    public static int greenFromArgb(int argb) {
+        return (argb >> 8) & 255;
+    }
+
+    /** Returns the blue component of a color in ARGB format. */
+    public static int blueFromArgb(int argb) {
+        return argb & 255;
+    }
+
+    /** Returns whether a color in ARGB format is opaque. */
+    public static boolean isOpaque(int argb) {
+        return alphaFromArgb(argb) >= 255;
+    }
+
+    /** Converts a color from ARGB to XYZ. */
+    public static int argbFromXyz(double x, double y, double z) {
+        double[][] matrix = XYZ_TO_SRGB;
+        double linearR = matrix[0][0] * x + matrix[0][1] * y + matrix[0][2] * z;
+        double linearG = matrix[1][0] * x + matrix[1][1] * y + matrix[1][2] * z;
+        double linearB = matrix[2][0] * x + matrix[2][1] * y + matrix[2][2] * z;
+        int r = delinearized(linearR);
+        int g = delinearized(linearG);
+        int b = delinearized(linearB);
+        return argbFromRgb(r, g, b);
+    }
+
+    /** Converts a color from XYZ to ARGB. */
+    public static double[] xyzFromArgb(int argb) {
+        double r = linearized(redFromArgb(argb));
+        double g = linearized(greenFromArgb(argb));
+        double b = linearized(blueFromArgb(argb));
+        return MathUtils.matrixMultiply(new double[]{r, g, b}, SRGB_TO_XYZ);
+    }
+
+    /** Converts a color represented in Lab color space into an ARGB integer. */
+    public static int argbFromLab(double l, double a, double b) {
+        double[] whitePoint = WHITE_POINT_D65;
+        double fy = (l + 16.0) / 116.0;
+        double fx = a / 500.0 + fy;
+        double fz = fy - b / 200.0;
+        double xNormalized = labInvf(fx);
+        double yNormalized = labInvf(fy);
+        double zNormalized = labInvf(fz);
+        double x = xNormalized * whitePoint[0];
+        double y = yNormalized * whitePoint[1];
+        double z = zNormalized * whitePoint[2];
+        return argbFromXyz(x, y, z);
+    }
+
+    /**
+     * Converts a color from ARGB representation to L*a*b* representation.
+     *
+     * @param argb the ARGB representation of a color
+     * @return a Lab object representing the color
+     */
+    public static double[] labFromArgb(int argb) {
+        double linearR = linearized(redFromArgb(argb));
+        double linearG = linearized(greenFromArgb(argb));
+        double linearB = linearized(blueFromArgb(argb));
+        double[][] matrix = SRGB_TO_XYZ;
+        double x = matrix[0][0] * linearR + matrix[0][1] * linearG + matrix[0][2] * linearB;
+        double y = matrix[1][0] * linearR + matrix[1][1] * linearG + matrix[1][2] * linearB;
+        double z = matrix[2][0] * linearR + matrix[2][1] * linearG + matrix[2][2] * linearB;
+        double[] whitePoint = WHITE_POINT_D65;
+        double xNormalized = x / whitePoint[0];
+        double yNormalized = y / whitePoint[1];
+        double zNormalized = z / whitePoint[2];
+        double fx = labF(xNormalized);
+        double fy = labF(yNormalized);
+        double fz = labF(zNormalized);
+        double l = 116.0 * fy - 16;
+        double a = 500.0 * (fx - fy);
+        double b = 200.0 * (fy - fz);
+        return new double[]{l, a, b};
+    }
+
+    /**
+     * Converts an L* value to an ARGB representation.
+     *
+     * @param lstar L* in L*a*b*
+     * @return ARGB representation of grayscale color with lightness matching L*
+     */
+    public static int argbFromLstar(double lstar) {
+        double y = yFromLstar(lstar);
+        int component = delinearized(y);
+        return argbFromRgb(component, component, component);
+    }
+
+    /**
+     * Computes the L* value of a color in ARGB representation.
+     *
+     * @param argb ARGB representation of a color
+     * @return L*, from L*a*b*, coordinate of the color
+     */
+    public static double lstarFromArgb(int argb) {
+        double y = xyzFromArgb(argb)[1];
+        return 116.0 * labF(y / 100.0) - 16.0;
+    }
+
+    /**
+     * Converts an L* value to a Y value.
+     *
+     * <p>L* in L*a*b* and Y in XYZ measure the same quantity, luminance.
+     *
+     * <p>L* measures perceptual luminance, a linear scale. Y in XYZ measures relative luminance, a
+     * logarithmic scale.
+     *
+     * @param lstar L* in L*a*b*
+     * @return Y in XYZ
+     */
+    public static double yFromLstar(double lstar) {
+        return 100.0 * labInvf((lstar + 16.0) / 116.0);
+    }
+
+    /**
+     * Converts a Y value to an L* value.
+     *
+     * <p>L* in L*a*b* and Y in XYZ measure the same quantity, luminance.
+     *
+     * <p>L* measures perceptual luminance, a linear scale. Y in XYZ measures relative luminance, a
+     * logarithmic scale.
+     *
+     * @param y Y in XYZ
+     * @return L* in L*a*b*
+     */
+    public static double lstarFromY(double y) {
+        return labF(y / 100.0) * 116.0 - 16.0;
+    }
+
+    /**
+     * Linearizes an RGB component.
+     *
+     * @param rgbComponent 0 <= rgb_component <= 255, represents R/G/B channel
+     * @return 0.0 <= output <= 100.0, color channel converted to linear RGB space
+     */
+    public static double linearized(int rgbComponent) {
+        double normalized = rgbComponent / 255.0;
+        if (normalized <= 0.040449936) {
+            return normalized / 12.92 * 100.0;
+        } else {
+            return Math.pow((normalized + 0.055) / 1.055, 2.4) * 100.0;
+        }
+    }
+
+    /**
+     * Delinearizes an RGB component.
+     *
+     * @param rgbComponent 0.0 <= rgb_component <= 100.0, represents linear R/G/B channel
+     * @return 0 <= output <= 255, color channel converted to regular RGB space
+     */
+    public static int delinearized(double rgbComponent) {
+        double normalized = rgbComponent / 100.0;
+        double delinearized = 0.0;
+        if (normalized <= 0.0031308) {
+            delinearized = normalized * 12.92;
+        } else {
+            delinearized = 1.055 * Math.pow(normalized, 1.0 / 2.4) - 0.055;
+        }
+        return MathUtils.clampInt(0, 255, (int) Math.round(delinearized * 255.0));
+    }
+
+    /**
+     * Returns the standard white point; white on a sunny day.
+     *
+     * @return The white point
+     */
+    public static double[] whitePointD65() {
+        return WHITE_POINT_D65;
+    }
+
+    static double labF(double t) {
+        double e = 216.0 / 24389.0;
+        double kappa = 24389.0 / 27.0;
+        if (t > e) {
+            return Math.pow(t, 1.0 / 3.0);
+        } else {
+            return (kappa * t + 16) / 116;
+        }
+    }
+
+    static double labInvf(double ft) {
+        double e = 216.0 / 24389.0;
+        double kappa = 24389.0 / 27.0;
+        double ft3 = ft * ft * ft;
+        if (ft3 > e) {
+            return ft3;
+        } else {
+            return (116 * ft - 16) / kappa;
+        }
+    }
+}
+
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/utils/MathUtils.java b/packages/SystemUI/monet/src/com/android/systemui/monet/utils/MathUtils.java
new file mode 100644
index 0000000..a7622ef
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/utils/MathUtils.java
@@ -0,0 +1,135 @@
+/*
+ * 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.monet.utils;
+
+/** Utility methods for mathematical operations. */
+public class MathUtils {
+    private MathUtils() {
+    }
+
+    /**
+     * The signum function.
+     *
+     * @return 1 if num > 0, -1 if num < 0, and 0 if num = 0
+     */
+    public static int signum(double num) {
+        if (num < 0) {
+            return -1;
+        } else if (num == 0) {
+            return 0;
+        } else {
+            return 1;
+        }
+    }
+
+    /**
+     * The linear interpolation function.
+     *
+     * @return start if amount = 0 and stop if amount = 1
+     */
+    public static double lerp(double start, double stop, double amount) {
+        return (1.0 - amount) * start + amount * stop;
+    }
+
+    /**
+     * Clamps an integer between two integers.
+     *
+     * @return input when min <= input <= max, and either min or max otherwise.
+     */
+    public static int clampInt(int min, int max, int input) {
+        if (input < min) {
+            return min;
+        } else if (input > max) {
+            return max;
+        }
+
+        return input;
+    }
+
+    /**
+     * Clamps an integer between two floating-point numbers.
+     *
+     * @return input when min <= input <= max, and either min or max otherwise.
+     */
+    public static double clampDouble(double min, double max, double input) {
+        if (input < min) {
+            return min;
+        } else if (input > max) {
+            return max;
+        }
+
+        return input;
+    }
+
+    /**
+     * Sanitizes a degree measure as an integer.
+     *
+     * @return a degree measure between 0 (inclusive) and 360 (exclusive).
+     */
+    public static int sanitizeDegreesInt(int degrees) {
+        degrees = degrees % 360;
+        if (degrees < 0) {
+            degrees = degrees + 360;
+        }
+        return degrees;
+    }
+
+    /**
+     * Sanitizes a degree measure as a floating-point number.
+     *
+     * @return a degree measure between 0.0 (inclusive) and 360.0 (exclusive).
+     */
+    public static double sanitizeDegreesDouble(double degrees) {
+        degrees = degrees % 360.0;
+        if (degrees < 0) {
+            degrees = degrees + 360.0;
+        }
+        return degrees;
+    }
+
+    /**
+     * Sign of direction change needed to travel from one angle to another.
+     *
+     * <p>For angles that are 180 degrees apart from each other, both directions have the same
+     * travel
+     * distance, so either direction is shortest. The value 1.0 is returned in this case.
+     *
+     * @param from The angle travel starts from, in degrees.
+     * @param to   The angle travel ends at, in degrees.
+     * @return -1 if decreasing from leads to the shortest travel distance, 1 if increasing from
+     * leads
+     * to the shortest travel distance.
+     */
+    public static double rotationDirection(double from, double to) {
+        double increasingDifference = sanitizeDegreesDouble(to - from);
+        return increasingDifference <= 180.0 ? 1.0 : -1.0;
+    }
+
+    /** Distance of two points on a circle, represented using degrees. */
+    public static double differenceDegrees(double a, double b) {
+        return 180.0 - Math.abs(Math.abs(a - b) - 180.0);
+    }
+
+    /** Multiplies a 1x3 row vector with a 3x3 matrix. */
+    public static double[] matrixMultiply(double[] row, double[][] matrix) {
+        double a = row[0] * matrix[0][0] + row[1] * matrix[0][1] + row[2] * matrix[0][2];
+        double b = row[0] * matrix[1][0] + row[1] * matrix[1][1] + row[2] * matrix[1][2];
+        double c = row[0] * matrix[2][0] + row[1] * matrix[2][1] + row[2] * matrix[2][2];
+        return new double[]{a, b, c};
+    }
+}
+
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/utils/StringUtils.java b/packages/SystemUI/monet/src/com/android/systemui/monet/utils/StringUtils.java
new file mode 100644
index 0000000..cb2b694
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/utils/StringUtils.java
@@ -0,0 +1,35 @@
+/*
+ * 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.monet.utils;
+
+/** Utility methods for string representations of colors. */
+final class StringUtils {
+    private StringUtils() {
+    }
+
+    /**
+     * Hex string representing color, ex. #ff0000 for red.
+     *
+     * @param argb ARGB representation of a color.
+     */
+    public static String hexFromArgb(int argb) {
+        int red = ColorUtils.redFromArgb(argb);
+        int blue = ColorUtils.blueFromArgb(argb);
+        int green = ColorUtils.greenFromArgb(argb);
+        return String.format("#%02x%02x%02x", red, green, blue);
+    }
+}
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 a2a0709..590015d 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -17,11 +17,13 @@
 import android.graphics.Rect
 import android.graphics.drawable.Drawable
 import android.view.View
+import com.android.internal.annotations.Keep
 import com.android.systemui.plugins.annotations.ProvidesInterface
 import com.android.systemui.plugins.log.LogBuffer
 import java.io.PrintWriter
 import java.util.Locale
 import java.util.TimeZone
+import org.json.JSONObject
 
 /** Identifies a clock design */
 typealias ClockId = String
@@ -41,7 +43,13 @@
     fun getClocks(): List<ClockMetadata>
 
     /** Initializes and returns the target clock design */
-    fun createClock(id: ClockId): ClockController
+    @Deprecated("Use overload with ClockSettings")
+    fun createClock(id: ClockId): ClockController {
+        return createClock(ClockSettings(id, null, null))
+    }
+
+    /** Initializes and returns the target clock design */
+    fun createClock(settings: ClockSettings): ClockController
 
     /** A static thumbnail for rendering in some examples */
     fun getClockThumbnail(id: ClockId): Drawable?
@@ -62,11 +70,16 @@
     val animations: ClockAnimations
 
     /** Initializes various rendering parameters. If never called, provides reasonable defaults. */
-    fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
+    fun initialize(
+        resources: Resources,
+        dozeFraction: Float,
+        foldFraction: Float,
+    ) {
         events.onColorPaletteChanged(resources)
         animations.doze(dozeFraction)
         animations.fold(foldFraction)
-        events.onTimeTick()
+        smallClock.events.onTimeTick()
+        largeClock.events.onTimeTick()
     }
 
     /** Optional method for dumping debug information */
@@ -87,9 +100,6 @@
 
 /** Events that should call when various rendering parameters change */
 interface ClockEvents {
-    /** Call every time tick */
-    fun onTimeTick() {}
-
     /** Call whenever timezone changes */
     fun onTimeZoneChanged(timeZone: TimeZone) {}
 
@@ -101,6 +111,9 @@
 
     /** Call whenever the color palette should update */
     fun onColorPaletteChanged(resources: Resources) {}
+
+    /** Call whenever the weather data should update */
+    fun onWeatherDataChanged(data: Weather) {}
 }
 
 /** Methods which trigger various clock animations */
@@ -131,6 +144,13 @@
 
 /** Events that have specific data about the related face */
 interface ClockFaceEvents {
+    /** Call every time tick */
+    fun onTimeTick() {}
+
+    /** Expected interval between calls to onTimeTick. Can always reduce to PER_MINUTE in AOD. */
+    val tickRate: ClockTickRate
+        get() = ClockTickRate.PER_MINUTE
+
     /** Region Darkness specific to the clock face */
     fun onRegionDarknessChanged(isDark: Boolean) {}
 
@@ -150,8 +170,46 @@
     fun onTargetRegionChanged(targetRegion: Rect?) {}
 }
 
+/** Tick rates for clocks */
+enum class ClockTickRate(val value: Int) {
+    PER_MINUTE(2), // Update the clock once per minute.
+    PER_SECOND(1), // Update the clock once per second.
+    PER_FRAME(0), // Update the clock every second.
+}
+
 /** Some data about a clock design */
 data class ClockMetadata(
     val clockId: ClockId,
     val name: String,
 )
+
+/** Structure for keeping clock-specific settings */
+@Keep
+data class ClockSettings(
+    var clockId: ClockId? = null,
+    var seedColor: Int? = null,
+    var _applied_timestamp: Long? = null,
+) {
+    companion object {
+        private val KEY_CLOCK_ID = "clockId"
+        private val KEY_SEED_COLOR = "seedColor"
+        private val KEY_TIMESTAMP = "_applied_timestamp"
+
+        fun serialize(setting: ClockSettings): String {
+            return JSONObject()
+                .put(KEY_CLOCK_ID, setting.clockId)
+                .put(KEY_SEED_COLOR, setting.seedColor)
+                .put(KEY_TIMESTAMP, setting._applied_timestamp)
+                .toString()
+        }
+
+        fun deserialize(jsonStr: String): ClockSettings {
+            val json = JSONObject(jsonStr)
+            return ClockSettings(
+                json.getString(KEY_CLOCK_ID),
+                if (!json.isNull(KEY_SEED_COLOR)) json.getInt(KEY_SEED_COLOR) else null,
+                if (!json.isNull(KEY_TIMESTAMP)) json.getLong(KEY_TIMESTAMP) else null
+            )
+        }
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt
new file mode 100644
index 0000000..302f175
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt
@@ -0,0 +1,85 @@
+package com.android.systemui.plugins
+
+import android.os.Bundle
+
+class Weather(val conditions: WeatherStateIcon, val temperature: Int, val isCelsius: Boolean) {
+    companion object {
+        private const val TAG = "Weather"
+        private const val WEATHER_STATE_ICON_KEY = "weather_state_icon_extra_key"
+        private const val TEMPERATURE_VALUE_KEY = "temperature_value_extra_key"
+        private const val TEMPERATURE_UNIT_KEY = "temperature_unit_extra_key"
+        private const val INVALID_TEMPERATURE = Int.MIN_VALUE
+
+        fun fromBundle(extras: Bundle): Weather? {
+            val icon =
+                WeatherStateIcon.fromInt(
+                    extras.getInt(WEATHER_STATE_ICON_KEY, WeatherStateIcon.UNKNOWN_ICON.id)
+                )
+            if (icon == null || icon == WeatherStateIcon.UNKNOWN_ICON) {
+                return null
+            }
+            val temperature = extras.getInt(TEMPERATURE_VALUE_KEY, INVALID_TEMPERATURE)
+            if (temperature == INVALID_TEMPERATURE) {
+                return null
+            }
+            return Weather(icon, temperature, extras.getBoolean(TEMPERATURE_UNIT_KEY))
+        }
+    }
+
+    enum class WeatherStateIcon(val id: Int) {
+        UNKNOWN_ICON(0),
+
+        // Clear, day & night.
+        SUNNY(1),
+        CLEAR_NIGHT(2),
+
+        // Mostly clear, day & night.
+        MOSTLY_SUNNY(3),
+        MOSTLY_CLEAR_NIGHT(4),
+
+        // Partly cloudy, day & night.
+        PARTLY_CLOUDY(5),
+        PARTLY_CLOUDY_NIGHT(6),
+
+        // Mostly cloudy, day & night.
+        MOSTLY_CLOUDY_DAY(7),
+        MOSTLY_CLOUDY_NIGHT(8),
+        CLOUDY(9),
+        HAZE_FOG_DUST_SMOKE(10),
+        DRIZZLE(11),
+        HEAVY_RAIN(12),
+        SHOWERS_RAIN(13),
+
+        // Scattered showers, day & night.
+        SCATTERED_SHOWERS_DAY(14),
+        SCATTERED_SHOWERS_NIGHT(15),
+
+        // Isolated scattered thunderstorms, day & night.
+        ISOLATED_SCATTERED_TSTORMS_DAY(16),
+        ISOLATED_SCATTERED_TSTORMS_NIGHT(17),
+        STRONG_TSTORMS(18),
+        BLIZZARD(19),
+        BLOWING_SNOW(20),
+        FLURRIES(21),
+        HEAVY_SNOW(22),
+
+        // Scattered snow showers, day & night.
+        SCATTERED_SNOW_SHOWERS_DAY(23),
+        SCATTERED_SNOW_SHOWERS_NIGHT(24),
+        SNOW_SHOWERS_SNOW(25),
+        MIXED_RAIN_HAIL_RAIN_SLEET(26),
+        SLEET_HAIL(27),
+        TORNADO(28),
+        TROPICAL_STORM_HURRICANE(29),
+        WINDY_BREEZY(30),
+        WINTRY_MIX_RAIN_SNOW(31);
+
+        companion object {
+            fun fromInt(value: Int) = values().firstOrNull { it.id == value }
+        }
+    }
+
+    override fun toString(): String {
+        return "$conditions $temperature${if (isCelsius) "C" else "F"}"
+    }
+}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher_item.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher_item.xml
index c388f15..81f4c8c 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher_item.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher_item.xml
@@ -15,6 +15,7 @@
   -->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/user_switcher_item"
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
   <TextView
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 64ece47..ca4028a 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -105,6 +105,7 @@
             android:id="@+id/key1"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key2"
             androidprv:digit="1"
             androidprv:textView="@+id/pinEntry" />
 
@@ -112,6 +113,7 @@
             android:id="@+id/key2"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key3"
             androidprv:digit="2"
             androidprv:textView="@+id/pinEntry" />
 
@@ -119,6 +121,7 @@
             android:id="@+id/key3"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key4"
             androidprv:digit="3"
             androidprv:textView="@+id/pinEntry" />
 
@@ -126,6 +129,7 @@
             android:id="@+id/key4"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key5"
             androidprv:digit="4"
             androidprv:textView="@+id/pinEntry" />
 
@@ -133,6 +137,7 @@
             android:id="@+id/key5"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key6"
             androidprv:digit="5"
             androidprv:textView="@+id/pinEntry" />
 
@@ -140,6 +145,7 @@
             android:id="@+id/key6"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key7"
             androidprv:digit="6"
             androidprv:textView="@+id/pinEntry" />
 
@@ -147,13 +153,16 @@
             android:id="@+id/key7"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key8"
             androidprv:digit="7"
             androidprv:textView="@+id/pinEntry" />
 
+
         <com.android.keyguard.NumPadKey
             android:id="@+id/key8"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key9"
             androidprv:digit="8"
             androidprv:textView="@+id/pinEntry" />
 
@@ -161,34 +170,33 @@
             android:id="@+id/key9"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/delete_button"
             androidprv:digit="9"
             androidprv:textView="@+id/pinEntry" />
 
-
         <com.android.keyguard.NumPadButton
             android:id="@+id/delete_button"
+            style="@style/NumPadKey.Delete"
             android:layout_width="0dp"
             android:layout_height="0dp"
-            style="@style/NumPadKey.Delete"
-            android:contentDescription="@string/keyboardview_keycode_delete"
-            />
+            android:accessibilityTraversalBefore="@id/key0"
+            android:contentDescription="@string/keyboardview_keycode_delete" />
 
         <com.android.keyguard.NumPadKey
             android:id="@+id/key0"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key_enter"
             androidprv:digit="0"
             androidprv:textView="@+id/pinEntry" />
 
         <com.android.keyguard.NumPadButton
             android:id="@+id/key_enter"
+            style="@style/NumPadKey.Enter"
             android:layout_width="0dp"
             android:layout_height="0dp"
-            style="@style/NumPadKey.Enter"
-            android:contentDescription="@string/keyboardview_keycode_enter"
-            />
-
-    </androidx.constraintlayout.widget.ConstraintLayout>
+            android:contentDescription="@string/keyboardview_keycode_enter" />
+</androidx.constraintlayout.widget.ConstraintLayout>
 
     <include layout="@layout/keyguard_eca"
              android:id="@+id/keyguard_selector_fade_container"
diff --git a/packages/SystemUI/res-keyguard/values/arrays.xml b/packages/SystemUI/res-keyguard/values/arrays.xml
index a8b3c1b..26bc865 100644
--- a/packages/SystemUI/res-keyguard/values/arrays.xml
+++ b/packages/SystemUI/res-keyguard/values/arrays.xml
@@ -32,4 +32,13 @@
         <item>TUV</item><!-- 8 -->
         <item>WXYZ</item><!-- 9 -->
     </string-array>
+
+    <integer-array name="bouncer_pin_shapes">
+        <item>@drawable/pin_dot_shape_1_avd</item>
+        <item>@drawable/pin_dot_shape_2_avd</item>
+        <item>@drawable/pin_dot_shape_3_avd</item>
+        <item>@drawable/pin_dot_shape_4_avd</item>
+        <item>@drawable/pin_dot_shape_5_avd</item>
+        <item>@drawable/pin_dot_shape_6_avd</item>
+    </integer-array>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 6cc5b9d..b9c7be2 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -69,6 +69,10 @@
 
     <!-- The size of the dots in the PIN unlock method. -->
     <dimen name="password_dot_size">9dp</dimen>
+
+    <!-- The size of the shape in the PIN unlock method. -->
+    <dimen name="password_shape_size">34dp</dimen>
+
     <!-- The size of PIN text in the PIN unlock method. -->
     <integer name="scaled_password_text_size">40</integer>
 
@@ -139,4 +143,9 @@
 
     <!-- Translation y for appear animation -->
     <dimen name="keyguard_host_view_translation_y">80dp</dimen>
+
+    <!-- Attributes for placeholder dots in 6 digit PIN view -->
+    <dimen name="default_dot_diameter">34dp</dimen>
+    <dimen name="default_dot_spacing">0dp</dimen>
+
 </resources>
diff --git a/packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml b/packages/SystemUI/res/color/accessibility_magnification_image_button_background.xml
similarity index 62%
copy from packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml
copy to packages/SystemUI/res/color/accessibility_magnification_image_button_background.xml
index 0a4e2bb..5e0539a 100644
--- a/packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml
+++ b/packages/SystemUI/res/color/accessibility_magnification_image_button_background.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2019 The Android Open Source Project
+  ~ 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.
@@ -14,8 +14,9 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.settingslib.display">
-
-</manifest>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:state_selected="true"
+          android:color="?androidprv:attr/colorAccent"  />
+    <item android:color="?androidprv:attr/colorSurfaceVariant" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml b/packages/SystemUI/res/color/accessibility_magnification_image_button_tint.xml
similarity index 61%
copy from packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml
copy to packages/SystemUI/res/color/accessibility_magnification_image_button_tint.xml
index 0a4e2bb..d444e4c 100644
--- a/packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml
+++ b/packages/SystemUI/res/color/accessibility_magnification_image_button_tint.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2019 The Android Open Source Project
+  ~ 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.
@@ -14,8 +14,9 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.settingslib.display">
-
-</manifest>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:state_selected="true"
+          android:color="?androidprv:attr/textColorPrimaryInverse"  />
+    <item android:color="?androidprv:attr/textColorPrimary" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_image_btn_bg.xml b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_image_btn_bg.xml
new file mode 100644
index 0000000..16ddcd8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_image_btn_bg.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:attr/colorControlHighlight">
+    <item android:id="@android:id/mask">
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/magnification_setting_image_button_corner_radius" />
+            <solid android:color="@color/accessibility_magnification_image_button_background" />
+        </shape>
+    </item>
+    <item android:id="@android:id/background">
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/magnification_setting_image_button_corner_radius" />
+            <solid android:color="@color/accessibility_magnification_image_button_background" />
+        </shape>
+    </item>
+</ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_btn_bg.xml b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_image_btn_layout_bg.xml
similarity index 61%
rename from packages/SystemUI/res/drawable/accessibility_magnification_setting_view_btn_bg.xml
rename to packages/SystemUI/res/drawable/accessibility_magnification_setting_view_image_btn_layout_bg.xml
index 5c9dd56..900711f 100644
--- a/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_btn_bg.xml
+++ b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_image_btn_layout_bg.xml
@@ -1,28 +1,22 @@
-<?xml version="1.0" encoding="utf-8"?>

-<!--

-    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.

--->

-<ripple xmlns:android="http://schemas.android.com/apk/res/android"

-android:color="?android:attr/colorControlHighlight">

-<item android:id="@android:id/mask">

-    <shape android:shape="oval">

-        <solid android:color="@color/accessibility_magnifier_bg" />

-        <size

-            android:width="56dp"

-            android:height="56dp"/>

-        <corners android:radius="2dp"/>

-    </shape>

-</item>

-</ripple>
\ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:shape="rectangle">
+    <solid android:color="?androidprv:attr/colorSurfaceVariant" />
+    <corners android:radius="@dimen/magnification_setting_image_button_background_corner_radius" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/accessibility_window_magnification_background.xml b/packages/SystemUI/res/drawable/accessibility_window_magnification_background.xml
new file mode 100644
index 0000000..58fe368
--- /dev/null
+++ b/packages/SystemUI/res/drawable/accessibility_window_magnification_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/magnifier_corner_radius" />
+            <stroke
+                android:color="@color/magnification_border_color"
+                android:width="@dimen/magnifier_border_width"/>
+        </shape>
+    </item>
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/magnifier_outer_corner_radius" />
+            <stroke
+                android:color="@android:color/black"
+                android:width="@dimen/magnifier_stroke_width"/>
+        </shape>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/accessibility_window_magnification_background_change.xml b/packages/SystemUI/res/drawable/accessibility_window_magnification_background_change.xml
new file mode 100644
index 0000000..693545b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/accessibility_window_magnification_background_change.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/magnifier_edit_corner_radius" />
+            <stroke
+                android:color="@color/magnification_border_color"
+                android:width="@dimen/magnifier_border_width"
+                android:dashWidth="@dimen/magnifier_edit_dash_gap"
+                android:dashGap="@dimen/magnifier_edit_dash_gap"/>
+        </shape>
+    </item>
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="@dimen/magnifier_edit_outer_corner_radius" />
+            <stroke
+                android:color="@android:color/black"
+                android:width="@dimen/magnifier_stroke_width"/>
+        </shape>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_corner_background.xml b/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_corner_background.xml
new file mode 100644
index 0000000..c8cd4c9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_corner_background.xml
@@ -0,0 +1,25 @@
+<?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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <size
+        android:width="@dimen/magnification_window_drag_corner_size"
+        android:height="@dimen/magnification_window_drag_corner_size"/>
+    <stroke
+        android:color="@android:color/black"
+        android:width="@dimen/magnification_window_drag_corner_stroke"/>
+    <solid android:color="@color/magnification_drag_corner_background" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background.xml b/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background.xml
new file mode 100644
index 0000000..a52e805
--- /dev/null
+++ b/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <stroke
+        android:color="@android:color/black"
+        android:width="@dimen/magnifier_stroke_width"/>
+    <corners android:radius="@dimen/magnifier_corner_radius" />
+    <solid android:color="@color/magnification_border_color" />
+</shape>
\ No newline at end of file
diff --git a/packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml b/packages/SystemUI/res/drawable/clipboard_minimized_background.xml
similarity index 64%
rename from packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml
rename to packages/SystemUI/res/drawable/clipboard_minimized_background.xml
index 0a4e2bb..a179c14 100644
--- a/packages/SettingsLib/DisplayDensityUtils/AndroidManifest.xml
+++ b/packages/SystemUI/res/drawable/clipboard_minimized_background.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2019 The Android Open Source Project
+  ~ 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.
@@ -14,8 +14,10 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.settingslib.display">
-
-</manifest>
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:shape="rectangle">
+    <solid android:color="?androidprv:attr/colorAccentSecondary"/>
+    <corners android:radius="10dp"/>
+</shape>
diff --git a/packages/SystemUI/res/drawable/dream_overlay_assistant_attention_indicator.xml b/packages/SystemUI/res/drawable/dream_overlay_assistant_attention_indicator.xml
new file mode 100644
index 0000000..dad2cdf8e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/dream_overlay_assistant_attention_indicator.xml
@@ -0,0 +1,32 @@
+<!--
+  ~ 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.
+  -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="56dp"
+    android:height="24dp"
+    android:viewportWidth="56"
+    android:viewportHeight="24">
+    <group>
+        <clip-path
+            android:pathData="M12 0H44C50.6274 0 56 5.37258 56 12C56 18.6274 50.6274 24 44 24H12C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0Z"
+            />
+        <path
+            android:pathData="M0 0V24H56V0"
+            android:fillColor="#FFFFFF"
+            />
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_arrow_top_left_and_bottom_right.xml b/packages/SystemUI/res/drawable/ic_arrow_top_left_and_bottom_right.xml
new file mode 100644
index 0000000..9cac38b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_arrow_top_left_and_bottom_right.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="12dp"
+        android:height="12dp"
+        android:viewportWidth="12"
+        android:viewportHeight="12">
+    <path
+        android:pathData="M4.304,5.717L8.731,10.141L6.903,11.969L11.959,11.953L11.973,6.899L10.131,8.74L5.703,4.318L3.229,1.843L5.073,0L0,0L0,5.071L1.83,3.243L4.304,5.717Z"
+        android:fillColor="#000000"
+        android:fillType="evenOdd"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_arrow_top_right_and_bottom_left.xml b/packages/SystemUI/res/drawable/ic_arrow_top_right_and_bottom_left.xml
new file mode 100644
index 0000000..0a87441
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_arrow_top_right_and_bottom_left.xml
@@ -0,0 +1,32 @@
+<!--
+  ~ 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="12dp"
+        android:height="12dp"
+        android:viewportWidth="12"
+        android:viewportHeight="12">
+    <group
+        android:pivotX="6"
+        android:pivotY="6"
+        android:rotation="90">
+        <path
+            android:pathData="M4.304,5.717L8.731,10.141L6.903,11.969L11.959,11.953L11.973,6.899L10.131,8.74L5.703,4.318L3.229,1.843L5.073,0L0,0L0,5.071L1.83,3.243L4.304,5.717Z"
+            android:fillColor="#000000"
+            android:fillType="evenOdd"/>
+    </group>
+</vector>
+
+
diff --git a/packages/SystemUI/res/drawable/ic_content_paste.xml b/packages/SystemUI/res/drawable/ic_content_paste.xml
new file mode 100644
index 0000000..8c8b81e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_content_paste.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="48"
+        android:viewportHeight="48"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M9,42Q7.7,42 6.85,41.15Q6,40.3 6,39V9Q6,7.7 6.85,6.85Q7.7,6 9,6H19.1Q19.45,4.25 20.825,3.125Q22.2,2 24,2Q25.8,2 27.175,3.125Q28.55,4.25 28.9,6H39Q40.3,6 41.15,6.85Q42,7.7 42,9V39Q42,40.3 41.15,41.15Q40.3,42 39,42ZM9,39H39Q39,39 39,39Q39,39 39,39V9Q39,9 39,9Q39,9 39,9H36V13.5H12V9H9Q9,9 9,9Q9,9 9,9V39Q9,39 9,39Q9,39 9,39ZM24,9Q24.85,9 25.425,8.425Q26,7.85 26,7Q26,6.15 25.425,5.575Q24.85,5 24,5Q23.15,5 22.575,5.575Q22,6.15 22,7Q22,7.85 22.575,8.425Q23.15,9 24,9Z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_move_magnification.xml b/packages/SystemUI/res/drawable/ic_move_magnification.xml
index dfedd28..641bb43 100644
--- a/packages/SystemUI/res/drawable/ic_move_magnification.xml
+++ b/packages/SystemUI/res/drawable/ic_move_magnification.xml
@@ -20,6 +20,6 @@
     android:viewportHeight="24"
     android:tint="?attr/colorControlNormal">
   <path
-      android:fillColor="@android:color/white"
+      android:fillColor="@color/magnification_drag_handle_tint"
       android:pathData="M12,15Q10.75,15 9.875,14.125Q9,13.25 9,12Q9,10.75 9.875,9.875Q10.75,9 12,9Q13.25,9 14.125,9.875Q15,10.75 15,12Q15,13.25 14.125,14.125Q13.25,15 12,15ZM12,22 L7.75,17.75 9.15,16.35 12,19.15 14.85,16.35 16.25,17.75ZM6.25,16.25 L2,12 6.25,7.75 7.65,9.15 4.85,12 7.65,14.85ZM9.15,7.65 L7.75,6.25 12,2 16.25,6.25 14.85,7.65 12,4.85ZM17.75,16.25 L16.35,14.85 19.15,12 16.35,9.15 17.75,7.75 22,12Z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_open_in_full.xml b/packages/SystemUI/res/drawable/ic_open_in_full.xml
new file mode 100644
index 0000000..c7f3236
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_open_in_full.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48"
+    android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M6,42V27H9V36.9L36.9,9H27V6H42V21H39V11.1L11.1,39H21V42Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
deleted file mode 100644
index c7434f5..0000000
--- a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="36dp"
-    android:height="36dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <group>
-        <clip-path
-            android:pathData="M0,0h24v24h-24z"/>
-        <path
-            android:pathData="M11,6.05V8.05H14.59L8,14.64V11.05H6V18.05H13V16.05H9.41L16,9.46V13.05H18V6.05H11Z"
-            android:fillColor="#000000"/>
-        <path
-            android:pathData="M20,4.05V20.05H4V4.05H20ZM22,2.05H2V22.05H22V2.05Z"
-            android:fillColor="#000000"/>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/media_output_status_edit_session.xml b/packages/SystemUI/res/drawable/media_output_status_edit_session.xml
new file mode 100644
index 0000000..0bd45ed
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_status_edit_session.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M1,20V17.2Q1,16.35 1.438,15.637Q1.875,14.925 2.6,14.55Q4.15,13.775 5.75,13.387Q7.35,13 9,13Q10.65,13 12.25,13.387Q13.85,13.775 15.4,14.55Q16.125,14.925 16.562,15.637Q17,16.35 17,17.2V20ZM19,20V17Q19,15.9 18.388,14.887Q17.775,13.875 16.65,13.15Q17.925,13.3 19.05,13.662Q20.175,14.025 21.15,14.55Q22.05,15.05 22.525,15.662Q23,16.275 23,17V20ZM9,12Q7.35,12 6.175,10.825Q5,9.65 5,8Q5,6.35 6.175,5.175Q7.35,4 9,4Q10.65,4 11.825,5.175Q13,6.35 13,8Q13,9.65 11.825,10.825Q10.65,12 9,12ZM19,8Q19,9.65 17.825,10.825Q16.65,12 15,12Q14.725,12 14.3,11.938Q13.875,11.875 13.6,11.8Q14.275,11 14.637,10.025Q15,9.05 15,8Q15,6.95 14.637,5.975Q14.275,5 13.6,4.2Q13.95,4.075 14.3,4.037Q14.65,4 15,4Q16.65,4 17.825,5.175Q19,6.35 19,8Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/media_output_status_help.xml b/packages/SystemUI/res/drawable/media_output_status_help.xml
new file mode 100644
index 0000000..f93c07ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_status_help.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@color/media_dialog_item_main_content"
+        android:pathData="M11.95,18Q12.475,18 12.838,17.637Q13.2,17.275 13.2,16.75Q13.2,16.225 12.838,15.863Q12.475,15.5 11.95,15.5Q11.425,15.5 11.062,15.863Q10.7,16.225 10.7,16.75Q10.7,17.275 11.062,17.637Q11.425,18 11.95,18ZM11.05,14.15H12.9Q12.9,13.325 13.088,12.85Q13.275,12.375 14.15,11.55Q14.8,10.9 15.175,10.312Q15.55,9.725 15.55,8.9Q15.55,7.5 14.525,6.75Q13.5,6 12.1,6Q10.675,6 9.788,6.75Q8.9,7.5 8.55,8.55L10.2,9.2Q10.325,8.75 10.763,8.225Q11.2,7.7 12.1,7.7Q12.9,7.7 13.3,8.137Q13.7,8.575 13.7,9.1Q13.7,9.6 13.4,10.037Q13.1,10.475 12.65,10.85Q11.55,11.825 11.3,12.325Q11.05,12.825 11.05,14.15ZM12,22Q9.925,22 8.1,21.212Q6.275,20.425 4.925,19.075Q3.575,17.725 2.788,15.9Q2,14.075 2,12Q2,9.925 2.788,8.1Q3.575,6.275 4.925,4.925Q6.275,3.575 8.1,2.787Q9.925,2 12,2Q14.075,2 15.9,2.787Q17.725,3.575 19.075,4.925Q20.425,6.275 21.212,8.1Q22,9.925 22,12Q22,14.075 21.212,15.9Q20.425,17.725 19.075,19.075Q17.725,20.425 15.9,21.212Q14.075,22 12,22Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/media_output_status_session.xml b/packages/SystemUI/res/drawable/media_output_status_session.xml
new file mode 100644
index 0000000..1deba1e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_status_session.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M4,20V12H8V20ZM10,20V4H14V20ZM16,20V9H20V20Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/pin_dot_avd.xml b/packages/SystemUI/res/drawable/pin_dot_avd.xml
new file mode 100644
index 0000000..e0cd1fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_avd.xml
@@ -0,0 +1,56 @@
+<!--
+  ~ 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.
+  -->
+
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt">
+    <target android:name="time_group">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator
+                    android:duration="500"
+                    android:propertyName="translateX"
+                    android:startOffset="0"
+                    android:valueFrom="0"
+                    android:valueTo="1"
+                    android:valueType="floatType" />
+            </set>
+        </aapt:attr>
+    </target>
+    <aapt:attr name="android:drawable">
+        <vector
+            android:width="60dp"
+            android:height="61dp"
+            android:viewportHeight="60"
+            android:viewportWidth="60">
+            <group android:name="_R_G">
+                <group
+                    android:name="_R_G_L_0_G"
+                    android:translateX="43.237"
+                    android:translateY="38.112">
+                    <path
+                        android:name="_R_G_L_0_G_D_0_P_0"
+                        android:pathData=" M-13.24 -12.11 C-11.03,-12.11 -9.24,-10.32 -9.24,-8.11 C-9.24,-5.9 -11.03,-4.11 -13.24,-4.11 C-15.44,-4.11 -17.24,-5.9 -17.24,-8.11 C-17.24,-10.32 -15.44,-12.11 -13.24,-12.11c "
+                        android:strokeAlpha="1"
+                        android:strokeColor="#ffffff"
+                        android:strokeLineCap="round"
+                        android:strokeLineJoin="round"
+                        android:strokeWidth="2" />
+                </group>
+            </group>
+            <group android:name="time_group" />
+        </vector>
+    </aapt:attr>
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml b/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml
new file mode 100644
index 0000000..33f995c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml
@@ -0,0 +1 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="43.54" android:translateY="38.54"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c "/><path android:name="_R_G_L_0_G_D_1_P_0" android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="0" android:strokeAlpha="1" android:pathData=" M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="150" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="200" android:startOffset="150" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="150" android:startOffset="0" android:valueFrom="M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c " android:valueTo="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="200" android:startOffset="150" android:valueFrom="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueTo="M-13.54 -12.54 C-11.33,-12.54 -9.54,-10.75 -9.54,-8.54 C-9.54,-6.33 -11.33,-4.54 -13.54,-4.54 C-15.75,-4.54 -17.54,-6.33 -17.54,-8.54 C-17.54,-10.75 -15.75,-12.54 -13.54,-12.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeWidth" android:duration="150" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="strokeWidth" android:duration="50" android:startOffset="150" android:valueFrom="0" android:valueTo="2" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="150" android:startOffset="0" android:valueFrom="M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c " android:valueTo="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="200" android:startOffset="150" android:valueFrom="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueTo="M-13.54 -12.54 C-11.33,-12.54 -9.54,-10.75 -9.54,-8.54 C-9.54,-6.33 -11.33,-4.54 -13.54,-4.54 C-15.75,-4.54 -17.54,-6.33 -17.54,-8.54 C-17.54,-10.75 -15.75,-12.54 -13.54,-12.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml
new file mode 100644
index 0000000..da936a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml
@@ -0,0 +1 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.52 203.54 C217.52,203.54 217.83,203.53 217.83,203.53 C217.83,203.53 218.14,203.52 218.14,203.52 C218.14,203.52 218.44,203.49 218.44,203.49 C218.44,203.49 218.75,203.45 218.75,203.45 C218.75,203.45 219.05,203.41 219.05,203.41 C219.05,203.41 219.36,203.35 219.36,203.35 C219.36,203.35 219.66,203.28 219.66,203.28 C219.66,203.28 219.96,203.21 219.96,203.21 C219.96,203.21 220.25,203.11 220.25,203.11 C220.25,203.11 220.54,203.02 220.54,203.02 C220.54,203.02 220.83,202.9 220.83,202.9 C220.83,202.9 221.11,202.79 221.11,202.79 C221.11,202.79 221.4,202.66 221.4,202.66 C221.4,202.66 221.68,202.54 221.68,202.54 C221.68,202.54 221.96,202.42 221.96,202.42 C221.96,202.42 222.25,202.3 222.25,202.3 C222.25,202.3 222.53,202.19 222.53,202.19 C222.53,202.19 222.82,202.08 222.82,202.08 C222.82,202.08 223.11,201.97 223.11,201.97 C223.11,201.97 223.41,201.89 223.41,201.89 C223.41,201.89 223.71,201.81 223.71,201.81 C223.71,201.81 224,201.73 224,201.73 C224,201.73 224.31,201.68 224.31,201.68 C224.31,201.68 224.61,201.63 224.61,201.63 C224.61,201.63 224.92,201.59 224.92,201.59 C224.92,201.59 225.23,201.57 225.23,201.57 C225.23,201.57 225.53,201.55 225.53,201.55 C225.53,201.55 225.84,201.55 225.84,201.55 C225.84,201.55 226.15,201.56 226.15,201.56 C226.15,201.56 226.46,201.57 226.46,201.57 C226.46,201.57 226.76,201.6 226.76,201.6 C226.76,201.6 227.07,201.65 227.07,201.65 C227.07,201.65 227.37,201.69 227.37,201.69 C227.37,201.69 227.67,201.76 227.67,201.76 C227.67,201.76 227.97,201.84 227.97,201.84 C227.97,201.84 228.27,201.92 228.27,201.92 C228.27,201.92 228.56,202.02 228.56,202.02 C228.56,202.02 228.85,202.12 228.85,202.12 C228.85,202.12 229.14,202.24 229.14,202.24 C229.14,202.24 229.42,202.37 229.42,202.37 C229.42,202.37 229.7,202.5 229.7,202.5 C229.7,202.5 229.97,202.65 229.97,202.65 C229.97,202.65 230.23,202.8 230.23,202.8 C230.23,202.8 230.5,202.96 230.5,202.96 C230.5,202.96 230.75,203.14 230.75,203.14 C230.75,203.14 231,203.32 231,203.32 C231,203.32 231.24,203.51 231.24,203.51 C231.24,203.51 231.48,203.71 231.48,203.71 C231.48,203.71 231.71,203.91 231.71,203.91 C231.71,203.91 231.93,204.13 231.93,204.13 C231.93,204.13 232.15,204.35 232.15,204.35 C232.15,204.35 232.35,204.58 232.35,204.58 C232.35,204.58 232.55,204.81 232.55,204.81 C232.55,204.81 232.75,205.05 232.75,205.05 C232.75,205.05 232.92,205.3 232.92,205.3 C232.92,205.3 233.1,205.56 233.1,205.56 C233.1,205.56 233.27,205.81 233.27,205.81 C233.27,205.81 233.42,206.08 233.42,206.08 C233.42,206.08 233.57,206.35 233.57,206.35 C233.57,206.35 233.7,206.63 233.7,206.63 C233.7,206.63 233.83,206.91 233.83,206.91 C233.83,206.91 233.95,207.19 233.95,207.19 C233.95,207.19 234.05,207.48 234.05,207.48 C234.05,207.48 234.16,207.77 234.16,207.77 C234.16,207.77 234.24,208.07 234.24,208.07 C234.24,208.07 234.31,208.37 234.31,208.37 C234.31,208.37 234.39,208.67 234.39,208.67 C234.39,208.67 234.43,208.97 234.43,208.97 C234.43,208.97 234.48,209.28 234.48,209.28 C234.48,209.28 234.52,209.58 234.52,209.58 C234.52,209.58 234.53,209.89 234.53,209.89 C234.53,209.89 234.54,210.2 234.54,210.2 C234.54,210.2 234.54,210.51 234.54,210.51 C234.54,210.51 234.52,210.82 234.52,210.82 C234.52,210.82 234.5,211.12 234.5,211.12 C234.5,211.12 234.46,211.43 234.46,211.43 C234.46,211.43 234.42,211.73 234.42,211.73 C234.42,211.73 234.37,212.04 234.37,212.04 C234.37,212.04 234.29,212.34 234.29,212.34 C234.29,212.34 234.21,212.64 234.21,212.64 C234.21,212.64 234.13,212.93 234.13,212.93 C234.13,212.93 234.03,213.22 234.03,213.22 C234.03,213.22 233.92,213.51 233.92,213.51 C233.92,213.51 233.81,213.8 233.81,213.8 C233.81,213.8 233.69,214.08 233.69,214.08 C233.69,214.08 233.57,214.37 233.57,214.37 C233.57,214.37 233.44,214.65 233.44,214.65 C233.44,214.65 233.32,214.93 233.32,214.93 C233.32,214.93 233.21,215.22 233.21,215.22 C233.21,215.22 233.1,215.51 233.1,215.51 C233.1,215.51 232.99,215.79 232.99,215.79 C232.99,215.79 232.9,216.09 232.9,216.09 C232.9,216.09 232.82,216.39 232.82,216.39 C232.82,216.39 232.74,216.69 232.74,216.69 C232.74,216.69 232.69,216.99 232.69,216.99 C232.69,216.99 232.64,217.29 232.64,217.29 C232.64,217.29 232.6,217.6 232.6,217.6 C232.6,217.6 232.58,217.91 232.58,217.91 C232.58,217.91 232.56,218.21 232.56,218.21 C232.56,218.21 232.55,218.52 232.55,218.52 C232.55,218.52 232.56,218.83 232.56,218.83 C232.56,218.83 232.57,219.14 232.57,219.14 C232.57,219.14 232.6,219.45 232.6,219.45 C232.6,219.45 232.64,219.75 232.64,219.75 C232.64,219.75 232.68,220.06 232.68,220.06 C232.68,220.06 232.74,220.36 232.74,220.36 C232.74,220.36 232.81,220.66 232.81,220.66 C232.81,220.66 232.88,220.96 232.88,220.96 C232.88,220.96 232.98,221.25 232.98,221.25 C232.98,221.25 233.07,221.54 233.07,221.54 C233.07,221.54 233.19,221.83 233.19,221.83 C233.19,221.83 233.3,222.12 233.3,222.12 C233.3,222.12 233.42,222.4 233.42,222.4 C233.42,222.4 233.55,222.68 233.55,222.68 C233.55,222.68 233.67,222.96 233.67,222.96 C233.67,222.96 233.79,223.25 233.79,223.25 C233.79,223.25 233.9,223.54 233.9,223.54 C233.9,223.54 234.01,223.82 234.01,223.82 C234.01,223.82 234.12,224.11 234.12,224.11 C234.12,224.11 234.2,224.41 234.2,224.41 C234.2,224.41 234.28,224.71 234.28,224.71 C234.28,224.71 234.36,225.01 234.36,225.01 C234.36,225.01 234.41,225.31 234.41,225.31 C234.41,225.31 234.46,225.62 234.46,225.62 C234.46,225.62 234.5,225.92 234.5,225.92 C234.5,225.92 234.52,226.23 234.52,226.23 C234.52,226.23 234.54,226.54 234.54,226.54 C234.54,226.54 234.54,226.84 234.54,226.84 C234.54,226.84 234.53,227.15 234.53,227.15 C234.53,227.15 234.52,227.46 234.52,227.46 C234.52,227.46 234.48,227.77 234.48,227.77 C234.48,227.77 234.44,228.07 234.44,228.07 C234.44,228.07 234.4,228.38 234.4,228.38 C234.4,228.38 234.33,228.68 234.33,228.68 C234.33,228.68 234.25,228.98 234.25,228.98 C234.25,228.98 234.17,229.27 234.17,229.27 C234.17,229.27 234.07,229.56 234.07,229.56 C234.07,229.56 233.97,229.86 233.97,229.86 C233.97,229.86 233.85,230.14 233.85,230.14 C233.85,230.14 233.72,230.42 233.72,230.42 C233.72,230.42 233.59,230.7 233.59,230.7 C233.59,230.7 233.44,230.97 233.44,230.97 C233.44,230.97 233.29,231.24 233.29,231.24 C233.29,231.24 233.13,231.5 233.13,231.5 C233.13,231.5 232.95,231.75 232.95,231.75 C232.95,231.75 232.77,232 232.77,232 C232.77,232 232.58,232.24 232.58,232.24 C232.58,232.24 232.38,232.48 232.38,232.48 C232.38,232.48 232.18,232.71 232.18,232.71 C232.18,232.71 231.96,232.93 231.96,232.93 C231.96,232.93 231.74,233.15 231.74,233.15 C231.74,233.15 231.51,233.35 231.51,233.35 C231.51,233.35 231.28,233.55 231.28,233.55 C231.28,233.55 231.04,233.75 231.04,233.75 C231.04,233.75 230.79,233.92 230.79,233.92 C230.79,233.92 230.53,234.1 230.53,234.1 C230.53,234.1 230.28,234.27 230.28,234.27 C230.28,234.27 230.01,234.42 230.01,234.42 C230.01,234.42 229.74,234.57 229.74,234.57 C229.74,234.57 229.46,234.71 229.46,234.71 C229.46,234.71 229.18,234.83 229.18,234.83 C229.18,234.83 228.9,234.96 228.9,234.96 C228.9,234.96 228.61,235.06 228.61,235.06 C228.61,235.06 228.32,235.16 228.32,235.16 C228.32,235.16 228.02,235.24 228.02,235.24 C228.02,235.24 227.72,235.32 227.72,235.32 C227.72,235.32 227.42,235.39 227.42,235.39 C227.42,235.39 227.12,235.44 227.12,235.44 C227.12,235.44 226.81,235.48 226.81,235.48 C226.81,235.48 226.51,235.52 226.51,235.52 C226.51,235.52 226.2,235.53 226.2,235.53 C226.2,235.53 225.89,235.54 225.89,235.54 C225.89,235.54 225.58,235.54 225.58,235.54 C225.58,235.54 225.27,235.52 225.27,235.52 C225.27,235.52 224.97,235.51 224.97,235.51 C224.97,235.51 224.66,235.47 224.66,235.47 C224.66,235.47 224.36,235.42 224.36,235.42 C224.36,235.42 224.05,235.37 224.05,235.37 C224.05,235.37 223.75,235.3 223.75,235.3 C223.75,235.3 223.45,235.22 223.45,235.22 C223.45,235.22 223.16,235.14 223.16,235.14 C223.16,235.14 222.87,235.03 222.87,235.03 C222.87,235.03 222.58,234.92 222.58,234.92 C222.58,234.92 222.29,234.81 222.29,234.81 C222.29,234.81 222.01,234.69 222.01,234.69 C222.01,234.69 221.72,234.57 221.72,234.57 C221.72,234.57 221.44,234.45 221.44,234.45 C221.44,234.45 221.16,234.32 221.16,234.32 C221.16,234.32 220.87,234.21 220.87,234.21 C220.87,234.21 220.58,234.1 220.58,234.1 C220.58,234.1 220.29,233.99 220.29,233.99 C220.29,233.99 220,233.91 220,233.91 C220,233.91 219.7,233.83 219.7,233.83 C219.7,233.83 219.4,233.75 219.4,233.75 C219.4,233.75 219.1,233.7 219.1,233.7 C219.1,233.7 218.8,233.65 218.8,233.65 C218.8,233.65 218.49,233.6 218.49,233.6 C218.49,233.6 218.18,233.58 218.18,233.58 C218.18,233.58 217.88,233.56 217.88,233.56 C217.88,233.56 217.57,233.55 217.57,233.55 C217.57,233.55 217.26,233.56 217.26,233.56 C217.26,233.56 216.95,233.57 216.95,233.57 C216.95,233.57 216.64,233.6 216.64,233.6 C216.64,233.6 216.34,233.64 216.34,233.64 C216.34,233.64 216.03,233.68 216.03,233.68 C216.03,233.68 215.73,233.74 215.73,233.74 C215.73,233.74 215.43,233.81 215.43,233.81 C215.43,233.81 215.13,233.88 215.13,233.88 C215.13,233.88 214.84,233.98 214.84,233.98 C214.84,233.98 214.55,234.08 214.55,234.08 C214.55,234.08 214.26,234.19 214.26,234.19 C214.26,234.19 213.97,234.3 213.97,234.3 C213.97,234.3 213.69,234.43 213.69,234.43 C213.69,234.43 213.41,234.55 213.41,234.55 C213.41,234.55 213.12,234.67 213.12,234.67 C213.12,234.67 212.84,234.8 212.84,234.8 C212.84,234.8 212.55,234.9 212.55,234.9 C212.55,234.9 212.26,235.01 212.26,235.01 C212.26,235.01 211.98,235.12 211.98,235.12 C211.98,235.12 211.68,235.2 211.68,235.2 C211.68,235.2 211.38,235.28 211.38,235.28 C211.38,235.28 211.08,235.36 211.08,235.36 C211.08,235.36 210.78,235.41 210.78,235.41 C210.78,235.41 210.47,235.46 210.47,235.46 C210.47,235.46 210.17,235.5 210.17,235.5 C210.17,235.5 209.86,235.52 209.86,235.52 C209.86,235.52 209.55,235.54 209.55,235.54 C209.55,235.54 209.25,235.55 209.25,235.55 C209.25,235.55 208.94,235.53 208.94,235.53 C208.94,235.53 208.63,235.52 208.63,235.52 C208.63,235.52 208.32,235.49 208.32,235.49 C208.32,235.49 208.02,235.44 208.02,235.44 C208.02,235.44 207.71,235.4 207.71,235.4 C207.71,235.4 207.41,235.33 207.41,235.33 C207.41,235.33 207.11,235.26 207.11,235.26 C207.11,235.26 206.82,235.17 206.82,235.17 C206.82,235.17 206.53,235.07 206.53,235.07 C206.53,235.07 206.23,234.97 206.23,234.97 C206.23,234.97 205.95,234.85 205.95,234.85 C205.95,234.85 205.67,234.73 205.67,234.73 C205.67,234.73 205.39,234.6 205.39,234.6 C205.39,234.6 205.12,234.44 205.12,234.44 C205.12,234.44 204.85,234.29 204.85,234.29 C204.85,234.29 204.59,234.13 204.59,234.13 C204.59,234.13 204.34,233.95 204.34,233.95 C204.34,233.95 204.09,233.78 204.09,233.78 C204.09,233.78 203.85,233.58 203.85,233.58 C203.85,233.58 203.61,233.39 203.61,233.39 C203.61,233.39 203.38,233.18 203.38,233.18 C203.38,233.18 203.16,232.96 203.16,232.96 C203.16,232.96 202.94,232.75 202.94,232.75 C202.94,232.75 202.74,232.52 202.74,232.52 C202.74,232.52 202.54,232.28 202.54,232.28 C202.54,232.28 202.34,232.04 202.34,232.04 C202.34,232.04 202.16,231.79 202.16,231.79 C202.16,231.79 201.99,231.54 201.99,231.54 C201.99,231.54 201.82,231.28 201.82,231.28 C201.82,231.28 201.67,231.01 201.67,231.01 C201.67,231.01 201.52,230.74 201.52,230.74 C201.52,230.74 201.38,230.46 201.38,230.46 C201.38,230.46 201.26,230.19 201.26,230.19 C201.26,230.19 201.13,229.9 201.13,229.9 C201.13,229.9 201.03,229.61 201.03,229.61 C201.03,229.61 200.93,229.32 200.93,229.32 C200.93,229.32 200.84,229.02 200.84,229.02 C200.84,229.02 200.77,228.72 200.77,228.72 C200.77,228.72 200.7,228.43 200.7,228.43 C200.7,228.43 200.65,228.12 200.65,228.12 C200.65,228.12 200.61,227.82 200.61,227.82 C200.61,227.82 200.57,227.51 200.57,227.51 C200.57,227.51 200.56,227.2 200.56,227.2 C200.56,227.2 200.54,226.89 200.54,226.89 C200.54,226.89 200.55,226.58 200.55,226.58 C200.55,226.58 200.56,226.28 200.56,226.28 C200.56,226.28 200.58,225.97 200.58,225.97 C200.58,225.97 200.62,225.66 200.62,225.66 C200.62,225.66 200.67,225.36 200.67,225.36 C200.67,225.36 200.72,225.06 200.72,225.06 C200.72,225.06 200.79,224.76 200.79,224.76 C200.79,224.76 200.87,224.46 200.87,224.46 C200.87,224.46 200.95,224.16 200.95,224.16 C200.95,224.16 201.06,223.87 201.06,223.87 C201.06,223.87 201.17,223.58 201.17,223.58 C201.17,223.58 201.27,223.29 201.27,223.29 C201.27,223.29 201.4,223.01 201.4,223.01 C201.4,223.01 201.52,222.73 201.52,222.73 C201.52,222.73 201.64,222.45 201.64,222.45 C201.64,222.45 201.76,222.16 201.76,222.16 C201.76,222.16 201.88,221.88 201.88,221.88 C201.88,221.88 201.99,221.59 201.99,221.59 C201.99,221.59 202.1,221.3 202.1,221.3 C202.1,221.3 202.18,221 202.18,221 C202.18,221 202.26,220.71 202.26,220.71 C202.26,220.71 202.34,220.41 202.34,220.41 C202.34,220.41 202.39,220.1 202.39,220.1 C202.39,220.1 202.44,219.8 202.44,219.8 C202.44,219.8 202.49,219.5 202.49,219.5 C202.49,219.5 202.51,219.19 202.51,219.19 C202.51,219.19 202.53,218.88 202.53,218.88 C202.53,218.88 202.54,218.57 202.54,218.57 C202.54,218.57 202.53,218.26 202.53,218.26 C202.53,218.26 202.52,217.96 202.52,217.96 C202.52,217.96 202.49,217.65 202.49,217.65 C202.49,217.65 202.45,217.34 202.45,217.34 C202.45,217.34 202.41,217.04 202.41,217.04 C202.41,217.04 202.34,216.74 202.34,216.74 C202.34,216.74 202.27,216.44 202.27,216.44 C202.27,216.44 202.2,216.14 202.2,216.14 C202.2,216.14 202.11,215.84 202.11,215.84 C202.11,215.84 202.01,215.55 202.01,215.55 C202.01,215.55 201.9,215.26 201.9,215.26 C201.9,215.26 201.78,214.98 201.78,214.98 C201.78,214.98 201.66,214.69 201.66,214.69 C201.66,214.69 201.54,214.41 201.54,214.41 C201.54,214.41 201.42,214.13 201.42,214.13 C201.42,214.13 201.29,213.84 201.29,213.84 C201.29,213.84 201.18,213.55 201.18,213.55 C201.18,213.55 201.07,213.26 201.07,213.26 C201.07,213.26 200.96,212.98 200.96,212.98 C200.96,212.98 200.88,212.68 200.88,212.68 C200.88,212.68 200.8,212.38 200.8,212.38 C200.8,212.38 200.73,212.08 200.73,212.08 C200.73,212.08 200.68,211.78 200.68,211.78 C200.68,211.78 200.63,211.47 200.63,211.47 C200.63,211.47 200.58,211.17 200.58,211.17 C200.58,211.17 200.57,210.86 200.57,210.86 C200.57,210.86 200.55,210.55 200.55,210.55 C200.55,210.55 200.54,210.25 200.54,210.25 C200.54,210.25 200.56,209.94 200.56,209.94 C200.56,209.94 200.57,209.63 200.57,209.63 C200.57,209.63 200.6,209.32 200.6,209.32 C200.6,209.32 200.65,209.02 200.65,209.02 C200.65,209.02 200.69,208.71 200.69,208.71 C200.69,208.71 200.76,208.41 200.76,208.41 C200.76,208.41 200.83,208.11 200.83,208.11 C200.83,208.11 200.92,207.82 200.92,207.82 C200.92,207.82 201.02,207.52 201.02,207.52 C201.02,207.52 201.12,207.23 201.12,207.23 C201.12,207.23 201.24,206.95 201.24,206.95 C201.24,206.95 201.36,206.67 201.36,206.67 C201.36,206.67 201.49,206.39 201.49,206.39 C201.49,206.39 201.65,206.12 201.65,206.12 C201.65,206.12 201.8,205.85 201.8,205.85 C201.8,205.85 201.96,205.59 201.96,205.59 C201.96,205.59 202.14,205.34 202.14,205.34 C202.14,205.34 202.31,205.09 202.31,205.09 C202.31,205.09 202.51,204.85 202.51,204.85 C202.51,204.85 202.71,204.61 202.71,204.61 C202.71,204.61 202.91,204.38 202.91,204.38 C202.91,204.38 203.13,204.16 203.13,204.16 C203.13,204.16 203.34,203.94 203.34,203.94 C203.34,203.94 203.57,203.74 203.57,203.74 C203.57,203.74 203.81,203.54 203.81,203.54 C203.81,203.54 204.05,203.34 204.05,203.34 C204.05,203.34 204.3,203.17 204.3,203.17 C204.3,203.17 204.55,202.99 204.55,202.99 C204.55,202.99 204.81,202.82 204.81,202.82 C204.81,202.82 205.08,202.67 205.08,202.67 C205.08,202.67 205.35,202.52 205.35,202.52 C205.35,202.52 205.63,202.38 205.63,202.38 C205.63,202.38 205.91,202.26 205.91,202.26 C205.91,202.26 206.19,202.13 206.19,202.13 C206.19,202.13 206.48,202.03 206.48,202.03 C206.48,202.03 206.77,201.93 206.77,201.93 C206.77,201.93 207.07,201.85 207.07,201.85 C207.07,201.85 207.37,201.77 207.37,201.77 C207.37,201.77 207.67,201.7 207.67,201.7 C207.67,201.7 207.97,201.65 207.97,201.65 C207.97,201.65 208.28,201.61 208.28,201.61 C208.28,201.61 208.58,201.57 208.58,201.57 C208.58,201.57 208.89,201.56 208.89,201.56 C208.89,201.56 209.2,201.55 209.2,201.55 C209.2,201.55 209.51,201.55 209.51,201.55 C209.51,201.55 209.81,201.57 209.81,201.57 C209.81,201.57 210.12,201.58 210.12,201.58 C210.12,201.58 210.43,201.62 210.43,201.62 C210.43,201.62 210.73,201.67 210.73,201.67 C210.73,201.67 211.04,201.72 211.04,201.72 C211.04,201.72 211.34,201.8 211.34,201.8 C211.34,201.8 211.63,201.88 211.63,201.88 C211.63,201.88 211.93,201.96 211.93,201.96 C211.93,201.96 212.22,202.06 212.22,202.06 C212.22,202.06 212.51,202.17 212.51,202.17 C212.51,202.17 212.8,202.28 212.8,202.28 C212.8,202.28 213.08,202.4 213.08,202.4 C213.08,202.4 213.36,202.52 213.36,202.52 C213.36,202.52 213.65,202.65 213.65,202.65 C213.65,202.65 213.93,202.77 213.93,202.77 C213.93,202.77 214.22,202.88 214.22,202.88 C214.22,202.88 214.5,202.99 214.5,202.99 C214.5,202.99 214.79,203.1 214.79,203.1 C214.79,203.1 215.09,203.19 215.09,203.19 C215.09,203.19 215.39,203.27 215.39,203.27 C215.39,203.27 215.68,203.35 215.68,203.35 C215.68,203.35 215.99,203.4 215.99,203.4 C215.99,203.4 216.29,203.45 216.29,203.45 C216.29,203.45 216.6,203.49 216.6,203.49 C216.6,203.49 216.9,203.51 216.9,203.51 C216.9,203.51 217.21,203.53 217.21,203.53 C217.21,203.53 217.52,203.54 217.52,203.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.52 203.54 C217.52,203.54 217.83,203.53 217.83,203.53 C217.83,203.53 218.14,203.52 218.14,203.52 C218.14,203.52 218.44,203.49 218.44,203.49 C218.44,203.49 218.75,203.45 218.75,203.45 C218.75,203.45 219.05,203.41 219.05,203.41 C219.05,203.41 219.36,203.35 219.36,203.35 C219.36,203.35 219.66,203.28 219.66,203.28 C219.66,203.28 219.96,203.21 219.96,203.21 C219.96,203.21 220.25,203.11 220.25,203.11 C220.25,203.11 220.54,203.02 220.54,203.02 C220.54,203.02 220.83,202.9 220.83,202.9 C220.83,202.9 221.11,202.79 221.11,202.79 C221.11,202.79 221.4,202.66 221.4,202.66 C221.4,202.66 221.68,202.54 221.68,202.54 C221.68,202.54 221.96,202.42 221.96,202.42 C221.96,202.42 222.25,202.3 222.25,202.3 C222.25,202.3 222.53,202.19 222.53,202.19 C222.53,202.19 222.82,202.08 222.82,202.08 C222.82,202.08 223.11,201.97 223.11,201.97 C223.11,201.97 223.41,201.89 223.41,201.89 C223.41,201.89 223.71,201.81 223.71,201.81 C223.71,201.81 224,201.73 224,201.73 C224,201.73 224.31,201.68 224.31,201.68 C224.31,201.68 224.61,201.63 224.61,201.63 C224.61,201.63 224.92,201.59 224.92,201.59 C224.92,201.59 225.23,201.57 225.23,201.57 C225.23,201.57 225.53,201.55 225.53,201.55 C225.53,201.55 225.84,201.55 225.84,201.55 C225.84,201.55 226.15,201.56 226.15,201.56 C226.15,201.56 226.46,201.57 226.46,201.57 C226.46,201.57 226.76,201.6 226.76,201.6 C226.76,201.6 227.07,201.65 227.07,201.65 C227.07,201.65 227.37,201.69 227.37,201.69 C227.37,201.69 227.67,201.76 227.67,201.76 C227.67,201.76 227.97,201.84 227.97,201.84 C227.97,201.84 228.27,201.92 228.27,201.92 C228.27,201.92 228.56,202.02 228.56,202.02 C228.56,202.02 228.85,202.12 228.85,202.12 C228.85,202.12 229.14,202.24 229.14,202.24 C229.14,202.24 229.42,202.37 229.42,202.37 C229.42,202.37 229.7,202.5 229.7,202.5 C229.7,202.5 229.97,202.65 229.97,202.65 C229.97,202.65 230.23,202.8 230.23,202.8 C230.23,202.8 230.5,202.96 230.5,202.96 C230.5,202.96 230.75,203.14 230.75,203.14 C230.75,203.14 231,203.32 231,203.32 C231,203.32 231.24,203.51 231.24,203.51 C231.24,203.51 231.48,203.71 231.48,203.71 C231.48,203.71 231.71,203.91 231.71,203.91 C231.71,203.91 231.93,204.13 231.93,204.13 C231.93,204.13 232.15,204.35 232.15,204.35 C232.15,204.35 232.35,204.58 232.35,204.58 C232.35,204.58 232.55,204.81 232.55,204.81 C232.55,204.81 232.75,205.05 232.75,205.05 C232.75,205.05 232.92,205.3 232.92,205.3 C232.92,205.3 233.1,205.56 233.1,205.56 C233.1,205.56 233.27,205.81 233.27,205.81 C233.27,205.81 233.42,206.08 233.42,206.08 C233.42,206.08 233.57,206.35 233.57,206.35 C233.57,206.35 233.7,206.63 233.7,206.63 C233.7,206.63 233.83,206.91 233.83,206.91 C233.83,206.91 233.95,207.19 233.95,207.19 C233.95,207.19 234.05,207.48 234.05,207.48 C234.05,207.48 234.16,207.77 234.16,207.77 C234.16,207.77 234.24,208.07 234.24,208.07 C234.24,208.07 234.31,208.37 234.31,208.37 C234.31,208.37 234.39,208.67 234.39,208.67 C234.39,208.67 234.43,208.97 234.43,208.97 C234.43,208.97 234.48,209.28 234.48,209.28 C234.48,209.28 234.52,209.58 234.52,209.58 C234.52,209.58 234.53,209.89 234.53,209.89 C234.53,209.89 234.54,210.2 234.54,210.2 C234.54,210.2 234.54,210.51 234.54,210.51 C234.54,210.51 234.52,210.82 234.52,210.82 C234.52,210.82 234.5,211.12 234.5,211.12 C234.5,211.12 234.46,211.43 234.46,211.43 C234.46,211.43 234.42,211.73 234.42,211.73 C234.42,211.73 234.37,212.04 234.37,212.04 C234.37,212.04 234.29,212.34 234.29,212.34 C234.29,212.34 234.21,212.64 234.21,212.64 C234.21,212.64 234.13,212.93 234.13,212.93 C234.13,212.93 234.03,213.22 234.03,213.22 C234.03,213.22 233.92,213.51 233.92,213.51 C233.92,213.51 233.81,213.8 233.81,213.8 C233.81,213.8 233.69,214.08 233.69,214.08 C233.69,214.08 233.57,214.37 233.57,214.37 C233.57,214.37 233.44,214.65 233.44,214.65 C233.44,214.65 233.32,214.93 233.32,214.93 C233.32,214.93 233.21,215.22 233.21,215.22 C233.21,215.22 233.1,215.51 233.1,215.51 C233.1,215.51 232.99,215.79 232.99,215.79 C232.99,215.79 232.9,216.09 232.9,216.09 C232.9,216.09 232.82,216.39 232.82,216.39 C232.82,216.39 232.74,216.69 232.74,216.69 C232.74,216.69 232.69,216.99 232.69,216.99 C232.69,216.99 232.64,217.29 232.64,217.29 C232.64,217.29 232.6,217.6 232.6,217.6 C232.6,217.6 232.58,217.91 232.58,217.91 C232.58,217.91 232.56,218.21 232.56,218.21 C232.56,218.21 232.55,218.52 232.55,218.52 C232.55,218.52 232.56,218.83 232.56,218.83 C232.56,218.83 232.57,219.14 232.57,219.14 C232.57,219.14 232.6,219.45 232.6,219.45 C232.6,219.45 232.64,219.75 232.64,219.75 C232.64,219.75 232.68,220.06 232.68,220.06 C232.68,220.06 232.74,220.36 232.74,220.36 C232.74,220.36 232.81,220.66 232.81,220.66 C232.81,220.66 232.88,220.96 232.88,220.96 C232.88,220.96 232.98,221.25 232.98,221.25 C232.98,221.25 233.07,221.54 233.07,221.54 C233.07,221.54 233.19,221.83 233.19,221.83 C233.19,221.83 233.3,222.12 233.3,222.12 C233.3,222.12 233.42,222.4 233.42,222.4 C233.42,222.4 233.55,222.68 233.55,222.68 C233.55,222.68 233.67,222.96 233.67,222.96 C233.67,222.96 233.79,223.25 233.79,223.25 C233.79,223.25 233.9,223.54 233.9,223.54 C233.9,223.54 234.01,223.82 234.01,223.82 C234.01,223.82 234.12,224.11 234.12,224.11 C234.12,224.11 234.2,224.41 234.2,224.41 C234.2,224.41 234.28,224.71 234.28,224.71 C234.28,224.71 234.36,225.01 234.36,225.01 C234.36,225.01 234.41,225.31 234.41,225.31 C234.41,225.31 234.46,225.62 234.46,225.62 C234.46,225.62 234.5,225.92 234.5,225.92 C234.5,225.92 234.52,226.23 234.52,226.23 C234.52,226.23 234.54,226.54 234.54,226.54 C234.54,226.54 234.54,226.84 234.54,226.84 C234.54,226.84 234.53,227.15 234.53,227.15 C234.53,227.15 234.52,227.46 234.52,227.46 C234.52,227.46 234.48,227.77 234.48,227.77 C234.48,227.77 234.44,228.07 234.44,228.07 C234.44,228.07 234.4,228.38 234.4,228.38 C234.4,228.38 234.33,228.68 234.33,228.68 C234.33,228.68 234.25,228.98 234.25,228.98 C234.25,228.98 234.17,229.27 234.17,229.27 C234.17,229.27 234.07,229.56 234.07,229.56 C234.07,229.56 233.97,229.86 233.97,229.86 C233.97,229.86 233.85,230.14 233.85,230.14 C233.85,230.14 233.72,230.42 233.72,230.42 C233.72,230.42 233.59,230.7 233.59,230.7 C233.59,230.7 233.44,230.97 233.44,230.97 C233.44,230.97 233.29,231.24 233.29,231.24 C233.29,231.24 233.13,231.5 233.13,231.5 C233.13,231.5 232.95,231.75 232.95,231.75 C232.95,231.75 232.77,232 232.77,232 C232.77,232 232.58,232.24 232.58,232.24 C232.58,232.24 232.38,232.48 232.38,232.48 C232.38,232.48 232.18,232.71 232.18,232.71 C232.18,232.71 231.96,232.93 231.96,232.93 C231.96,232.93 231.74,233.15 231.74,233.15 C231.74,233.15 231.51,233.35 231.51,233.35 C231.51,233.35 231.28,233.55 231.28,233.55 C231.28,233.55 231.04,233.75 231.04,233.75 C231.04,233.75 230.79,233.92 230.79,233.92 C230.79,233.92 230.53,234.1 230.53,234.1 C230.53,234.1 230.28,234.27 230.28,234.27 C230.28,234.27 230.01,234.42 230.01,234.42 C230.01,234.42 229.74,234.57 229.74,234.57 C229.74,234.57 229.46,234.71 229.46,234.71 C229.46,234.71 229.18,234.83 229.18,234.83 C229.18,234.83 228.9,234.96 228.9,234.96 C228.9,234.96 228.61,235.06 228.61,235.06 C228.61,235.06 228.32,235.16 228.32,235.16 C228.32,235.16 228.02,235.24 228.02,235.24 C228.02,235.24 227.72,235.32 227.72,235.32 C227.72,235.32 227.42,235.39 227.42,235.39 C227.42,235.39 227.12,235.44 227.12,235.44 C227.12,235.44 226.81,235.48 226.81,235.48 C226.81,235.48 226.51,235.52 226.51,235.52 C226.51,235.52 226.2,235.53 226.2,235.53 C226.2,235.53 225.89,235.54 225.89,235.54 C225.89,235.54 225.58,235.54 225.58,235.54 C225.58,235.54 225.27,235.52 225.27,235.52 C225.27,235.52 224.97,235.51 224.97,235.51 C224.97,235.51 224.66,235.47 224.66,235.47 C224.66,235.47 224.36,235.42 224.36,235.42 C224.36,235.42 224.05,235.37 224.05,235.37 C224.05,235.37 223.75,235.3 223.75,235.3 C223.75,235.3 223.45,235.22 223.45,235.22 C223.45,235.22 223.16,235.14 223.16,235.14 C223.16,235.14 222.87,235.03 222.87,235.03 C222.87,235.03 222.58,234.92 222.58,234.92 C222.58,234.92 222.29,234.81 222.29,234.81 C222.29,234.81 222.01,234.69 222.01,234.69 C222.01,234.69 221.72,234.57 221.72,234.57 C221.72,234.57 221.44,234.45 221.44,234.45 C221.44,234.45 221.16,234.32 221.16,234.32 C221.16,234.32 220.87,234.21 220.87,234.21 C220.87,234.21 220.58,234.1 220.58,234.1 C220.58,234.1 220.29,233.99 220.29,233.99 C220.29,233.99 220,233.91 220,233.91 C220,233.91 219.7,233.83 219.7,233.83 C219.7,233.83 219.4,233.75 219.4,233.75 C219.4,233.75 219.1,233.7 219.1,233.7 C219.1,233.7 218.8,233.65 218.8,233.65 C218.8,233.65 218.49,233.6 218.49,233.6 C218.49,233.6 218.18,233.58 218.18,233.58 C218.18,233.58 217.88,233.56 217.88,233.56 C217.88,233.56 217.57,233.55 217.57,233.55 C217.57,233.55 217.26,233.56 217.26,233.56 C217.26,233.56 216.95,233.57 216.95,233.57 C216.95,233.57 216.64,233.6 216.64,233.6 C216.64,233.6 216.34,233.64 216.34,233.64 C216.34,233.64 216.03,233.68 216.03,233.68 C216.03,233.68 215.73,233.74 215.73,233.74 C215.73,233.74 215.43,233.81 215.43,233.81 C215.43,233.81 215.13,233.88 215.13,233.88 C215.13,233.88 214.84,233.98 214.84,233.98 C214.84,233.98 214.55,234.08 214.55,234.08 C214.55,234.08 214.26,234.19 214.26,234.19 C214.26,234.19 213.97,234.3 213.97,234.3 C213.97,234.3 213.69,234.43 213.69,234.43 C213.69,234.43 213.41,234.55 213.41,234.55 C213.41,234.55 213.12,234.67 213.12,234.67 C213.12,234.67 212.84,234.8 212.84,234.8 C212.84,234.8 212.55,234.9 212.55,234.9 C212.55,234.9 212.26,235.01 212.26,235.01 C212.26,235.01 211.98,235.12 211.98,235.12 C211.98,235.12 211.68,235.2 211.68,235.2 C211.68,235.2 211.38,235.28 211.38,235.28 C211.38,235.28 211.08,235.36 211.08,235.36 C211.08,235.36 210.78,235.41 210.78,235.41 C210.78,235.41 210.47,235.46 210.47,235.46 C210.47,235.46 210.17,235.5 210.17,235.5 C210.17,235.5 209.86,235.52 209.86,235.52 C209.86,235.52 209.55,235.54 209.55,235.54 C209.55,235.54 209.25,235.55 209.25,235.55 C209.25,235.55 208.94,235.53 208.94,235.53 C208.94,235.53 208.63,235.52 208.63,235.52 C208.63,235.52 208.32,235.49 208.32,235.49 C208.32,235.49 208.02,235.44 208.02,235.44 C208.02,235.44 207.71,235.4 207.71,235.4 C207.71,235.4 207.41,235.33 207.41,235.33 C207.41,235.33 207.11,235.26 207.11,235.26 C207.11,235.26 206.82,235.17 206.82,235.17 C206.82,235.17 206.53,235.07 206.53,235.07 C206.53,235.07 206.23,234.97 206.23,234.97 C206.23,234.97 205.95,234.85 205.95,234.85 C205.95,234.85 205.67,234.73 205.67,234.73 C205.67,234.73 205.39,234.6 205.39,234.6 C205.39,234.6 205.12,234.44 205.12,234.44 C205.12,234.44 204.85,234.29 204.85,234.29 C204.85,234.29 204.59,234.13 204.59,234.13 C204.59,234.13 204.34,233.95 204.34,233.95 C204.34,233.95 204.09,233.78 204.09,233.78 C204.09,233.78 203.85,233.58 203.85,233.58 C203.85,233.58 203.61,233.39 203.61,233.39 C203.61,233.39 203.38,233.18 203.38,233.18 C203.38,233.18 203.16,232.96 203.16,232.96 C203.16,232.96 202.94,232.75 202.94,232.75 C202.94,232.75 202.74,232.52 202.74,232.52 C202.74,232.52 202.54,232.28 202.54,232.28 C202.54,232.28 202.34,232.04 202.34,232.04 C202.34,232.04 202.16,231.79 202.16,231.79 C202.16,231.79 201.99,231.54 201.99,231.54 C201.99,231.54 201.82,231.28 201.82,231.28 C201.82,231.28 201.67,231.01 201.67,231.01 C201.67,231.01 201.52,230.74 201.52,230.74 C201.52,230.74 201.38,230.46 201.38,230.46 C201.38,230.46 201.26,230.19 201.26,230.19 C201.26,230.19 201.13,229.9 201.13,229.9 C201.13,229.9 201.03,229.61 201.03,229.61 C201.03,229.61 200.93,229.32 200.93,229.32 C200.93,229.32 200.84,229.02 200.84,229.02 C200.84,229.02 200.77,228.72 200.77,228.72 C200.77,228.72 200.7,228.43 200.7,228.43 C200.7,228.43 200.65,228.12 200.65,228.12 C200.65,228.12 200.61,227.82 200.61,227.82 C200.61,227.82 200.57,227.51 200.57,227.51 C200.57,227.51 200.56,227.2 200.56,227.2 C200.56,227.2 200.54,226.89 200.54,226.89 C200.54,226.89 200.55,226.58 200.55,226.58 C200.55,226.58 200.56,226.28 200.56,226.28 C200.56,226.28 200.58,225.97 200.58,225.97 C200.58,225.97 200.62,225.66 200.62,225.66 C200.62,225.66 200.67,225.36 200.67,225.36 C200.67,225.36 200.72,225.06 200.72,225.06 C200.72,225.06 200.79,224.76 200.79,224.76 C200.79,224.76 200.87,224.46 200.87,224.46 C200.87,224.46 200.95,224.16 200.95,224.16 C200.95,224.16 201.06,223.87 201.06,223.87 C201.06,223.87 201.17,223.58 201.17,223.58 C201.17,223.58 201.27,223.29 201.27,223.29 C201.27,223.29 201.4,223.01 201.4,223.01 C201.4,223.01 201.52,222.73 201.52,222.73 C201.52,222.73 201.64,222.45 201.64,222.45 C201.64,222.45 201.76,222.16 201.76,222.16 C201.76,222.16 201.88,221.88 201.88,221.88 C201.88,221.88 201.99,221.59 201.99,221.59 C201.99,221.59 202.1,221.3 202.1,221.3 C202.1,221.3 202.18,221 202.18,221 C202.18,221 202.26,220.71 202.26,220.71 C202.26,220.71 202.34,220.41 202.34,220.41 C202.34,220.41 202.39,220.1 202.39,220.1 C202.39,220.1 202.44,219.8 202.44,219.8 C202.44,219.8 202.49,219.5 202.49,219.5 C202.49,219.5 202.51,219.19 202.51,219.19 C202.51,219.19 202.53,218.88 202.53,218.88 C202.53,218.88 202.54,218.57 202.54,218.57 C202.54,218.57 202.53,218.26 202.53,218.26 C202.53,218.26 202.52,217.96 202.52,217.96 C202.52,217.96 202.49,217.65 202.49,217.65 C202.49,217.65 202.45,217.34 202.45,217.34 C202.45,217.34 202.41,217.04 202.41,217.04 C202.41,217.04 202.34,216.74 202.34,216.74 C202.34,216.74 202.27,216.44 202.27,216.44 C202.27,216.44 202.2,216.14 202.2,216.14 C202.2,216.14 202.11,215.84 202.11,215.84 C202.11,215.84 202.01,215.55 202.01,215.55 C202.01,215.55 201.9,215.26 201.9,215.26 C201.9,215.26 201.78,214.98 201.78,214.98 C201.78,214.98 201.66,214.69 201.66,214.69 C201.66,214.69 201.54,214.41 201.54,214.41 C201.54,214.41 201.42,214.13 201.42,214.13 C201.42,214.13 201.29,213.84 201.29,213.84 C201.29,213.84 201.18,213.55 201.18,213.55 C201.18,213.55 201.07,213.26 201.07,213.26 C201.07,213.26 200.96,212.98 200.96,212.98 C200.96,212.98 200.88,212.68 200.88,212.68 C200.88,212.68 200.8,212.38 200.8,212.38 C200.8,212.38 200.73,212.08 200.73,212.08 C200.73,212.08 200.68,211.78 200.68,211.78 C200.68,211.78 200.63,211.47 200.63,211.47 C200.63,211.47 200.58,211.17 200.58,211.17 C200.58,211.17 200.57,210.86 200.57,210.86 C200.57,210.86 200.55,210.55 200.55,210.55 C200.55,210.55 200.54,210.25 200.54,210.25 C200.54,210.25 200.56,209.94 200.56,209.94 C200.56,209.94 200.57,209.63 200.57,209.63 C200.57,209.63 200.6,209.32 200.6,209.32 C200.6,209.32 200.65,209.02 200.65,209.02 C200.65,209.02 200.69,208.71 200.69,208.71 C200.69,208.71 200.76,208.41 200.76,208.41 C200.76,208.41 200.83,208.11 200.83,208.11 C200.83,208.11 200.92,207.82 200.92,207.82 C200.92,207.82 201.02,207.52 201.02,207.52 C201.02,207.52 201.12,207.23 201.12,207.23 C201.12,207.23 201.24,206.95 201.24,206.95 C201.24,206.95 201.36,206.67 201.36,206.67 C201.36,206.67 201.49,206.39 201.49,206.39 C201.49,206.39 201.65,206.12 201.65,206.12 C201.65,206.12 201.8,205.85 201.8,205.85 C201.8,205.85 201.96,205.59 201.96,205.59 C201.96,205.59 202.14,205.34 202.14,205.34 C202.14,205.34 202.31,205.09 202.31,205.09 C202.31,205.09 202.51,204.85 202.51,204.85 C202.51,204.85 202.71,204.61 202.71,204.61 C202.71,204.61 202.91,204.38 202.91,204.38 C202.91,204.38 203.13,204.16 203.13,204.16 C203.13,204.16 203.34,203.94 203.34,203.94 C203.34,203.94 203.57,203.74 203.57,203.74 C203.57,203.74 203.81,203.54 203.81,203.54 C203.81,203.54 204.05,203.34 204.05,203.34 C204.05,203.34 204.3,203.17 204.3,203.17 C204.3,203.17 204.55,202.99 204.55,202.99 C204.55,202.99 204.81,202.82 204.81,202.82 C204.81,202.82 205.08,202.67 205.08,202.67 C205.08,202.67 205.35,202.52 205.35,202.52 C205.35,202.52 205.63,202.38 205.63,202.38 C205.63,202.38 205.91,202.26 205.91,202.26 C205.91,202.26 206.19,202.13 206.19,202.13 C206.19,202.13 206.48,202.03 206.48,202.03 C206.48,202.03 206.77,201.93 206.77,201.93 C206.77,201.93 207.07,201.85 207.07,201.85 C207.07,201.85 207.37,201.77 207.37,201.77 C207.37,201.77 207.67,201.7 207.67,201.7 C207.67,201.7 207.97,201.65 207.97,201.65 C207.97,201.65 208.28,201.61 208.28,201.61 C208.28,201.61 208.58,201.57 208.58,201.57 C208.58,201.57 208.89,201.56 208.89,201.56 C208.89,201.56 209.2,201.55 209.2,201.55 C209.2,201.55 209.51,201.55 209.51,201.55 C209.51,201.55 209.81,201.57 209.81,201.57 C209.81,201.57 210.12,201.58 210.12,201.58 C210.12,201.58 210.43,201.62 210.43,201.62 C210.43,201.62 210.73,201.67 210.73,201.67 C210.73,201.67 211.04,201.72 211.04,201.72 C211.04,201.72 211.34,201.8 211.34,201.8 C211.34,201.8 211.63,201.88 211.63,201.88 C211.63,201.88 211.93,201.96 211.93,201.96 C211.93,201.96 212.22,202.06 212.22,202.06 C212.22,202.06 212.51,202.17 212.51,202.17 C212.51,202.17 212.8,202.28 212.8,202.28 C212.8,202.28 213.08,202.4 213.08,202.4 C213.08,202.4 213.36,202.52 213.36,202.52 C213.36,202.52 213.65,202.65 213.65,202.65 C213.65,202.65 213.93,202.77 213.93,202.77 C213.93,202.77 214.22,202.88 214.22,202.88 C214.22,202.88 214.5,202.99 214.5,202.99 C214.5,202.99 214.79,203.1 214.79,203.1 C214.79,203.1 215.09,203.19 215.09,203.19 C215.09,203.19 215.39,203.27 215.39,203.27 C215.39,203.27 215.68,203.35 215.68,203.35 C215.68,203.35 215.99,203.4 215.99,203.4 C215.99,203.4 216.29,203.45 216.29,203.45 C216.29,203.45 216.6,203.49 216.6,203.49 C216.6,203.49 216.9,203.51 216.9,203.51 C216.9,203.51 217.21,203.53 217.21,203.53 C217.21,203.53 217.52,203.54 217.52,203.54c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml
new file mode 100644
index 0000000..d910990
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml
@@ -0,0 +1 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.78 201.61 C217.78,201.61 218.06,201.63 218.06,201.63 C218.06,201.63 218.33,201.65 218.33,201.65 C218.33,201.65 218.6,201.68 218.6,201.68 C218.6,201.68 218.87,201.73 218.87,201.73 C218.87,201.73 219.14,201.78 219.14,201.78 C219.14,201.78 219.41,201.84 219.41,201.84 C219.41,201.84 219.67,201.93 219.67,201.93 C219.67,201.93 219.93,202.01 219.93,202.01 C219.93,202.01 220.19,202.09 220.19,202.09 C220.19,202.09 220.44,202.21 220.44,202.21 C220.44,202.21 220.69,202.32 220.69,202.32 C220.69,202.32 220.93,202.45 220.93,202.45 C220.93,202.45 221.17,202.58 221.17,202.58 C221.17,202.58 221.4,202.73 221.4,202.73 C221.4,202.73 221.62,202.88 221.62,202.88 C221.62,202.88 221.85,203.04 221.85,203.04 C221.85,203.04 222.06,203.22 222.06,203.22 C222.06,203.22 222.27,203.39 222.27,203.39 C222.27,203.39 222.46,203.59 222.46,203.59 C222.46,203.59 222.65,203.78 222.65,203.78 C222.65,203.78 222.83,203.99 222.83,203.99 C222.83,203.99 223.01,204.2 223.01,204.2 C223.01,204.2 223.18,204.41 223.18,204.41 C223.18,204.41 223.33,204.64 223.33,204.64 C223.33,204.64 223.48,204.87 223.48,204.87 C223.48,204.87 223.62,205.11 223.62,205.11 C223.62,205.11 223.75,205.34 223.75,205.34 C223.75,205.34 223.88,205.59 223.88,205.59 C223.88,205.59 224,205.83 224,205.83 C224,205.83 224.12,206.08 224.12,206.08 C224.12,206.08 224.24,206.32 224.24,206.32 C224.24,206.32 224.37,206.57 224.37,206.57 C224.37,206.57 224.49,206.81 224.49,206.81 C224.49,206.81 224.61,207.06 224.61,207.06 C224.61,207.06 224.73,207.3 224.73,207.3 C224.73,207.3 224.86,207.55 224.86,207.55 C224.86,207.55 224.98,207.79 224.98,207.79 C224.98,207.79 225.1,208.04 225.1,208.04 C225.1,208.04 225.22,208.28 225.22,208.28 C225.22,208.28 225.35,208.53 225.35,208.53 C225.35,208.53 225.47,208.77 225.47,208.77 C225.47,208.77 225.59,209.02 225.59,209.02 C225.59,209.02 225.71,209.26 225.71,209.26 C225.71,209.26 225.84,209.51 225.84,209.51 C225.84,209.51 225.96,209.75 225.96,209.75 C225.96,209.75 226.08,210 226.08,210 C226.08,210 226.2,210.24 226.2,210.24 C226.2,210.24 226.33,210.49 226.33,210.49 C226.33,210.49 226.45,210.73 226.45,210.73 C226.45,210.73 226.57,210.98 226.57,210.98 C226.57,210.98 226.69,211.22 226.69,211.22 C226.69,211.22 226.82,211.47 226.82,211.47 C226.82,211.47 226.94,211.71 226.94,211.71 C226.94,211.71 227.06,211.96 227.06,211.96 C227.06,211.96 227.18,212.2 227.18,212.2 C227.18,212.2 227.3,212.45 227.3,212.45 C227.3,212.45 227.43,212.69 227.43,212.69 C227.43,212.69 227.55,212.94 227.55,212.94 C227.55,212.94 227.67,213.18 227.67,213.18 C227.67,213.18 227.79,213.43 227.79,213.43 C227.79,213.43 227.92,213.67 227.92,213.67 C227.92,213.67 228.04,213.92 228.04,213.92 C228.04,213.92 228.16,214.16 228.16,214.16 C228.16,214.16 228.28,214.41 228.28,214.41 C228.28,214.41 228.41,214.65 228.41,214.65 C228.41,214.65 228.53,214.9 228.53,214.9 C228.53,214.9 228.65,215.14 228.65,215.14 C228.65,215.14 228.77,215.39 228.77,215.39 C228.77,215.39 228.9,215.63 228.9,215.63 C228.9,215.63 229.02,215.88 229.02,215.88 C229.02,215.88 229.14,216.12 229.14,216.12 C229.14,216.12 229.26,216.37 229.26,216.37 C229.26,216.37 229.39,216.61 229.39,216.61 C229.39,216.61 229.51,216.86 229.51,216.86 C229.51,216.86 229.63,217.1 229.63,217.1 C229.63,217.1 229.75,217.35 229.75,217.35 C229.75,217.35 229.87,217.59 229.87,217.59 C229.87,217.59 230,217.84 230,217.84 C230,217.84 230.12,218.08 230.12,218.08 C230.12,218.08 230.24,218.33 230.24,218.33 C230.24,218.33 230.36,218.57 230.36,218.57 C230.36,218.57 230.49,218.82 230.49,218.82 C230.49,218.82 230.61,219.06 230.61,219.06 C230.61,219.06 230.73,219.31 230.73,219.31 C230.73,219.31 230.85,219.55 230.85,219.55 C230.85,219.55 230.98,219.8 230.98,219.8 C230.98,219.8 231.1,220.04 231.1,220.04 C231.1,220.04 231.22,220.29 231.22,220.29 C231.22,220.29 231.34,220.53 231.34,220.53 C231.34,220.53 231.47,220.78 231.47,220.78 C231.47,220.78 231.59,221.02 231.59,221.02 C231.59,221.02 231.71,221.27 231.71,221.27 C231.71,221.27 231.83,221.51 231.83,221.51 C231.83,221.51 231.96,221.76 231.96,221.76 C231.96,221.76 232.08,222 232.08,222 C232.08,222 232.2,222.25 232.2,222.25 C232.2,222.25 232.32,222.49 232.32,222.49 C232.32,222.49 232.44,222.74 232.44,222.74 C232.44,222.74 232.57,222.98 232.57,222.98 C232.57,222.98 232.69,223.23 232.69,223.23 C232.69,223.23 232.81,223.47 232.81,223.47 C232.81,223.47 232.93,223.71 232.93,223.71 C232.93,223.71 233.06,223.96 233.06,223.96 C233.06,223.96 233.18,224.21 233.18,224.21 C233.18,224.21 233.3,224.45 233.3,224.45 C233.3,224.45 233.42,224.7 233.42,224.7 C233.42,224.7 233.55,224.94 233.55,224.94 C233.55,224.94 233.67,225.19 233.67,225.19 C233.67,225.19 233.79,225.43 233.79,225.43 C233.79,225.43 233.9,225.69 233.9,225.69 C233.9,225.69 234.01,225.94 234.01,225.94 C234.01,225.94 234.12,226.19 234.12,226.19 C234.12,226.19 234.2,226.45 234.2,226.45 C234.2,226.45 234.28,226.71 234.28,226.71 C234.28,226.71 234.35,226.98 234.35,226.98 C234.35,226.98 234.41,227.24 234.41,227.24 C234.41,227.24 234.47,227.51 234.47,227.51 C234.47,227.51 234.5,227.78 234.5,227.78 C234.5,227.78 234.52,228.06 234.52,228.06 C234.52,228.06 234.54,228.33 234.54,228.33 C234.54,228.33 234.54,228.6 234.54,228.6 C234.54,228.6 234.54,228.88 234.54,228.88 C234.54,228.88 234.52,229.15 234.52,229.15 C234.52,229.15 234.49,229.42 234.49,229.42 C234.49,229.42 234.45,229.69 234.45,229.69 C234.45,229.69 234.4,229.96 234.4,229.96 C234.4,229.96 234.34,230.23 234.34,230.23 C234.34,230.23 234.26,230.49 234.26,230.49 C234.26,230.49 234.18,230.75 234.18,230.75 C234.18,230.75 234.08,231.01 234.08,231.01 C234.08,231.01 233.98,231.26 233.98,231.26 C233.98,231.26 233.87,231.51 233.87,231.51 C233.87,231.51 233.74,231.75 233.74,231.75 C233.74,231.75 233.61,232 233.61,232 C233.61,232 233.46,232.23 233.46,232.23 C233.46,232.23 233.31,232.46 233.31,232.46 C233.31,232.46 233.16,232.68 233.16,232.68 C233.16,232.68 232.98,232.89 232.98,232.89 C232.98,232.89 232.81,233.11 232.81,233.11 C232.81,233.11 232.62,233.3 232.62,233.3 C232.62,233.3 232.44,233.5 232.44,233.5 C232.44,233.5 232.24,233.69 232.24,233.69 C232.24,233.69 232.03,233.87 232.03,233.87 C232.03,233.87 231.82,234.04 231.82,234.04 C231.82,234.04 231.6,234.2 231.6,234.2 C231.6,234.2 231.37,234.37 231.37,234.37 C231.37,234.37 231.14,234.51 231.14,234.51 C231.14,234.51 230.91,234.65 230.91,234.65 C230.91,234.65 230.66,234.78 230.66,234.78 C230.66,234.78 230.42,234.89 230.42,234.89 C230.42,234.89 230.17,235.01 230.17,235.01 C230.17,235.01 229.91,235.1 229.91,235.1 C229.91,235.1 229.65,235.19 229.65,235.19 C229.65,235.19 229.39,235.27 229.39,235.27 C229.39,235.27 229.12,235.33 229.12,235.33 C229.12,235.33 228.86,235.4 228.86,235.4 C228.86,235.4 228.59,235.44 228.59,235.44 C228.59,235.44 228.32,235.48 228.32,235.48 C228.32,235.48 228.04,235.49 228.04,235.49 C228.04,235.49 227.77,235.51 227.77,235.51 C227.77,235.51 227.5,235.51 227.5,235.51 C227.5,235.51 227.22,235.49 227.22,235.49 C227.22,235.49 226.95,235.48 226.95,235.48 C226.95,235.48 226.68,235.44 226.68,235.44 C226.68,235.44 226.41,235.4 226.41,235.4 C226.41,235.4 226.14,235.35 226.14,235.35 C226.14,235.35 225.87,235.27 225.87,235.27 C225.87,235.27 225.61,235.2 225.61,235.2 C225.61,235.2 225.35,235.12 225.35,235.12 C225.35,235.12 225.09,235.02 225.09,235.02 C225.09,235.02 224.84,234.92 224.84,234.92 C224.84,234.92 224.59,234.81 224.59,234.81 C224.59,234.81 224.34,234.7 224.34,234.7 C224.34,234.7 224.09,234.59 224.09,234.59 C224.09,234.59 223.84,234.48 223.84,234.48 C223.84,234.48 223.59,234.36 223.59,234.36 C223.59,234.36 223.34,234.25 223.34,234.25 C223.34,234.25 223.09,234.14 223.09,234.14 C223.09,234.14 222.84,234.02 222.84,234.02 C222.84,234.02 222.59,233.91 222.59,233.91 C222.59,233.91 222.34,233.8 222.34,233.8 C222.34,233.8 222.09,233.69 222.09,233.69 C222.09,233.69 221.84,233.58 221.84,233.58 C221.84,233.58 221.59,233.46 221.59,233.46 C221.59,233.46 221.34,233.35 221.34,233.35 C221.34,233.35 221.09,233.24 221.09,233.24 C221.09,233.24 220.84,233.13 220.84,233.13 C220.84,233.13 220.59,233.01 220.59,233.01 C220.59,233.01 220.34,232.9 220.34,232.9 C220.34,232.9 220.09,232.8 220.09,232.8 C220.09,232.8 219.83,232.71 219.83,232.71 C219.83,232.71 219.57,232.62 219.57,232.62 C219.57,232.62 219.3,232.56 219.3,232.56 C219.3,232.56 219.04,232.49 219.04,232.49 C219.04,232.49 218.77,232.44 218.77,232.44 C218.77,232.44 218.5,232.4 218.5,232.4 C218.5,232.4 218.23,232.37 218.23,232.37 C218.23,232.37 217.95,232.35 217.95,232.35 C217.95,232.35 217.68,232.34 217.68,232.34 C217.68,232.34 217.41,232.34 217.41,232.34 C217.41,232.34 217.13,232.36 217.13,232.36 C217.13,232.36 216.86,232.38 216.86,232.38 C216.86,232.38 216.59,232.42 216.59,232.42 C216.59,232.42 216.32,232.46 216.32,232.46 C216.32,232.46 216.05,232.51 216.05,232.51 C216.05,232.51 215.79,232.58 215.79,232.58 C215.79,232.58 215.52,232.66 215.52,232.66 C215.52,232.66 215.26,232.75 215.26,232.75 C215.26,232.75 215.01,232.84 215.01,232.84 C215.01,232.84 214.75,232.94 214.75,232.94 C214.75,232.94 214.5,233.06 214.5,233.06 C214.5,233.06 214.25,233.17 214.25,233.17 C214.25,233.17 214,233.28 214,233.28 C214,233.28 213.75,233.39 213.75,233.39 C213.75,233.39 213.5,233.51 213.5,233.51 C213.5,233.51 213.25,233.62 213.25,233.62 C213.25,233.62 213,233.73 213,233.73 C213,233.73 212.75,233.84 212.75,233.84 C212.75,233.84 212.5,233.96 212.5,233.96 C212.5,233.96 212.26,234.07 212.26,234.07 C212.26,234.07 212.01,234.18 212.01,234.18 C212.01,234.18 211.76,234.29 211.76,234.29 C211.76,234.29 211.51,234.4 211.51,234.4 C211.51,234.4 211.26,234.52 211.26,234.52 C211.26,234.52 211.01,234.63 211.01,234.63 C211.01,234.63 210.76,234.74 210.76,234.74 C210.76,234.74 210.51,234.86 210.51,234.86 C210.51,234.86 210.25,234.96 210.25,234.96 C210.25,234.96 210,235.06 210,235.06 C210,235.06 209.74,235.16 209.74,235.16 C209.74,235.16 209.48,235.23 209.48,235.23 C209.48,235.23 209.22,235.3 209.22,235.3 C209.22,235.3 208.95,235.37 208.95,235.37 C208.95,235.37 208.68,235.41 208.68,235.41 C208.68,235.41 208.41,235.46 208.41,235.46 C208.41,235.46 208.14,235.48 208.14,235.48 C208.14,235.48 207.86,235.5 207.86,235.5 C207.86,235.5 207.59,235.51 207.59,235.51 C207.59,235.51 207.32,235.5 207.32,235.5 C207.32,235.5 207.04,235.49 207.04,235.49 C207.04,235.49 206.77,235.46 206.77,235.46 C206.77,235.46 206.5,235.42 206.5,235.42 C206.5,235.42 206.23,235.38 206.23,235.38 C206.23,235.38 205.96,235.31 205.96,235.31 C205.96,235.31 205.7,235.24 205.7,235.24 C205.7,235.24 205.44,235.16 205.44,235.16 C205.44,235.16 205.18,235.06 205.18,235.06 C205.18,235.06 204.93,234.96 204.93,234.96 C204.93,234.96 204.68,234.85 204.68,234.85 C204.68,234.85 204.43,234.73 204.43,234.73 C204.43,234.73 204.19,234.59 204.19,234.59 C204.19,234.59 203.96,234.45 203.96,234.45 C203.96,234.45 203.73,234.3 203.73,234.3 C203.73,234.3 203.51,234.14 203.51,234.14 C203.51,234.14 203.29,233.98 203.29,233.98 C203.29,233.98 203.08,233.8 203.08,233.8 C203.08,233.8 202.88,233.62 202.88,233.62 C202.88,233.62 202.68,233.43 202.68,233.43 C202.68,233.43 202.49,233.23 202.49,233.23 C202.49,233.23 202.31,233.02 202.31,233.02 C202.31,233.02 202.14,232.81 202.14,232.81 C202.14,232.81 201.97,232.6 201.97,232.6 C201.97,232.6 201.82,232.37 201.82,232.37 C201.82,232.37 201.67,232.14 201.67,232.14 C201.67,232.14 201.53,231.9 201.53,231.9 C201.53,231.9 201.4,231.66 201.4,231.66 C201.4,231.66 201.28,231.42 201.28,231.42 C201.28,231.42 201.17,231.16 201.17,231.16 C201.17,231.16 201.07,230.91 201.07,230.91 C201.07,230.91 200.98,230.65 200.98,230.65 C200.98,230.65 200.9,230.39 200.9,230.39 C200.9,230.39 200.83,230.13 200.83,230.13 C200.83,230.13 200.77,229.86 200.77,229.86 C200.77,229.86 200.72,229.59 200.72,229.59 C200.72,229.59 200.69,229.32 200.69,229.32 C200.69,229.32 200.66,229.04 200.66,229.04 C200.66,229.04 200.65,228.77 200.65,228.77 C200.65,228.77 200.65,228.5 200.65,228.5 C200.65,228.5 200.65,228.22 200.65,228.22 C200.65,228.22 200.68,227.95 200.68,227.95 C200.68,227.95 200.7,227.68 200.7,227.68 C200.7,227.68 200.75,227.41 200.75,227.41 C200.75,227.41 200.8,227.14 200.8,227.14 C200.8,227.14 200.86,226.87 200.86,226.87 C200.86,226.87 200.94,226.61 200.94,226.61 C200.94,226.61 201.02,226.35 201.02,226.35 C201.02,226.35 201.11,226.09 201.11,226.09 C201.11,226.09 201.22,225.84 201.22,225.84 C201.22,225.84 201.33,225.59 201.33,225.59 C201.33,225.59 201.44,225.34 201.44,225.34 C201.44,225.34 201.57,225.1 201.57,225.1 C201.57,225.1 201.69,224.85 201.69,224.85 C201.69,224.85 201.81,224.61 201.81,224.61 C201.81,224.61 201.93,224.36 201.93,224.36 C201.93,224.36 202.06,224.12 202.06,224.12 C202.06,224.12 202.18,223.87 202.18,223.87 C202.18,223.87 202.3,223.63 202.3,223.63 C202.3,223.63 202.42,223.38 202.42,223.38 C202.42,223.38 202.55,223.14 202.55,223.14 C202.55,223.14 202.67,222.89 202.67,222.89 C202.67,222.89 202.79,222.65 202.79,222.65 C202.79,222.65 202.91,222.4 202.91,222.4 C202.91,222.4 203.04,222.16 203.04,222.16 C203.04,222.16 203.16,221.91 203.16,221.91 C203.16,221.91 203.28,221.67 203.28,221.67 C203.28,221.67 203.4,221.42 203.4,221.42 C203.4,221.42 203.52,221.18 203.52,221.18 C203.52,221.18 203.65,220.93 203.65,220.93 C203.65,220.93 203.77,220.69 203.77,220.69 C203.77,220.69 203.89,220.44 203.89,220.44 C203.89,220.44 204.01,220.2 204.01,220.2 C204.01,220.2 204.14,219.95 204.14,219.95 C204.14,219.95 204.26,219.71 204.26,219.71 C204.26,219.71 204.38,219.46 204.38,219.46 C204.38,219.46 204.5,219.22 204.5,219.22 C204.5,219.22 204.63,218.97 204.63,218.97 C204.63,218.97 204.75,218.73 204.75,218.73 C204.75,218.73 204.87,218.48 204.87,218.48 C204.87,218.48 204.99,218.24 204.99,218.24 C204.99,218.24 205.12,217.99 205.12,217.99 C205.12,217.99 205.24,217.75 205.24,217.75 C205.24,217.75 205.36,217.5 205.36,217.5 C205.36,217.5 205.48,217.26 205.48,217.26 C205.48,217.26 205.61,217.01 205.61,217.01 C205.61,217.01 205.73,216.77 205.73,216.77 C205.73,216.77 205.85,216.52 205.85,216.52 C205.85,216.52 205.97,216.28 205.97,216.28 C205.97,216.28 206.09,216.03 206.09,216.03 C206.09,216.03 206.22,215.79 206.22,215.79 C206.22,215.79 206.34,215.54 206.34,215.54 C206.34,215.54 206.46,215.3 206.46,215.3 C206.46,215.3 206.58,215.05 206.58,215.05 C206.58,215.05 206.71,214.81 206.71,214.81 C206.71,214.81 206.83,214.56 206.83,214.56 C206.83,214.56 206.95,214.32 206.95,214.32 C206.95,214.32 207.07,214.07 207.07,214.07 C207.07,214.07 207.2,213.83 207.2,213.83 C207.2,213.83 207.32,213.58 207.32,213.58 C207.32,213.58 207.44,213.34 207.44,213.34 C207.44,213.34 207.56,213.09 207.56,213.09 C207.56,213.09 207.69,212.85 207.69,212.85 C207.69,212.85 207.81,212.6 207.81,212.6 C207.81,212.6 207.93,212.36 207.93,212.36 C207.93,212.36 208.05,212.11 208.05,212.11 C208.05,212.11 208.18,211.87 208.18,211.87 C208.18,211.87 208.3,211.62 208.3,211.62 C208.3,211.62 208.42,211.38 208.42,211.38 C208.42,211.38 208.54,211.13 208.54,211.13 C208.54,211.13 208.66,210.89 208.66,210.89 C208.66,210.89 208.79,210.64 208.79,210.64 C208.79,210.64 208.91,210.4 208.91,210.4 C208.91,210.4 209.03,210.15 209.03,210.15 C209.03,210.15 209.15,209.91 209.15,209.91 C209.15,209.91 209.28,209.66 209.28,209.66 C209.28,209.66 209.4,209.42 209.4,209.42 C209.4,209.42 209.52,209.17 209.52,209.17 C209.52,209.17 209.64,208.93 209.64,208.93 C209.64,208.93 209.77,208.68 209.77,208.68 C209.77,208.68 209.89,208.44 209.89,208.44 C209.89,208.44 210.01,208.19 210.01,208.19 C210.01,208.19 210.13,207.95 210.13,207.95 C210.13,207.95 210.26,207.7 210.26,207.7 C210.26,207.7 210.38,207.46 210.38,207.46 C210.38,207.46 210.5,207.21 210.5,207.21 C210.5,207.21 210.62,206.97 210.62,206.97 C210.62,206.97 210.75,206.72 210.75,206.72 C210.75,206.72 210.87,206.48 210.87,206.48 C210.87,206.48 210.99,206.23 210.99,206.23 C210.99,206.23 211.11,205.99 211.11,205.99 C211.11,205.99 211.24,205.74 211.24,205.74 C211.24,205.74 211.36,205.5 211.36,205.5 C211.36,205.5 211.49,205.26 211.49,205.26 C211.49,205.26 211.62,205.02 211.62,205.02 C211.62,205.02 211.76,204.78 211.76,204.78 C211.76,204.78 211.92,204.56 211.92,204.56 C211.92,204.56 212.07,204.33 212.07,204.33 C212.07,204.33 212.25,204.12 212.25,204.12 C212.25,204.12 212.42,203.91 212.42,203.91 C212.42,203.91 212.61,203.71 212.61,203.71 C212.61,203.71 212.8,203.52 212.8,203.52 C212.8,203.52 213,203.33 213,203.33 C213,203.33 213.21,203.15 213.21,203.15 C213.21,203.15 213.42,202.98 213.42,202.98 C213.42,202.98 213.65,202.82 213.65,202.82 C213.65,202.82 213.87,202.67 213.87,202.67 C213.87,202.67 214.11,202.53 214.11,202.53 C214.11,202.53 214.35,202.4 214.35,202.4 C214.35,202.4 214.6,202.28 214.6,202.28 C214.6,202.28 214.85,202.16 214.85,202.16 C214.85,202.16 215.1,202.06 215.1,202.06 C215.1,202.06 215.36,201.98 215.36,201.98 C215.36,201.98 215.62,201.89 215.62,201.89 C215.62,201.89 215.88,201.81 215.88,201.81 C215.88,201.81 216.15,201.76 216.15,201.76 C216.15,201.76 216.42,201.71 216.42,201.71 C216.42,201.71 216.69,201.66 216.69,201.66 C216.69,201.66 216.96,201.64 216.96,201.64 C216.96,201.64 217.24,201.62 217.24,201.62 C217.24,201.62 217.51,201.61 217.51,201.61 C217.51,201.61 217.78,201.61 217.78,201.61c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.78 201.61 C217.78,201.61 218.06,201.63 218.06,201.63 C218.06,201.63 218.33,201.65 218.33,201.65 C218.33,201.65 218.6,201.68 218.6,201.68 C218.6,201.68 218.87,201.73 218.87,201.73 C218.87,201.73 219.14,201.78 219.14,201.78 C219.14,201.78 219.41,201.84 219.41,201.84 C219.41,201.84 219.67,201.93 219.67,201.93 C219.67,201.93 219.93,202.01 219.93,202.01 C219.93,202.01 220.19,202.09 220.19,202.09 C220.19,202.09 220.44,202.21 220.44,202.21 C220.44,202.21 220.69,202.32 220.69,202.32 C220.69,202.32 220.93,202.45 220.93,202.45 C220.93,202.45 221.17,202.58 221.17,202.58 C221.17,202.58 221.4,202.73 221.4,202.73 C221.4,202.73 221.62,202.88 221.62,202.88 C221.62,202.88 221.85,203.04 221.85,203.04 C221.85,203.04 222.06,203.22 222.06,203.22 C222.06,203.22 222.27,203.39 222.27,203.39 C222.27,203.39 222.46,203.59 222.46,203.59 C222.46,203.59 222.65,203.78 222.65,203.78 C222.65,203.78 222.83,203.99 222.83,203.99 C222.83,203.99 223.01,204.2 223.01,204.2 C223.01,204.2 223.18,204.41 223.18,204.41 C223.18,204.41 223.33,204.64 223.33,204.64 C223.33,204.64 223.48,204.87 223.48,204.87 C223.48,204.87 223.62,205.11 223.62,205.11 C223.62,205.11 223.75,205.34 223.75,205.34 C223.75,205.34 223.88,205.59 223.88,205.59 C223.88,205.59 224,205.83 224,205.83 C224,205.83 224.12,206.08 224.12,206.08 C224.12,206.08 224.24,206.32 224.24,206.32 C224.24,206.32 224.37,206.57 224.37,206.57 C224.37,206.57 224.49,206.81 224.49,206.81 C224.49,206.81 224.61,207.06 224.61,207.06 C224.61,207.06 224.73,207.3 224.73,207.3 C224.73,207.3 224.86,207.55 224.86,207.55 C224.86,207.55 224.98,207.79 224.98,207.79 C224.98,207.79 225.1,208.04 225.1,208.04 C225.1,208.04 225.22,208.28 225.22,208.28 C225.22,208.28 225.35,208.53 225.35,208.53 C225.35,208.53 225.47,208.77 225.47,208.77 C225.47,208.77 225.59,209.02 225.59,209.02 C225.59,209.02 225.71,209.26 225.71,209.26 C225.71,209.26 225.84,209.51 225.84,209.51 C225.84,209.51 225.96,209.75 225.96,209.75 C225.96,209.75 226.08,210 226.08,210 C226.08,210 226.2,210.24 226.2,210.24 C226.2,210.24 226.33,210.49 226.33,210.49 C226.33,210.49 226.45,210.73 226.45,210.73 C226.45,210.73 226.57,210.98 226.57,210.98 C226.57,210.98 226.69,211.22 226.69,211.22 C226.69,211.22 226.82,211.47 226.82,211.47 C226.82,211.47 226.94,211.71 226.94,211.71 C226.94,211.71 227.06,211.96 227.06,211.96 C227.06,211.96 227.18,212.2 227.18,212.2 C227.18,212.2 227.3,212.45 227.3,212.45 C227.3,212.45 227.43,212.69 227.43,212.69 C227.43,212.69 227.55,212.94 227.55,212.94 C227.55,212.94 227.67,213.18 227.67,213.18 C227.67,213.18 227.79,213.43 227.79,213.43 C227.79,213.43 227.92,213.67 227.92,213.67 C227.92,213.67 228.04,213.92 228.04,213.92 C228.04,213.92 228.16,214.16 228.16,214.16 C228.16,214.16 228.28,214.41 228.28,214.41 C228.28,214.41 228.41,214.65 228.41,214.65 C228.41,214.65 228.53,214.9 228.53,214.9 C228.53,214.9 228.65,215.14 228.65,215.14 C228.65,215.14 228.77,215.39 228.77,215.39 C228.77,215.39 228.9,215.63 228.9,215.63 C228.9,215.63 229.02,215.88 229.02,215.88 C229.02,215.88 229.14,216.12 229.14,216.12 C229.14,216.12 229.26,216.37 229.26,216.37 C229.26,216.37 229.39,216.61 229.39,216.61 C229.39,216.61 229.51,216.86 229.51,216.86 C229.51,216.86 229.63,217.1 229.63,217.1 C229.63,217.1 229.75,217.35 229.75,217.35 C229.75,217.35 229.87,217.59 229.87,217.59 C229.87,217.59 230,217.84 230,217.84 C230,217.84 230.12,218.08 230.12,218.08 C230.12,218.08 230.24,218.33 230.24,218.33 C230.24,218.33 230.36,218.57 230.36,218.57 C230.36,218.57 230.49,218.82 230.49,218.82 C230.49,218.82 230.61,219.06 230.61,219.06 C230.61,219.06 230.73,219.31 230.73,219.31 C230.73,219.31 230.85,219.55 230.85,219.55 C230.85,219.55 230.98,219.8 230.98,219.8 C230.98,219.8 231.1,220.04 231.1,220.04 C231.1,220.04 231.22,220.29 231.22,220.29 C231.22,220.29 231.34,220.53 231.34,220.53 C231.34,220.53 231.47,220.78 231.47,220.78 C231.47,220.78 231.59,221.02 231.59,221.02 C231.59,221.02 231.71,221.27 231.71,221.27 C231.71,221.27 231.83,221.51 231.83,221.51 C231.83,221.51 231.96,221.76 231.96,221.76 C231.96,221.76 232.08,222 232.08,222 C232.08,222 232.2,222.25 232.2,222.25 C232.2,222.25 232.32,222.49 232.32,222.49 C232.32,222.49 232.44,222.74 232.44,222.74 C232.44,222.74 232.57,222.98 232.57,222.98 C232.57,222.98 232.69,223.23 232.69,223.23 C232.69,223.23 232.81,223.47 232.81,223.47 C232.81,223.47 232.93,223.71 232.93,223.71 C232.93,223.71 233.06,223.96 233.06,223.96 C233.06,223.96 233.18,224.21 233.18,224.21 C233.18,224.21 233.3,224.45 233.3,224.45 C233.3,224.45 233.42,224.7 233.42,224.7 C233.42,224.7 233.55,224.94 233.55,224.94 C233.55,224.94 233.67,225.19 233.67,225.19 C233.67,225.19 233.79,225.43 233.79,225.43 C233.79,225.43 233.9,225.69 233.9,225.69 C233.9,225.69 234.01,225.94 234.01,225.94 C234.01,225.94 234.12,226.19 234.12,226.19 C234.12,226.19 234.2,226.45 234.2,226.45 C234.2,226.45 234.28,226.71 234.28,226.71 C234.28,226.71 234.35,226.98 234.35,226.98 C234.35,226.98 234.41,227.24 234.41,227.24 C234.41,227.24 234.47,227.51 234.47,227.51 C234.47,227.51 234.5,227.78 234.5,227.78 C234.5,227.78 234.52,228.06 234.52,228.06 C234.52,228.06 234.54,228.33 234.54,228.33 C234.54,228.33 234.54,228.6 234.54,228.6 C234.54,228.6 234.54,228.88 234.54,228.88 C234.54,228.88 234.52,229.15 234.52,229.15 C234.52,229.15 234.49,229.42 234.49,229.42 C234.49,229.42 234.45,229.69 234.45,229.69 C234.45,229.69 234.4,229.96 234.4,229.96 C234.4,229.96 234.34,230.23 234.34,230.23 C234.34,230.23 234.26,230.49 234.26,230.49 C234.26,230.49 234.18,230.75 234.18,230.75 C234.18,230.75 234.08,231.01 234.08,231.01 C234.08,231.01 233.98,231.26 233.98,231.26 C233.98,231.26 233.87,231.51 233.87,231.51 C233.87,231.51 233.74,231.75 233.74,231.75 C233.74,231.75 233.61,232 233.61,232 C233.61,232 233.46,232.23 233.46,232.23 C233.46,232.23 233.31,232.46 233.31,232.46 C233.31,232.46 233.16,232.68 233.16,232.68 C233.16,232.68 232.98,232.89 232.98,232.89 C232.98,232.89 232.81,233.11 232.81,233.11 C232.81,233.11 232.62,233.3 232.62,233.3 C232.62,233.3 232.44,233.5 232.44,233.5 C232.44,233.5 232.24,233.69 232.24,233.69 C232.24,233.69 232.03,233.87 232.03,233.87 C232.03,233.87 231.82,234.04 231.82,234.04 C231.82,234.04 231.6,234.2 231.6,234.2 C231.6,234.2 231.37,234.37 231.37,234.37 C231.37,234.37 231.14,234.51 231.14,234.51 C231.14,234.51 230.91,234.65 230.91,234.65 C230.91,234.65 230.66,234.78 230.66,234.78 C230.66,234.78 230.42,234.89 230.42,234.89 C230.42,234.89 230.17,235.01 230.17,235.01 C230.17,235.01 229.91,235.1 229.91,235.1 C229.91,235.1 229.65,235.19 229.65,235.19 C229.65,235.19 229.39,235.27 229.39,235.27 C229.39,235.27 229.12,235.33 229.12,235.33 C229.12,235.33 228.86,235.4 228.86,235.4 C228.86,235.4 228.59,235.44 228.59,235.44 C228.59,235.44 228.32,235.48 228.32,235.48 C228.32,235.48 228.04,235.49 228.04,235.49 C228.04,235.49 227.77,235.51 227.77,235.51 C227.77,235.51 227.5,235.51 227.5,235.51 C227.5,235.51 227.22,235.49 227.22,235.49 C227.22,235.49 226.95,235.48 226.95,235.48 C226.95,235.48 226.68,235.44 226.68,235.44 C226.68,235.44 226.41,235.4 226.41,235.4 C226.41,235.4 226.14,235.35 226.14,235.35 C226.14,235.35 225.87,235.27 225.87,235.27 C225.87,235.27 225.61,235.2 225.61,235.2 C225.61,235.2 225.35,235.12 225.35,235.12 C225.35,235.12 225.09,235.02 225.09,235.02 C225.09,235.02 224.84,234.92 224.84,234.92 C224.84,234.92 224.59,234.81 224.59,234.81 C224.59,234.81 224.34,234.7 224.34,234.7 C224.34,234.7 224.09,234.59 224.09,234.59 C224.09,234.59 223.84,234.48 223.84,234.48 C223.84,234.48 223.59,234.36 223.59,234.36 C223.59,234.36 223.34,234.25 223.34,234.25 C223.34,234.25 223.09,234.14 223.09,234.14 C223.09,234.14 222.84,234.02 222.84,234.02 C222.84,234.02 222.59,233.91 222.59,233.91 C222.59,233.91 222.34,233.8 222.34,233.8 C222.34,233.8 222.09,233.69 222.09,233.69 C222.09,233.69 221.84,233.58 221.84,233.58 C221.84,233.58 221.59,233.46 221.59,233.46 C221.59,233.46 221.34,233.35 221.34,233.35 C221.34,233.35 221.09,233.24 221.09,233.24 C221.09,233.24 220.84,233.13 220.84,233.13 C220.84,233.13 220.59,233.01 220.59,233.01 C220.59,233.01 220.34,232.9 220.34,232.9 C220.34,232.9 220.09,232.8 220.09,232.8 C220.09,232.8 219.83,232.71 219.83,232.71 C219.83,232.71 219.57,232.62 219.57,232.62 C219.57,232.62 219.3,232.56 219.3,232.56 C219.3,232.56 219.04,232.49 219.04,232.49 C219.04,232.49 218.77,232.44 218.77,232.44 C218.77,232.44 218.5,232.4 218.5,232.4 C218.5,232.4 218.23,232.37 218.23,232.37 C218.23,232.37 217.95,232.35 217.95,232.35 C217.95,232.35 217.68,232.34 217.68,232.34 C217.68,232.34 217.41,232.34 217.41,232.34 C217.41,232.34 217.13,232.36 217.13,232.36 C217.13,232.36 216.86,232.38 216.86,232.38 C216.86,232.38 216.59,232.42 216.59,232.42 C216.59,232.42 216.32,232.46 216.32,232.46 C216.32,232.46 216.05,232.51 216.05,232.51 C216.05,232.51 215.79,232.58 215.79,232.58 C215.79,232.58 215.52,232.66 215.52,232.66 C215.52,232.66 215.26,232.75 215.26,232.75 C215.26,232.75 215.01,232.84 215.01,232.84 C215.01,232.84 214.75,232.94 214.75,232.94 C214.75,232.94 214.5,233.06 214.5,233.06 C214.5,233.06 214.25,233.17 214.25,233.17 C214.25,233.17 214,233.28 214,233.28 C214,233.28 213.75,233.39 213.75,233.39 C213.75,233.39 213.5,233.51 213.5,233.51 C213.5,233.51 213.25,233.62 213.25,233.62 C213.25,233.62 213,233.73 213,233.73 C213,233.73 212.75,233.84 212.75,233.84 C212.75,233.84 212.5,233.96 212.5,233.96 C212.5,233.96 212.26,234.07 212.26,234.07 C212.26,234.07 212.01,234.18 212.01,234.18 C212.01,234.18 211.76,234.29 211.76,234.29 C211.76,234.29 211.51,234.4 211.51,234.4 C211.51,234.4 211.26,234.52 211.26,234.52 C211.26,234.52 211.01,234.63 211.01,234.63 C211.01,234.63 210.76,234.74 210.76,234.74 C210.76,234.74 210.51,234.86 210.51,234.86 C210.51,234.86 210.25,234.96 210.25,234.96 C210.25,234.96 210,235.06 210,235.06 C210,235.06 209.74,235.16 209.74,235.16 C209.74,235.16 209.48,235.23 209.48,235.23 C209.48,235.23 209.22,235.3 209.22,235.3 C209.22,235.3 208.95,235.37 208.95,235.37 C208.95,235.37 208.68,235.41 208.68,235.41 C208.68,235.41 208.41,235.46 208.41,235.46 C208.41,235.46 208.14,235.48 208.14,235.48 C208.14,235.48 207.86,235.5 207.86,235.5 C207.86,235.5 207.59,235.51 207.59,235.51 C207.59,235.51 207.32,235.5 207.32,235.5 C207.32,235.5 207.04,235.49 207.04,235.49 C207.04,235.49 206.77,235.46 206.77,235.46 C206.77,235.46 206.5,235.42 206.5,235.42 C206.5,235.42 206.23,235.38 206.23,235.38 C206.23,235.38 205.96,235.31 205.96,235.31 C205.96,235.31 205.7,235.24 205.7,235.24 C205.7,235.24 205.44,235.16 205.44,235.16 C205.44,235.16 205.18,235.06 205.18,235.06 C205.18,235.06 204.93,234.96 204.93,234.96 C204.93,234.96 204.68,234.85 204.68,234.85 C204.68,234.85 204.43,234.73 204.43,234.73 C204.43,234.73 204.19,234.59 204.19,234.59 C204.19,234.59 203.96,234.45 203.96,234.45 C203.96,234.45 203.73,234.3 203.73,234.3 C203.73,234.3 203.51,234.14 203.51,234.14 C203.51,234.14 203.29,233.98 203.29,233.98 C203.29,233.98 203.08,233.8 203.08,233.8 C203.08,233.8 202.88,233.62 202.88,233.62 C202.88,233.62 202.68,233.43 202.68,233.43 C202.68,233.43 202.49,233.23 202.49,233.23 C202.49,233.23 202.31,233.02 202.31,233.02 C202.31,233.02 202.14,232.81 202.14,232.81 C202.14,232.81 201.97,232.6 201.97,232.6 C201.97,232.6 201.82,232.37 201.82,232.37 C201.82,232.37 201.67,232.14 201.67,232.14 C201.67,232.14 201.53,231.9 201.53,231.9 C201.53,231.9 201.4,231.66 201.4,231.66 C201.4,231.66 201.28,231.42 201.28,231.42 C201.28,231.42 201.17,231.16 201.17,231.16 C201.17,231.16 201.07,230.91 201.07,230.91 C201.07,230.91 200.98,230.65 200.98,230.65 C200.98,230.65 200.9,230.39 200.9,230.39 C200.9,230.39 200.83,230.13 200.83,230.13 C200.83,230.13 200.77,229.86 200.77,229.86 C200.77,229.86 200.72,229.59 200.72,229.59 C200.72,229.59 200.69,229.32 200.69,229.32 C200.69,229.32 200.66,229.04 200.66,229.04 C200.66,229.04 200.65,228.77 200.65,228.77 C200.65,228.77 200.65,228.5 200.65,228.5 C200.65,228.5 200.65,228.22 200.65,228.22 C200.65,228.22 200.68,227.95 200.68,227.95 C200.68,227.95 200.7,227.68 200.7,227.68 C200.7,227.68 200.75,227.41 200.75,227.41 C200.75,227.41 200.8,227.14 200.8,227.14 C200.8,227.14 200.86,226.87 200.86,226.87 C200.86,226.87 200.94,226.61 200.94,226.61 C200.94,226.61 201.02,226.35 201.02,226.35 C201.02,226.35 201.11,226.09 201.11,226.09 C201.11,226.09 201.22,225.84 201.22,225.84 C201.22,225.84 201.33,225.59 201.33,225.59 C201.33,225.59 201.44,225.34 201.44,225.34 C201.44,225.34 201.57,225.1 201.57,225.1 C201.57,225.1 201.69,224.85 201.69,224.85 C201.69,224.85 201.81,224.61 201.81,224.61 C201.81,224.61 201.93,224.36 201.93,224.36 C201.93,224.36 202.06,224.12 202.06,224.12 C202.06,224.12 202.18,223.87 202.18,223.87 C202.18,223.87 202.3,223.63 202.3,223.63 C202.3,223.63 202.42,223.38 202.42,223.38 C202.42,223.38 202.55,223.14 202.55,223.14 C202.55,223.14 202.67,222.89 202.67,222.89 C202.67,222.89 202.79,222.65 202.79,222.65 C202.79,222.65 202.91,222.4 202.91,222.4 C202.91,222.4 203.04,222.16 203.04,222.16 C203.04,222.16 203.16,221.91 203.16,221.91 C203.16,221.91 203.28,221.67 203.28,221.67 C203.28,221.67 203.4,221.42 203.4,221.42 C203.4,221.42 203.52,221.18 203.52,221.18 C203.52,221.18 203.65,220.93 203.65,220.93 C203.65,220.93 203.77,220.69 203.77,220.69 C203.77,220.69 203.89,220.44 203.89,220.44 C203.89,220.44 204.01,220.2 204.01,220.2 C204.01,220.2 204.14,219.95 204.14,219.95 C204.14,219.95 204.26,219.71 204.26,219.71 C204.26,219.71 204.38,219.46 204.38,219.46 C204.38,219.46 204.5,219.22 204.5,219.22 C204.5,219.22 204.63,218.97 204.63,218.97 C204.63,218.97 204.75,218.73 204.75,218.73 C204.75,218.73 204.87,218.48 204.87,218.48 C204.87,218.48 204.99,218.24 204.99,218.24 C204.99,218.24 205.12,217.99 205.12,217.99 C205.12,217.99 205.24,217.75 205.24,217.75 C205.24,217.75 205.36,217.5 205.36,217.5 C205.36,217.5 205.48,217.26 205.48,217.26 C205.48,217.26 205.61,217.01 205.61,217.01 C205.61,217.01 205.73,216.77 205.73,216.77 C205.73,216.77 205.85,216.52 205.85,216.52 C205.85,216.52 205.97,216.28 205.97,216.28 C205.97,216.28 206.09,216.03 206.09,216.03 C206.09,216.03 206.22,215.79 206.22,215.79 C206.22,215.79 206.34,215.54 206.34,215.54 C206.34,215.54 206.46,215.3 206.46,215.3 C206.46,215.3 206.58,215.05 206.58,215.05 C206.58,215.05 206.71,214.81 206.71,214.81 C206.71,214.81 206.83,214.56 206.83,214.56 C206.83,214.56 206.95,214.32 206.95,214.32 C206.95,214.32 207.07,214.07 207.07,214.07 C207.07,214.07 207.2,213.83 207.2,213.83 C207.2,213.83 207.32,213.58 207.32,213.58 C207.32,213.58 207.44,213.34 207.44,213.34 C207.44,213.34 207.56,213.09 207.56,213.09 C207.56,213.09 207.69,212.85 207.69,212.85 C207.69,212.85 207.81,212.6 207.81,212.6 C207.81,212.6 207.93,212.36 207.93,212.36 C207.93,212.36 208.05,212.11 208.05,212.11 C208.05,212.11 208.18,211.87 208.18,211.87 C208.18,211.87 208.3,211.62 208.3,211.62 C208.3,211.62 208.42,211.38 208.42,211.38 C208.42,211.38 208.54,211.13 208.54,211.13 C208.54,211.13 208.66,210.89 208.66,210.89 C208.66,210.89 208.79,210.64 208.79,210.64 C208.79,210.64 208.91,210.4 208.91,210.4 C208.91,210.4 209.03,210.15 209.03,210.15 C209.03,210.15 209.15,209.91 209.15,209.91 C209.15,209.91 209.28,209.66 209.28,209.66 C209.28,209.66 209.4,209.42 209.4,209.42 C209.4,209.42 209.52,209.17 209.52,209.17 C209.52,209.17 209.64,208.93 209.64,208.93 C209.64,208.93 209.77,208.68 209.77,208.68 C209.77,208.68 209.89,208.44 209.89,208.44 C209.89,208.44 210.01,208.19 210.01,208.19 C210.01,208.19 210.13,207.95 210.13,207.95 C210.13,207.95 210.26,207.7 210.26,207.7 C210.26,207.7 210.38,207.46 210.38,207.46 C210.38,207.46 210.5,207.21 210.5,207.21 C210.5,207.21 210.62,206.97 210.62,206.97 C210.62,206.97 210.75,206.72 210.75,206.72 C210.75,206.72 210.87,206.48 210.87,206.48 C210.87,206.48 210.99,206.23 210.99,206.23 C210.99,206.23 211.11,205.99 211.11,205.99 C211.11,205.99 211.24,205.74 211.24,205.74 C211.24,205.74 211.36,205.5 211.36,205.5 C211.36,205.5 211.49,205.26 211.49,205.26 C211.49,205.26 211.62,205.02 211.62,205.02 C211.62,205.02 211.76,204.78 211.76,204.78 C211.76,204.78 211.92,204.56 211.92,204.56 C211.92,204.56 212.07,204.33 212.07,204.33 C212.07,204.33 212.25,204.12 212.25,204.12 C212.25,204.12 212.42,203.91 212.42,203.91 C212.42,203.91 212.61,203.71 212.61,203.71 C212.61,203.71 212.8,203.52 212.8,203.52 C212.8,203.52 213,203.33 213,203.33 C213,203.33 213.21,203.15 213.21,203.15 C213.21,203.15 213.42,202.98 213.42,202.98 C213.42,202.98 213.65,202.82 213.65,202.82 C213.65,202.82 213.87,202.67 213.87,202.67 C213.87,202.67 214.11,202.53 214.11,202.53 C214.11,202.53 214.35,202.4 214.35,202.4 C214.35,202.4 214.6,202.28 214.6,202.28 C214.6,202.28 214.85,202.16 214.85,202.16 C214.85,202.16 215.1,202.06 215.1,202.06 C215.1,202.06 215.36,201.98 215.36,201.98 C215.36,201.98 215.62,201.89 215.62,201.89 C215.62,201.89 215.88,201.81 215.88,201.81 C215.88,201.81 216.15,201.76 216.15,201.76 C216.15,201.76 216.42,201.71 216.42,201.71 C216.42,201.71 216.69,201.66 216.69,201.66 C216.69,201.66 216.96,201.64 216.96,201.64 C216.96,201.64 217.24,201.62 217.24,201.62 C217.24,201.62 217.51,201.61 217.51,201.61 C217.51,201.61 217.78,201.61 217.78,201.61c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml
new file mode 100644
index 0000000..cf08899
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml
@@ -0,0 +1 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.57 201.76 C217.57,201.76 217.82,201.81 217.82,201.81 C217.82,201.81 218.08,201.86 218.08,201.86 C218.08,201.86 218.34,201.92 218.34,201.92 C218.34,201.92 218.6,201.97 218.6,201.97 C218.6,201.97 218.85,202.04 218.85,202.04 C218.85,202.04 219.11,202.12 219.11,202.12 C219.11,202.12 219.36,202.19 219.36,202.19 C219.36,202.19 219.61,202.27 219.61,202.27 C219.61,202.27 219.86,202.34 219.86,202.34 C219.86,202.34 220.11,202.44 220.11,202.44 C220.11,202.44 220.35,202.54 220.35,202.54 C220.35,202.54 220.6,202.64 220.6,202.64 C220.6,202.64 220.84,202.73 220.84,202.73 C220.84,202.73 221.09,202.83 221.09,202.83 C221.09,202.83 221.32,202.94 221.32,202.94 C221.32,202.94 221.56,203.07 221.56,203.07 C221.56,203.07 221.79,203.19 221.79,203.19 C221.79,203.19 222.03,203.31 222.03,203.31 C222.03,203.31 222.26,203.43 222.26,203.43 C222.26,203.43 222.49,203.56 222.49,203.56 C222.49,203.56 222.71,203.7 222.71,203.7 C222.71,203.7 222.93,203.85 222.93,203.85 C222.93,203.85 223.15,203.99 223.15,203.99 C223.15,203.99 223.37,204.13 223.37,204.13 C223.37,204.13 223.59,204.28 223.59,204.28 C223.59,204.28 223.8,204.44 223.8,204.44 C223.8,204.44 224.01,204.6 224.01,204.6 C224.01,204.6 224.22,204.76 224.22,204.76 C224.22,204.76 224.42,204.93 224.42,204.93 C224.42,204.93 224.62,205.1 224.62,205.1 C224.62,205.1 224.81,205.28 224.81,205.28 C224.81,205.28 225.01,205.46 225.01,205.46 C225.01,205.46 225.2,205.64 225.2,205.64 C225.2,205.64 225.4,205.81 225.4,205.81 C225.4,205.81 225.59,206 225.59,206 C225.59,206 225.77,206.19 225.77,206.19 C225.77,206.19 225.96,206.37 225.96,206.37 C225.96,206.37 226.15,206.56 226.15,206.56 C226.15,206.56 226.33,206.74 226.33,206.74 C226.33,206.74 226.52,206.93 226.52,206.93 C226.52,206.93 226.7,207.12 226.7,207.12 C226.7,207.12 226.89,207.3 226.89,207.3 C226.89,207.3 227.08,207.49 227.08,207.49 C227.08,207.49 227.26,207.68 227.26,207.68 C227.26,207.68 227.45,207.86 227.45,207.86 C227.45,207.86 227.64,208.05 227.64,208.05 C227.64,208.05 227.82,208.24 227.82,208.24 C227.82,208.24 228.01,208.42 228.01,208.42 C228.01,208.42 228.2,208.61 228.2,208.61 C228.2,208.61 228.38,208.79 228.38,208.79 C228.38,208.79 228.57,208.98 228.57,208.98 C228.57,208.98 228.75,209.17 228.75,209.17 C228.75,209.17 228.94,209.35 228.94,209.35 C228.94,209.35 229.13,209.54 229.13,209.54 C229.13,209.54 229.31,209.73 229.31,209.73 C229.31,209.73 229.5,209.91 229.5,209.91 C229.5,209.91 229.69,210.1 229.69,210.1 C229.69,210.1 229.87,210.29 229.87,210.29 C229.87,210.29 230.06,210.47 230.06,210.47 C230.06,210.47 230.25,210.66 230.25,210.66 C230.25,210.66 230.42,210.85 230.42,210.85 C230.42,210.85 230.6,211.05 230.6,211.05 C230.6,211.05 230.78,211.24 230.78,211.24 C230.78,211.24 230.95,211.44 230.95,211.44 C230.95,211.44 231.13,211.63 231.13,211.63 C231.13,211.63 231.3,211.84 231.3,211.84 C231.3,211.84 231.45,212.05 231.45,212.05 C231.45,212.05 231.61,212.26 231.61,212.26 C231.61,212.26 231.77,212.47 231.77,212.47 C231.77,212.47 231.93,212.68 231.93,212.68 C231.93,212.68 232.08,212.9 232.08,212.9 C232.08,212.9 232.22,213.12 232.22,213.12 C232.22,213.12 232.35,213.35 232.35,213.35 C232.35,213.35 232.49,213.57 232.49,213.57 C232.49,213.57 232.63,213.8 232.63,213.8 C232.63,213.8 232.76,214.02 232.76,214.02 C232.76,214.02 232.88,214.26 232.88,214.26 C232.88,214.26 232.99,214.5 232.99,214.5 C232.99,214.5 233.11,214.74 233.11,214.74 C233.11,214.74 233.22,214.97 233.22,214.97 C233.22,214.97 233.33,215.21 233.33,215.21 C233.33,215.21 233.43,215.46 233.43,215.46 C233.43,215.46 233.52,215.7 233.52,215.7 C233.52,215.7 233.62,215.95 233.62,215.95 C233.62,215.95 233.71,216.2 233.71,216.2 C233.71,216.2 233.8,216.45 233.8,216.45 C233.8,216.45 233.88,216.7 233.88,216.7 C233.88,216.7 233.94,216.95 233.94,216.95 C233.94,216.95 234.01,217.21 234.01,217.21 C234.01,217.21 234.08,217.46 234.08,217.46 C234.08,217.46 234.15,217.71 234.15,217.71 C234.15,217.71 234.21,217.97 234.21,217.97 C234.21,217.97 234.25,218.23 234.25,218.23 C234.25,218.23 234.3,218.49 234.3,218.49 C234.3,218.49 234.34,218.75 234.34,218.75 C234.34,218.75 234.38,219.01 234.38,219.01 C234.38,219.01 234.42,219.27 234.42,219.27 C234.42,219.27 234.44,219.53 234.44,219.53 C234.44,219.53 234.46,219.8 234.46,219.8 C234.46,219.8 234.48,220.06 234.48,220.06 C234.48,220.06 234.5,220.32 234.5,220.32 C234.5,220.32 234.52,220.58 234.52,220.58 C234.52,220.58 234.51,220.85 234.51,220.85 C234.51,220.85 234.51,221.11 234.51,221.11 C234.51,221.11 234.5,221.38 234.5,221.38 C234.5,221.38 234.5,221.64 234.5,221.64 C234.5,221.64 234.49,221.9 234.49,221.9 C234.49,221.9 234.47,222.17 234.47,222.17 C234.47,222.17 234.44,222.43 234.44,222.43 C234.44,222.43 234.41,222.69 234.41,222.69 C234.41,222.69 234.38,222.95 234.38,222.95 C234.38,222.95 234.35,223.21 234.35,223.21 C234.35,223.21 234.3,223.47 234.3,223.47 C234.3,223.47 234.25,223.73 234.25,223.73 C234.25,223.73 234.2,223.99 234.2,223.99 C234.2,223.99 234.15,224.25 234.15,224.25 C234.15,224.25 234.09,224.51 234.09,224.51 C234.09,224.51 234.02,224.76 234.02,224.76 C234.02,224.76 233.95,225.01 233.95,225.01 C233.95,225.01 233.87,225.26 233.87,225.26 C233.87,225.26 233.79,225.52 233.79,225.52 C233.79,225.52 233.72,225.77 233.72,225.77 C233.72,225.77 233.63,226.01 233.63,226.01 C233.63,226.01 233.53,226.26 233.53,226.26 C233.53,226.26 233.43,226.5 233.43,226.5 C233.43,226.5 233.33,226.75 233.33,226.75 C233.33,226.75 233.23,226.99 233.23,226.99 C233.23,226.99 233.12,227.23 233.12,227.23 C233.12,227.23 233,227.46 233,227.46 C233,227.46 232.88,227.7 232.88,227.7 C232.88,227.7 232.75,227.93 232.75,227.93 C232.75,227.93 232.63,228.17 232.63,228.17 C232.63,228.17 232.5,228.4 232.5,228.4 C232.5,228.4 232.36,228.62 232.36,228.62 C232.36,228.62 232.22,228.84 232.22,228.84 C232.22,228.84 232.07,229.06 232.07,229.06 C232.07,229.06 231.93,229.28 231.93,229.28 C231.93,229.28 231.79,229.5 231.79,229.5 C231.79,229.5 231.63,229.71 231.63,229.71 C231.63,229.71 231.46,229.92 231.46,229.92 C231.46,229.92 231.3,230.13 231.3,230.13 C231.3,230.13 231.14,230.33 231.14,230.33 C231.14,230.33 230.96,230.52 230.96,230.52 C230.96,230.52 230.78,230.72 230.78,230.72 C230.78,230.72 230.6,230.92 230.6,230.92 C230.6,230.92 230.43,231.11 230.43,231.11 C230.43,231.11 230.25,231.31 230.25,231.31 C230.25,231.31 230.05,231.49 230.05,231.49 C230.05,231.49 229.86,231.66 229.86,231.66 C229.86,231.66 229.66,231.84 229.66,231.84 C229.66,231.84 229.47,232.02 229.47,232.02 C229.47,232.02 229.27,232.19 229.27,232.19 C229.27,232.19 229.07,232.36 229.07,232.36 C229.07,232.36 228.86,232.52 228.86,232.52 C228.86,232.52 228.64,232.68 228.64,232.68 C228.64,232.68 228.43,232.83 228.43,232.83 C228.43,232.83 228.22,232.99 228.22,232.99 C228.22,232.99 228.01,233.14 228.01,233.14 C228.01,233.14 227.78,233.28 227.78,233.28 C227.78,233.28 227.56,233.42 227.56,233.42 C227.56,233.42 227.33,233.55 227.33,233.55 C227.33,233.55 227.11,233.69 227.11,233.69 C227.11,233.69 226.88,233.83 226.88,233.83 C226.88,233.83 226.64,233.94 226.64,233.94 C226.64,233.94 226.41,234.06 226.41,234.06 C226.41,234.06 226.17,234.17 226.17,234.17 C226.17,234.17 225.93,234.28 225.93,234.28 C225.93,234.28 225.69,234.4 225.69,234.4 C225.69,234.4 225.45,234.5 225.45,234.5 C225.45,234.5 225.2,234.59 225.2,234.59 C225.2,234.59 224.95,234.68 224.95,234.68 C224.95,234.68 224.71,234.77 224.71,234.77 C224.71,234.77 224.46,234.86 224.46,234.86 C224.46,234.86 224.21,234.94 224.21,234.94 C224.21,234.94 223.95,235.01 223.95,235.01 C223.95,235.01 223.7,235.08 223.7,235.08 C223.7,235.08 223.44,235.14 223.44,235.14 C223.44,235.14 223.19,235.21 223.19,235.21 C223.19,235.21 222.93,235.27 222.93,235.27 C222.93,235.27 222.67,235.31 222.67,235.31 C222.67,235.31 222.41,235.36 222.41,235.36 C222.41,235.36 222.15,235.4 222.15,235.4 C222.15,235.4 221.89,235.45 221.89,235.45 C221.89,235.45 221.63,235.48 221.63,235.48 C221.63,235.48 221.37,235.5 221.37,235.5 C221.37,235.5 221.11,235.52 221.11,235.52 C221.11,235.52 220.84,235.54 220.84,235.54 C220.84,235.54 220.58,235.56 220.58,235.56 C220.58,235.56 220.32,235.58 220.32,235.58 C220.32,235.58 220.06,235.57 220.06,235.57 C220.06,235.57 219.79,235.57 219.79,235.57 C219.79,235.57 219.53,235.57 219.53,235.57 C219.53,235.57 219.26,235.56 219.26,235.56 C219.26,235.56 219,235.56 219,235.56 C219,235.56 218.74,235.53 218.74,235.53 C218.74,235.53 218.48,235.5 218.48,235.5 C218.48,235.5 218.22,235.47 218.22,235.47 C218.22,235.47 217.95,235.44 217.95,235.44 C217.95,235.44 217.69,235.41 217.69,235.41 C217.69,235.41 217.43,235.36 217.43,235.36 C217.43,235.36 217.17,235.31 217.17,235.31 C217.17,235.31 216.92,235.26 216.92,235.26 C216.92,235.26 216.66,235.21 216.66,235.21 C216.66,235.21 216.4,235.15 216.4,235.15 C216.4,235.15 216.15,235.08 216.15,235.08 C216.15,235.08 215.89,235.01 215.89,235.01 C215.89,235.01 215.64,234.93 215.64,234.93 C215.64,234.93 215.39,234.85 215.39,234.85 C215.39,234.85 215.14,234.78 215.14,234.78 C215.14,234.78 214.89,234.69 214.89,234.69 C214.89,234.69 214.65,234.59 214.65,234.59 C214.65,234.59 214.4,234.49 214.4,234.49 C214.4,234.49 214.16,234.39 214.16,234.39 C214.16,234.39 213.91,234.29 213.91,234.29 C213.91,234.29 213.67,234.18 213.67,234.18 C213.67,234.18 213.44,234.06 213.44,234.06 C213.44,234.06 213.21,233.94 213.21,233.94 C213.21,233.94 212.97,233.81 212.97,233.81 C212.97,233.81 212.74,233.69 212.74,233.69 C212.74,233.69 212.51,233.56 212.51,233.56 C212.51,233.56 212.29,233.42 212.29,233.42 C212.29,233.42 212.07,233.28 212.07,233.28 C212.07,233.28 211.85,233.13 211.85,233.13 C211.85,233.13 211.63,232.99 211.63,232.99 C211.63,232.99 211.4,232.85 211.4,232.85 C211.4,232.85 211.2,232.69 211.2,232.69 C211.2,232.69 210.99,232.52 210.99,232.52 C210.99,232.52 210.78,232.36 210.78,232.36 C210.78,232.36 210.58,232.2 210.58,232.2 C210.58,232.2 210.38,232.02 210.38,232.02 C210.38,232.02 210.18,231.84 210.18,231.84 C210.18,231.84 209.99,231.66 209.99,231.66 C209.99,231.66 209.79,231.49 209.79,231.49 C209.79,231.49 209.6,231.31 209.6,231.31 C209.6,231.31 209.41,231.12 209.41,231.12 C209.41,231.12 209.23,230.94 209.23,230.94 C209.23,230.94 209.04,230.75 209.04,230.75 C209.04,230.75 208.85,230.56 208.85,230.56 C208.85,230.56 208.67,230.38 208.67,230.38 C208.67,230.38 208.48,230.19 208.48,230.19 C208.48,230.19 208.29,230.01 208.29,230.01 C208.29,230.01 208.11,229.82 208.11,229.82 C208.11,229.82 207.92,229.63 207.92,229.63 C207.92,229.63 207.74,229.45 207.74,229.45 C207.74,229.45 207.55,229.26 207.55,229.26 C207.55,229.26 207.36,229.07 207.36,229.07 C207.36,229.07 207.18,228.89 207.18,228.89 C207.18,228.89 206.99,228.7 206.99,228.7 C206.99,228.7 206.8,228.51 206.8,228.51 C206.8,228.51 206.62,228.33 206.62,228.33 C206.62,228.33 206.43,228.14 206.43,228.14 C206.43,228.14 206.24,227.96 206.24,227.96 C206.24,227.96 206.06,227.77 206.06,227.77 C206.06,227.77 205.87,227.58 205.87,227.58 C205.87,227.58 205.69,227.4 205.69,227.4 C205.69,227.4 205.5,227.21 205.5,227.21 C205.5,227.21 205.31,227.02 205.31,227.02 C205.31,227.02 205.13,226.84 205.13,226.84 C205.13,226.84 204.94,226.65 204.94,226.65 C204.94,226.65 204.75,226.46 204.75,226.46 C204.75,226.46 204.58,226.27 204.58,226.27 C204.58,226.27 204.4,226.07 204.4,226.07 C204.4,226.07 204.22,225.88 204.22,225.88 C204.22,225.88 204.05,225.68 204.05,225.68 C204.05,225.68 203.87,225.49 203.87,225.49 C203.87,225.49 203.7,225.28 203.7,225.28 C203.7,225.28 203.54,225.07 203.54,225.07 C203.54,225.07 203.39,224.86 203.39,224.86 C203.39,224.86 203.23,224.65 203.23,224.65 C203.23,224.65 203.07,224.44 203.07,224.44 C203.07,224.44 202.92,224.22 202.92,224.22 C202.92,224.22 202.78,224 202.78,224 C202.78,224 202.65,223.77 202.65,223.77 C202.65,223.77 202.51,223.55 202.51,223.55 C202.51,223.55 202.37,223.32 202.37,223.32 C202.37,223.32 202.24,223.1 202.24,223.1 C202.24,223.1 202.12,222.86 202.12,222.86 C202.12,222.86 202.01,222.62 202.01,222.62 C202.01,222.62 201.89,222.39 201.89,222.39 C201.89,222.39 201.78,222.15 201.78,222.15 C201.78,222.15 201.67,221.91 201.67,221.91 C201.67,221.91 201.57,221.67 201.57,221.67 C201.57,221.67 201.48,221.42 201.48,221.42 C201.48,221.42 201.38,221.17 201.38,221.17 C201.38,221.17 201.29,220.92 201.29,220.92 C201.29,220.92 201.2,220.68 201.2,220.68 C201.2,220.68 201.12,220.43 201.12,220.43 C201.12,220.43 201.06,220.17 201.06,220.17 C201.06,220.17 200.99,219.92 200.99,219.92 C200.99,219.92 200.92,219.66 200.92,219.66 C200.92,219.66 200.85,219.41 200.85,219.41 C200.85,219.41 200.79,219.15 200.79,219.15 C200.79,219.15 200.75,218.89 200.75,218.89 C200.75,218.89 200.71,218.63 200.71,218.63 C200.71,218.63 200.66,218.37 200.66,218.37 C200.66,218.37 200.62,218.11 200.62,218.11 C200.62,218.11 200.58,217.85 200.58,217.85 C200.58,217.85 200.56,217.59 200.56,217.59 C200.56,217.59 200.54,217.32 200.54,217.32 C200.54,217.32 200.52,217.06 200.52,217.06 C200.52,217.06 200.5,216.8 200.5,216.8 C200.5,216.8 200.48,216.54 200.48,216.54 C200.48,216.54 200.49,216.27 200.49,216.27 C200.49,216.27 200.49,216.01 200.49,216.01 C200.49,216.01 200.5,215.75 200.5,215.75 C200.5,215.75 200.5,215.48 200.5,215.48 C200.5,215.48 200.51,215.22 200.51,215.22 C200.51,215.22 200.53,214.96 200.53,214.96 C200.53,214.96 200.56,214.69 200.56,214.69 C200.56,214.69 200.59,214.43 200.59,214.43 C200.59,214.43 200.62,214.17 200.62,214.17 C200.62,214.17 200.65,213.91 200.65,213.91 C200.65,213.91 200.7,213.65 200.7,213.65 C200.7,213.65 200.75,213.39 200.75,213.39 C200.75,213.39 200.8,213.13 200.8,213.13 C200.8,213.13 200.86,212.88 200.86,212.88 C200.86,212.88 200.91,212.62 200.91,212.62 C200.91,212.62 200.98,212.36 200.98,212.36 C200.98,212.36 201.06,212.11 201.06,212.11 C201.06,212.11 201.13,211.86 201.13,211.86 C201.13,211.86 201.21,211.61 201.21,211.61 C201.21,211.61 201.28,211.35 201.28,211.35 C201.28,211.35 201.38,211.11 201.38,211.11 C201.38,211.11 201.47,210.86 201.47,210.86 C201.47,210.86 201.57,210.62 201.57,210.62 C201.57,210.62 201.67,210.37 201.67,210.37 C201.67,210.37 201.77,210.13 201.77,210.13 C201.77,210.13 201.88,209.89 201.88,209.89 C201.88,209.89 202,209.66 202,209.66 C202,209.66 202.13,209.42 202.13,209.42 C202.13,209.42 202.25,209.19 202.25,209.19 C202.25,209.19 202.37,208.96 202.37,208.96 C202.37,208.96 202.5,208.73 202.5,208.73 C202.5,208.73 202.64,208.51 202.64,208.51 C202.64,208.51 202.79,208.28 202.79,208.28 C202.79,208.28 202.93,208.06 202.93,208.06 C202.93,208.06 203.07,207.84 203.07,207.84 C203.07,207.84 203.22,207.62 203.22,207.62 C203.22,207.62 203.38,207.41 203.38,207.41 C203.38,207.41 203.54,207.2 203.54,207.2 C203.54,207.2 203.7,207 203.7,207 C203.7,207 203.87,206.79 203.87,206.79 C203.87,206.79 204.04,206.6 204.04,206.6 C204.04,206.6 204.22,206.4 204.22,206.4 C204.22,206.4 204.4,206.21 204.4,206.21 C204.4,206.21 204.57,206.01 204.57,206.01 C204.57,206.01 204.75,205.82 204.75,205.82 C204.75,205.82 204.95,205.64 204.95,205.64 C204.95,205.64 205.14,205.46 205.14,205.46 C205.14,205.46 205.34,205.29 205.34,205.29 C205.34,205.29 205.53,205.11 205.53,205.11 C205.53,205.11 205.73,204.93 205.73,204.93 C205.73,204.93 205.93,204.76 205.93,204.76 C205.93,204.76 206.14,204.61 206.14,204.61 C206.14,204.61 206.35,204.45 206.35,204.45 C206.35,204.45 206.57,204.29 206.57,204.29 C206.57,204.29 206.78,204.13 206.78,204.13 C206.78,204.13 206.99,203.98 206.99,203.98 C206.99,203.98 207.22,203.85 207.22,203.85 C207.22,203.85 207.44,203.71 207.44,203.71 C207.44,203.71 207.67,203.57 207.67,203.57 C207.67,203.57 207.89,203.44 207.89,203.44 C207.89,203.44 208.12,203.3 208.12,203.3 C208.12,203.3 208.36,203.18 208.36,203.18 C208.36,203.18 208.59,203.07 208.59,203.07 C208.59,203.07 208.83,202.96 208.83,202.96 C208.83,202.96 209.07,202.84 209.07,202.84 C209.07,202.84 209.31,202.73 209.31,202.73 C209.31,202.73 209.55,202.63 209.55,202.63 C209.55,202.63 209.8,202.54 209.8,202.54 C209.8,202.54 210.04,202.45 210.04,202.45 C210.04,202.45 210.29,202.36 210.29,202.36 C210.29,202.36 210.54,202.26 210.54,202.26 C210.54,202.26 210.79,202.19 210.79,202.19 C210.79,202.19 211.05,202.12 211.05,202.12 C211.05,202.12 211.3,202.05 211.3,202.05 C211.3,202.05 211.55,201.98 211.55,201.98 C211.55,201.98 211.81,201.91 211.81,201.91 C211.81,201.91 212.07,201.86 212.07,201.86 C212.07,201.86 212.33,201.81 212.33,201.81 C212.33,201.81 212.59,201.77 212.59,201.77 C212.59,201.77 212.85,201.72 212.85,201.72 C212.85,201.72 213.11,201.68 213.11,201.68 C213.11,201.68 213.37,201.64 213.37,201.64 C213.37,201.64 213.63,201.62 213.63,201.62 C213.63,201.62 213.89,201.6 213.89,201.6 C213.89,201.6 214.15,201.58 214.15,201.58 C214.15,201.58 214.42,201.56 214.42,201.56 C214.42,201.56 214.68,201.55 214.68,201.55 C214.68,201.55 214.94,201.55 214.94,201.55 C214.94,201.55 215.21,201.55 215.21,201.55 C215.21,201.55 215.47,201.56 215.47,201.56 C215.47,201.56 215.73,201.56 215.73,201.56 C215.73,201.56 216,201.57 216,201.57 C216,201.57 216.26,201.6 216.26,201.6 C216.26,201.6 216.52,201.62 216.52,201.62 C216.52,201.62 216.78,201.65 216.78,201.65 C216.78,201.65 217.05,201.68 217.05,201.68 C217.05,201.68 217.31,201.71 217.31,201.71 C217.31,201.71 217.57,201.76 217.57,201.76c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.57 201.76 C217.57,201.76 217.82,201.81 217.82,201.81 C217.82,201.81 218.08,201.86 218.08,201.86 C218.08,201.86 218.34,201.92 218.34,201.92 C218.34,201.92 218.6,201.97 218.6,201.97 C218.6,201.97 218.85,202.04 218.85,202.04 C218.85,202.04 219.11,202.12 219.11,202.12 C219.11,202.12 219.36,202.19 219.36,202.19 C219.36,202.19 219.61,202.27 219.61,202.27 C219.61,202.27 219.86,202.34 219.86,202.34 C219.86,202.34 220.11,202.44 220.11,202.44 C220.11,202.44 220.35,202.54 220.35,202.54 C220.35,202.54 220.6,202.64 220.6,202.64 C220.6,202.64 220.84,202.73 220.84,202.73 C220.84,202.73 221.09,202.83 221.09,202.83 C221.09,202.83 221.32,202.94 221.32,202.94 C221.32,202.94 221.56,203.07 221.56,203.07 C221.56,203.07 221.79,203.19 221.79,203.19 C221.79,203.19 222.03,203.31 222.03,203.31 C222.03,203.31 222.26,203.43 222.26,203.43 C222.26,203.43 222.49,203.56 222.49,203.56 C222.49,203.56 222.71,203.7 222.71,203.7 C222.71,203.7 222.93,203.85 222.93,203.85 C222.93,203.85 223.15,203.99 223.15,203.99 C223.15,203.99 223.37,204.13 223.37,204.13 C223.37,204.13 223.59,204.28 223.59,204.28 C223.59,204.28 223.8,204.44 223.8,204.44 C223.8,204.44 224.01,204.6 224.01,204.6 C224.01,204.6 224.22,204.76 224.22,204.76 C224.22,204.76 224.42,204.93 224.42,204.93 C224.42,204.93 224.62,205.1 224.62,205.1 C224.62,205.1 224.81,205.28 224.81,205.28 C224.81,205.28 225.01,205.46 225.01,205.46 C225.01,205.46 225.2,205.64 225.2,205.64 C225.2,205.64 225.4,205.81 225.4,205.81 C225.4,205.81 225.59,206 225.59,206 C225.59,206 225.77,206.19 225.77,206.19 C225.77,206.19 225.96,206.37 225.96,206.37 C225.96,206.37 226.15,206.56 226.15,206.56 C226.15,206.56 226.33,206.74 226.33,206.74 C226.33,206.74 226.52,206.93 226.52,206.93 C226.52,206.93 226.7,207.12 226.7,207.12 C226.7,207.12 226.89,207.3 226.89,207.3 C226.89,207.3 227.08,207.49 227.08,207.49 C227.08,207.49 227.26,207.68 227.26,207.68 C227.26,207.68 227.45,207.86 227.45,207.86 C227.45,207.86 227.64,208.05 227.64,208.05 C227.64,208.05 227.82,208.24 227.82,208.24 C227.82,208.24 228.01,208.42 228.01,208.42 C228.01,208.42 228.2,208.61 228.2,208.61 C228.2,208.61 228.38,208.79 228.38,208.79 C228.38,208.79 228.57,208.98 228.57,208.98 C228.57,208.98 228.75,209.17 228.75,209.17 C228.75,209.17 228.94,209.35 228.94,209.35 C228.94,209.35 229.13,209.54 229.13,209.54 C229.13,209.54 229.31,209.73 229.31,209.73 C229.31,209.73 229.5,209.91 229.5,209.91 C229.5,209.91 229.69,210.1 229.69,210.1 C229.69,210.1 229.87,210.29 229.87,210.29 C229.87,210.29 230.06,210.47 230.06,210.47 C230.06,210.47 230.25,210.66 230.25,210.66 C230.25,210.66 230.42,210.85 230.42,210.85 C230.42,210.85 230.6,211.05 230.6,211.05 C230.6,211.05 230.78,211.24 230.78,211.24 C230.78,211.24 230.95,211.44 230.95,211.44 C230.95,211.44 231.13,211.63 231.13,211.63 C231.13,211.63 231.3,211.84 231.3,211.84 C231.3,211.84 231.45,212.05 231.45,212.05 C231.45,212.05 231.61,212.26 231.61,212.26 C231.61,212.26 231.77,212.47 231.77,212.47 C231.77,212.47 231.93,212.68 231.93,212.68 C231.93,212.68 232.08,212.9 232.08,212.9 C232.08,212.9 232.22,213.12 232.22,213.12 C232.22,213.12 232.35,213.35 232.35,213.35 C232.35,213.35 232.49,213.57 232.49,213.57 C232.49,213.57 232.63,213.8 232.63,213.8 C232.63,213.8 232.76,214.02 232.76,214.02 C232.76,214.02 232.88,214.26 232.88,214.26 C232.88,214.26 232.99,214.5 232.99,214.5 C232.99,214.5 233.11,214.74 233.11,214.74 C233.11,214.74 233.22,214.97 233.22,214.97 C233.22,214.97 233.33,215.21 233.33,215.21 C233.33,215.21 233.43,215.46 233.43,215.46 C233.43,215.46 233.52,215.7 233.52,215.7 C233.52,215.7 233.62,215.95 233.62,215.95 C233.62,215.95 233.71,216.2 233.71,216.2 C233.71,216.2 233.8,216.45 233.8,216.45 C233.8,216.45 233.88,216.7 233.88,216.7 C233.88,216.7 233.94,216.95 233.94,216.95 C233.94,216.95 234.01,217.21 234.01,217.21 C234.01,217.21 234.08,217.46 234.08,217.46 C234.08,217.46 234.15,217.71 234.15,217.71 C234.15,217.71 234.21,217.97 234.21,217.97 C234.21,217.97 234.25,218.23 234.25,218.23 C234.25,218.23 234.3,218.49 234.3,218.49 C234.3,218.49 234.34,218.75 234.34,218.75 C234.34,218.75 234.38,219.01 234.38,219.01 C234.38,219.01 234.42,219.27 234.42,219.27 C234.42,219.27 234.44,219.53 234.44,219.53 C234.44,219.53 234.46,219.8 234.46,219.8 C234.46,219.8 234.48,220.06 234.48,220.06 C234.48,220.06 234.5,220.32 234.5,220.32 C234.5,220.32 234.52,220.58 234.52,220.58 C234.52,220.58 234.51,220.85 234.51,220.85 C234.51,220.85 234.51,221.11 234.51,221.11 C234.51,221.11 234.5,221.38 234.5,221.38 C234.5,221.38 234.5,221.64 234.5,221.64 C234.5,221.64 234.49,221.9 234.49,221.9 C234.49,221.9 234.47,222.17 234.47,222.17 C234.47,222.17 234.44,222.43 234.44,222.43 C234.44,222.43 234.41,222.69 234.41,222.69 C234.41,222.69 234.38,222.95 234.38,222.95 C234.38,222.95 234.35,223.21 234.35,223.21 C234.35,223.21 234.3,223.47 234.3,223.47 C234.3,223.47 234.25,223.73 234.25,223.73 C234.25,223.73 234.2,223.99 234.2,223.99 C234.2,223.99 234.15,224.25 234.15,224.25 C234.15,224.25 234.09,224.51 234.09,224.51 C234.09,224.51 234.02,224.76 234.02,224.76 C234.02,224.76 233.95,225.01 233.95,225.01 C233.95,225.01 233.87,225.26 233.87,225.26 C233.87,225.26 233.79,225.52 233.79,225.52 C233.79,225.52 233.72,225.77 233.72,225.77 C233.72,225.77 233.63,226.01 233.63,226.01 C233.63,226.01 233.53,226.26 233.53,226.26 C233.53,226.26 233.43,226.5 233.43,226.5 C233.43,226.5 233.33,226.75 233.33,226.75 C233.33,226.75 233.23,226.99 233.23,226.99 C233.23,226.99 233.12,227.23 233.12,227.23 C233.12,227.23 233,227.46 233,227.46 C233,227.46 232.88,227.7 232.88,227.7 C232.88,227.7 232.75,227.93 232.75,227.93 C232.75,227.93 232.63,228.17 232.63,228.17 C232.63,228.17 232.5,228.4 232.5,228.4 C232.5,228.4 232.36,228.62 232.36,228.62 C232.36,228.62 232.22,228.84 232.22,228.84 C232.22,228.84 232.07,229.06 232.07,229.06 C232.07,229.06 231.93,229.28 231.93,229.28 C231.93,229.28 231.79,229.5 231.79,229.5 C231.79,229.5 231.63,229.71 231.63,229.71 C231.63,229.71 231.46,229.92 231.46,229.92 C231.46,229.92 231.3,230.13 231.3,230.13 C231.3,230.13 231.14,230.33 231.14,230.33 C231.14,230.33 230.96,230.52 230.96,230.52 C230.96,230.52 230.78,230.72 230.78,230.72 C230.78,230.72 230.6,230.92 230.6,230.92 C230.6,230.92 230.43,231.11 230.43,231.11 C230.43,231.11 230.25,231.31 230.25,231.31 C230.25,231.31 230.05,231.49 230.05,231.49 C230.05,231.49 229.86,231.66 229.86,231.66 C229.86,231.66 229.66,231.84 229.66,231.84 C229.66,231.84 229.47,232.02 229.47,232.02 C229.47,232.02 229.27,232.19 229.27,232.19 C229.27,232.19 229.07,232.36 229.07,232.36 C229.07,232.36 228.86,232.52 228.86,232.52 C228.86,232.52 228.64,232.68 228.64,232.68 C228.64,232.68 228.43,232.83 228.43,232.83 C228.43,232.83 228.22,232.99 228.22,232.99 C228.22,232.99 228.01,233.14 228.01,233.14 C228.01,233.14 227.78,233.28 227.78,233.28 C227.78,233.28 227.56,233.42 227.56,233.42 C227.56,233.42 227.33,233.55 227.33,233.55 C227.33,233.55 227.11,233.69 227.11,233.69 C227.11,233.69 226.88,233.83 226.88,233.83 C226.88,233.83 226.64,233.94 226.64,233.94 C226.64,233.94 226.41,234.06 226.41,234.06 C226.41,234.06 226.17,234.17 226.17,234.17 C226.17,234.17 225.93,234.28 225.93,234.28 C225.93,234.28 225.69,234.4 225.69,234.4 C225.69,234.4 225.45,234.5 225.45,234.5 C225.45,234.5 225.2,234.59 225.2,234.59 C225.2,234.59 224.95,234.68 224.95,234.68 C224.95,234.68 224.71,234.77 224.71,234.77 C224.71,234.77 224.46,234.86 224.46,234.86 C224.46,234.86 224.21,234.94 224.21,234.94 C224.21,234.94 223.95,235.01 223.95,235.01 C223.95,235.01 223.7,235.08 223.7,235.08 C223.7,235.08 223.44,235.14 223.44,235.14 C223.44,235.14 223.19,235.21 223.19,235.21 C223.19,235.21 222.93,235.27 222.93,235.27 C222.93,235.27 222.67,235.31 222.67,235.31 C222.67,235.31 222.41,235.36 222.41,235.36 C222.41,235.36 222.15,235.4 222.15,235.4 C222.15,235.4 221.89,235.45 221.89,235.45 C221.89,235.45 221.63,235.48 221.63,235.48 C221.63,235.48 221.37,235.5 221.37,235.5 C221.37,235.5 221.11,235.52 221.11,235.52 C221.11,235.52 220.84,235.54 220.84,235.54 C220.84,235.54 220.58,235.56 220.58,235.56 C220.58,235.56 220.32,235.58 220.32,235.58 C220.32,235.58 220.06,235.57 220.06,235.57 C220.06,235.57 219.79,235.57 219.79,235.57 C219.79,235.57 219.53,235.57 219.53,235.57 C219.53,235.57 219.26,235.56 219.26,235.56 C219.26,235.56 219,235.56 219,235.56 C219,235.56 218.74,235.53 218.74,235.53 C218.74,235.53 218.48,235.5 218.48,235.5 C218.48,235.5 218.22,235.47 218.22,235.47 C218.22,235.47 217.95,235.44 217.95,235.44 C217.95,235.44 217.69,235.41 217.69,235.41 C217.69,235.41 217.43,235.36 217.43,235.36 C217.43,235.36 217.17,235.31 217.17,235.31 C217.17,235.31 216.92,235.26 216.92,235.26 C216.92,235.26 216.66,235.21 216.66,235.21 C216.66,235.21 216.4,235.15 216.4,235.15 C216.4,235.15 216.15,235.08 216.15,235.08 C216.15,235.08 215.89,235.01 215.89,235.01 C215.89,235.01 215.64,234.93 215.64,234.93 C215.64,234.93 215.39,234.85 215.39,234.85 C215.39,234.85 215.14,234.78 215.14,234.78 C215.14,234.78 214.89,234.69 214.89,234.69 C214.89,234.69 214.65,234.59 214.65,234.59 C214.65,234.59 214.4,234.49 214.4,234.49 C214.4,234.49 214.16,234.39 214.16,234.39 C214.16,234.39 213.91,234.29 213.91,234.29 C213.91,234.29 213.67,234.18 213.67,234.18 C213.67,234.18 213.44,234.06 213.44,234.06 C213.44,234.06 213.21,233.94 213.21,233.94 C213.21,233.94 212.97,233.81 212.97,233.81 C212.97,233.81 212.74,233.69 212.74,233.69 C212.74,233.69 212.51,233.56 212.51,233.56 C212.51,233.56 212.29,233.42 212.29,233.42 C212.29,233.42 212.07,233.28 212.07,233.28 C212.07,233.28 211.85,233.13 211.85,233.13 C211.85,233.13 211.63,232.99 211.63,232.99 C211.63,232.99 211.4,232.85 211.4,232.85 C211.4,232.85 211.2,232.69 211.2,232.69 C211.2,232.69 210.99,232.52 210.99,232.52 C210.99,232.52 210.78,232.36 210.78,232.36 C210.78,232.36 210.58,232.2 210.58,232.2 C210.58,232.2 210.38,232.02 210.38,232.02 C210.38,232.02 210.18,231.84 210.18,231.84 C210.18,231.84 209.99,231.66 209.99,231.66 C209.99,231.66 209.79,231.49 209.79,231.49 C209.79,231.49 209.6,231.31 209.6,231.31 C209.6,231.31 209.41,231.12 209.41,231.12 C209.41,231.12 209.23,230.94 209.23,230.94 C209.23,230.94 209.04,230.75 209.04,230.75 C209.04,230.75 208.85,230.56 208.85,230.56 C208.85,230.56 208.67,230.38 208.67,230.38 C208.67,230.38 208.48,230.19 208.48,230.19 C208.48,230.19 208.29,230.01 208.29,230.01 C208.29,230.01 208.11,229.82 208.11,229.82 C208.11,229.82 207.92,229.63 207.92,229.63 C207.92,229.63 207.74,229.45 207.74,229.45 C207.74,229.45 207.55,229.26 207.55,229.26 C207.55,229.26 207.36,229.07 207.36,229.07 C207.36,229.07 207.18,228.89 207.18,228.89 C207.18,228.89 206.99,228.7 206.99,228.7 C206.99,228.7 206.8,228.51 206.8,228.51 C206.8,228.51 206.62,228.33 206.62,228.33 C206.62,228.33 206.43,228.14 206.43,228.14 C206.43,228.14 206.24,227.96 206.24,227.96 C206.24,227.96 206.06,227.77 206.06,227.77 C206.06,227.77 205.87,227.58 205.87,227.58 C205.87,227.58 205.69,227.4 205.69,227.4 C205.69,227.4 205.5,227.21 205.5,227.21 C205.5,227.21 205.31,227.02 205.31,227.02 C205.31,227.02 205.13,226.84 205.13,226.84 C205.13,226.84 204.94,226.65 204.94,226.65 C204.94,226.65 204.75,226.46 204.75,226.46 C204.75,226.46 204.58,226.27 204.58,226.27 C204.58,226.27 204.4,226.07 204.4,226.07 C204.4,226.07 204.22,225.88 204.22,225.88 C204.22,225.88 204.05,225.68 204.05,225.68 C204.05,225.68 203.87,225.49 203.87,225.49 C203.87,225.49 203.7,225.28 203.7,225.28 C203.7,225.28 203.54,225.07 203.54,225.07 C203.54,225.07 203.39,224.86 203.39,224.86 C203.39,224.86 203.23,224.65 203.23,224.65 C203.23,224.65 203.07,224.44 203.07,224.44 C203.07,224.44 202.92,224.22 202.92,224.22 C202.92,224.22 202.78,224 202.78,224 C202.78,224 202.65,223.77 202.65,223.77 C202.65,223.77 202.51,223.55 202.51,223.55 C202.51,223.55 202.37,223.32 202.37,223.32 C202.37,223.32 202.24,223.1 202.24,223.1 C202.24,223.1 202.12,222.86 202.12,222.86 C202.12,222.86 202.01,222.62 202.01,222.62 C202.01,222.62 201.89,222.39 201.89,222.39 C201.89,222.39 201.78,222.15 201.78,222.15 C201.78,222.15 201.67,221.91 201.67,221.91 C201.67,221.91 201.57,221.67 201.57,221.67 C201.57,221.67 201.48,221.42 201.48,221.42 C201.48,221.42 201.38,221.17 201.38,221.17 C201.38,221.17 201.29,220.92 201.29,220.92 C201.29,220.92 201.2,220.68 201.2,220.68 C201.2,220.68 201.12,220.43 201.12,220.43 C201.12,220.43 201.06,220.17 201.06,220.17 C201.06,220.17 200.99,219.92 200.99,219.92 C200.99,219.92 200.92,219.66 200.92,219.66 C200.92,219.66 200.85,219.41 200.85,219.41 C200.85,219.41 200.79,219.15 200.79,219.15 C200.79,219.15 200.75,218.89 200.75,218.89 C200.75,218.89 200.71,218.63 200.71,218.63 C200.71,218.63 200.66,218.37 200.66,218.37 C200.66,218.37 200.62,218.11 200.62,218.11 C200.62,218.11 200.58,217.85 200.58,217.85 C200.58,217.85 200.56,217.59 200.56,217.59 C200.56,217.59 200.54,217.32 200.54,217.32 C200.54,217.32 200.52,217.06 200.52,217.06 C200.52,217.06 200.5,216.8 200.5,216.8 C200.5,216.8 200.48,216.54 200.48,216.54 C200.48,216.54 200.49,216.27 200.49,216.27 C200.49,216.27 200.49,216.01 200.49,216.01 C200.49,216.01 200.5,215.75 200.5,215.75 C200.5,215.75 200.5,215.48 200.5,215.48 C200.5,215.48 200.51,215.22 200.51,215.22 C200.51,215.22 200.53,214.96 200.53,214.96 C200.53,214.96 200.56,214.69 200.56,214.69 C200.56,214.69 200.59,214.43 200.59,214.43 C200.59,214.43 200.62,214.17 200.62,214.17 C200.62,214.17 200.65,213.91 200.65,213.91 C200.65,213.91 200.7,213.65 200.7,213.65 C200.7,213.65 200.75,213.39 200.75,213.39 C200.75,213.39 200.8,213.13 200.8,213.13 C200.8,213.13 200.86,212.88 200.86,212.88 C200.86,212.88 200.91,212.62 200.91,212.62 C200.91,212.62 200.98,212.36 200.98,212.36 C200.98,212.36 201.06,212.11 201.06,212.11 C201.06,212.11 201.13,211.86 201.13,211.86 C201.13,211.86 201.21,211.61 201.21,211.61 C201.21,211.61 201.28,211.35 201.28,211.35 C201.28,211.35 201.38,211.11 201.38,211.11 C201.38,211.11 201.47,210.86 201.47,210.86 C201.47,210.86 201.57,210.62 201.57,210.62 C201.57,210.62 201.67,210.37 201.67,210.37 C201.67,210.37 201.77,210.13 201.77,210.13 C201.77,210.13 201.88,209.89 201.88,209.89 C201.88,209.89 202,209.66 202,209.66 C202,209.66 202.13,209.42 202.13,209.42 C202.13,209.42 202.25,209.19 202.25,209.19 C202.25,209.19 202.37,208.96 202.37,208.96 C202.37,208.96 202.5,208.73 202.5,208.73 C202.5,208.73 202.64,208.51 202.64,208.51 C202.64,208.51 202.79,208.28 202.79,208.28 C202.79,208.28 202.93,208.06 202.93,208.06 C202.93,208.06 203.07,207.84 203.07,207.84 C203.07,207.84 203.22,207.62 203.22,207.62 C203.22,207.62 203.38,207.41 203.38,207.41 C203.38,207.41 203.54,207.2 203.54,207.2 C203.54,207.2 203.7,207 203.7,207 C203.7,207 203.87,206.79 203.87,206.79 C203.87,206.79 204.04,206.6 204.04,206.6 C204.04,206.6 204.22,206.4 204.22,206.4 C204.22,206.4 204.4,206.21 204.4,206.21 C204.4,206.21 204.57,206.01 204.57,206.01 C204.57,206.01 204.75,205.82 204.75,205.82 C204.75,205.82 204.95,205.64 204.95,205.64 C204.95,205.64 205.14,205.46 205.14,205.46 C205.14,205.46 205.34,205.29 205.34,205.29 C205.34,205.29 205.53,205.11 205.53,205.11 C205.53,205.11 205.73,204.93 205.73,204.93 C205.73,204.93 205.93,204.76 205.93,204.76 C205.93,204.76 206.14,204.61 206.14,204.61 C206.14,204.61 206.35,204.45 206.35,204.45 C206.35,204.45 206.57,204.29 206.57,204.29 C206.57,204.29 206.78,204.13 206.78,204.13 C206.78,204.13 206.99,203.98 206.99,203.98 C206.99,203.98 207.22,203.85 207.22,203.85 C207.22,203.85 207.44,203.71 207.44,203.71 C207.44,203.71 207.67,203.57 207.67,203.57 C207.67,203.57 207.89,203.44 207.89,203.44 C207.89,203.44 208.12,203.3 208.12,203.3 C208.12,203.3 208.36,203.18 208.36,203.18 C208.36,203.18 208.59,203.07 208.59,203.07 C208.59,203.07 208.83,202.96 208.83,202.96 C208.83,202.96 209.07,202.84 209.07,202.84 C209.07,202.84 209.31,202.73 209.31,202.73 C209.31,202.73 209.55,202.63 209.55,202.63 C209.55,202.63 209.8,202.54 209.8,202.54 C209.8,202.54 210.04,202.45 210.04,202.45 C210.04,202.45 210.29,202.36 210.29,202.36 C210.29,202.36 210.54,202.26 210.54,202.26 C210.54,202.26 210.79,202.19 210.79,202.19 C210.79,202.19 211.05,202.12 211.05,202.12 C211.05,202.12 211.3,202.05 211.3,202.05 C211.3,202.05 211.55,201.98 211.55,201.98 C211.55,201.98 211.81,201.91 211.81,201.91 C211.81,201.91 212.07,201.86 212.07,201.86 C212.07,201.86 212.33,201.81 212.33,201.81 C212.33,201.81 212.59,201.77 212.59,201.77 C212.59,201.77 212.85,201.72 212.85,201.72 C212.85,201.72 213.11,201.68 213.11,201.68 C213.11,201.68 213.37,201.64 213.37,201.64 C213.37,201.64 213.63,201.62 213.63,201.62 C213.63,201.62 213.89,201.6 213.89,201.6 C213.89,201.6 214.15,201.58 214.15,201.58 C214.15,201.58 214.42,201.56 214.42,201.56 C214.42,201.56 214.68,201.55 214.68,201.55 C214.68,201.55 214.94,201.55 214.94,201.55 C214.94,201.55 215.21,201.55 215.21,201.55 C215.21,201.55 215.47,201.56 215.47,201.56 C215.47,201.56 215.73,201.56 215.73,201.56 C215.73,201.56 216,201.57 216,201.57 C216,201.57 216.26,201.6 216.26,201.6 C216.26,201.6 216.52,201.62 216.52,201.62 C216.52,201.62 216.78,201.65 216.78,201.65 C216.78,201.65 217.05,201.68 217.05,201.68 C217.05,201.68 217.31,201.71 217.31,201.71 C217.31,201.71 217.57,201.76 217.57,201.76c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml
new file mode 100644
index 0000000..76ee65b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml
@@ -0,0 +1 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.78 201.58 C217.78,201.58 218.07,201.62 218.07,201.62 C218.07,201.62 218.35,201.69 218.35,201.69 C218.35,201.69 218.63,201.78 218.63,201.78 C218.63,201.78 218.89,201.9 218.89,201.9 C218.89,201.9 219.14,202.04 219.14,202.04 C219.14,202.04 219.38,202.21 219.38,202.21 C219.38,202.21 219.59,202.41 219.59,202.41 C219.59,202.41 219.78,202.62 219.78,202.62 C219.78,202.62 219.95,202.86 219.95,202.86 C219.95,202.86 220.11,203.1 220.11,203.1 C220.11,203.1 220.26,203.35 220.26,203.35 C220.26,203.35 220.41,203.6 220.41,203.6 C220.41,203.6 220.55,203.85 220.55,203.85 C220.55,203.85 220.7,204.1 220.7,204.1 C220.7,204.1 220.85,204.35 220.85,204.35 C220.85,204.35 221,204.59 221,204.59 C221,204.59 221.15,204.84 221.15,204.84 C221.15,204.84 221.3,205.09 221.3,205.09 C221.3,205.09 221.46,205.33 221.46,205.33 C221.46,205.33 221.65,205.55 221.65,205.55 C221.65,205.55 221.86,205.75 221.86,205.75 C221.86,205.75 222.09,205.93 222.09,205.93 C222.09,205.93 222.33,206.09 222.33,206.09 C222.33,206.09 222.59,206.22 222.59,206.22 C222.59,206.22 222.86,206.32 222.86,206.32 C222.86,206.32 223.14,206.4 223.14,206.4 C223.14,206.4 223.42,206.45 223.42,206.45 C223.42,206.45 223.71,206.46 223.71,206.46 C223.71,206.46 224,206.45 224,206.45 C224,206.45 224.29,206.41 224.29,206.41 C224.29,206.41 224.57,206.35 224.57,206.35 C224.57,206.35 224.85,206.28 224.85,206.28 C224.85,206.28 225.13,206.21 225.13,206.21 C225.13,206.21 225.41,206.14 225.41,206.14 C225.41,206.14 225.7,206.07 225.7,206.07 C225.7,206.07 225.98,206 225.98,206 C225.98,206 226.26,205.93 226.26,205.93 C226.26,205.93 226.54,205.86 226.54,205.86 C226.54,205.86 226.82,205.78 226.82,205.78 C226.82,205.78 227.1,205.73 227.1,205.73 C227.1,205.73 227.39,205.71 227.39,205.71 C227.39,205.71 227.68,205.7 227.68,205.7 C227.68,205.7 227.97,205.73 227.97,205.73 C227.97,205.73 228.25,205.79 228.25,205.79 C228.25,205.79 228.53,205.88 228.53,205.88 C228.53,205.88 228.79,206 228.79,206 C228.79,206 229.04,206.14 229.04,206.14 C229.04,206.14 229.28,206.31 229.28,206.31 C229.28,206.31 229.5,206.49 229.5,206.49 C229.5,206.49 229.7,206.7 229.7,206.7 C229.7,206.7 229.88,206.93 229.88,206.93 C229.88,206.93 230.03,207.18 230.03,207.18 C230.03,207.18 230.16,207.44 230.16,207.44 C230.16,207.44 230.26,207.71 230.26,207.71 C230.26,207.71 230.34,207.99 230.34,207.99 C230.34,207.99 230.38,208.27 230.38,208.27 C230.38,208.27 230.39,208.56 230.39,208.56 C230.39,208.56 230.38,208.85 230.38,208.85 C230.38,208.85 230.33,209.14 230.33,209.14 C230.33,209.14 230.27,209.42 230.27,209.42 C230.27,209.42 230.2,209.7 230.2,209.7 C230.2,209.7 230.13,209.98 230.13,209.98 C230.13,209.98 230.06,210.26 230.06,210.26 C230.06,210.26 229.99,210.55 229.99,210.55 C229.99,210.55 229.92,210.83 229.92,210.83 C229.92,210.83 229.85,211.11 229.85,211.11 C229.85,211.11 229.78,211.39 229.78,211.39 C229.78,211.39 229.71,211.67 229.71,211.67 C229.71,211.67 229.66,211.95 229.66,211.95 C229.66,211.95 229.63,212.24 229.63,212.24 C229.63,212.24 229.64,212.53 229.64,212.53 C229.64,212.53 229.67,212.82 229.67,212.82 C229.67,212.82 229.73,213.1 229.73,213.1 C229.73,213.1 229.82,213.38 229.82,213.38 C229.82,213.38 229.94,213.64 229.94,213.64 C229.94,213.64 230.08,213.89 230.08,213.89 C230.08,213.89 230.25,214.13 230.25,214.13 C230.25,214.13 230.44,214.35 230.44,214.35 C230.44,214.35 230.66,214.54 230.66,214.54 C230.66,214.54 230.89,214.72 230.89,214.72 C230.89,214.72 231.13,214.87 231.13,214.87 C231.13,214.87 231.38,215.02 231.38,215.02 C231.38,215.02 231.63,215.17 231.63,215.17 C231.63,215.17 231.88,215.32 231.88,215.32 C231.88,215.32 232.13,215.47 232.13,215.47 C232.13,215.47 232.38,215.62 232.38,215.62 C232.38,215.62 232.62,215.77 232.62,215.77 C232.62,215.77 232.87,215.91 232.87,215.91 C232.87,215.91 233.12,216.06 233.12,216.06 C233.12,216.06 233.36,216.23 233.36,216.23 C233.36,216.23 233.58,216.41 233.58,216.41 C233.58,216.41 233.79,216.62 233.79,216.62 C233.79,216.62 233.97,216.84 233.97,216.84 C233.97,216.84 234.13,217.08 234.13,217.08 C234.13,217.08 234.26,217.34 234.26,217.34 C234.26,217.34 234.36,217.61 234.36,217.61 C234.36,217.61 234.44,217.89 234.44,217.89 C234.44,217.89 234.49,218.17 234.49,218.17 C234.49,218.17 234.52,218.46 234.52,218.46 C234.52,218.46 234.51,218.75 234.51,218.75 C234.51,218.75 234.47,219.04 234.47,219.04 C234.47,219.04 234.41,219.32 234.41,219.32 C234.41,219.32 234.31,219.59 234.31,219.59 C234.31,219.59 234.19,219.86 234.19,219.86 C234.19,219.86 234.05,220.11 234.05,220.11 C234.05,220.11 233.88,220.34 233.88,220.34 C233.88,220.34 233.68,220.56 233.68,220.56 C233.68,220.56 233.47,220.75 233.47,220.75 C233.47,220.75 233.23,220.92 233.23,220.92 C233.23,220.92 232.99,221.08 232.99,221.08 C232.99,221.08 232.74,221.22 232.74,221.22 C232.74,221.22 232.49,221.37 232.49,221.37 C232.49,221.37 232.25,221.52 232.25,221.52 C232.25,221.52 232,221.67 232,221.67 C232,221.67 231.75,221.82 231.75,221.82 C231.75,221.82 231.5,221.97 231.5,221.97 C231.5,221.97 231.25,222.12 231.25,222.12 C231.25,222.12 231,222.27 231,222.27 C231,222.27 230.76,222.43 230.76,222.43 C230.76,222.43 230.54,222.62 230.54,222.62 C230.54,222.62 230.34,222.83 230.34,222.83 C230.34,222.83 230.16,223.05 230.16,223.05 C230.16,223.05 230.01,223.3 230.01,223.3 C230.01,223.3 229.87,223.56 229.87,223.56 C229.87,223.56 229.77,223.83 229.77,223.83 C229.77,223.83 229.7,224.11 229.7,224.11 C229.7,224.11 229.65,224.39 229.65,224.39 C229.65,224.39 229.63,224.68 229.63,224.68 C229.63,224.68 229.64,224.97 229.64,224.97 C229.64,224.97 229.68,225.26 229.68,225.26 C229.68,225.26 229.75,225.54 229.75,225.54 C229.75,225.54 229.82,225.82 229.82,225.82 C229.82,225.82 229.89,226.1 229.89,226.1 C229.89,226.1 229.96,226.38 229.96,226.38 C229.96,226.38 230.03,226.66 230.03,226.66 C230.03,226.66 230.1,226.94 230.1,226.94 C230.1,226.94 230.17,227.22 230.17,227.22 C230.17,227.22 230.24,227.51 230.24,227.51 C230.24,227.51 230.31,227.79 230.31,227.79 C230.31,227.79 230.36,228.07 230.36,228.07 C230.36,228.07 230.39,228.36 230.39,228.36 C230.39,228.36 230.39,228.65 230.39,228.65 C230.39,228.65 230.36,228.94 230.36,228.94 C230.36,228.94 230.3,229.22 230.3,229.22 C230.3,229.22 230.21,229.5 230.21,229.5 C230.21,229.5 230.1,229.76 230.1,229.76 C230.1,229.76 229.95,230.01 229.95,230.01 C229.95,230.01 229.79,230.25 229.79,230.25 C229.79,230.25 229.6,230.47 229.6,230.47 C229.6,230.47 229.39,230.67 229.39,230.67 C229.39,230.67 229.16,230.85 229.16,230.85 C229.16,230.85 228.91,231 228.91,231 C228.91,231 228.66,231.13 228.66,231.13 C228.66,231.13 228.38,231.23 228.38,231.23 C228.38,231.23 228.11,231.3 228.11,231.3 C228.11,231.3 227.82,231.35 227.82,231.35 C227.82,231.35 227.53,231.36 227.53,231.36 C227.53,231.36 227.24,231.35 227.24,231.35 C227.24,231.35 226.96,231.3 226.96,231.3 C226.96,231.3 226.67,231.24 226.67,231.24 C226.67,231.24 226.39,231.17 226.39,231.17 C226.39,231.17 226.11,231.1 226.11,231.1 C226.11,231.1 225.83,231.03 225.83,231.03 C225.83,231.03 225.55,230.96 225.55,230.96 C225.55,230.96 225.27,230.89 225.27,230.89 C225.27,230.89 224.99,230.82 224.99,230.82 C224.99,230.82 224.71,230.75 224.71,230.75 C224.71,230.75 224.42,230.68 224.42,230.68 C224.42,230.68 224.14,230.62 224.14,230.62 C224.14,230.62 223.85,230.6 223.85,230.6 C223.85,230.6 223.56,230.6 223.56,230.6 C223.56,230.6 223.27,230.64 223.27,230.64 C223.27,230.64 222.99,230.7 222.99,230.7 C222.99,230.7 222.72,230.79 222.72,230.79 C222.72,230.79 222.45,230.91 222.45,230.91 C222.45,230.91 222.2,231.05 222.2,231.05 C222.2,231.05 221.96,231.22 221.96,231.22 C221.96,231.22 221.75,231.41 221.75,231.41 C221.75,231.41 221.55,231.62 221.55,231.62 C221.55,231.62 221.38,231.85 221.38,231.85 C221.38,231.85 221.22,232.1 221.22,232.1 C221.22,232.1 221.07,232.35 221.07,232.35 C221.07,232.35 220.92,232.6 220.92,232.6 C220.92,232.6 220.77,232.85 220.77,232.85 C220.77,232.85 220.63,233.09 220.63,233.09 C220.63,233.09 220.48,233.34 220.48,233.34 C220.48,233.34 220.33,233.59 220.33,233.59 C220.33,233.59 220.18,233.84 220.18,233.84 C220.18,233.84 220.03,234.09 220.03,234.09 C220.03,234.09 219.87,234.33 219.87,234.33 C219.87,234.33 219.68,234.55 219.68,234.55 C219.68,234.55 219.48,234.75 219.48,234.75 C219.48,234.75 219.25,234.94 219.25,234.94 C219.25,234.94 219.01,235.1 219.01,235.1 C219.01,235.1 218.75,235.23 218.75,235.23 C218.75,235.23 218.48,235.33 218.48,235.33 C218.48,235.33 218.21,235.41 218.21,235.41 C218.21,235.41 217.92,235.46 217.92,235.46 C217.92,235.46 217.63,235.48 217.63,235.48 C217.63,235.48 217.34,235.48 217.34,235.48 C217.34,235.48 217.06,235.44 217.06,235.44 C217.06,235.44 216.77,235.37 216.77,235.37 C216.77,235.37 216.5,235.28 216.5,235.28 C216.5,235.28 216.24,235.16 216.24,235.16 C216.24,235.16 215.99,235.02 215.99,235.02 C215.99,235.02 215.75,234.85 215.75,234.85 C215.75,234.85 215.54,234.65 215.54,234.65 C215.54,234.65 215.34,234.44 215.34,234.44 C215.34,234.44 215.17,234.2 215.17,234.2 C215.17,234.2 215.02,233.96 215.02,233.96 C215.02,233.96 214.87,233.71 214.87,233.71 C214.87,233.71 214.72,233.46 214.72,233.46 C214.72,233.46 214.57,233.21 214.57,233.21 C214.57,233.21 214.42,232.96 214.42,232.96 C214.42,232.96 214.27,232.72 214.27,232.72 C214.27,232.72 214.12,232.47 214.12,232.47 C214.12,232.47 213.98,232.22 213.98,232.22 C213.98,232.22 213.83,231.97 213.83,231.97 C213.83,231.97 213.66,231.73 213.66,231.73 C213.66,231.73 213.48,231.51 213.48,231.51 C213.48,231.51 213.27,231.31 213.27,231.31 C213.27,231.31 213.04,231.13 213.04,231.13 C213.04,231.13 212.8,230.97 212.8,230.97 C212.8,230.97 212.54,230.84 212.54,230.84 C212.54,230.84 212.27,230.74 212.27,230.74 C212.27,230.74 211.99,230.66 211.99,230.66 C211.99,230.66 211.7,230.62 211.7,230.62 C211.7,230.62 211.41,230.6 211.41,230.6 C211.41,230.6 211.12,230.61 211.12,230.61 C211.12,230.61 210.84,230.65 210.84,230.65 C210.84,230.65 210.56,230.71 210.56,230.71 C210.56,230.71 210.27,230.78 210.27,230.78 C210.27,230.78 209.99,230.85 209.99,230.85 C209.99,230.85 209.71,230.92 209.71,230.92 C209.71,230.92 209.43,230.99 209.43,230.99 C209.43,230.99 209.15,231.06 209.15,231.06 C209.15,231.06 208.87,231.14 208.87,231.14 C208.87,231.14 208.59,231.21 208.59,231.21 C208.59,231.21 208.31,231.28 208.31,231.28 C208.31,231.28 208.02,231.33 208.02,231.33 C208.02,231.33 207.73,231.36 207.73,231.36 C207.73,231.36 207.45,231.36 207.45,231.36 C207.45,231.36 207.16,231.33 207.16,231.33 C207.16,231.33 206.87,231.27 206.87,231.27 C206.87,231.27 206.6,231.18 206.6,231.18 C206.6,231.18 206.33,231.06 206.33,231.06 C206.33,231.06 206.08,230.92 206.08,230.92 C206.08,230.92 205.85,230.76 205.85,230.76 C205.85,230.76 205.62,230.57 205.62,230.57 C205.62,230.57 205.42,230.36 205.42,230.36 C205.42,230.36 205.25,230.13 205.25,230.13 C205.25,230.13 205.1,229.88 205.1,229.88 C205.1,229.88 204.97,229.62 204.97,229.62 C204.97,229.62 204.87,229.35 204.87,229.35 C204.87,229.35 204.79,229.07 204.79,229.07 C204.79,229.07 204.74,228.79 204.74,228.79 C204.74,228.79 204.73,228.5 204.73,228.5 C204.73,228.5 204.74,228.21 204.74,228.21 C204.74,228.21 204.79,227.92 204.79,227.92 C204.79,227.92 204.85,227.64 204.85,227.64 C204.85,227.64 204.92,227.36 204.92,227.36 C204.92,227.36 204.99,227.08 204.99,227.08 C204.99,227.08 205.06,226.8 205.06,226.8 C205.06,226.8 205.13,226.52 205.13,226.52 C205.13,226.52 205.21,226.24 205.21,226.24 C205.21,226.24 205.28,225.96 205.28,225.96 C205.28,225.96 205.35,225.68 205.35,225.68 C205.35,225.68 205.42,225.39 205.42,225.39 C205.42,225.39 205.47,225.11 205.47,225.11 C205.47,225.11 205.49,224.82 205.49,224.82 C205.49,224.82 205.49,224.53 205.49,224.53 C205.49,224.53 205.46,224.24 205.46,224.24 C205.46,224.24 205.39,223.96 205.39,223.96 C205.39,223.96 205.3,223.69 205.3,223.69 C205.3,223.69 205.19,223.42 205.19,223.42 C205.19,223.42 205.04,223.17 205.04,223.17 C205.04,223.17 204.87,222.93 204.87,222.93 C204.87,222.93 204.68,222.71 204.68,222.71 C204.68,222.71 204.47,222.52 204.47,222.52 C204.47,222.52 204.24,222.34 204.24,222.34 C204.24,222.34 203.99,222.19 203.99,222.19 C203.99,222.19 203.75,222.04 203.75,222.04 C203.75,222.04 203.5,221.89 203.5,221.89 C203.5,221.89 203.25,221.74 203.25,221.74 C203.25,221.74 203,221.59 203,221.59 C203,221.59 202.75,221.45 202.75,221.45 C202.75,221.45 202.5,221.3 202.5,221.3 C202.5,221.3 202.25,221.15 202.25,221.15 C202.25,221.15 202.01,221 202.01,221 C202.01,221 201.77,220.83 201.77,220.83 C201.77,220.83 201.54,220.65 201.54,220.65 C201.54,220.65 201.34,220.45 201.34,220.45 C201.34,220.45 201.16,220.22 201.16,220.22 C201.16,220.22 201,219.98 201,219.98 C201,219.98 200.87,219.72 200.87,219.72 C200.87,219.72 200.76,219.45 200.76,219.45 C200.76,219.45 200.68,219.18 200.68,219.18 C200.68,219.18 200.63,218.89 200.63,218.89 C200.63,218.89 200.61,218.6 200.61,218.6 C200.61,218.6 200.61,218.31 200.61,218.31 C200.61,218.31 200.65,218.02 200.65,218.02 C200.65,218.02 200.72,217.74 200.72,217.74 C200.72,217.74 200.81,217.47 200.81,217.47 C200.81,217.47 200.93,217.21 200.93,217.21 C200.93,217.21 201.07,216.96 201.07,216.96 C201.07,216.96 201.24,216.72 201.24,216.72 C201.24,216.72 201.44,216.51 201.44,216.51 C201.44,216.51 201.65,216.31 201.65,216.31 C201.65,216.31 201.89,216.14 201.89,216.14 C201.89,216.14 202.13,215.99 202.13,215.99 C202.13,215.99 202.38,215.84 202.38,215.84 C202.38,215.84 202.63,215.69 202.63,215.69 C202.63,215.69 202.88,215.54 202.88,215.54 C202.88,215.54 203.13,215.39 203.13,215.39 C203.13,215.39 203.37,215.24 203.37,215.24 C203.37,215.24 203.62,215.09 203.62,215.09 C203.62,215.09 203.87,214.94 203.87,214.94 C203.87,214.94 204.12,214.79 204.12,214.79 C204.12,214.79 204.36,214.63 204.36,214.63 C204.36,214.63 204.58,214.45 204.58,214.45 C204.58,214.45 204.78,214.24 204.78,214.24 C204.78,214.24 204.96,214.01 204.96,214.01 C204.96,214.01 205.12,213.77 205.12,213.77 C205.12,213.77 205.25,213.51 205.25,213.51 C205.25,213.51 205.35,213.24 205.35,213.24 C205.35,213.24 205.43,212.96 205.43,212.96 C205.43,212.96 205.48,212.67 205.48,212.67 C205.48,212.67 205.5,212.38 205.5,212.38 C205.5,212.38 205.49,212.09 205.49,212.09 C205.49,212.09 205.44,211.81 205.44,211.81 C205.44,211.81 205.38,211.52 205.38,211.52 C205.38,211.52 205.31,211.24 205.31,211.24 C205.31,211.24 205.24,210.96 205.24,210.96 C205.24,210.96 205.17,210.68 205.17,210.68 C205.17,210.68 205.1,210.4 205.1,210.4 C205.1,210.4 205.03,210.12 205.03,210.12 C205.03,210.12 204.96,209.84 204.96,209.84 C204.96,209.84 204.89,209.56 204.89,209.56 C204.89,209.56 204.82,209.28 204.82,209.28 C204.82,209.28 204.76,208.99 204.76,208.99 C204.76,208.99 204.74,208.7 204.74,208.7 C204.74,208.7 204.74,208.42 204.74,208.42 C204.74,208.42 204.76,208.13 204.76,208.13 C204.76,208.13 204.82,207.84 204.82,207.84 C204.82,207.84 204.91,207.57 204.91,207.57 C204.91,207.57 205.03,207.3 205.03,207.3 C205.03,207.3 205.17,207.05 205.17,207.05 C205.17,207.05 205.34,206.81 205.34,206.81 C205.34,206.81 205.52,206.59 205.52,206.59 C205.52,206.59 205.73,206.39 205.73,206.39 C205.73,206.39 205.96,206.22 205.96,206.22 C205.96,206.22 206.21,206.06 206.21,206.06 C206.21,206.06 206.47,205.94 206.47,205.94 C206.47,205.94 206.74,205.83 206.74,205.83 C206.74,205.83 207.02,205.76 207.02,205.76 C207.02,205.76 207.3,205.71 207.3,205.71 C207.3,205.71 207.59,205.7 207.59,205.7 C207.59,205.7 207.88,205.71 207.88,205.71 C207.88,205.71 208.17,205.76 208.17,205.76 C208.17,205.76 208.45,205.82 208.45,205.82 C208.45,205.82 208.73,205.89 208.73,205.89 C208.73,205.89 209.01,205.96 209.01,205.96 C209.01,205.96 209.29,206.03 209.29,206.03 C209.29,206.03 209.57,206.1 209.57,206.1 C209.57,206.1 209.85,206.17 209.85,206.17 C209.85,206.17 210.14,206.24 210.14,206.24 C210.14,206.24 210.42,206.31 210.42,206.31 C210.42,206.31 210.7,206.38 210.7,206.38 C210.7,206.38 210.98,206.44 210.98,206.44 C210.98,206.44 211.27,206.46 211.27,206.46 C211.27,206.46 211.56,206.46 211.56,206.46 C211.56,206.46 211.85,206.43 211.85,206.43 C211.85,206.43 212.13,206.36 212.13,206.36 C212.13,206.36 212.41,206.27 212.41,206.27 C212.41,206.27 212.67,206.15 212.67,206.15 C212.67,206.15 212.92,206.01 212.92,206.01 C212.92,206.01 213.16,205.84 213.16,205.84 C213.16,205.84 213.38,205.65 213.38,205.65 C213.38,205.65 213.57,205.44 213.57,205.44 C213.57,205.44 213.75,205.21 213.75,205.21 C213.75,205.21 213.9,204.96 213.9,204.96 C213.9,204.96 214.05,204.71 214.05,204.71 C214.05,204.71 214.2,204.47 214.2,204.47 C214.2,204.47 214.35,204.22 214.35,204.22 C214.35,204.22 214.5,203.97 214.5,203.97 C214.5,203.97 214.65,203.72 214.65,203.72 C214.65,203.72 214.8,203.47 214.8,203.47 C214.8,203.47 214.94,203.22 214.94,203.22 C214.94,203.22 215.1,202.97 215.1,202.97 C215.1,202.97 215.26,202.73 215.26,202.73 C215.26,202.73 215.44,202.51 215.44,202.51 C215.44,202.51 215.65,202.31 215.65,202.31 C215.65,202.31 215.87,202.12 215.87,202.12 C215.87,202.12 216.11,201.96 216.11,201.96 C216.11,201.96 216.37,201.83 216.37,201.83 C216.37,201.83 216.64,201.73 216.64,201.73 C216.64,201.73 216.92,201.65 216.92,201.65 C216.92,201.65 217.21,201.6 217.21,201.6 C217.21,201.6 217.49,201.58 217.49,201.58 C217.49,201.58 217.78,201.58 217.78,201.58c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.78 201.58 C217.78,201.58 218.07,201.62 218.07,201.62 C218.07,201.62 218.35,201.69 218.35,201.69 C218.35,201.69 218.63,201.78 218.63,201.78 C218.63,201.78 218.89,201.9 218.89,201.9 C218.89,201.9 219.14,202.04 219.14,202.04 C219.14,202.04 219.38,202.21 219.38,202.21 C219.38,202.21 219.59,202.41 219.59,202.41 C219.59,202.41 219.78,202.62 219.78,202.62 C219.78,202.62 219.95,202.86 219.95,202.86 C219.95,202.86 220.11,203.1 220.11,203.1 C220.11,203.1 220.26,203.35 220.26,203.35 C220.26,203.35 220.41,203.6 220.41,203.6 C220.41,203.6 220.55,203.85 220.55,203.85 C220.55,203.85 220.7,204.1 220.7,204.1 C220.7,204.1 220.85,204.35 220.85,204.35 C220.85,204.35 221,204.59 221,204.59 C221,204.59 221.15,204.84 221.15,204.84 C221.15,204.84 221.3,205.09 221.3,205.09 C221.3,205.09 221.46,205.33 221.46,205.33 C221.46,205.33 221.65,205.55 221.65,205.55 C221.65,205.55 221.86,205.75 221.86,205.75 C221.86,205.75 222.09,205.93 222.09,205.93 C222.09,205.93 222.33,206.09 222.33,206.09 C222.33,206.09 222.59,206.22 222.59,206.22 C222.59,206.22 222.86,206.32 222.86,206.32 C222.86,206.32 223.14,206.4 223.14,206.4 C223.14,206.4 223.42,206.45 223.42,206.45 C223.42,206.45 223.71,206.46 223.71,206.46 C223.71,206.46 224,206.45 224,206.45 C224,206.45 224.29,206.41 224.29,206.41 C224.29,206.41 224.57,206.35 224.57,206.35 C224.57,206.35 224.85,206.28 224.85,206.28 C224.85,206.28 225.13,206.21 225.13,206.21 C225.13,206.21 225.41,206.14 225.41,206.14 C225.41,206.14 225.7,206.07 225.7,206.07 C225.7,206.07 225.98,206 225.98,206 C225.98,206 226.26,205.93 226.26,205.93 C226.26,205.93 226.54,205.86 226.54,205.86 C226.54,205.86 226.82,205.78 226.82,205.78 C226.82,205.78 227.1,205.73 227.1,205.73 C227.1,205.73 227.39,205.71 227.39,205.71 C227.39,205.71 227.68,205.7 227.68,205.7 C227.68,205.7 227.97,205.73 227.97,205.73 C227.97,205.73 228.25,205.79 228.25,205.79 C228.25,205.79 228.53,205.88 228.53,205.88 C228.53,205.88 228.79,206 228.79,206 C228.79,206 229.04,206.14 229.04,206.14 C229.04,206.14 229.28,206.31 229.28,206.31 C229.28,206.31 229.5,206.49 229.5,206.49 C229.5,206.49 229.7,206.7 229.7,206.7 C229.7,206.7 229.88,206.93 229.88,206.93 C229.88,206.93 230.03,207.18 230.03,207.18 C230.03,207.18 230.16,207.44 230.16,207.44 C230.16,207.44 230.26,207.71 230.26,207.71 C230.26,207.71 230.34,207.99 230.34,207.99 C230.34,207.99 230.38,208.27 230.38,208.27 C230.38,208.27 230.39,208.56 230.39,208.56 C230.39,208.56 230.38,208.85 230.38,208.85 C230.38,208.85 230.33,209.14 230.33,209.14 C230.33,209.14 230.27,209.42 230.27,209.42 C230.27,209.42 230.2,209.7 230.2,209.7 C230.2,209.7 230.13,209.98 230.13,209.98 C230.13,209.98 230.06,210.26 230.06,210.26 C230.06,210.26 229.99,210.55 229.99,210.55 C229.99,210.55 229.92,210.83 229.92,210.83 C229.92,210.83 229.85,211.11 229.85,211.11 C229.85,211.11 229.78,211.39 229.78,211.39 C229.78,211.39 229.71,211.67 229.71,211.67 C229.71,211.67 229.66,211.95 229.66,211.95 C229.66,211.95 229.63,212.24 229.63,212.24 C229.63,212.24 229.64,212.53 229.64,212.53 C229.64,212.53 229.67,212.82 229.67,212.82 C229.67,212.82 229.73,213.1 229.73,213.1 C229.73,213.1 229.82,213.38 229.82,213.38 C229.82,213.38 229.94,213.64 229.94,213.64 C229.94,213.64 230.08,213.89 230.08,213.89 C230.08,213.89 230.25,214.13 230.25,214.13 C230.25,214.13 230.44,214.35 230.44,214.35 C230.44,214.35 230.66,214.54 230.66,214.54 C230.66,214.54 230.89,214.72 230.89,214.72 C230.89,214.72 231.13,214.87 231.13,214.87 C231.13,214.87 231.38,215.02 231.38,215.02 C231.38,215.02 231.63,215.17 231.63,215.17 C231.63,215.17 231.88,215.32 231.88,215.32 C231.88,215.32 232.13,215.47 232.13,215.47 C232.13,215.47 232.38,215.62 232.38,215.62 C232.38,215.62 232.62,215.77 232.62,215.77 C232.62,215.77 232.87,215.91 232.87,215.91 C232.87,215.91 233.12,216.06 233.12,216.06 C233.12,216.06 233.36,216.23 233.36,216.23 C233.36,216.23 233.58,216.41 233.58,216.41 C233.58,216.41 233.79,216.62 233.79,216.62 C233.79,216.62 233.97,216.84 233.97,216.84 C233.97,216.84 234.13,217.08 234.13,217.08 C234.13,217.08 234.26,217.34 234.26,217.34 C234.26,217.34 234.36,217.61 234.36,217.61 C234.36,217.61 234.44,217.89 234.44,217.89 C234.44,217.89 234.49,218.17 234.49,218.17 C234.49,218.17 234.52,218.46 234.52,218.46 C234.52,218.46 234.51,218.75 234.51,218.75 C234.51,218.75 234.47,219.04 234.47,219.04 C234.47,219.04 234.41,219.32 234.41,219.32 C234.41,219.32 234.31,219.59 234.31,219.59 C234.31,219.59 234.19,219.86 234.19,219.86 C234.19,219.86 234.05,220.11 234.05,220.11 C234.05,220.11 233.88,220.34 233.88,220.34 C233.88,220.34 233.68,220.56 233.68,220.56 C233.68,220.56 233.47,220.75 233.47,220.75 C233.47,220.75 233.23,220.92 233.23,220.92 C233.23,220.92 232.99,221.08 232.99,221.08 C232.99,221.08 232.74,221.22 232.74,221.22 C232.74,221.22 232.49,221.37 232.49,221.37 C232.49,221.37 232.25,221.52 232.25,221.52 C232.25,221.52 232,221.67 232,221.67 C232,221.67 231.75,221.82 231.75,221.82 C231.75,221.82 231.5,221.97 231.5,221.97 C231.5,221.97 231.25,222.12 231.25,222.12 C231.25,222.12 231,222.27 231,222.27 C231,222.27 230.76,222.43 230.76,222.43 C230.76,222.43 230.54,222.62 230.54,222.62 C230.54,222.62 230.34,222.83 230.34,222.83 C230.34,222.83 230.16,223.05 230.16,223.05 C230.16,223.05 230.01,223.3 230.01,223.3 C230.01,223.3 229.87,223.56 229.87,223.56 C229.87,223.56 229.77,223.83 229.77,223.83 C229.77,223.83 229.7,224.11 229.7,224.11 C229.7,224.11 229.65,224.39 229.65,224.39 C229.65,224.39 229.63,224.68 229.63,224.68 C229.63,224.68 229.64,224.97 229.64,224.97 C229.64,224.97 229.68,225.26 229.68,225.26 C229.68,225.26 229.75,225.54 229.75,225.54 C229.75,225.54 229.82,225.82 229.82,225.82 C229.82,225.82 229.89,226.1 229.89,226.1 C229.89,226.1 229.96,226.38 229.96,226.38 C229.96,226.38 230.03,226.66 230.03,226.66 C230.03,226.66 230.1,226.94 230.1,226.94 C230.1,226.94 230.17,227.22 230.17,227.22 C230.17,227.22 230.24,227.51 230.24,227.51 C230.24,227.51 230.31,227.79 230.31,227.79 C230.31,227.79 230.36,228.07 230.36,228.07 C230.36,228.07 230.39,228.36 230.39,228.36 C230.39,228.36 230.39,228.65 230.39,228.65 C230.39,228.65 230.36,228.94 230.36,228.94 C230.36,228.94 230.3,229.22 230.3,229.22 C230.3,229.22 230.21,229.5 230.21,229.5 C230.21,229.5 230.1,229.76 230.1,229.76 C230.1,229.76 229.95,230.01 229.95,230.01 C229.95,230.01 229.79,230.25 229.79,230.25 C229.79,230.25 229.6,230.47 229.6,230.47 C229.6,230.47 229.39,230.67 229.39,230.67 C229.39,230.67 229.16,230.85 229.16,230.85 C229.16,230.85 228.91,231 228.91,231 C228.91,231 228.66,231.13 228.66,231.13 C228.66,231.13 228.38,231.23 228.38,231.23 C228.38,231.23 228.11,231.3 228.11,231.3 C228.11,231.3 227.82,231.35 227.82,231.35 C227.82,231.35 227.53,231.36 227.53,231.36 C227.53,231.36 227.24,231.35 227.24,231.35 C227.24,231.35 226.96,231.3 226.96,231.3 C226.96,231.3 226.67,231.24 226.67,231.24 C226.67,231.24 226.39,231.17 226.39,231.17 C226.39,231.17 226.11,231.1 226.11,231.1 C226.11,231.1 225.83,231.03 225.83,231.03 C225.83,231.03 225.55,230.96 225.55,230.96 C225.55,230.96 225.27,230.89 225.27,230.89 C225.27,230.89 224.99,230.82 224.99,230.82 C224.99,230.82 224.71,230.75 224.71,230.75 C224.71,230.75 224.42,230.68 224.42,230.68 C224.42,230.68 224.14,230.62 224.14,230.62 C224.14,230.62 223.85,230.6 223.85,230.6 C223.85,230.6 223.56,230.6 223.56,230.6 C223.56,230.6 223.27,230.64 223.27,230.64 C223.27,230.64 222.99,230.7 222.99,230.7 C222.99,230.7 222.72,230.79 222.72,230.79 C222.72,230.79 222.45,230.91 222.45,230.91 C222.45,230.91 222.2,231.05 222.2,231.05 C222.2,231.05 221.96,231.22 221.96,231.22 C221.96,231.22 221.75,231.41 221.75,231.41 C221.75,231.41 221.55,231.62 221.55,231.62 C221.55,231.62 221.38,231.85 221.38,231.85 C221.38,231.85 221.22,232.1 221.22,232.1 C221.22,232.1 221.07,232.35 221.07,232.35 C221.07,232.35 220.92,232.6 220.92,232.6 C220.92,232.6 220.77,232.85 220.77,232.85 C220.77,232.85 220.63,233.09 220.63,233.09 C220.63,233.09 220.48,233.34 220.48,233.34 C220.48,233.34 220.33,233.59 220.33,233.59 C220.33,233.59 220.18,233.84 220.18,233.84 C220.18,233.84 220.03,234.09 220.03,234.09 C220.03,234.09 219.87,234.33 219.87,234.33 C219.87,234.33 219.68,234.55 219.68,234.55 C219.68,234.55 219.48,234.75 219.48,234.75 C219.48,234.75 219.25,234.94 219.25,234.94 C219.25,234.94 219.01,235.1 219.01,235.1 C219.01,235.1 218.75,235.23 218.75,235.23 C218.75,235.23 218.48,235.33 218.48,235.33 C218.48,235.33 218.21,235.41 218.21,235.41 C218.21,235.41 217.92,235.46 217.92,235.46 C217.92,235.46 217.63,235.48 217.63,235.48 C217.63,235.48 217.34,235.48 217.34,235.48 C217.34,235.48 217.06,235.44 217.06,235.44 C217.06,235.44 216.77,235.37 216.77,235.37 C216.77,235.37 216.5,235.28 216.5,235.28 C216.5,235.28 216.24,235.16 216.24,235.16 C216.24,235.16 215.99,235.02 215.99,235.02 C215.99,235.02 215.75,234.85 215.75,234.85 C215.75,234.85 215.54,234.65 215.54,234.65 C215.54,234.65 215.34,234.44 215.34,234.44 C215.34,234.44 215.17,234.2 215.17,234.2 C215.17,234.2 215.02,233.96 215.02,233.96 C215.02,233.96 214.87,233.71 214.87,233.71 C214.87,233.71 214.72,233.46 214.72,233.46 C214.72,233.46 214.57,233.21 214.57,233.21 C214.57,233.21 214.42,232.96 214.42,232.96 C214.42,232.96 214.27,232.72 214.27,232.72 C214.27,232.72 214.12,232.47 214.12,232.47 C214.12,232.47 213.98,232.22 213.98,232.22 C213.98,232.22 213.83,231.97 213.83,231.97 C213.83,231.97 213.66,231.73 213.66,231.73 C213.66,231.73 213.48,231.51 213.48,231.51 C213.48,231.51 213.27,231.31 213.27,231.31 C213.27,231.31 213.04,231.13 213.04,231.13 C213.04,231.13 212.8,230.97 212.8,230.97 C212.8,230.97 212.54,230.84 212.54,230.84 C212.54,230.84 212.27,230.74 212.27,230.74 C212.27,230.74 211.99,230.66 211.99,230.66 C211.99,230.66 211.7,230.62 211.7,230.62 C211.7,230.62 211.41,230.6 211.41,230.6 C211.41,230.6 211.12,230.61 211.12,230.61 C211.12,230.61 210.84,230.65 210.84,230.65 C210.84,230.65 210.56,230.71 210.56,230.71 C210.56,230.71 210.27,230.78 210.27,230.78 C210.27,230.78 209.99,230.85 209.99,230.85 C209.99,230.85 209.71,230.92 209.71,230.92 C209.71,230.92 209.43,230.99 209.43,230.99 C209.43,230.99 209.15,231.06 209.15,231.06 C209.15,231.06 208.87,231.14 208.87,231.14 C208.87,231.14 208.59,231.21 208.59,231.21 C208.59,231.21 208.31,231.28 208.31,231.28 C208.31,231.28 208.02,231.33 208.02,231.33 C208.02,231.33 207.73,231.36 207.73,231.36 C207.73,231.36 207.45,231.36 207.45,231.36 C207.45,231.36 207.16,231.33 207.16,231.33 C207.16,231.33 206.87,231.27 206.87,231.27 C206.87,231.27 206.6,231.18 206.6,231.18 C206.6,231.18 206.33,231.06 206.33,231.06 C206.33,231.06 206.08,230.92 206.08,230.92 C206.08,230.92 205.85,230.76 205.85,230.76 C205.85,230.76 205.62,230.57 205.62,230.57 C205.62,230.57 205.42,230.36 205.42,230.36 C205.42,230.36 205.25,230.13 205.25,230.13 C205.25,230.13 205.1,229.88 205.1,229.88 C205.1,229.88 204.97,229.62 204.97,229.62 C204.97,229.62 204.87,229.35 204.87,229.35 C204.87,229.35 204.79,229.07 204.79,229.07 C204.79,229.07 204.74,228.79 204.74,228.79 C204.74,228.79 204.73,228.5 204.73,228.5 C204.73,228.5 204.74,228.21 204.74,228.21 C204.74,228.21 204.79,227.92 204.79,227.92 C204.79,227.92 204.85,227.64 204.85,227.64 C204.85,227.64 204.92,227.36 204.92,227.36 C204.92,227.36 204.99,227.08 204.99,227.08 C204.99,227.08 205.06,226.8 205.06,226.8 C205.06,226.8 205.13,226.52 205.13,226.52 C205.13,226.52 205.21,226.24 205.21,226.24 C205.21,226.24 205.28,225.96 205.28,225.96 C205.28,225.96 205.35,225.68 205.35,225.68 C205.35,225.68 205.42,225.39 205.42,225.39 C205.42,225.39 205.47,225.11 205.47,225.11 C205.47,225.11 205.49,224.82 205.49,224.82 C205.49,224.82 205.49,224.53 205.49,224.53 C205.49,224.53 205.46,224.24 205.46,224.24 C205.46,224.24 205.39,223.96 205.39,223.96 C205.39,223.96 205.3,223.69 205.3,223.69 C205.3,223.69 205.19,223.42 205.19,223.42 C205.19,223.42 205.04,223.17 205.04,223.17 C205.04,223.17 204.87,222.93 204.87,222.93 C204.87,222.93 204.68,222.71 204.68,222.71 C204.68,222.71 204.47,222.52 204.47,222.52 C204.47,222.52 204.24,222.34 204.24,222.34 C204.24,222.34 203.99,222.19 203.99,222.19 C203.99,222.19 203.75,222.04 203.75,222.04 C203.75,222.04 203.5,221.89 203.5,221.89 C203.5,221.89 203.25,221.74 203.25,221.74 C203.25,221.74 203,221.59 203,221.59 C203,221.59 202.75,221.45 202.75,221.45 C202.75,221.45 202.5,221.3 202.5,221.3 C202.5,221.3 202.25,221.15 202.25,221.15 C202.25,221.15 202.01,221 202.01,221 C202.01,221 201.77,220.83 201.77,220.83 C201.77,220.83 201.54,220.65 201.54,220.65 C201.54,220.65 201.34,220.45 201.34,220.45 C201.34,220.45 201.16,220.22 201.16,220.22 C201.16,220.22 201,219.98 201,219.98 C201,219.98 200.87,219.72 200.87,219.72 C200.87,219.72 200.76,219.45 200.76,219.45 C200.76,219.45 200.68,219.18 200.68,219.18 C200.68,219.18 200.63,218.89 200.63,218.89 C200.63,218.89 200.61,218.6 200.61,218.6 C200.61,218.6 200.61,218.31 200.61,218.31 C200.61,218.31 200.65,218.02 200.65,218.02 C200.65,218.02 200.72,217.74 200.72,217.74 C200.72,217.74 200.81,217.47 200.81,217.47 C200.81,217.47 200.93,217.21 200.93,217.21 C200.93,217.21 201.07,216.96 201.07,216.96 C201.07,216.96 201.24,216.72 201.24,216.72 C201.24,216.72 201.44,216.51 201.44,216.51 C201.44,216.51 201.65,216.31 201.65,216.31 C201.65,216.31 201.89,216.14 201.89,216.14 C201.89,216.14 202.13,215.99 202.13,215.99 C202.13,215.99 202.38,215.84 202.38,215.84 C202.38,215.84 202.63,215.69 202.63,215.69 C202.63,215.69 202.88,215.54 202.88,215.54 C202.88,215.54 203.13,215.39 203.13,215.39 C203.13,215.39 203.37,215.24 203.37,215.24 C203.37,215.24 203.62,215.09 203.62,215.09 C203.62,215.09 203.87,214.94 203.87,214.94 C203.87,214.94 204.12,214.79 204.12,214.79 C204.12,214.79 204.36,214.63 204.36,214.63 C204.36,214.63 204.58,214.45 204.58,214.45 C204.58,214.45 204.78,214.24 204.78,214.24 C204.78,214.24 204.96,214.01 204.96,214.01 C204.96,214.01 205.12,213.77 205.12,213.77 C205.12,213.77 205.25,213.51 205.25,213.51 C205.25,213.51 205.35,213.24 205.35,213.24 C205.35,213.24 205.43,212.96 205.43,212.96 C205.43,212.96 205.48,212.67 205.48,212.67 C205.48,212.67 205.5,212.38 205.5,212.38 C205.5,212.38 205.49,212.09 205.49,212.09 C205.49,212.09 205.44,211.81 205.44,211.81 C205.44,211.81 205.38,211.52 205.38,211.52 C205.38,211.52 205.31,211.24 205.31,211.24 C205.31,211.24 205.24,210.96 205.24,210.96 C205.24,210.96 205.17,210.68 205.17,210.68 C205.17,210.68 205.1,210.4 205.1,210.4 C205.1,210.4 205.03,210.12 205.03,210.12 C205.03,210.12 204.96,209.84 204.96,209.84 C204.96,209.84 204.89,209.56 204.89,209.56 C204.89,209.56 204.82,209.28 204.82,209.28 C204.82,209.28 204.76,208.99 204.76,208.99 C204.76,208.99 204.74,208.7 204.74,208.7 C204.74,208.7 204.74,208.42 204.74,208.42 C204.74,208.42 204.76,208.13 204.76,208.13 C204.76,208.13 204.82,207.84 204.82,207.84 C204.82,207.84 204.91,207.57 204.91,207.57 C204.91,207.57 205.03,207.3 205.03,207.3 C205.03,207.3 205.17,207.05 205.17,207.05 C205.17,207.05 205.34,206.81 205.34,206.81 C205.34,206.81 205.52,206.59 205.52,206.59 C205.52,206.59 205.73,206.39 205.73,206.39 C205.73,206.39 205.96,206.22 205.96,206.22 C205.96,206.22 206.21,206.06 206.21,206.06 C206.21,206.06 206.47,205.94 206.47,205.94 C206.47,205.94 206.74,205.83 206.74,205.83 C206.74,205.83 207.02,205.76 207.02,205.76 C207.02,205.76 207.3,205.71 207.3,205.71 C207.3,205.71 207.59,205.7 207.59,205.7 C207.59,205.7 207.88,205.71 207.88,205.71 C207.88,205.71 208.17,205.76 208.17,205.76 C208.17,205.76 208.45,205.82 208.45,205.82 C208.45,205.82 208.73,205.89 208.73,205.89 C208.73,205.89 209.01,205.96 209.01,205.96 C209.01,205.96 209.29,206.03 209.29,206.03 C209.29,206.03 209.57,206.1 209.57,206.1 C209.57,206.1 209.85,206.17 209.85,206.17 C209.85,206.17 210.14,206.24 210.14,206.24 C210.14,206.24 210.42,206.31 210.42,206.31 C210.42,206.31 210.7,206.38 210.7,206.38 C210.7,206.38 210.98,206.44 210.98,206.44 C210.98,206.44 211.27,206.46 211.27,206.46 C211.27,206.46 211.56,206.46 211.56,206.46 C211.56,206.46 211.85,206.43 211.85,206.43 C211.85,206.43 212.13,206.36 212.13,206.36 C212.13,206.36 212.41,206.27 212.41,206.27 C212.41,206.27 212.67,206.15 212.67,206.15 C212.67,206.15 212.92,206.01 212.92,206.01 C212.92,206.01 213.16,205.84 213.16,205.84 C213.16,205.84 213.38,205.65 213.38,205.65 C213.38,205.65 213.57,205.44 213.57,205.44 C213.57,205.44 213.75,205.21 213.75,205.21 C213.75,205.21 213.9,204.96 213.9,204.96 C213.9,204.96 214.05,204.71 214.05,204.71 C214.05,204.71 214.2,204.47 214.2,204.47 C214.2,204.47 214.35,204.22 214.35,204.22 C214.35,204.22 214.5,203.97 214.5,203.97 C214.5,203.97 214.65,203.72 214.65,203.72 C214.65,203.72 214.8,203.47 214.8,203.47 C214.8,203.47 214.94,203.22 214.94,203.22 C214.94,203.22 215.1,202.97 215.1,202.97 C215.1,202.97 215.26,202.73 215.26,202.73 C215.26,202.73 215.44,202.51 215.44,202.51 C215.44,202.51 215.65,202.31 215.65,202.31 C215.65,202.31 215.87,202.12 215.87,202.12 C215.87,202.12 216.11,201.96 216.11,201.96 C216.11,201.96 216.37,201.83 216.37,201.83 C216.37,201.83 216.64,201.73 216.64,201.73 C216.64,201.73 216.92,201.65 216.92,201.65 C216.92,201.65 217.21,201.6 217.21,201.6 C217.21,201.6 217.49,201.58 217.49,201.58 C217.49,201.58 217.78,201.58 217.78,201.58c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml
new file mode 100644
index 0000000..de2a7db
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml
@@ -0,0 +1 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.59 202.73 C217.59,202.73 217.85,202.75 217.85,202.75 C217.85,202.75 218.11,202.76 218.11,202.76 C218.11,202.76 218.37,202.79 218.37,202.79 C218.37,202.79 218.63,202.83 218.63,202.83 C218.63,202.83 218.88,202.88 218.88,202.88 C218.88,202.88 219.14,202.93 219.14,202.93 C219.14,202.93 219.39,203.01 219.39,203.01 C219.39,203.01 219.64,203.09 219.64,203.09 C219.64,203.09 219.88,203.18 219.88,203.18 C219.88,203.18 220.12,203.28 220.12,203.28 C220.12,203.28 220.36,203.39 220.36,203.39 C220.36,203.39 220.59,203.51 220.59,203.51 C220.59,203.51 220.82,203.64 220.82,203.64 C220.82,203.64 221.04,203.78 221.04,203.78 C221.04,203.78 221.26,203.92 221.26,203.92 C221.26,203.92 221.46,204.09 221.46,204.09 C221.46,204.09 221.66,204.25 221.66,204.25 C221.66,204.25 221.87,204.42 221.87,204.42 C221.87,204.42 222.05,204.61 222.05,204.61 C222.05,204.61 222.23,204.79 222.23,204.79 C222.23,204.79 222.4,204.99 222.4,204.99 C222.4,204.99 222.57,205.19 222.57,205.19 C222.57,205.19 222.72,205.41 222.72,205.41 C222.72,205.41 222.86,205.62 222.86,205.62 C222.86,205.62 223.01,205.84 223.01,205.84 C223.01,205.84 223.14,206.06 223.14,206.06 C223.14,206.06 223.27,206.29 223.27,206.29 C223.27,206.29 223.4,206.52 223.4,206.52 C223.4,206.52 223.53,206.75 223.53,206.75 C223.53,206.75 223.66,206.97 223.66,206.97 C223.66,206.97 223.79,207.2 223.79,207.2 C223.79,207.2 223.92,207.43 223.92,207.43 C223.92,207.43 224.05,207.65 224.05,207.65 C224.05,207.65 224.18,207.88 224.18,207.88 C224.18,207.88 224.31,208.11 224.31,208.11 C224.31,208.11 224.44,208.34 224.44,208.34 C224.44,208.34 224.56,208.56 224.56,208.56 C224.56,208.56 224.69,208.79 224.69,208.79 C224.69,208.79 224.82,209.02 224.82,209.02 C224.82,209.02 224.95,209.25 224.95,209.25 C224.95,209.25 225.08,209.47 225.08,209.47 C225.08,209.47 225.21,209.7 225.21,209.7 C225.21,209.7 225.34,209.93 225.34,209.93 C225.34,209.93 225.47,210.15 225.47,210.15 C225.47,210.15 225.6,210.38 225.6,210.38 C225.6,210.38 225.73,210.61 225.73,210.61 C225.73,210.61 225.86,210.84 225.86,210.84 C225.86,210.84 225.99,211.06 225.99,211.06 C225.99,211.06 226.11,211.29 226.11,211.29 C226.11,211.29 226.24,211.52 226.24,211.52 C226.24,211.52 226.37,211.75 226.37,211.75 C226.37,211.75 226.5,211.97 226.5,211.97 C226.5,211.97 226.63,212.2 226.63,212.2 C226.63,212.2 226.76,212.43 226.76,212.43 C226.76,212.43 226.89,212.65 226.89,212.65 C226.89,212.65 227.02,212.88 227.02,212.88 C227.02,212.88 227.15,213.11 227.15,213.11 C227.15,213.11 227.28,213.34 227.28,213.34 C227.28,213.34 227.41,213.56 227.41,213.56 C227.41,213.56 227.54,213.79 227.54,213.79 C227.54,213.79 227.66,214.02 227.66,214.02 C227.66,214.02 227.79,214.25 227.79,214.25 C227.79,214.25 227.92,214.47 227.92,214.47 C227.92,214.47 228.05,214.7 228.05,214.7 C228.05,214.7 228.18,214.93 228.18,214.93 C228.18,214.93 228.31,215.15 228.31,215.15 C228.31,215.15 228.44,215.38 228.44,215.38 C228.44,215.38 228.57,215.61 228.57,215.61 C228.57,215.61 228.7,215.83 228.7,215.83 C228.7,215.83 228.83,216.06 228.83,216.06 C228.83,216.06 228.96,216.29 228.96,216.29 C228.96,216.29 229.09,216.52 229.09,216.52 C229.09,216.52 229.21,216.74 229.21,216.74 C229.21,216.74 229.34,216.97 229.34,216.97 C229.34,216.97 229.47,217.2 229.47,217.2 C229.47,217.2 229.6,217.43 229.6,217.43 C229.6,217.43 229.73,217.65 229.73,217.65 C229.73,217.65 229.86,217.88 229.86,217.88 C229.86,217.88 229.99,218.11 229.99,218.11 C229.99,218.11 230.12,218.33 230.12,218.33 C230.12,218.33 230.25,218.56 230.25,218.56 C230.25,218.56 230.38,218.79 230.38,218.79 C230.38,218.79 230.51,219.02 230.51,219.02 C230.51,219.02 230.64,219.24 230.64,219.24 C230.64,219.24 230.76,219.47 230.76,219.47 C230.76,219.47 230.89,219.7 230.89,219.7 C230.89,219.7 231.02,219.93 231.02,219.93 C231.02,219.93 231.15,220.15 231.15,220.15 C231.15,220.15 231.28,220.38 231.28,220.38 C231.28,220.38 231.41,220.61 231.41,220.61 C231.41,220.61 231.54,220.83 231.54,220.83 C231.54,220.83 231.67,221.06 231.67,221.06 C231.67,221.06 231.8,221.29 231.8,221.29 C231.8,221.29 231.93,221.52 231.93,221.52 C231.93,221.52 232.06,221.74 232.06,221.74 C232.06,221.74 232.19,221.97 232.19,221.97 C232.19,221.97 232.31,222.2 232.31,222.2 C232.31,222.2 232.44,222.43 232.44,222.43 C232.44,222.43 232.57,222.65 232.57,222.65 C232.57,222.65 232.7,222.88 232.7,222.88 C232.7,222.88 232.83,223.11 232.83,223.11 C232.83,223.11 232.96,223.33 232.96,223.33 C232.96,223.33 233.09,223.56 233.09,223.56 C233.09,223.56 233.22,223.79 233.22,223.79 C233.22,223.79 233.35,224.02 233.35,224.02 C233.35,224.02 233.48,224.24 233.48,224.24 C233.48,224.24 233.61,224.47 233.61,224.47 C233.61,224.47 233.73,224.7 233.73,224.7 C233.73,224.7 233.84,224.94 233.84,224.94 C233.84,224.94 233.96,225.17 233.96,225.17 C233.96,225.17 234.07,225.41 234.07,225.41 C234.07,225.41 234.16,225.65 234.16,225.65 C234.16,225.65 234.24,225.9 234.24,225.9 C234.24,225.9 234.32,226.15 234.32,226.15 C234.32,226.15 234.38,226.4 234.38,226.4 C234.38,226.4 234.43,226.66 234.43,226.66 C234.43,226.66 234.48,226.92 234.48,226.92 C234.48,226.92 234.51,227.18 234.51,227.18 C234.51,227.18 234.53,227.44 234.53,227.44 C234.53,227.44 234.54,227.7 234.54,227.7 C234.54,227.7 234.54,227.96 234.54,227.96 C234.54,227.96 234.53,228.22 234.53,228.22 C234.53,228.22 234.51,228.48 234.51,228.48 C234.51,228.48 234.48,228.74 234.48,228.74 C234.48,228.74 234.43,229 234.43,229 C234.43,229 234.39,229.25 234.39,229.25 C234.39,229.25 234.32,229.51 234.32,229.51 C234.32,229.51 234.25,229.76 234.25,229.76 C234.25,229.76 234.17,230.01 234.17,230.01 C234.17,230.01 234.08,230.25 234.08,230.25 C234.08,230.25 233.97,230.49 233.97,230.49 C233.97,230.49 233.86,230.73 233.86,230.73 C233.86,230.73 233.75,230.96 233.75,230.96 C233.75,230.96 233.61,231.18 233.61,231.18 C233.61,231.18 233.48,231.41 233.48,231.41 C233.48,231.41 233.33,231.63 233.33,231.63 C233.33,231.63 233.17,231.83 233.17,231.83 C233.17,231.83 233.01,232.04 233.01,232.04 C233.01,232.04 232.84,232.24 232.84,232.24 C232.84,232.24 232.66,232.42 232.66,232.42 C232.66,232.42 232.47,232.61 232.47,232.61 C232.47,232.61 232.28,232.78 232.28,232.78 C232.28,232.78 232.08,232.95 232.08,232.95 C232.08,232.95 231.87,233.11 231.87,233.11 C231.87,233.11 231.66,233.26 231.66,233.26 C231.66,233.26 231.43,233.39 231.43,233.39 C231.43,233.39 231.21,233.53 231.21,233.53 C231.21,233.53 230.98,233.65 230.98,233.65 C230.98,233.65 230.74,233.76 230.74,233.76 C230.74,233.76 230.5,233.87 230.5,233.87 C230.5,233.87 230.26,233.96 230.26,233.96 C230.26,233.96 230.01,234.04 230.01,234.04 C230.01,234.04 229.76,234.12 229.76,234.12 C229.76,234.12 229.51,234.17 229.51,234.17 C229.51,234.17 229.25,234.23 229.25,234.23 C229.25,234.23 228.99,234.26 228.99,234.26 C228.99,234.26 228.73,234.3 228.73,234.3 C228.73,234.3 228.47,234.31 228.47,234.31 C228.47,234.31 228.21,234.32 228.21,234.32 C228.21,234.32 227.95,234.32 227.95,234.32 C227.95,234.32 227.69,234.32 227.69,234.32 C227.69,234.32 227.43,234.32 227.43,234.32 C227.43,234.32 227.16,234.32 227.16,234.32 C227.16,234.32 226.9,234.32 226.9,234.32 C226.9,234.32 226.64,234.32 226.64,234.32 C226.64,234.32 226.38,234.32 226.38,234.32 C226.38,234.32 226.12,234.32 226.12,234.32 C226.12,234.32 225.86,234.32 225.86,234.32 C225.86,234.32 225.6,234.32 225.6,234.32 C225.6,234.32 225.33,234.32 225.33,234.32 C225.33,234.32 225.07,234.32 225.07,234.32 C225.07,234.32 224.81,234.32 224.81,234.32 C224.81,234.32 224.55,234.32 224.55,234.32 C224.55,234.32 224.29,234.32 224.29,234.32 C224.29,234.32 224.03,234.32 224.03,234.32 C224.03,234.32 223.77,234.32 223.77,234.32 C223.77,234.32 223.5,234.32 223.5,234.32 C223.5,234.32 223.24,234.32 223.24,234.32 C223.24,234.32 222.98,234.32 222.98,234.32 C222.98,234.32 222.72,234.32 222.72,234.32 C222.72,234.32 222.46,234.32 222.46,234.32 C222.46,234.32 222.2,234.32 222.2,234.32 C222.2,234.32 221.94,234.32 221.94,234.32 C221.94,234.32 221.68,234.32 221.68,234.32 C221.68,234.32 221.41,234.32 221.41,234.32 C221.41,234.32 221.15,234.32 221.15,234.32 C221.15,234.32 220.89,234.32 220.89,234.32 C220.89,234.32 220.63,234.32 220.63,234.32 C220.63,234.32 220.37,234.32 220.37,234.32 C220.37,234.32 220.11,234.32 220.11,234.32 C220.11,234.32 219.85,234.32 219.85,234.32 C219.85,234.32 219.58,234.32 219.58,234.32 C219.58,234.32 219.32,234.32 219.32,234.32 C219.32,234.32 219.06,234.32 219.06,234.32 C219.06,234.32 218.8,234.32 218.8,234.32 C218.8,234.32 218.54,234.32 218.54,234.32 C218.54,234.32 218.28,234.32 218.28,234.32 C218.28,234.32 218.02,234.32 218.02,234.32 C218.02,234.32 217.75,234.32 217.75,234.32 C217.75,234.32 217.49,234.32 217.49,234.32 C217.49,234.32 217.23,234.32 217.23,234.32 C217.23,234.32 216.97,234.32 216.97,234.32 C216.97,234.32 216.71,234.32 216.71,234.32 C216.71,234.32 216.45,234.32 216.45,234.32 C216.45,234.32 216.19,234.32 216.19,234.32 C216.19,234.32 215.92,234.32 215.92,234.32 C215.92,234.32 215.66,234.32 215.66,234.32 C215.66,234.32 215.4,234.32 215.4,234.32 C215.4,234.32 215.14,234.32 215.14,234.32 C215.14,234.32 214.88,234.32 214.88,234.32 C214.88,234.32 214.62,234.32 214.62,234.32 C214.62,234.32 214.36,234.32 214.36,234.32 C214.36,234.32 214.1,234.32 214.1,234.32 C214.1,234.32 213.83,234.32 213.83,234.32 C213.83,234.32 213.57,234.32 213.57,234.32 C213.57,234.32 213.31,234.32 213.31,234.32 C213.31,234.32 213.05,234.32 213.05,234.32 C213.05,234.32 212.79,234.32 212.79,234.32 C212.79,234.32 212.53,234.32 212.53,234.32 C212.53,234.32 212.27,234.32 212.27,234.32 C212.27,234.32 212,234.32 212,234.32 C212,234.32 211.74,234.32 211.74,234.32 C211.74,234.32 211.48,234.32 211.48,234.32 C211.48,234.32 211.22,234.32 211.22,234.32 C211.22,234.32 210.96,234.32 210.96,234.32 C210.96,234.32 210.7,234.32 210.7,234.32 C210.7,234.32 210.44,234.32 210.44,234.32 C210.44,234.32 210.17,234.32 210.17,234.32 C210.17,234.32 209.91,234.32 209.91,234.32 C209.91,234.32 209.65,234.32 209.65,234.32 C209.65,234.32 209.39,234.32 209.39,234.32 C209.39,234.32 209.13,234.32 209.13,234.32 C209.13,234.32 208.87,234.32 208.87,234.32 C208.87,234.32 208.61,234.32 208.61,234.32 C208.61,234.32 208.34,234.32 208.34,234.32 C208.34,234.32 208.08,234.32 208.08,234.32 C208.08,234.32 207.82,234.32 207.82,234.32 C207.82,234.32 207.56,234.32 207.56,234.32 C207.56,234.32 207.3,234.32 207.3,234.32 C207.3,234.32 207.04,234.32 207.04,234.32 C207.04,234.32 206.78,234.32 206.78,234.32 C206.78,234.32 206.52,234.3 206.52,234.3 C206.52,234.3 206.26,234.28 206.26,234.28 C206.26,234.28 206,234.25 206,234.25 C206,234.25 205.74,234.21 205.74,234.21 C205.74,234.21 205.48,234.15 205.48,234.15 C205.48,234.15 205.23,234.09 205.23,234.09 C205.23,234.09 204.98,234.01 204.98,234.01 C204.98,234.01 204.73,233.93 204.73,233.93 C204.73,233.93 204.49,233.83 204.49,233.83 C204.49,233.83 204.25,233.72 204.25,233.72 C204.25,233.72 204.01,233.62 204.01,233.62 C204.01,233.62 203.79,233.48 203.79,233.48 C203.79,233.48 203.57,233.35 203.57,233.35 C203.57,233.35 203.34,233.21 203.34,233.21 C203.34,233.21 203.14,233.05 203.14,233.05 C203.14,233.05 202.93,232.89 202.93,232.89 C202.93,232.89 202.73,232.73 202.73,232.73 C202.73,232.73 202.54,232.54 202.54,232.54 C202.54,232.54 202.36,232.36 202.36,232.36 C202.36,232.36 202.17,232.17 202.17,232.17 C202.17,232.17 202.01,231.97 202.01,231.97 C202.01,231.97 201.85,231.76 201.85,231.76 C201.85,231.76 201.69,231.55 201.69,231.55 C201.69,231.55 201.55,231.33 201.55,231.33 C201.55,231.33 201.42,231.11 201.42,231.11 C201.42,231.11 201.29,230.88 201.29,230.88 C201.29,230.88 201.18,230.64 201.18,230.64 C201.18,230.64 201.07,230.4 201.07,230.4 C201.07,230.4 200.96,230.17 200.96,230.17 C200.96,230.17 200.88,229.92 200.88,229.92 C200.88,229.92 200.8,229.67 200.8,229.67 C200.8,229.67 200.73,229.42 200.73,229.42 C200.73,229.42 200.68,229.16 200.68,229.16 C200.68,229.16 200.63,228.91 200.63,228.91 C200.63,228.91 200.58,228.65 200.58,228.65 C200.58,228.65 200.56,228.39 200.56,228.39 C200.56,228.39 200.55,228.13 200.55,228.13 C200.55,228.13 200.53,227.87 200.53,227.87 C200.53,227.87 200.54,227.61 200.54,227.61 C200.54,227.61 200.56,227.35 200.56,227.35 C200.56,227.35 200.58,227.08 200.58,227.08 C200.58,227.08 200.62,226.83 200.62,226.83 C200.62,226.83 200.67,226.57 200.67,226.57 C200.67,226.57 200.72,226.31 200.72,226.31 C200.72,226.31 200.79,226.06 200.79,226.06 C200.79,226.06 200.87,225.81 200.87,225.81 C200.87,225.81 200.95,225.57 200.95,225.57 C200.95,225.57 201.05,225.32 201.05,225.32 C201.05,225.32 201.16,225.09 201.16,225.09 C201.16,225.09 201.27,224.85 201.27,224.85 C201.27,224.85 201.39,224.62 201.39,224.62 C201.39,224.62 201.52,224.39 201.52,224.39 C201.52,224.39 201.65,224.16 201.65,224.16 C201.65,224.16 201.78,223.94 201.78,223.94 C201.78,223.94 201.91,223.71 201.91,223.71 C201.91,223.71 202.03,223.48 202.03,223.48 C202.03,223.48 202.16,223.25 202.16,223.25 C202.16,223.25 202.29,223.03 202.29,223.03 C202.29,223.03 202.42,222.8 202.42,222.8 C202.42,222.8 202.55,222.57 202.55,222.57 C202.55,222.57 202.68,222.35 202.68,222.35 C202.68,222.35 202.81,222.12 202.81,222.12 C202.81,222.12 202.94,221.89 202.94,221.89 C202.94,221.89 203.07,221.66 203.07,221.66 C203.07,221.66 203.2,221.44 203.2,221.44 C203.2,221.44 203.33,221.21 203.33,221.21 C203.33,221.21 203.46,220.98 203.46,220.98 C203.46,220.98 203.58,220.76 203.58,220.76 C203.58,220.76 203.71,220.53 203.71,220.53 C203.71,220.53 203.84,220.3 203.84,220.3 C203.84,220.3 203.97,220.07 203.97,220.07 C203.97,220.07 204.1,219.85 204.1,219.85 C204.1,219.85 204.23,219.62 204.23,219.62 C204.23,219.62 204.36,219.39 204.36,219.39 C204.36,219.39 204.49,219.16 204.49,219.16 C204.49,219.16 204.62,218.94 204.62,218.94 C204.62,218.94 204.75,218.71 204.75,218.71 C204.75,218.71 204.88,218.48 204.88,218.48 C204.88,218.48 205.01,218.26 205.01,218.26 C205.01,218.26 205.13,218.03 205.13,218.03 C205.13,218.03 205.26,217.8 205.26,217.8 C205.26,217.8 205.39,217.57 205.39,217.57 C205.39,217.57 205.52,217.35 205.52,217.35 C205.52,217.35 205.65,217.12 205.65,217.12 C205.65,217.12 205.78,216.89 205.78,216.89 C205.78,216.89 205.91,216.66 205.91,216.66 C205.91,216.66 206.04,216.44 206.04,216.44 C206.04,216.44 206.17,216.21 206.17,216.21 C206.17,216.21 206.3,215.98 206.3,215.98 C206.3,215.98 206.43,215.76 206.43,215.76 C206.43,215.76 206.56,215.53 206.56,215.53 C206.56,215.53 206.68,215.3 206.68,215.3 C206.68,215.3 206.81,215.07 206.81,215.07 C206.81,215.07 206.94,214.85 206.94,214.85 C206.94,214.85 207.07,214.62 207.07,214.62 C207.07,214.62 207.2,214.39 207.2,214.39 C207.2,214.39 207.33,214.17 207.33,214.17 C207.33,214.17 207.46,213.94 207.46,213.94 C207.46,213.94 207.59,213.71 207.59,213.71 C207.59,213.71 207.72,213.48 207.72,213.48 C207.72,213.48 207.85,213.26 207.85,213.26 C207.85,213.26 207.98,213.03 207.98,213.03 C207.98,213.03 208.11,212.8 208.11,212.8 C208.11,212.8 208.23,212.57 208.23,212.57 C208.23,212.57 208.36,212.35 208.36,212.35 C208.36,212.35 208.49,212.12 208.49,212.12 C208.49,212.12 208.62,211.89 208.62,211.89 C208.62,211.89 208.75,211.67 208.75,211.67 C208.75,211.67 208.88,211.44 208.88,211.44 C208.88,211.44 209.01,211.21 209.01,211.21 C209.01,211.21 209.14,210.98 209.14,210.98 C209.14,210.98 209.27,210.76 209.27,210.76 C209.27,210.76 209.4,210.53 209.4,210.53 C209.4,210.53 209.53,210.3 209.53,210.3 C209.53,210.3 209.66,210.08 209.66,210.08 C209.66,210.08 209.78,209.85 209.78,209.85 C209.78,209.85 209.91,209.62 209.91,209.62 C209.91,209.62 210.04,209.39 210.04,209.39 C210.04,209.39 210.17,209.17 210.17,209.17 C210.17,209.17 210.3,208.94 210.3,208.94 C210.3,208.94 210.43,208.71 210.43,208.71 C210.43,208.71 210.56,208.48 210.56,208.48 C210.56,208.48 210.69,208.26 210.69,208.26 C210.69,208.26 210.82,208.03 210.82,208.03 C210.82,208.03 210.95,207.8 210.95,207.8 C210.95,207.8 211.08,207.58 211.08,207.58 C211.08,207.58 211.21,207.35 211.21,207.35 C211.21,207.35 211.33,207.12 211.33,207.12 C211.33,207.12 211.46,206.89 211.46,206.89 C211.46,206.89 211.59,206.67 211.59,206.67 C211.59,206.67 211.72,206.44 211.72,206.44 C211.72,206.44 211.85,206.21 211.85,206.21 C211.85,206.21 211.98,205.98 211.98,205.98 C211.98,205.98 212.13,205.76 212.13,205.76 C212.13,205.76 212.27,205.54 212.27,205.54 C212.27,205.54 212.41,205.33 212.41,205.33 C212.41,205.33 212.57,205.12 212.57,205.12 C212.57,205.12 212.74,204.92 212.74,204.92 C212.74,204.92 212.91,204.72 212.91,204.72 C212.91,204.72 213.1,204.54 213.1,204.54 C213.1,204.54 213.29,204.36 213.29,204.36 C213.29,204.36 213.49,204.19 213.49,204.19 C213.49,204.19 213.69,204.03 213.69,204.03 C213.69,204.03 213.9,203.87 213.9,203.87 C213.9,203.87 214.12,203.73 214.12,203.73 C214.12,203.73 214.34,203.59 214.34,203.59 C214.34,203.59 214.57,203.46 214.57,203.46 C214.57,203.46 214.81,203.35 214.81,203.35 C214.81,203.35 215.04,203.24 215.04,203.24 C215.04,203.24 215.28,203.14 215.28,203.14 C215.28,203.14 215.53,203.06 215.53,203.06 C215.53,203.06 215.78,202.98 215.78,202.98 C215.78,202.98 216.03,202.91 216.03,202.91 C216.03,202.91 216.29,202.86 216.29,202.86 C216.29,202.86 216.55,202.82 216.55,202.82 C216.55,202.82 216.8,202.77 216.8,202.77 C216.8,202.77 217.07,202.76 217.07,202.76 C217.07,202.76 217.33,202.74 217.33,202.74 C217.33,202.74 217.59,202.73 217.59,202.73c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.59 202.73 C217.59,202.73 217.85,202.75 217.85,202.75 C217.85,202.75 218.11,202.76 218.11,202.76 C218.11,202.76 218.37,202.79 218.37,202.79 C218.37,202.79 218.63,202.83 218.63,202.83 C218.63,202.83 218.88,202.88 218.88,202.88 C218.88,202.88 219.14,202.93 219.14,202.93 C219.14,202.93 219.39,203.01 219.39,203.01 C219.39,203.01 219.64,203.09 219.64,203.09 C219.64,203.09 219.88,203.18 219.88,203.18 C219.88,203.18 220.12,203.28 220.12,203.28 C220.12,203.28 220.36,203.39 220.36,203.39 C220.36,203.39 220.59,203.51 220.59,203.51 C220.59,203.51 220.82,203.64 220.82,203.64 C220.82,203.64 221.04,203.78 221.04,203.78 C221.04,203.78 221.26,203.92 221.26,203.92 C221.26,203.92 221.46,204.09 221.46,204.09 C221.46,204.09 221.66,204.25 221.66,204.25 C221.66,204.25 221.87,204.42 221.87,204.42 C221.87,204.42 222.05,204.61 222.05,204.61 C222.05,204.61 222.23,204.79 222.23,204.79 C222.23,204.79 222.4,204.99 222.4,204.99 C222.4,204.99 222.57,205.19 222.57,205.19 C222.57,205.19 222.72,205.41 222.72,205.41 C222.72,205.41 222.86,205.62 222.86,205.62 C222.86,205.62 223.01,205.84 223.01,205.84 C223.01,205.84 223.14,206.06 223.14,206.06 C223.14,206.06 223.27,206.29 223.27,206.29 C223.27,206.29 223.4,206.52 223.4,206.52 C223.4,206.52 223.53,206.75 223.53,206.75 C223.53,206.75 223.66,206.97 223.66,206.97 C223.66,206.97 223.79,207.2 223.79,207.2 C223.79,207.2 223.92,207.43 223.92,207.43 C223.92,207.43 224.05,207.65 224.05,207.65 C224.05,207.65 224.18,207.88 224.18,207.88 C224.18,207.88 224.31,208.11 224.31,208.11 C224.31,208.11 224.44,208.34 224.44,208.34 C224.44,208.34 224.56,208.56 224.56,208.56 C224.56,208.56 224.69,208.79 224.69,208.79 C224.69,208.79 224.82,209.02 224.82,209.02 C224.82,209.02 224.95,209.25 224.95,209.25 C224.95,209.25 225.08,209.47 225.08,209.47 C225.08,209.47 225.21,209.7 225.21,209.7 C225.21,209.7 225.34,209.93 225.34,209.93 C225.34,209.93 225.47,210.15 225.47,210.15 C225.47,210.15 225.6,210.38 225.6,210.38 C225.6,210.38 225.73,210.61 225.73,210.61 C225.73,210.61 225.86,210.84 225.86,210.84 C225.86,210.84 225.99,211.06 225.99,211.06 C225.99,211.06 226.11,211.29 226.11,211.29 C226.11,211.29 226.24,211.52 226.24,211.52 C226.24,211.52 226.37,211.75 226.37,211.75 C226.37,211.75 226.5,211.97 226.5,211.97 C226.5,211.97 226.63,212.2 226.63,212.2 C226.63,212.2 226.76,212.43 226.76,212.43 C226.76,212.43 226.89,212.65 226.89,212.65 C226.89,212.65 227.02,212.88 227.02,212.88 C227.02,212.88 227.15,213.11 227.15,213.11 C227.15,213.11 227.28,213.34 227.28,213.34 C227.28,213.34 227.41,213.56 227.41,213.56 C227.41,213.56 227.54,213.79 227.54,213.79 C227.54,213.79 227.66,214.02 227.66,214.02 C227.66,214.02 227.79,214.25 227.79,214.25 C227.79,214.25 227.92,214.47 227.92,214.47 C227.92,214.47 228.05,214.7 228.05,214.7 C228.05,214.7 228.18,214.93 228.18,214.93 C228.18,214.93 228.31,215.15 228.31,215.15 C228.31,215.15 228.44,215.38 228.44,215.38 C228.44,215.38 228.57,215.61 228.57,215.61 C228.57,215.61 228.7,215.83 228.7,215.83 C228.7,215.83 228.83,216.06 228.83,216.06 C228.83,216.06 228.96,216.29 228.96,216.29 C228.96,216.29 229.09,216.52 229.09,216.52 C229.09,216.52 229.21,216.74 229.21,216.74 C229.21,216.74 229.34,216.97 229.34,216.97 C229.34,216.97 229.47,217.2 229.47,217.2 C229.47,217.2 229.6,217.43 229.6,217.43 C229.6,217.43 229.73,217.65 229.73,217.65 C229.73,217.65 229.86,217.88 229.86,217.88 C229.86,217.88 229.99,218.11 229.99,218.11 C229.99,218.11 230.12,218.33 230.12,218.33 C230.12,218.33 230.25,218.56 230.25,218.56 C230.25,218.56 230.38,218.79 230.38,218.79 C230.38,218.79 230.51,219.02 230.51,219.02 C230.51,219.02 230.64,219.24 230.64,219.24 C230.64,219.24 230.76,219.47 230.76,219.47 C230.76,219.47 230.89,219.7 230.89,219.7 C230.89,219.7 231.02,219.93 231.02,219.93 C231.02,219.93 231.15,220.15 231.15,220.15 C231.15,220.15 231.28,220.38 231.28,220.38 C231.28,220.38 231.41,220.61 231.41,220.61 C231.41,220.61 231.54,220.83 231.54,220.83 C231.54,220.83 231.67,221.06 231.67,221.06 C231.67,221.06 231.8,221.29 231.8,221.29 C231.8,221.29 231.93,221.52 231.93,221.52 C231.93,221.52 232.06,221.74 232.06,221.74 C232.06,221.74 232.19,221.97 232.19,221.97 C232.19,221.97 232.31,222.2 232.31,222.2 C232.31,222.2 232.44,222.43 232.44,222.43 C232.44,222.43 232.57,222.65 232.57,222.65 C232.57,222.65 232.7,222.88 232.7,222.88 C232.7,222.88 232.83,223.11 232.83,223.11 C232.83,223.11 232.96,223.33 232.96,223.33 C232.96,223.33 233.09,223.56 233.09,223.56 C233.09,223.56 233.22,223.79 233.22,223.79 C233.22,223.79 233.35,224.02 233.35,224.02 C233.35,224.02 233.48,224.24 233.48,224.24 C233.48,224.24 233.61,224.47 233.61,224.47 C233.61,224.47 233.73,224.7 233.73,224.7 C233.73,224.7 233.84,224.94 233.84,224.94 C233.84,224.94 233.96,225.17 233.96,225.17 C233.96,225.17 234.07,225.41 234.07,225.41 C234.07,225.41 234.16,225.65 234.16,225.65 C234.16,225.65 234.24,225.9 234.24,225.9 C234.24,225.9 234.32,226.15 234.32,226.15 C234.32,226.15 234.38,226.4 234.38,226.4 C234.38,226.4 234.43,226.66 234.43,226.66 C234.43,226.66 234.48,226.92 234.48,226.92 C234.48,226.92 234.51,227.18 234.51,227.18 C234.51,227.18 234.53,227.44 234.53,227.44 C234.53,227.44 234.54,227.7 234.54,227.7 C234.54,227.7 234.54,227.96 234.54,227.96 C234.54,227.96 234.53,228.22 234.53,228.22 C234.53,228.22 234.51,228.48 234.51,228.48 C234.51,228.48 234.48,228.74 234.48,228.74 C234.48,228.74 234.43,229 234.43,229 C234.43,229 234.39,229.25 234.39,229.25 C234.39,229.25 234.32,229.51 234.32,229.51 C234.32,229.51 234.25,229.76 234.25,229.76 C234.25,229.76 234.17,230.01 234.17,230.01 C234.17,230.01 234.08,230.25 234.08,230.25 C234.08,230.25 233.97,230.49 233.97,230.49 C233.97,230.49 233.86,230.73 233.86,230.73 C233.86,230.73 233.75,230.96 233.75,230.96 C233.75,230.96 233.61,231.18 233.61,231.18 C233.61,231.18 233.48,231.41 233.48,231.41 C233.48,231.41 233.33,231.63 233.33,231.63 C233.33,231.63 233.17,231.83 233.17,231.83 C233.17,231.83 233.01,232.04 233.01,232.04 C233.01,232.04 232.84,232.24 232.84,232.24 C232.84,232.24 232.66,232.42 232.66,232.42 C232.66,232.42 232.47,232.61 232.47,232.61 C232.47,232.61 232.28,232.78 232.28,232.78 C232.28,232.78 232.08,232.95 232.08,232.95 C232.08,232.95 231.87,233.11 231.87,233.11 C231.87,233.11 231.66,233.26 231.66,233.26 C231.66,233.26 231.43,233.39 231.43,233.39 C231.43,233.39 231.21,233.53 231.21,233.53 C231.21,233.53 230.98,233.65 230.98,233.65 C230.98,233.65 230.74,233.76 230.74,233.76 C230.74,233.76 230.5,233.87 230.5,233.87 C230.5,233.87 230.26,233.96 230.26,233.96 C230.26,233.96 230.01,234.04 230.01,234.04 C230.01,234.04 229.76,234.12 229.76,234.12 C229.76,234.12 229.51,234.17 229.51,234.17 C229.51,234.17 229.25,234.23 229.25,234.23 C229.25,234.23 228.99,234.26 228.99,234.26 C228.99,234.26 228.73,234.3 228.73,234.3 C228.73,234.3 228.47,234.31 228.47,234.31 C228.47,234.31 228.21,234.32 228.21,234.32 C228.21,234.32 227.95,234.32 227.95,234.32 C227.95,234.32 227.69,234.32 227.69,234.32 C227.69,234.32 227.43,234.32 227.43,234.32 C227.43,234.32 227.16,234.32 227.16,234.32 C227.16,234.32 226.9,234.32 226.9,234.32 C226.9,234.32 226.64,234.32 226.64,234.32 C226.64,234.32 226.38,234.32 226.38,234.32 C226.38,234.32 226.12,234.32 226.12,234.32 C226.12,234.32 225.86,234.32 225.86,234.32 C225.86,234.32 225.6,234.32 225.6,234.32 C225.6,234.32 225.33,234.32 225.33,234.32 C225.33,234.32 225.07,234.32 225.07,234.32 C225.07,234.32 224.81,234.32 224.81,234.32 C224.81,234.32 224.55,234.32 224.55,234.32 C224.55,234.32 224.29,234.32 224.29,234.32 C224.29,234.32 224.03,234.32 224.03,234.32 C224.03,234.32 223.77,234.32 223.77,234.32 C223.77,234.32 223.5,234.32 223.5,234.32 C223.5,234.32 223.24,234.32 223.24,234.32 C223.24,234.32 222.98,234.32 222.98,234.32 C222.98,234.32 222.72,234.32 222.72,234.32 C222.72,234.32 222.46,234.32 222.46,234.32 C222.46,234.32 222.2,234.32 222.2,234.32 C222.2,234.32 221.94,234.32 221.94,234.32 C221.94,234.32 221.68,234.32 221.68,234.32 C221.68,234.32 221.41,234.32 221.41,234.32 C221.41,234.32 221.15,234.32 221.15,234.32 C221.15,234.32 220.89,234.32 220.89,234.32 C220.89,234.32 220.63,234.32 220.63,234.32 C220.63,234.32 220.37,234.32 220.37,234.32 C220.37,234.32 220.11,234.32 220.11,234.32 C220.11,234.32 219.85,234.32 219.85,234.32 C219.85,234.32 219.58,234.32 219.58,234.32 C219.58,234.32 219.32,234.32 219.32,234.32 C219.32,234.32 219.06,234.32 219.06,234.32 C219.06,234.32 218.8,234.32 218.8,234.32 C218.8,234.32 218.54,234.32 218.54,234.32 C218.54,234.32 218.28,234.32 218.28,234.32 C218.28,234.32 218.02,234.32 218.02,234.32 C218.02,234.32 217.75,234.32 217.75,234.32 C217.75,234.32 217.49,234.32 217.49,234.32 C217.49,234.32 217.23,234.32 217.23,234.32 C217.23,234.32 216.97,234.32 216.97,234.32 C216.97,234.32 216.71,234.32 216.71,234.32 C216.71,234.32 216.45,234.32 216.45,234.32 C216.45,234.32 216.19,234.32 216.19,234.32 C216.19,234.32 215.92,234.32 215.92,234.32 C215.92,234.32 215.66,234.32 215.66,234.32 C215.66,234.32 215.4,234.32 215.4,234.32 C215.4,234.32 215.14,234.32 215.14,234.32 C215.14,234.32 214.88,234.32 214.88,234.32 C214.88,234.32 214.62,234.32 214.62,234.32 C214.62,234.32 214.36,234.32 214.36,234.32 C214.36,234.32 214.1,234.32 214.1,234.32 C214.1,234.32 213.83,234.32 213.83,234.32 C213.83,234.32 213.57,234.32 213.57,234.32 C213.57,234.32 213.31,234.32 213.31,234.32 C213.31,234.32 213.05,234.32 213.05,234.32 C213.05,234.32 212.79,234.32 212.79,234.32 C212.79,234.32 212.53,234.32 212.53,234.32 C212.53,234.32 212.27,234.32 212.27,234.32 C212.27,234.32 212,234.32 212,234.32 C212,234.32 211.74,234.32 211.74,234.32 C211.74,234.32 211.48,234.32 211.48,234.32 C211.48,234.32 211.22,234.32 211.22,234.32 C211.22,234.32 210.96,234.32 210.96,234.32 C210.96,234.32 210.7,234.32 210.7,234.32 C210.7,234.32 210.44,234.32 210.44,234.32 C210.44,234.32 210.17,234.32 210.17,234.32 C210.17,234.32 209.91,234.32 209.91,234.32 C209.91,234.32 209.65,234.32 209.65,234.32 C209.65,234.32 209.39,234.32 209.39,234.32 C209.39,234.32 209.13,234.32 209.13,234.32 C209.13,234.32 208.87,234.32 208.87,234.32 C208.87,234.32 208.61,234.32 208.61,234.32 C208.61,234.32 208.34,234.32 208.34,234.32 C208.34,234.32 208.08,234.32 208.08,234.32 C208.08,234.32 207.82,234.32 207.82,234.32 C207.82,234.32 207.56,234.32 207.56,234.32 C207.56,234.32 207.3,234.32 207.3,234.32 C207.3,234.32 207.04,234.32 207.04,234.32 C207.04,234.32 206.78,234.32 206.78,234.32 C206.78,234.32 206.52,234.3 206.52,234.3 C206.52,234.3 206.26,234.28 206.26,234.28 C206.26,234.28 206,234.25 206,234.25 C206,234.25 205.74,234.21 205.74,234.21 C205.74,234.21 205.48,234.15 205.48,234.15 C205.48,234.15 205.23,234.09 205.23,234.09 C205.23,234.09 204.98,234.01 204.98,234.01 C204.98,234.01 204.73,233.93 204.73,233.93 C204.73,233.93 204.49,233.83 204.49,233.83 C204.49,233.83 204.25,233.72 204.25,233.72 C204.25,233.72 204.01,233.62 204.01,233.62 C204.01,233.62 203.79,233.48 203.79,233.48 C203.79,233.48 203.57,233.35 203.57,233.35 C203.57,233.35 203.34,233.21 203.34,233.21 C203.34,233.21 203.14,233.05 203.14,233.05 C203.14,233.05 202.93,232.89 202.93,232.89 C202.93,232.89 202.73,232.73 202.73,232.73 C202.73,232.73 202.54,232.54 202.54,232.54 C202.54,232.54 202.36,232.36 202.36,232.36 C202.36,232.36 202.17,232.17 202.17,232.17 C202.17,232.17 202.01,231.97 202.01,231.97 C202.01,231.97 201.85,231.76 201.85,231.76 C201.85,231.76 201.69,231.55 201.69,231.55 C201.69,231.55 201.55,231.33 201.55,231.33 C201.55,231.33 201.42,231.11 201.42,231.11 C201.42,231.11 201.29,230.88 201.29,230.88 C201.29,230.88 201.18,230.64 201.18,230.64 C201.18,230.64 201.07,230.4 201.07,230.4 C201.07,230.4 200.96,230.17 200.96,230.17 C200.96,230.17 200.88,229.92 200.88,229.92 C200.88,229.92 200.8,229.67 200.8,229.67 C200.8,229.67 200.73,229.42 200.73,229.42 C200.73,229.42 200.68,229.16 200.68,229.16 C200.68,229.16 200.63,228.91 200.63,228.91 C200.63,228.91 200.58,228.65 200.58,228.65 C200.58,228.65 200.56,228.39 200.56,228.39 C200.56,228.39 200.55,228.13 200.55,228.13 C200.55,228.13 200.53,227.87 200.53,227.87 C200.53,227.87 200.54,227.61 200.54,227.61 C200.54,227.61 200.56,227.35 200.56,227.35 C200.56,227.35 200.58,227.08 200.58,227.08 C200.58,227.08 200.62,226.83 200.62,226.83 C200.62,226.83 200.67,226.57 200.67,226.57 C200.67,226.57 200.72,226.31 200.72,226.31 C200.72,226.31 200.79,226.06 200.79,226.06 C200.79,226.06 200.87,225.81 200.87,225.81 C200.87,225.81 200.95,225.57 200.95,225.57 C200.95,225.57 201.05,225.32 201.05,225.32 C201.05,225.32 201.16,225.09 201.16,225.09 C201.16,225.09 201.27,224.85 201.27,224.85 C201.27,224.85 201.39,224.62 201.39,224.62 C201.39,224.62 201.52,224.39 201.52,224.39 C201.52,224.39 201.65,224.16 201.65,224.16 C201.65,224.16 201.78,223.94 201.78,223.94 C201.78,223.94 201.91,223.71 201.91,223.71 C201.91,223.71 202.03,223.48 202.03,223.48 C202.03,223.48 202.16,223.25 202.16,223.25 C202.16,223.25 202.29,223.03 202.29,223.03 C202.29,223.03 202.42,222.8 202.42,222.8 C202.42,222.8 202.55,222.57 202.55,222.57 C202.55,222.57 202.68,222.35 202.68,222.35 C202.68,222.35 202.81,222.12 202.81,222.12 C202.81,222.12 202.94,221.89 202.94,221.89 C202.94,221.89 203.07,221.66 203.07,221.66 C203.07,221.66 203.2,221.44 203.2,221.44 C203.2,221.44 203.33,221.21 203.33,221.21 C203.33,221.21 203.46,220.98 203.46,220.98 C203.46,220.98 203.58,220.76 203.58,220.76 C203.58,220.76 203.71,220.53 203.71,220.53 C203.71,220.53 203.84,220.3 203.84,220.3 C203.84,220.3 203.97,220.07 203.97,220.07 C203.97,220.07 204.1,219.85 204.1,219.85 C204.1,219.85 204.23,219.62 204.23,219.62 C204.23,219.62 204.36,219.39 204.36,219.39 C204.36,219.39 204.49,219.16 204.49,219.16 C204.49,219.16 204.62,218.94 204.62,218.94 C204.62,218.94 204.75,218.71 204.75,218.71 C204.75,218.71 204.88,218.48 204.88,218.48 C204.88,218.48 205.01,218.26 205.01,218.26 C205.01,218.26 205.13,218.03 205.13,218.03 C205.13,218.03 205.26,217.8 205.26,217.8 C205.26,217.8 205.39,217.57 205.39,217.57 C205.39,217.57 205.52,217.35 205.52,217.35 C205.52,217.35 205.65,217.12 205.65,217.12 C205.65,217.12 205.78,216.89 205.78,216.89 C205.78,216.89 205.91,216.66 205.91,216.66 C205.91,216.66 206.04,216.44 206.04,216.44 C206.04,216.44 206.17,216.21 206.17,216.21 C206.17,216.21 206.3,215.98 206.3,215.98 C206.3,215.98 206.43,215.76 206.43,215.76 C206.43,215.76 206.56,215.53 206.56,215.53 C206.56,215.53 206.68,215.3 206.68,215.3 C206.68,215.3 206.81,215.07 206.81,215.07 C206.81,215.07 206.94,214.85 206.94,214.85 C206.94,214.85 207.07,214.62 207.07,214.62 C207.07,214.62 207.2,214.39 207.2,214.39 C207.2,214.39 207.33,214.17 207.33,214.17 C207.33,214.17 207.46,213.94 207.46,213.94 C207.46,213.94 207.59,213.71 207.59,213.71 C207.59,213.71 207.72,213.48 207.72,213.48 C207.72,213.48 207.85,213.26 207.85,213.26 C207.85,213.26 207.98,213.03 207.98,213.03 C207.98,213.03 208.11,212.8 208.11,212.8 C208.11,212.8 208.23,212.57 208.23,212.57 C208.23,212.57 208.36,212.35 208.36,212.35 C208.36,212.35 208.49,212.12 208.49,212.12 C208.49,212.12 208.62,211.89 208.62,211.89 C208.62,211.89 208.75,211.67 208.75,211.67 C208.75,211.67 208.88,211.44 208.88,211.44 C208.88,211.44 209.01,211.21 209.01,211.21 C209.01,211.21 209.14,210.98 209.14,210.98 C209.14,210.98 209.27,210.76 209.27,210.76 C209.27,210.76 209.4,210.53 209.4,210.53 C209.4,210.53 209.53,210.3 209.53,210.3 C209.53,210.3 209.66,210.08 209.66,210.08 C209.66,210.08 209.78,209.85 209.78,209.85 C209.78,209.85 209.91,209.62 209.91,209.62 C209.91,209.62 210.04,209.39 210.04,209.39 C210.04,209.39 210.17,209.17 210.17,209.17 C210.17,209.17 210.3,208.94 210.3,208.94 C210.3,208.94 210.43,208.71 210.43,208.71 C210.43,208.71 210.56,208.48 210.56,208.48 C210.56,208.48 210.69,208.26 210.69,208.26 C210.69,208.26 210.82,208.03 210.82,208.03 C210.82,208.03 210.95,207.8 210.95,207.8 C210.95,207.8 211.08,207.58 211.08,207.58 C211.08,207.58 211.21,207.35 211.21,207.35 C211.21,207.35 211.33,207.12 211.33,207.12 C211.33,207.12 211.46,206.89 211.46,206.89 C211.46,206.89 211.59,206.67 211.59,206.67 C211.59,206.67 211.72,206.44 211.72,206.44 C211.72,206.44 211.85,206.21 211.85,206.21 C211.85,206.21 211.98,205.98 211.98,205.98 C211.98,205.98 212.13,205.76 212.13,205.76 C212.13,205.76 212.27,205.54 212.27,205.54 C212.27,205.54 212.41,205.33 212.41,205.33 C212.41,205.33 212.57,205.12 212.57,205.12 C212.57,205.12 212.74,204.92 212.74,204.92 C212.74,204.92 212.91,204.72 212.91,204.72 C212.91,204.72 213.1,204.54 213.1,204.54 C213.1,204.54 213.29,204.36 213.29,204.36 C213.29,204.36 213.49,204.19 213.49,204.19 C213.49,204.19 213.69,204.03 213.69,204.03 C213.69,204.03 213.9,203.87 213.9,203.87 C213.9,203.87 214.12,203.73 214.12,203.73 C214.12,203.73 214.34,203.59 214.34,203.59 C214.34,203.59 214.57,203.46 214.57,203.46 C214.57,203.46 214.81,203.35 214.81,203.35 C214.81,203.35 215.04,203.24 215.04,203.24 C215.04,203.24 215.28,203.14 215.28,203.14 C215.28,203.14 215.53,203.06 215.53,203.06 C215.53,203.06 215.78,202.98 215.78,202.98 C215.78,202.98 216.03,202.91 216.03,202.91 C216.03,202.91 216.29,202.86 216.29,202.86 C216.29,202.86 216.55,202.82 216.55,202.82 C216.55,202.82 216.8,202.77 216.8,202.77 C216.8,202.77 217.07,202.76 217.07,202.76 C217.07,202.76 217.33,202.74 217.33,202.74 C217.33,202.74 217.59,202.73 217.59,202.73c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml
new file mode 100644
index 0000000..e7ce426
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml
@@ -0,0 +1 @@
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.7 202.08 C217.7,202.08 217.97,202.09 217.97,202.09 C217.97,202.09 218.23,202.13 218.23,202.13 C218.23,202.13 218.49,202.16 218.49,202.16 C218.49,202.16 218.75,202.22 218.75,202.22 C218.75,202.22 219.01,202.28 219.01,202.28 C219.01,202.28 219.26,202.36 219.26,202.36 C219.26,202.36 219.51,202.44 219.51,202.44 C219.51,202.44 219.75,202.54 219.75,202.54 C219.75,202.54 219.99,202.65 219.99,202.65 C219.99,202.65 220.23,202.77 220.23,202.77 C220.23,202.77 220.46,202.9 220.46,202.9 C220.46,202.9 220.68,203.05 220.68,203.05 C220.68,203.05 220.9,203.2 220.9,203.2 C220.9,203.2 221.11,203.35 221.11,203.35 C221.11,203.35 221.33,203.51 221.33,203.51 C221.33,203.51 221.54,203.66 221.54,203.66 C221.54,203.66 221.75,203.82 221.75,203.82 C221.75,203.82 221.97,203.97 221.97,203.97 C221.97,203.97 222.18,204.13 222.18,204.13 C222.18,204.13 222.4,204.28 222.4,204.28 C222.4,204.28 222.61,204.44 222.61,204.44 C222.61,204.44 222.83,204.59 222.83,204.59 C222.83,204.59 223.04,204.75 223.04,204.75 C223.04,204.75 223.25,204.9 223.25,204.9 C223.25,204.9 223.47,205.06 223.47,205.06 C223.47,205.06 223.68,205.21 223.68,205.21 C223.68,205.21 223.9,205.37 223.9,205.37 C223.9,205.37 224.11,205.52 224.11,205.52 C224.11,205.52 224.33,205.68 224.33,205.68 C224.33,205.68 224.54,205.83 224.54,205.83 C224.54,205.83 224.75,205.98 224.75,205.98 C224.75,205.98 224.97,206.14 224.97,206.14 C224.97,206.14 225.18,206.29 225.18,206.29 C225.18,206.29 225.4,206.45 225.4,206.45 C225.4,206.45 225.61,206.6 225.61,206.6 C225.61,206.6 225.83,206.76 225.83,206.76 C225.83,206.76 226.04,206.91 226.04,206.91 C226.04,206.91 226.25,207.07 226.25,207.07 C226.25,207.07 226.47,207.22 226.47,207.22 C226.47,207.22 226.68,207.38 226.68,207.38 C226.68,207.38 226.9,207.53 226.9,207.53 C226.9,207.53 227.11,207.69 227.11,207.69 C227.11,207.69 227.32,207.84 227.32,207.84 C227.32,207.84 227.54,208 227.54,208 C227.54,208 227.75,208.15 227.75,208.15 C227.75,208.15 227.96,208.31 227.96,208.31 C227.96,208.31 228.18,208.46 228.18,208.46 C228.18,208.46 228.39,208.62 228.39,208.62 C228.39,208.62 228.61,208.78 228.61,208.78 C228.61,208.78 228.82,208.93 228.82,208.93 C228.82,208.93 229.03,209.09 229.03,209.09 C229.03,209.09 229.25,209.24 229.25,209.24 C229.25,209.24 229.46,209.4 229.46,209.4 C229.46,209.4 229.67,209.55 229.67,209.55 C229.67,209.55 229.89,209.71 229.89,209.71 C229.89,209.71 230.1,209.86 230.1,209.86 C230.1,209.86 230.32,210.02 230.32,210.02 C230.32,210.02 230.53,210.17 230.53,210.17 C230.53,210.17 230.74,210.33 230.74,210.33 C230.74,210.33 230.96,210.49 230.96,210.49 C230.96,210.49 231.17,210.64 231.17,210.64 C231.17,210.64 231.38,210.8 231.38,210.8 C231.38,210.8 231.6,210.95 231.6,210.95 C231.6,210.95 231.81,211.11 231.81,211.11 C231.81,211.11 232.03,211.26 232.03,211.26 C232.03,211.26 232.24,211.42 232.24,211.42 C232.24,211.42 232.44,211.59 232.44,211.59 C232.44,211.59 232.65,211.75 232.65,211.75 C232.65,211.75 232.84,211.94 232.84,211.94 C232.84,211.94 233.03,212.12 233.03,212.12 C233.03,212.12 233.2,212.32 233.2,212.32 C233.2,212.32 233.37,212.53 233.37,212.53 C233.37,212.53 233.52,212.74 233.52,212.74 C233.52,212.74 233.67,212.96 233.67,212.96 C233.67,212.96 233.8,213.19 233.8,213.19 C233.8,213.19 233.93,213.42 233.93,213.42 C233.93,213.42 234.04,213.66 234.04,213.66 C234.04,213.66 234.14,213.9 234.14,213.9 C234.14,213.9 234.24,214.15 234.24,214.15 C234.24,214.15 234.31,214.4 234.31,214.4 C234.31,214.4 234.39,214.66 234.39,214.66 C234.39,214.66 234.44,214.92 234.44,214.92 C234.44,214.92 234.49,215.18 234.49,215.18 C234.49,215.18 234.51,215.44 234.51,215.44 C234.51,215.44 234.54,215.7 234.54,215.7 C234.54,215.7 234.54,215.96 234.54,215.96 C234.54,215.96 234.54,216.23 234.54,216.23 C234.54,216.23 234.52,216.49 234.52,216.49 C234.52,216.49 234.49,216.76 234.49,216.76 C234.49,216.76 234.46,217.02 234.46,217.02 C234.46,217.02 234.4,217.28 234.4,217.28 C234.4,217.28 234.34,217.53 234.34,217.53 C234.34,217.53 234.26,217.79 234.26,217.79 C234.26,217.79 234.18,218.04 234.18,218.04 C234.18,218.04 234.1,218.29 234.1,218.29 C234.1,218.29 234.02,218.54 234.02,218.54 C234.02,218.54 233.94,218.79 233.94,218.79 C233.94,218.79 233.86,219.04 233.86,219.04 C233.86,219.04 233.78,219.29 233.78,219.29 C233.78,219.29 233.69,219.55 233.69,219.55 C233.69,219.55 233.61,219.8 233.61,219.8 C233.61,219.8 233.53,220.05 233.53,220.05 C233.53,220.05 233.45,220.3 233.45,220.3 C233.45,220.3 233.37,220.55 233.37,220.55 C233.37,220.55 233.29,220.8 233.29,220.8 C233.29,220.8 233.21,221.05 233.21,221.05 C233.21,221.05 233.12,221.31 233.12,221.31 C233.12,221.31 233.04,221.56 233.04,221.56 C233.04,221.56 232.96,221.81 232.96,221.81 C232.96,221.81 232.88,222.06 232.88,222.06 C232.88,222.06 232.8,222.31 232.8,222.31 C232.8,222.31 232.72,222.56 232.72,222.56 C232.72,222.56 232.64,222.81 232.64,222.81 C232.64,222.81 232.55,223.07 232.55,223.07 C232.55,223.07 232.47,223.32 232.47,223.32 C232.47,223.32 232.39,223.57 232.39,223.57 C232.39,223.57 232.31,223.82 232.31,223.82 C232.31,223.82 232.23,224.07 232.23,224.07 C232.23,224.07 232.15,224.32 232.15,224.32 C232.15,224.32 232.06,224.57 232.06,224.57 C232.06,224.57 231.98,224.83 231.98,224.83 C231.98,224.83 231.9,225.08 231.9,225.08 C231.9,225.08 231.82,225.33 231.82,225.33 C231.82,225.33 231.74,225.58 231.74,225.58 C231.74,225.58 231.65,225.83 231.65,225.83 C231.65,225.83 231.57,226.08 231.57,226.08 C231.57,226.08 231.49,226.33 231.49,226.33 C231.49,226.33 231.41,226.58 231.41,226.58 C231.41,226.58 231.32,226.83 231.32,226.83 C231.32,226.83 231.24,227.08 231.24,227.08 C231.24,227.08 231.16,227.34 231.16,227.34 C231.16,227.34 231.08,227.59 231.08,227.59 C231.08,227.59 230.99,227.84 230.99,227.84 C230.99,227.84 230.91,228.09 230.91,228.09 C230.91,228.09 230.83,228.34 230.83,228.34 C230.83,228.34 230.75,228.59 230.75,228.59 C230.75,228.59 230.67,228.84 230.67,228.84 C230.67,228.84 230.58,229.09 230.58,229.09 C230.58,229.09 230.5,229.35 230.5,229.35 C230.5,229.35 230.42,229.6 230.42,229.6 C230.42,229.6 230.34,229.85 230.34,229.85 C230.34,229.85 230.25,230.1 230.25,230.1 C230.25,230.1 230.17,230.35 230.17,230.35 C230.17,230.35 230.09,230.6 230.09,230.6 C230.09,230.6 230.01,230.85 230.01,230.85 C230.01,230.85 229.92,231.1 229.92,231.1 C229.92,231.1 229.83,231.35 229.83,231.35 C229.83,231.35 229.73,231.6 229.73,231.6 C229.73,231.6 229.61,231.83 229.61,231.83 C229.61,231.83 229.49,232.07 229.49,232.07 C229.49,232.07 229.36,232.29 229.36,232.29 C229.36,232.29 229.21,232.52 229.21,232.52 C229.21,232.52 229.06,232.73 229.06,232.73 C229.06,232.73 228.89,232.94 228.89,232.94 C228.89,232.94 228.72,233.13 228.72,233.13 C228.72,233.13 228.54,233.32 228.54,233.32 C228.54,233.32 228.34,233.51 228.34,233.51 C228.34,233.51 228.14,233.68 228.14,233.68 C228.14,233.68 227.94,233.84 227.94,233.84 C227.94,233.84 227.72,233.99 227.72,233.99 C227.72,233.99 227.5,234.14 227.5,234.14 C227.5,234.14 227.27,234.27 227.27,234.27 C227.27,234.27 227.04,234.39 227.04,234.39 C227.04,234.39 226.79,234.5 226.79,234.5 C226.79,234.5 226.55,234.6 226.55,234.6 C226.55,234.6 226.3,234.68 226.3,234.68 C226.3,234.68 226.05,234.76 226.05,234.76 C226.05,234.76 225.79,234.82 225.79,234.82 C225.79,234.82 225.53,234.88 225.53,234.88 C225.53,234.88 225.27,234.92 225.27,234.92 C225.27,234.92 225.01,234.95 225.01,234.95 C225.01,234.95 224.74,234.96 224.74,234.96 C224.74,234.96 224.48,234.96 224.48,234.96 C224.48,234.96 224.22,234.96 224.22,234.96 C224.22,234.96 223.95,234.96 223.95,234.96 C223.95,234.96 223.69,234.96 223.69,234.96 C223.69,234.96 223.42,234.96 223.42,234.96 C223.42,234.96 223.16,234.96 223.16,234.96 C223.16,234.96 222.89,234.96 222.89,234.96 C222.89,234.96 222.63,234.96 222.63,234.96 C222.63,234.96 222.37,234.97 222.37,234.97 C222.37,234.97 222.1,234.97 222.1,234.97 C222.1,234.97 221.84,234.97 221.84,234.97 C221.84,234.97 221.57,234.97 221.57,234.97 C221.57,234.97 221.31,234.97 221.31,234.97 C221.31,234.97 221.04,234.97 221.04,234.97 C221.04,234.97 220.78,234.97 220.78,234.97 C220.78,234.97 220.52,234.97 220.52,234.97 C220.52,234.97 220.25,234.97 220.25,234.97 C220.25,234.97 219.99,234.97 219.99,234.97 C219.99,234.97 219.72,234.97 219.72,234.97 C219.72,234.97 219.46,234.97 219.46,234.97 C219.46,234.97 219.19,234.97 219.19,234.97 C219.19,234.97 218.93,234.97 218.93,234.97 C218.93,234.97 218.67,234.97 218.67,234.97 C218.67,234.97 218.4,234.97 218.4,234.97 C218.4,234.97 218.14,234.97 218.14,234.97 C218.14,234.97 217.87,234.97 217.87,234.97 C217.87,234.97 217.61,234.97 217.61,234.97 C217.61,234.97 217.34,234.97 217.34,234.97 C217.34,234.97 217.08,234.97 217.08,234.97 C217.08,234.97 216.82,234.97 216.82,234.97 C216.82,234.97 216.55,234.97 216.55,234.97 C216.55,234.97 216.29,234.97 216.29,234.97 C216.29,234.97 216.02,234.97 216.02,234.97 C216.02,234.97 215.76,234.97 215.76,234.97 C215.76,234.97 215.49,234.97 215.49,234.97 C215.49,234.97 215.23,234.97 215.23,234.97 C215.23,234.97 214.97,234.97 214.97,234.97 C214.97,234.97 214.7,234.97 214.7,234.97 C214.7,234.97 214.44,234.97 214.44,234.97 C214.44,234.97 214.17,234.97 214.17,234.97 C214.17,234.97 213.91,234.97 213.91,234.97 C213.91,234.97 213.64,234.97 213.64,234.97 C213.64,234.97 213.38,234.97 213.38,234.97 C213.38,234.97 213.12,234.97 213.12,234.97 C213.12,234.97 212.85,234.97 212.85,234.97 C212.85,234.97 212.59,234.96 212.59,234.96 C212.59,234.96 212.32,234.96 212.32,234.96 C212.32,234.96 212.06,234.96 212.06,234.96 C212.06,234.96 211.79,234.96 211.79,234.96 C211.79,234.96 211.53,234.96 211.53,234.96 C211.53,234.96 211.27,234.96 211.27,234.96 C211.27,234.96 211,234.96 211,234.96 C211,234.96 210.74,234.96 210.74,234.96 C210.74,234.96 210.47,234.96 210.47,234.96 C210.47,234.96 210.21,234.95 210.21,234.95 C210.21,234.95 209.94,234.93 209.94,234.93 C209.94,234.93 209.68,234.9 209.68,234.9 C209.68,234.9 209.42,234.86 209.42,234.86 C209.42,234.86 209.16,234.8 209.16,234.8 C209.16,234.8 208.91,234.74 208.91,234.74 C208.91,234.74 208.66,234.66 208.66,234.66 C208.66,234.66 208.41,234.56 208.41,234.56 C208.41,234.56 208.17,234.46 208.17,234.46 C208.17,234.46 207.93,234.35 207.93,234.35 C207.93,234.35 207.69,234.22 207.69,234.22 C207.69,234.22 207.47,234.08 207.47,234.08 C207.47,234.08 207.25,233.94 207.25,233.94 C207.25,233.94 207.04,233.78 207.04,233.78 C207.04,233.78 206.83,233.62 206.83,233.62 C206.83,233.62 206.63,233.44 206.63,233.44 C206.63,233.44 206.44,233.26 206.44,233.26 C206.44,233.26 206.27,233.06 206.27,233.06 C206.27,233.06 206.09,232.86 206.09,232.86 C206.09,232.86 205.93,232.65 205.93,232.65 C205.93,232.65 205.78,232.44 205.78,232.44 C205.78,232.44 205.64,232.21 205.64,232.21 C205.64,232.21 205.51,231.98 205.51,231.98 C205.51,231.98 205.39,231.75 205.39,231.75 C205.39,231.75 205.28,231.51 205.28,231.51 C205.28,231.51 205.18,231.26 205.18,231.26 C205.18,231.26 205.09,231.01 205.09,231.01 C205.09,231.01 205.01,230.76 205.01,230.76 C205.01,230.76 204.93,230.51 204.93,230.51 C204.93,230.51 204.85,230.26 204.85,230.26 C204.85,230.26 204.76,230.01 204.76,230.01 C204.76,230.01 204.68,229.76 204.68,229.76 C204.68,229.76 204.6,229.51 204.6,229.51 C204.6,229.51 204.52,229.26 204.52,229.26 C204.52,229.26 204.43,229.01 204.43,229.01 C204.43,229.01 204.35,228.75 204.35,228.75 C204.35,228.75 204.27,228.5 204.27,228.5 C204.27,228.5 204.19,228.25 204.19,228.25 C204.19,228.25 204.1,228 204.1,228 C204.1,228 204.02,227.75 204.02,227.75 C204.02,227.75 203.94,227.5 203.94,227.5 C203.94,227.5 203.86,227.25 203.86,227.25 C203.86,227.25 203.78,227 203.78,227 C203.78,227 203.69,226.74 203.69,226.74 C203.69,226.74 203.61,226.49 203.61,226.49 C203.61,226.49 203.53,226.24 203.53,226.24 C203.53,226.24 203.45,225.99 203.45,225.99 C203.45,225.99 203.36,225.74 203.36,225.74 C203.36,225.74 203.28,225.49 203.28,225.49 C203.28,225.49 203.2,225.24 203.2,225.24 C203.2,225.24 203.12,224.99 203.12,224.99 C203.12,224.99 203.03,224.74 203.03,224.74 C203.03,224.74 202.95,224.48 202.95,224.48 C202.95,224.48 202.87,224.23 202.87,224.23 C202.87,224.23 202.79,223.98 202.79,223.98 C202.79,223.98 202.71,223.73 202.71,223.73 C202.71,223.73 202.63,223.48 202.63,223.48 C202.63,223.48 202.54,223.23 202.54,223.23 C202.54,223.23 202.46,222.98 202.46,222.98 C202.46,222.98 202.38,222.72 202.38,222.72 C202.38,222.72 202.3,222.47 202.3,222.47 C202.3,222.47 202.22,222.22 202.22,222.22 C202.22,222.22 202.14,221.97 202.14,221.97 C202.14,221.97 202.06,221.72 202.06,221.72 C202.06,221.72 201.97,221.47 201.97,221.47 C201.97,221.47 201.89,221.22 201.89,221.22 C201.89,221.22 201.81,220.96 201.81,220.96 C201.81,220.96 201.73,220.71 201.73,220.71 C201.73,220.71 201.65,220.46 201.65,220.46 C201.65,220.46 201.57,220.21 201.57,220.21 C201.57,220.21 201.49,219.96 201.49,219.96 C201.49,219.96 201.4,219.71 201.4,219.71 C201.4,219.71 201.32,219.46 201.32,219.46 C201.32,219.46 201.24,219.2 201.24,219.2 C201.24,219.2 201.16,218.95 201.16,218.95 C201.16,218.95 201.08,218.7 201.08,218.7 C201.08,218.7 201,218.45 201,218.45 C201,218.45 200.92,218.2 200.92,218.2 C200.92,218.2 200.83,217.95 200.83,217.95 C200.83,217.95 200.76,217.7 200.76,217.7 C200.76,217.7 200.69,217.44 200.69,217.44 C200.69,217.44 200.62,217.18 200.62,217.18 C200.62,217.18 200.58,216.92 200.58,216.92 C200.58,216.92 200.54,216.66 200.54,216.66 C200.54,216.66 200.52,216.4 200.52,216.4 C200.52,216.4 200.5,216.14 200.5,216.14 C200.5,216.14 200.5,215.87 200.5,215.87 C200.5,215.87 200.52,215.61 200.52,215.61 C200.52,215.61 200.54,215.34 200.54,215.34 C200.54,215.34 200.58,215.08 200.58,215.08 C200.58,215.08 200.62,214.82 200.62,214.82 C200.62,214.82 200.69,214.57 200.69,214.57 C200.69,214.57 200.76,214.31 200.76,214.31 C200.76,214.31 200.84,214.06 200.84,214.06 C200.84,214.06 200.93,213.81 200.93,213.81 C200.93,213.81 201.05,213.57 201.05,213.57 C201.05,213.57 201.16,213.33 201.16,213.33 C201.16,213.33 201.29,213.11 201.29,213.11 C201.29,213.11 201.43,212.88 201.43,212.88 C201.43,212.88 201.58,212.67 201.58,212.67 C201.58,212.67 201.74,212.45 201.74,212.45 C201.74,212.45 201.91,212.25 201.91,212.25 C201.91,212.25 202.09,212.06 202.09,212.06 C202.09,212.06 202.27,211.87 202.27,211.87 C202.27,211.87 202.47,211.69 202.47,211.69 C202.47,211.69 202.67,211.52 202.67,211.52 C202.67,211.52 202.88,211.36 202.88,211.36 C202.88,211.36 203.1,211.21 203.1,211.21 C203.1,211.21 203.31,211.05 203.31,211.05 C203.31,211.05 203.52,210.9 203.52,210.9 C203.52,210.9 203.74,210.74 203.74,210.74 C203.74,210.74 203.95,210.58 203.95,210.58 C203.95,210.58 204.16,210.43 204.16,210.43 C204.16,210.43 204.38,210.27 204.38,210.27 C204.38,210.27 204.59,210.12 204.59,210.12 C204.59,210.12 204.81,209.96 204.81,209.96 C204.81,209.96 205.02,209.81 205.02,209.81 C205.02,209.81 205.23,209.65 205.23,209.65 C205.23,209.65 205.45,209.5 205.45,209.5 C205.45,209.5 205.66,209.34 205.66,209.34 C205.66,209.34 205.87,209.19 205.87,209.19 C205.87,209.19 206.09,209.03 206.09,209.03 C206.09,209.03 206.3,208.88 206.3,208.88 C206.3,208.88 206.52,208.72 206.52,208.72 C206.52,208.72 206.73,208.57 206.73,208.57 C206.73,208.57 206.94,208.41 206.94,208.41 C206.94,208.41 207.16,208.25 207.16,208.25 C207.16,208.25 207.37,208.1 207.37,208.1 C207.37,208.1 207.58,207.94 207.58,207.94 C207.58,207.94 207.8,207.79 207.8,207.79 C207.8,207.79 208.01,207.63 208.01,207.63 C208.01,207.63 208.23,207.48 208.23,207.48 C208.23,207.48 208.44,207.32 208.44,207.32 C208.44,207.32 208.65,207.17 208.65,207.17 C208.65,207.17 208.87,207.01 208.87,207.01 C208.87,207.01 209.08,206.86 209.08,206.86 C209.08,206.86 209.3,206.7 209.3,206.7 C209.3,206.7 209.51,206.55 209.51,206.55 C209.51,206.55 209.73,206.39 209.73,206.39 C209.73,206.39 209.94,206.24 209.94,206.24 C209.94,206.24 210.15,206.08 210.15,206.08 C210.15,206.08 210.37,205.93 210.37,205.93 C210.37,205.93 210.58,205.77 210.58,205.77 C210.58,205.77 210.8,205.62 210.8,205.62 C210.8,205.62 211.01,205.46 211.01,205.46 C211.01,205.46 211.23,205.31 211.23,205.31 C211.23,205.31 211.44,205.16 211.44,205.16 C211.44,205.16 211.65,205 211.65,205 C211.65,205 211.87,204.85 211.87,204.85 C211.87,204.85 212.08,204.69 212.08,204.69 C212.08,204.69 212.3,204.54 212.3,204.54 C212.3,204.54 212.51,204.38 212.51,204.38 C212.51,204.38 212.73,204.23 212.73,204.23 C212.73,204.23 212.94,204.07 212.94,204.07 C212.94,204.07 213.15,203.92 213.15,203.92 C213.15,203.92 213.37,203.76 213.37,203.76 C213.37,203.76 213.58,203.61 213.58,203.61 C213.58,203.61 213.8,203.45 213.8,203.45 C213.8,203.45 214.01,203.3 214.01,203.3 C214.01,203.3 214.23,203.14 214.23,203.14 C214.23,203.14 214.45,203 214.45,203 C214.45,203 214.67,202.86 214.67,202.86 C214.67,202.86 214.9,202.73 214.9,202.73 C214.9,202.73 215.14,202.61 215.14,202.61 C215.14,202.61 215.38,202.51 215.38,202.51 C215.38,202.51 215.63,202.41 215.63,202.41 C215.63,202.41 215.88,202.33 215.88,202.33 C215.88,202.33 216.13,202.26 216.13,202.26 C216.13,202.26 216.39,202.2 216.39,202.2 C216.39,202.2 216.65,202.15 216.65,202.15 C216.65,202.15 216.91,202.11 216.91,202.11 C216.91,202.11 217.18,202.09 217.18,202.09 C217.18,202.09 217.44,202.08 217.44,202.08 C217.44,202.08 217.7,202.08 217.7,202.08c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.7 202.08 C217.7,202.08 217.97,202.09 217.97,202.09 C217.97,202.09 218.23,202.13 218.23,202.13 C218.23,202.13 218.49,202.16 218.49,202.16 C218.49,202.16 218.75,202.22 218.75,202.22 C218.75,202.22 219.01,202.28 219.01,202.28 C219.01,202.28 219.26,202.36 219.26,202.36 C219.26,202.36 219.51,202.44 219.51,202.44 C219.51,202.44 219.75,202.54 219.75,202.54 C219.75,202.54 219.99,202.65 219.99,202.65 C219.99,202.65 220.23,202.77 220.23,202.77 C220.23,202.77 220.46,202.9 220.46,202.9 C220.46,202.9 220.68,203.05 220.68,203.05 C220.68,203.05 220.9,203.2 220.9,203.2 C220.9,203.2 221.11,203.35 221.11,203.35 C221.11,203.35 221.33,203.51 221.33,203.51 C221.33,203.51 221.54,203.66 221.54,203.66 C221.54,203.66 221.75,203.82 221.75,203.82 C221.75,203.82 221.97,203.97 221.97,203.97 C221.97,203.97 222.18,204.13 222.18,204.13 C222.18,204.13 222.4,204.28 222.4,204.28 C222.4,204.28 222.61,204.44 222.61,204.44 C222.61,204.44 222.83,204.59 222.83,204.59 C222.83,204.59 223.04,204.75 223.04,204.75 C223.04,204.75 223.25,204.9 223.25,204.9 C223.25,204.9 223.47,205.06 223.47,205.06 C223.47,205.06 223.68,205.21 223.68,205.21 C223.68,205.21 223.9,205.37 223.9,205.37 C223.9,205.37 224.11,205.52 224.11,205.52 C224.11,205.52 224.33,205.68 224.33,205.68 C224.33,205.68 224.54,205.83 224.54,205.83 C224.54,205.83 224.75,205.98 224.75,205.98 C224.75,205.98 224.97,206.14 224.97,206.14 C224.97,206.14 225.18,206.29 225.18,206.29 C225.18,206.29 225.4,206.45 225.4,206.45 C225.4,206.45 225.61,206.6 225.61,206.6 C225.61,206.6 225.83,206.76 225.83,206.76 C225.83,206.76 226.04,206.91 226.04,206.91 C226.04,206.91 226.25,207.07 226.25,207.07 C226.25,207.07 226.47,207.22 226.47,207.22 C226.47,207.22 226.68,207.38 226.68,207.38 C226.68,207.38 226.9,207.53 226.9,207.53 C226.9,207.53 227.11,207.69 227.11,207.69 C227.11,207.69 227.32,207.84 227.32,207.84 C227.32,207.84 227.54,208 227.54,208 C227.54,208 227.75,208.15 227.75,208.15 C227.75,208.15 227.96,208.31 227.96,208.31 C227.96,208.31 228.18,208.46 228.18,208.46 C228.18,208.46 228.39,208.62 228.39,208.62 C228.39,208.62 228.61,208.78 228.61,208.78 C228.61,208.78 228.82,208.93 228.82,208.93 C228.82,208.93 229.03,209.09 229.03,209.09 C229.03,209.09 229.25,209.24 229.25,209.24 C229.25,209.24 229.46,209.4 229.46,209.4 C229.46,209.4 229.67,209.55 229.67,209.55 C229.67,209.55 229.89,209.71 229.89,209.71 C229.89,209.71 230.1,209.86 230.1,209.86 C230.1,209.86 230.32,210.02 230.32,210.02 C230.32,210.02 230.53,210.17 230.53,210.17 C230.53,210.17 230.74,210.33 230.74,210.33 C230.74,210.33 230.96,210.49 230.96,210.49 C230.96,210.49 231.17,210.64 231.17,210.64 C231.17,210.64 231.38,210.8 231.38,210.8 C231.38,210.8 231.6,210.95 231.6,210.95 C231.6,210.95 231.81,211.11 231.81,211.11 C231.81,211.11 232.03,211.26 232.03,211.26 C232.03,211.26 232.24,211.42 232.24,211.42 C232.24,211.42 232.44,211.59 232.44,211.59 C232.44,211.59 232.65,211.75 232.65,211.75 C232.65,211.75 232.84,211.94 232.84,211.94 C232.84,211.94 233.03,212.12 233.03,212.12 C233.03,212.12 233.2,212.32 233.2,212.32 C233.2,212.32 233.37,212.53 233.37,212.53 C233.37,212.53 233.52,212.74 233.52,212.74 C233.52,212.74 233.67,212.96 233.67,212.96 C233.67,212.96 233.8,213.19 233.8,213.19 C233.8,213.19 233.93,213.42 233.93,213.42 C233.93,213.42 234.04,213.66 234.04,213.66 C234.04,213.66 234.14,213.9 234.14,213.9 C234.14,213.9 234.24,214.15 234.24,214.15 C234.24,214.15 234.31,214.4 234.31,214.4 C234.31,214.4 234.39,214.66 234.39,214.66 C234.39,214.66 234.44,214.92 234.44,214.92 C234.44,214.92 234.49,215.18 234.49,215.18 C234.49,215.18 234.51,215.44 234.51,215.44 C234.51,215.44 234.54,215.7 234.54,215.7 C234.54,215.7 234.54,215.96 234.54,215.96 C234.54,215.96 234.54,216.23 234.54,216.23 C234.54,216.23 234.52,216.49 234.52,216.49 C234.52,216.49 234.49,216.76 234.49,216.76 C234.49,216.76 234.46,217.02 234.46,217.02 C234.46,217.02 234.4,217.28 234.4,217.28 C234.4,217.28 234.34,217.53 234.34,217.53 C234.34,217.53 234.26,217.79 234.26,217.79 C234.26,217.79 234.18,218.04 234.18,218.04 C234.18,218.04 234.1,218.29 234.1,218.29 C234.1,218.29 234.02,218.54 234.02,218.54 C234.02,218.54 233.94,218.79 233.94,218.79 C233.94,218.79 233.86,219.04 233.86,219.04 C233.86,219.04 233.78,219.29 233.78,219.29 C233.78,219.29 233.69,219.55 233.69,219.55 C233.69,219.55 233.61,219.8 233.61,219.8 C233.61,219.8 233.53,220.05 233.53,220.05 C233.53,220.05 233.45,220.3 233.45,220.3 C233.45,220.3 233.37,220.55 233.37,220.55 C233.37,220.55 233.29,220.8 233.29,220.8 C233.29,220.8 233.21,221.05 233.21,221.05 C233.21,221.05 233.12,221.31 233.12,221.31 C233.12,221.31 233.04,221.56 233.04,221.56 C233.04,221.56 232.96,221.81 232.96,221.81 C232.96,221.81 232.88,222.06 232.88,222.06 C232.88,222.06 232.8,222.31 232.8,222.31 C232.8,222.31 232.72,222.56 232.72,222.56 C232.72,222.56 232.64,222.81 232.64,222.81 C232.64,222.81 232.55,223.07 232.55,223.07 C232.55,223.07 232.47,223.32 232.47,223.32 C232.47,223.32 232.39,223.57 232.39,223.57 C232.39,223.57 232.31,223.82 232.31,223.82 C232.31,223.82 232.23,224.07 232.23,224.07 C232.23,224.07 232.15,224.32 232.15,224.32 C232.15,224.32 232.06,224.57 232.06,224.57 C232.06,224.57 231.98,224.83 231.98,224.83 C231.98,224.83 231.9,225.08 231.9,225.08 C231.9,225.08 231.82,225.33 231.82,225.33 C231.82,225.33 231.74,225.58 231.74,225.58 C231.74,225.58 231.65,225.83 231.65,225.83 C231.65,225.83 231.57,226.08 231.57,226.08 C231.57,226.08 231.49,226.33 231.49,226.33 C231.49,226.33 231.41,226.58 231.41,226.58 C231.41,226.58 231.32,226.83 231.32,226.83 C231.32,226.83 231.24,227.08 231.24,227.08 C231.24,227.08 231.16,227.34 231.16,227.34 C231.16,227.34 231.08,227.59 231.08,227.59 C231.08,227.59 230.99,227.84 230.99,227.84 C230.99,227.84 230.91,228.09 230.91,228.09 C230.91,228.09 230.83,228.34 230.83,228.34 C230.83,228.34 230.75,228.59 230.75,228.59 C230.75,228.59 230.67,228.84 230.67,228.84 C230.67,228.84 230.58,229.09 230.58,229.09 C230.58,229.09 230.5,229.35 230.5,229.35 C230.5,229.35 230.42,229.6 230.42,229.6 C230.42,229.6 230.34,229.85 230.34,229.85 C230.34,229.85 230.25,230.1 230.25,230.1 C230.25,230.1 230.17,230.35 230.17,230.35 C230.17,230.35 230.09,230.6 230.09,230.6 C230.09,230.6 230.01,230.85 230.01,230.85 C230.01,230.85 229.92,231.1 229.92,231.1 C229.92,231.1 229.83,231.35 229.83,231.35 C229.83,231.35 229.73,231.6 229.73,231.6 C229.73,231.6 229.61,231.83 229.61,231.83 C229.61,231.83 229.49,232.07 229.49,232.07 C229.49,232.07 229.36,232.29 229.36,232.29 C229.36,232.29 229.21,232.52 229.21,232.52 C229.21,232.52 229.06,232.73 229.06,232.73 C229.06,232.73 228.89,232.94 228.89,232.94 C228.89,232.94 228.72,233.13 228.72,233.13 C228.72,233.13 228.54,233.32 228.54,233.32 C228.54,233.32 228.34,233.51 228.34,233.51 C228.34,233.51 228.14,233.68 228.14,233.68 C228.14,233.68 227.94,233.84 227.94,233.84 C227.94,233.84 227.72,233.99 227.72,233.99 C227.72,233.99 227.5,234.14 227.5,234.14 C227.5,234.14 227.27,234.27 227.27,234.27 C227.27,234.27 227.04,234.39 227.04,234.39 C227.04,234.39 226.79,234.5 226.79,234.5 C226.79,234.5 226.55,234.6 226.55,234.6 C226.55,234.6 226.3,234.68 226.3,234.68 C226.3,234.68 226.05,234.76 226.05,234.76 C226.05,234.76 225.79,234.82 225.79,234.82 C225.79,234.82 225.53,234.88 225.53,234.88 C225.53,234.88 225.27,234.92 225.27,234.92 C225.27,234.92 225.01,234.95 225.01,234.95 C225.01,234.95 224.74,234.96 224.74,234.96 C224.74,234.96 224.48,234.96 224.48,234.96 C224.48,234.96 224.22,234.96 224.22,234.96 C224.22,234.96 223.95,234.96 223.95,234.96 C223.95,234.96 223.69,234.96 223.69,234.96 C223.69,234.96 223.42,234.96 223.42,234.96 C223.42,234.96 223.16,234.96 223.16,234.96 C223.16,234.96 222.89,234.96 222.89,234.96 C222.89,234.96 222.63,234.96 222.63,234.96 C222.63,234.96 222.37,234.97 222.37,234.97 C222.37,234.97 222.1,234.97 222.1,234.97 C222.1,234.97 221.84,234.97 221.84,234.97 C221.84,234.97 221.57,234.97 221.57,234.97 C221.57,234.97 221.31,234.97 221.31,234.97 C221.31,234.97 221.04,234.97 221.04,234.97 C221.04,234.97 220.78,234.97 220.78,234.97 C220.78,234.97 220.52,234.97 220.52,234.97 C220.52,234.97 220.25,234.97 220.25,234.97 C220.25,234.97 219.99,234.97 219.99,234.97 C219.99,234.97 219.72,234.97 219.72,234.97 C219.72,234.97 219.46,234.97 219.46,234.97 C219.46,234.97 219.19,234.97 219.19,234.97 C219.19,234.97 218.93,234.97 218.93,234.97 C218.93,234.97 218.67,234.97 218.67,234.97 C218.67,234.97 218.4,234.97 218.4,234.97 C218.4,234.97 218.14,234.97 218.14,234.97 C218.14,234.97 217.87,234.97 217.87,234.97 C217.87,234.97 217.61,234.97 217.61,234.97 C217.61,234.97 217.34,234.97 217.34,234.97 C217.34,234.97 217.08,234.97 217.08,234.97 C217.08,234.97 216.82,234.97 216.82,234.97 C216.82,234.97 216.55,234.97 216.55,234.97 C216.55,234.97 216.29,234.97 216.29,234.97 C216.29,234.97 216.02,234.97 216.02,234.97 C216.02,234.97 215.76,234.97 215.76,234.97 C215.76,234.97 215.49,234.97 215.49,234.97 C215.49,234.97 215.23,234.97 215.23,234.97 C215.23,234.97 214.97,234.97 214.97,234.97 C214.97,234.97 214.7,234.97 214.7,234.97 C214.7,234.97 214.44,234.97 214.44,234.97 C214.44,234.97 214.17,234.97 214.17,234.97 C214.17,234.97 213.91,234.97 213.91,234.97 C213.91,234.97 213.64,234.97 213.64,234.97 C213.64,234.97 213.38,234.97 213.38,234.97 C213.38,234.97 213.12,234.97 213.12,234.97 C213.12,234.97 212.85,234.97 212.85,234.97 C212.85,234.97 212.59,234.96 212.59,234.96 C212.59,234.96 212.32,234.96 212.32,234.96 C212.32,234.96 212.06,234.96 212.06,234.96 C212.06,234.96 211.79,234.96 211.79,234.96 C211.79,234.96 211.53,234.96 211.53,234.96 C211.53,234.96 211.27,234.96 211.27,234.96 C211.27,234.96 211,234.96 211,234.96 C211,234.96 210.74,234.96 210.74,234.96 C210.74,234.96 210.47,234.96 210.47,234.96 C210.47,234.96 210.21,234.95 210.21,234.95 C210.21,234.95 209.94,234.93 209.94,234.93 C209.94,234.93 209.68,234.9 209.68,234.9 C209.68,234.9 209.42,234.86 209.42,234.86 C209.42,234.86 209.16,234.8 209.16,234.8 C209.16,234.8 208.91,234.74 208.91,234.74 C208.91,234.74 208.66,234.66 208.66,234.66 C208.66,234.66 208.41,234.56 208.41,234.56 C208.41,234.56 208.17,234.46 208.17,234.46 C208.17,234.46 207.93,234.35 207.93,234.35 C207.93,234.35 207.69,234.22 207.69,234.22 C207.69,234.22 207.47,234.08 207.47,234.08 C207.47,234.08 207.25,233.94 207.25,233.94 C207.25,233.94 207.04,233.78 207.04,233.78 C207.04,233.78 206.83,233.62 206.83,233.62 C206.83,233.62 206.63,233.44 206.63,233.44 C206.63,233.44 206.44,233.26 206.44,233.26 C206.44,233.26 206.27,233.06 206.27,233.06 C206.27,233.06 206.09,232.86 206.09,232.86 C206.09,232.86 205.93,232.65 205.93,232.65 C205.93,232.65 205.78,232.44 205.78,232.44 C205.78,232.44 205.64,232.21 205.64,232.21 C205.64,232.21 205.51,231.98 205.51,231.98 C205.51,231.98 205.39,231.75 205.39,231.75 C205.39,231.75 205.28,231.51 205.28,231.51 C205.28,231.51 205.18,231.26 205.18,231.26 C205.18,231.26 205.09,231.01 205.09,231.01 C205.09,231.01 205.01,230.76 205.01,230.76 C205.01,230.76 204.93,230.51 204.93,230.51 C204.93,230.51 204.85,230.26 204.85,230.26 C204.85,230.26 204.76,230.01 204.76,230.01 C204.76,230.01 204.68,229.76 204.68,229.76 C204.68,229.76 204.6,229.51 204.6,229.51 C204.6,229.51 204.52,229.26 204.52,229.26 C204.52,229.26 204.43,229.01 204.43,229.01 C204.43,229.01 204.35,228.75 204.35,228.75 C204.35,228.75 204.27,228.5 204.27,228.5 C204.27,228.5 204.19,228.25 204.19,228.25 C204.19,228.25 204.1,228 204.1,228 C204.1,228 204.02,227.75 204.02,227.75 C204.02,227.75 203.94,227.5 203.94,227.5 C203.94,227.5 203.86,227.25 203.86,227.25 C203.86,227.25 203.78,227 203.78,227 C203.78,227 203.69,226.74 203.69,226.74 C203.69,226.74 203.61,226.49 203.61,226.49 C203.61,226.49 203.53,226.24 203.53,226.24 C203.53,226.24 203.45,225.99 203.45,225.99 C203.45,225.99 203.36,225.74 203.36,225.74 C203.36,225.74 203.28,225.49 203.28,225.49 C203.28,225.49 203.2,225.24 203.2,225.24 C203.2,225.24 203.12,224.99 203.12,224.99 C203.12,224.99 203.03,224.74 203.03,224.74 C203.03,224.74 202.95,224.48 202.95,224.48 C202.95,224.48 202.87,224.23 202.87,224.23 C202.87,224.23 202.79,223.98 202.79,223.98 C202.79,223.98 202.71,223.73 202.71,223.73 C202.71,223.73 202.63,223.48 202.63,223.48 C202.63,223.48 202.54,223.23 202.54,223.23 C202.54,223.23 202.46,222.98 202.46,222.98 C202.46,222.98 202.38,222.72 202.38,222.72 C202.38,222.72 202.3,222.47 202.3,222.47 C202.3,222.47 202.22,222.22 202.22,222.22 C202.22,222.22 202.14,221.97 202.14,221.97 C202.14,221.97 202.06,221.72 202.06,221.72 C202.06,221.72 201.97,221.47 201.97,221.47 C201.97,221.47 201.89,221.22 201.89,221.22 C201.89,221.22 201.81,220.96 201.81,220.96 C201.81,220.96 201.73,220.71 201.73,220.71 C201.73,220.71 201.65,220.46 201.65,220.46 C201.65,220.46 201.57,220.21 201.57,220.21 C201.57,220.21 201.49,219.96 201.49,219.96 C201.49,219.96 201.4,219.71 201.4,219.71 C201.4,219.71 201.32,219.46 201.32,219.46 C201.32,219.46 201.24,219.2 201.24,219.2 C201.24,219.2 201.16,218.95 201.16,218.95 C201.16,218.95 201.08,218.7 201.08,218.7 C201.08,218.7 201,218.45 201,218.45 C201,218.45 200.92,218.2 200.92,218.2 C200.92,218.2 200.83,217.95 200.83,217.95 C200.83,217.95 200.76,217.7 200.76,217.7 C200.76,217.7 200.69,217.44 200.69,217.44 C200.69,217.44 200.62,217.18 200.62,217.18 C200.62,217.18 200.58,216.92 200.58,216.92 C200.58,216.92 200.54,216.66 200.54,216.66 C200.54,216.66 200.52,216.4 200.52,216.4 C200.52,216.4 200.5,216.14 200.5,216.14 C200.5,216.14 200.5,215.87 200.5,215.87 C200.5,215.87 200.52,215.61 200.52,215.61 C200.52,215.61 200.54,215.34 200.54,215.34 C200.54,215.34 200.58,215.08 200.58,215.08 C200.58,215.08 200.62,214.82 200.62,214.82 C200.62,214.82 200.69,214.57 200.69,214.57 C200.69,214.57 200.76,214.31 200.76,214.31 C200.76,214.31 200.84,214.06 200.84,214.06 C200.84,214.06 200.93,213.81 200.93,213.81 C200.93,213.81 201.05,213.57 201.05,213.57 C201.05,213.57 201.16,213.33 201.16,213.33 C201.16,213.33 201.29,213.11 201.29,213.11 C201.29,213.11 201.43,212.88 201.43,212.88 C201.43,212.88 201.58,212.67 201.58,212.67 C201.58,212.67 201.74,212.45 201.74,212.45 C201.74,212.45 201.91,212.25 201.91,212.25 C201.91,212.25 202.09,212.06 202.09,212.06 C202.09,212.06 202.27,211.87 202.27,211.87 C202.27,211.87 202.47,211.69 202.47,211.69 C202.47,211.69 202.67,211.52 202.67,211.52 C202.67,211.52 202.88,211.36 202.88,211.36 C202.88,211.36 203.1,211.21 203.1,211.21 C203.1,211.21 203.31,211.05 203.31,211.05 C203.31,211.05 203.52,210.9 203.52,210.9 C203.52,210.9 203.74,210.74 203.74,210.74 C203.74,210.74 203.95,210.58 203.95,210.58 C203.95,210.58 204.16,210.43 204.16,210.43 C204.16,210.43 204.38,210.27 204.38,210.27 C204.38,210.27 204.59,210.12 204.59,210.12 C204.59,210.12 204.81,209.96 204.81,209.96 C204.81,209.96 205.02,209.81 205.02,209.81 C205.02,209.81 205.23,209.65 205.23,209.65 C205.23,209.65 205.45,209.5 205.45,209.5 C205.45,209.5 205.66,209.34 205.66,209.34 C205.66,209.34 205.87,209.19 205.87,209.19 C205.87,209.19 206.09,209.03 206.09,209.03 C206.09,209.03 206.3,208.88 206.3,208.88 C206.3,208.88 206.52,208.72 206.52,208.72 C206.52,208.72 206.73,208.57 206.73,208.57 C206.73,208.57 206.94,208.41 206.94,208.41 C206.94,208.41 207.16,208.25 207.16,208.25 C207.16,208.25 207.37,208.1 207.37,208.1 C207.37,208.1 207.58,207.94 207.58,207.94 C207.58,207.94 207.8,207.79 207.8,207.79 C207.8,207.79 208.01,207.63 208.01,207.63 C208.01,207.63 208.23,207.48 208.23,207.48 C208.23,207.48 208.44,207.32 208.44,207.32 C208.44,207.32 208.65,207.17 208.65,207.17 C208.65,207.17 208.87,207.01 208.87,207.01 C208.87,207.01 209.08,206.86 209.08,206.86 C209.08,206.86 209.3,206.7 209.3,206.7 C209.3,206.7 209.51,206.55 209.51,206.55 C209.51,206.55 209.73,206.39 209.73,206.39 C209.73,206.39 209.94,206.24 209.94,206.24 C209.94,206.24 210.15,206.08 210.15,206.08 C210.15,206.08 210.37,205.93 210.37,205.93 C210.37,205.93 210.58,205.77 210.58,205.77 C210.58,205.77 210.8,205.62 210.8,205.62 C210.8,205.62 211.01,205.46 211.01,205.46 C211.01,205.46 211.23,205.31 211.23,205.31 C211.23,205.31 211.44,205.16 211.44,205.16 C211.44,205.16 211.65,205 211.65,205 C211.65,205 211.87,204.85 211.87,204.85 C211.87,204.85 212.08,204.69 212.08,204.69 C212.08,204.69 212.3,204.54 212.3,204.54 C212.3,204.54 212.51,204.38 212.51,204.38 C212.51,204.38 212.73,204.23 212.73,204.23 C212.73,204.23 212.94,204.07 212.94,204.07 C212.94,204.07 213.15,203.92 213.15,203.92 C213.15,203.92 213.37,203.76 213.37,203.76 C213.37,203.76 213.58,203.61 213.58,203.61 C213.58,203.61 213.8,203.45 213.8,203.45 C213.8,203.45 214.01,203.3 214.01,203.3 C214.01,203.3 214.23,203.14 214.23,203.14 C214.23,203.14 214.45,203 214.45,203 C214.45,203 214.67,202.86 214.67,202.86 C214.67,202.86 214.9,202.73 214.9,202.73 C214.9,202.73 215.14,202.61 215.14,202.61 C215.14,202.61 215.38,202.51 215.38,202.51 C215.38,202.51 215.63,202.41 215.63,202.41 C215.63,202.41 215.88,202.33 215.88,202.33 C215.88,202.33 216.13,202.26 216.13,202.26 C216.13,202.26 216.39,202.2 216.39,202.2 C216.39,202.2 216.65,202.15 216.65,202.15 C216.65,202.15 216.91,202.11 216.91,202.11 C216.91,202.11 217.18,202.09 217.18,202.09 C217.18,202.09 217.44,202.08 217.44,202.08 C217.44,202.08 217.7,202.08 217.7,202.08c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/app_clips_screenshot.xml b/packages/SystemUI/res/layout/app_clips_screenshot.xml
new file mode 100644
index 0000000..5155b77
--- /dev/null
+++ b/packages/SystemUI/res/layout/app_clips_screenshot.xml
@@ -0,0 +1,105 @@
+<?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.
+  -->
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:background="@null"
+    android:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <Button
+        android:id="@+id/save"
+        style="@android:style/Widget.DeviceDefault.Button.Colored"
+        android:layout_width="wrap_content"
+        android:layout_height="48dp"
+        android:text="@string/app_clips_save_add_to_note"
+        android:layout_marginStart="8dp"
+        android:background="@drawable/overlay_button_background"
+        android:textColor="?android:textColorSecondary"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toTopOf="@id/preview" />
+
+    <Button
+        android:id="@+id/cancel"
+        style="@android:style/Widget.DeviceDefault.Button.Colored"
+        android:layout_width="wrap_content"
+        android:layout_height="48dp"
+        android:text="@android:string/cancel"
+        android:layout_marginStart="6dp"
+        android:background="@drawable/overlay_button_background"
+        android:textColor="?android:textColorSecondary"
+        app:layout_constraintStart_toEndOf="@id/save"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toTopOf="@id/preview" />
+
+    <ImageView
+        android:id="@+id/preview"
+        android:layout_width="0px"
+        android:layout_height="0px"
+        android:paddingHorizontal="48dp"
+        android:paddingTop="8dp"
+        android:paddingBottom="42dp"
+        android:contentDescription="@string/screenshot_preview_description"
+        app:layout_constrainedHeight="true"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintTop_toBottomOf="@id/save"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        tools:background="?android:colorBackground"
+        tools:minHeight="100dp"
+        tools:minWidth="100dp" />
+
+    <com.android.systemui.screenshot.CropView
+        android:id="@+id/crop_view"
+        android:layout_width="0px"
+        android:layout_height="0px"
+        android:paddingTop="8dp"
+        android:paddingBottom="42dp"
+        app:layout_constrainedHeight="true"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintTop_toTopOf="@id/preview"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:handleThickness="@dimen/screenshot_crop_handle_thickness"
+        app:handleColor="?android:attr/colorAccent"
+        app:scrimColor="?android:colorBackgroundFloating"
+        app:scrimAlpha="128"
+        app:containerBackgroundColor="?android:colorBackgroundFloating"
+        tools:background="?android:colorBackground"
+        tools:minHeight="100dp"
+        tools:minWidth="100dp" />
+
+    <com.android.systemui.screenshot.MagnifierView
+        android:id="@+id/magnifier"
+        android:visibility="invisible"
+        android:layout_width="200dp"
+        android:layout_height="200dp"
+        android:elevation="2dp"
+        app:layout_constraintTop_toTopOf="@id/preview"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:handleThickness="@dimen/screenshot_crop_handle_thickness"
+        app:handleColor="?android:attr/colorAccent"
+        app:scrimColor="?android:colorBackgroundFloating"
+        app:scrimAlpha="128"
+        app:borderThickness="4dp"
+        app:borderColor="#fff" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/layout/clipboard_overlay.xml b/packages/SystemUI/res/layout/clipboard_overlay.xml
index eec3b11..9b01bd8 100644
--- a/packages/SystemUI/res/layout/clipboard_overlay.xml
+++ b/packages/SystemUI/res/layout/clipboard_overlay.xml
@@ -125,6 +125,45 @@
             android:layout_width="@dimen/clipboard_preview_size"
             android:layout_height="@dimen/clipboard_preview_size"/>
     </FrameLayout>
+    <LinearLayout
+        android:id="@+id/minimized_preview"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:visibility="gone"
+        android:elevation="7dp"
+        android:padding="8dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal"
+        android:layout_marginBottom="@dimen/overlay_action_container_margin_bottom"
+        android:background="@drawable/clipboard_minimized_background">
+        <ImageView
+            android:src="@drawable/ic_content_paste"
+            android:tint="?attr/overlayButtonTextColor"
+            android:layout_width="24dp"
+            android:layout_height="24dp"/>
+        <ImageView
+            android:src="@*android:drawable/ic_chevron_end"
+            android:tint="?attr/overlayButtonTextColor"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:paddingEnd="-8dp"
+            android:paddingStart="-4dp"/>
+    </LinearLayout>
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/clipboard_content_top"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        app:barrierDirection="top"
+        app:constraint_referenced_ids="clipboard_preview,minimized_preview"/>
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/clipboard_content_end"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:barrierDirection="end"
+        app:constraint_referenced_ids="clipboard_preview,minimized_preview"/>
     <FrameLayout
         android:id="@+id/dismiss_button"
         android:layout_width="@dimen/overlay_dismiss_button_tappable_size"
@@ -132,10 +171,10 @@
         android:elevation="10dp"
         android:visibility="gone"
         android:alpha="0"
-        app:layout_constraintStart_toEndOf="@id/clipboard_preview"
-        app:layout_constraintEnd_toEndOf="@id/clipboard_preview"
-        app:layout_constraintTop_toTopOf="@id/clipboard_preview"
-        app:layout_constraintBottom_toTopOf="@id/clipboard_preview"
+        app:layout_constraintStart_toEndOf="@id/clipboard_content_end"
+        app:layout_constraintEnd_toEndOf="@id/clipboard_content_end"
+        app:layout_constraintTop_toTopOf="@id/clipboard_content_top"
+        app:layout_constraintBottom_toTopOf="@id/clipboard_content_top"
         android:contentDescription="@string/clipboard_dismiss_description">
         <ImageView
             android:id="@+id/dismiss_image"
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index ee3adba..aa211bf 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -20,7 +20,6 @@
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal"
-      android:layout_marginTop="@dimen/controls_top_margin"
       android:layout_marginBottom="@dimen/controls_header_bottom_margin">
 
     <!-- make sure the header stays centered in the layout by adding a spacer -->
@@ -78,6 +77,7 @@
         android:layout_weight="1"
         android:orientation="vertical"
         android:clipChildren="true"
+        android:paddingHorizontal="16dp"
         android:scrollbars="none">
     <include layout="@layout/global_actions_controls_list_view" />
 
@@ -88,10 +88,7 @@
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:layout_weight="1"
-      android:layout_marginLeft="@dimen/global_actions_side_margin"
-      android:layout_marginRight="@dimen/global_actions_side_margin"
       android:background="@drawable/controls_panel_background"
-      android:padding="@dimen/global_actions_side_margin"
       android:visibility="gone"
       />
 </merge>
diff --git a/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml b/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml
index 885e5e2..50dcaf3 100644
--- a/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml
@@ -111,5 +111,15 @@
             android:visibility="gone"
             android:contentDescription="@string/dream_overlay_status_bar_camera_mic_off" />
 
+        <ImageView
+            android:id="@+id/dream_overlay_assistant_attention_indicator"
+            android:layout_width="@dimen/dream_overlay_grey_chip_width"
+            android:layout_height="match_parent"
+            android:layout_marginStart="@dimen/dream_overlay_status_icon_margin"
+            android:src="@drawable/dream_overlay_assistant_attention_indicator"
+            android:visibility="gone"
+            android:contentDescription=
+                "@string/dream_overlay_status_bar_assistant_attention_indicator" />
+
     </LinearLayout>
 </com.android.systemui.dreams.DreamOverlayStatusBarView>
diff --git a/packages/SystemUI/res/layout/keyguard_pin_shape_hinting_view.xml b/packages/SystemUI/res/layout/keyguard_pin_shape_hinting_view.xml
new file mode 100644
index 0000000..aab9870
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_pin_shape_hinting_view.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<com.android.keyguard.PinShapeHintingView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:gravity="center"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+</com.android.keyguard.PinShapeHintingView>
diff --git a/packages/SystemUI/res/layout/keyguard_pin_shape_non_hinting_view.xml b/packages/SystemUI/res/layout/keyguard_pin_shape_non_hinting_view.xml
new file mode 100644
index 0000000..cba1db0
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_pin_shape_non_hinting_view.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<com.android.keyguard.PinShapeNonHintingView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:gravity="center"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+</com.android.keyguard.PinShapeNonHintingView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
index aaa372a..e39f1a9 100644
--- a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
+++ b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
@@ -18,6 +18,7 @@
 
 <!-- LinearLayout -->
 <com.android.systemui.statusbar.policy.KeyguardUserDetailItemView
+        android:id="@+id/user_item"
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:systemui="http://schemas.android.com/apk/res-auto"
         android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/media_output_list_item_advanced.xml b/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
index d49b9f1..a650512 100644
--- a/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
+++ b/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
@@ -152,5 +152,16 @@
             android:button="@drawable/media_output_item_check_box"
             android:visibility="gone"
             />
+        <ImageView
+            android:id="@+id/media_output_item_end_click_icon"
+            android:src="@drawable/media_output_status_edit_session"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:focusable="false"
+            android:importantForAccessibility="no"
+            android:layout_gravity="center"
+            android:indeterminate="true"
+            android:indeterminateOnly="true"
+            android:visibility="gone"/>
     </FrameLayout>
 </FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/media_recommendation_view.xml b/packages/SystemUI/res/layout/media_recommendation_view.xml
index 101fad9..c54c4e4 100644
--- a/packages/SystemUI/res/layout/media_recommendation_view.xml
+++ b/packages/SystemUI/res/layout/media_recommendation_view.xml
@@ -47,7 +47,8 @@
         android:singleLine="true"
         android:textSize="12sp"
         android:gravity="top"
-        android:layout_gravity="bottom"/>
+        android:layout_gravity="bottom"
+        android:importantForAccessibility="no"/>
 
     <!-- Album name -->
     <TextView
@@ -61,5 +62,26 @@
         android:singleLine="true"
         android:textSize="11sp"
         android:gravity="center_vertical"
-        android:layout_gravity="bottom"/>
+        android:layout_gravity="bottom"
+        android:importantForAccessibility="no"/>
+
+    <!-- Seek Bar -->
+    <SeekBar
+        android:id="@+id/media_progress_bar"
+        android:layout_width="match_parent"
+        android:layout_height="12dp"
+        android:layout_gravity="bottom"
+        android:maxHeight="@dimen/qs_media_enabled_seekbar_height"
+        android:thumb="@android:color/transparent"
+        android:splitTrack="false"
+        android:clickable="false"
+        android:progressTint="?android:attr/textColorPrimary"
+        android:progressBackgroundTint="?android:attr/textColorTertiary"
+        android:paddingTop="5dp"
+        android:paddingBottom="5dp"
+        android:paddingStart="0dp"
+        android:paddingEnd="0dp"
+        android:layout_marginEnd="@dimen/qs_media_info_spacing"
+        android:layout_marginStart="@dimen/qs_media_info_spacing"
+        android:layout_marginBottom="@dimen/qs_media_info_spacing"/>
 </merge>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/media_ttt_chip_receiver.xml b/packages/SystemUI/res/layout/media_ttt_chip_receiver.xml
index 4483db8..1daff9f 100644
--- a/packages/SystemUI/res/layout/media_ttt_chip_receiver.xml
+++ b/packages/SystemUI/res/layout/media_ttt_chip_receiver.xml
@@ -27,22 +27,27 @@
         android:layout_height="wrap_content"
         />
 
-    <com.android.systemui.media.taptotransfer.receiver.ReceiverChipRippleView
-        android:id="@+id/icon_glow_ripple"
+    <FrameLayout
+        android:id="@+id/icon_container_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        />
+        >
+        <com.android.systemui.media.taptotransfer.receiver.ReceiverChipRippleView
+            android:id="@+id/icon_glow_ripple"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            />
 
-    <!-- Add a bottom margin to avoid the glow of the icon ripple from being cropped by screen
-     bounds while animating with the icon -->
-    <com.android.internal.widget.CachingIconView
-        android:id="@+id/app_icon"
-        android:background="@drawable/media_ttt_chip_background_receiver"
-        android:layout_width="@dimen/media_ttt_icon_size_receiver"
-        android:layout_height="@dimen/media_ttt_icon_size_receiver"
-        android:layout_gravity="center|bottom"
-        android:alpha="0.0"
-        android:layout_marginBottom="@dimen/media_ttt_receiver_icon_bottom_margin"
-        />
+        <!-- Add a bottom margin to avoid the glow of the icon ripple from being cropped by screen
+        bounds while animating with the icon -->
+        <com.android.internal.widget.CachingIconView
+            android:id="@+id/app_icon"
+            android:background="@drawable/media_ttt_chip_background_receiver"
+            android:layout_width="@dimen/media_ttt_icon_size_receiver"
+            android:layout_height="@dimen/media_ttt_icon_size_receiver"
+            android:layout_gravity="center|bottom"
+            android:layout_marginBottom="@dimen/media_ttt_receiver_icon_bottom_margin"
+            />
+    </FrameLayout>
 
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index 7c86bc7..ad129e8 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -18,6 +18,7 @@
 
 <!-- LinearLayout -->
 <com.android.systemui.qs.tiles.UserDetailItemView
+        android:id="@+id/user_item"
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:systemui="http://schemas.android.com/apk/res-auto"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/screen_record_dialog_audio_source.xml b/packages/SystemUI/res/layout/screen_record_dialog_audio_source.xml
index 2567176..130472d 100644
--- a/packages/SystemUI/res/layout/screen_record_dialog_audio_source.xml
+++ b/packages/SystemUI/res/layout/screen_record_dialog_audio_source.xml
@@ -23,7 +23,7 @@
     <TextView
         android:id="@+id/screen_recording_dialog_source_text"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="14sp"
diff --git a/packages/SystemUI/res/layout/screen_record_dialog_audio_source_selected.xml b/packages/SystemUI/res/layout/screen_record_dialog_audio_source_selected.xml
index e2b8d33..9d9f5c2 100644
--- a/packages/SystemUI/res/layout/screen_record_dialog_audio_source_selected.xml
+++ b/packages/SystemUI/res/layout/screen_record_dialog_audio_source_selected.xml
@@ -22,7 +22,7 @@
     android:layout_weight="1">
     <TextView
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:text="@string/screenrecord_audio_label"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:fontFamily="@*android:string/config_headlineFontFamily"
@@ -30,7 +30,7 @@
     <TextView
         android:id="@+id/screen_recording_dialog_source_text"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:textColor="?android:attr/textColorSecondary"
         android:textAppearance="?android:attr/textAppearanceSmall"/>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/screen_record_options.xml b/packages/SystemUI/res/layout/screen_record_options.xml
index 3f0eea9..6cc72dd 100644
--- a/packages/SystemUI/res/layout/screen_record_options.xml
+++ b/packages/SystemUI/res/layout/screen_record_options.xml
@@ -67,7 +67,7 @@
             android:importantForAccessibility="no"/>
         <TextView
             android:layout_width="0dp"
-            android:layout_height="match_parent"
+            android:layout_height="wrap_content"
             android:minHeight="48dp"
             android:layout_weight="1"
             android:gravity="center_vertical"
diff --git a/packages/SystemUI/res/layout/screenshot_detection_notice.xml b/packages/SystemUI/res/layout/screenshot_detection_notice.xml
new file mode 100644
index 0000000..fc936c0
--- /dev/null
+++ b/packages/SystemUI/res/layout/screenshot_detection_notice.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/screenshot_detection_notice"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:padding="12dp"
+    android:visibility="gone">
+
+    <TextView
+        android:id="@+id/screenshot_detection_notice_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:lineHeight="24sp"
+        android:textSize="18sp" />
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/screenshot_static.xml b/packages/SystemUI/res/layout/screenshot_static.xml
index 7e8bc2c..7e9202c 100644
--- a/packages/SystemUI/res/layout/screenshot_static.xml
+++ b/packages/SystemUI/res/layout/screenshot_static.xml
@@ -134,7 +134,7 @@
         android:orientation="horizontal"
         app:layout_constraintGuide_end="0dp" />
 
-    <androidx.constraintlayout.widget.ConstraintLayout
+    <FrameLayout
         android:id="@+id/screenshot_message_container"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
@@ -145,10 +145,14 @@
         android:paddingVertical="@dimen/overlay_action_container_padding_vertical"
         android:elevation="4dp"
         android:background="@drawable/action_chip_container_background"
-        android:visibility="invisible"
+        android:visibility="gone"
         app:layout_constraintTop_toBottomOf="@id/guideline"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintWidth_max="450dp"
+        app:layout_constraintHorizontal_bias="0"
         >
-    </androidx.constraintlayout.widget.ConstraintLayout>
+        <include layout="@layout/screenshot_work_profile_first_run" />
+        <include layout="@layout/screenshot_detection_notice" />
+    </FrameLayout>
 </com.android.systemui.screenshot.DraggableConstraintLayout>
diff --git a/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml b/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml
index c794d91..392d845 100644
--- a/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml
+++ b/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml
@@ -1,41 +1,41 @@
 <?xml version="1.0" encoding="utf-8"?>
-<merge
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
+    android:id="@+id/work_profile_first_run"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:paddingStart="16dp"
+    android:paddingEnd="4dp"
+    android:paddingVertical="16dp"
+    android:visibility="gone">
     <ImageView
         android:id="@+id/screenshot_message_icon"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:paddingEnd="4dp"
-        android:src="@drawable/ic_work_app_badge"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toStartOf="@id/screenshot_message_content"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toBottomOf="parent"/>
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_marginEnd="12dp"
+        android:layout_gravity="center_vertical"
+        android:src="@drawable/ic_work_app_badge"/>
 
     <TextView
         android:id="@+id/screenshot_message_content"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_gravity="start"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toEndOf="@id/screenshot_message_icon"
-        app:layout_constraintEnd_toStartOf="@id/message_dismiss_button"/>
+        android:layout_weight="1"
+        android:layout_gravity="start|center_vertical"
+        android:textSize="18sp"
+        android:textColor="?android:attr/textColorPrimary"
+        android:lineHeight="24sp"
+        />
 
     <FrameLayout
         android:id="@+id/message_dismiss_button"
         android:layout_width="@dimen/overlay_dismiss_button_tappable_size"
         android:layout_height="@dimen/overlay_dismiss_button_tappable_size"
-        app:layout_constraintStart_toEndOf="@id/screenshot_message_content"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintBottom_toBottomOf="parent"
         android:contentDescription="@string/screenshot_dismiss_work_profile">
         <ImageView
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_margin="@dimen/overlay_dismiss_button_margin"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:layout_gravity="center"
             android:src="@drawable/overlay_cancel"/>
     </FrameLayout>
-</merge>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/seekbar_with_icon_buttons.xml b/packages/SystemUI/res/layout/seekbar_with_icon_buttons.xml
new file mode 100644
index 0000000..f20b582
--- /dev/null
+++ b/packages/SystemUI/res/layout/seekbar_with_icon_buttons.xml
@@ -0,0 +1,60 @@
+<?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.
+  -->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:tools="http://schemas.android.com/tools"
+              android:id="@+id/seekbar_frame"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:clipChildren="false"
+              android:gravity="center_vertical"
+              android:orientation="horizontal"
+              tools:parentTag="android.widget.LinearLayout">
+
+    <ImageView
+        android:id="@+id/icon_start"
+        android:layout_width="@dimen/magnification_setting_seekbar_icon_size"
+        android:layout_height="@dimen/magnification_setting_seekbar_icon_size"
+        android:layout_gravity="center"
+        android:background="?android:attr/selectableItemBackgroundBorderless"
+        android:adjustViewBounds="true"
+        android:focusable="true"
+        android:src="@drawable/ic_remove"
+        android:tint="?android:attr/textColorPrimary"
+        android:tintMode="src_in" />
+
+    <SeekBar
+        android:id="@+id/seekbar"
+        style="@android:style/Widget.Material.SeekBar.Discrete"
+        android:layout_width="0dp"
+        android:layout_height="48dp"
+        android:layout_gravity="center_vertical"
+        android:layout_weight="1" />
+
+    <ImageView
+        android:id="@+id/icon_end"
+        android:layout_width="@dimen/magnification_setting_seekbar_icon_size"
+        android:layout_height="@dimen/magnification_setting_seekbar_icon_size"
+        android:layout_gravity="center"
+        android:background="?android:attr/selectableItemBackgroundBorderless"
+        android:adjustViewBounds="true"
+        android:focusable="true"
+        android:src="@drawable/ic_add"
+        android:tint="?android:attr/textColorPrimary"
+        android:tintMode="src_in" />
+
+</merge>
diff --git a/packages/SystemUI/res/layout/udfps_fpm_empty_view.xml b/packages/SystemUI/res/layout/udfps_fpm_empty_view.xml
index de43a5e..4799f8c 100644
--- a/packages/SystemUI/res/layout/udfps_fpm_empty_view.xml
+++ b/packages/SystemUI/res/layout/udfps_fpm_empty_view.xml
@@ -19,4 +19,12 @@
     android:id="@+id/udfps_animation_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
+    <!-- The layout height/width are placeholders, which will be overwritten by
+     FingerprintSensorPropertiesInternal. -->
+    <View
+        android:id="@+id/udfps_enroll_accessibility_view"
+        android:layout_gravity="center"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:contentDescription="@string/accessibility_fingerprint_label"/>
 </com.android.systemui.biometrics.UdfpsFpmEmptyView>
diff --git a/packages/SystemUI/res/layout/window_magnification_settings_view.xml b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
index 714d551..7dfe7c4 100644
--- a/packages/SystemUI/res/layout/window_magnification_settings_view.xml
+++ b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
@@ -15,6 +15,7 @@
     limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/magnifier_panel_view"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
@@ -46,55 +47,72 @@
     </LinearLayout>
 
     <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:background="@drawable/accessibility_magnification_setting_view_image_btn_layout_bg"
+        android:layout_width="@dimen/magnification_setting_image_button_background_width"
+        android:layout_height="@dimen/magnification_setting_image_button_height"
         android:orientation="horizontal">
         <ImageButton
             android:id="@+id/magnifier_small_button"
             android:layout_width="0dp"
-            android:layout_height="56dp"
-            android:scaleType="center"
+            android:layout_height="@dimen/magnification_setting_image_button_height"
             android:layout_weight="1"
-            android:background="@drawable/accessibility_magnification_setting_view_btn_bg"
-            android:padding="@dimen/magnification_switch_button_padding"
+            android:scaleType="fitCenter"
+            android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg"
+            android:paddingLeft="@dimen/magnification_setting_image_button_padding_horizontal"
+            android:paddingRight="@dimen/magnification_setting_image_button_padding_horizontal"
+            android:paddingTop="@dimen/magnification_setting_image_button_padding_vertical"
+            android:paddingBottom="@dimen/magnification_setting_image_button_padding_vertical"
             android:src="@drawable/ic_magnification_menu_small"
-            android:tint="@color/accessibility_magnifier_icon_color"
+            android:tint="@color/accessibility_magnification_image_button_tint"
             android:tintMode="src_atop" />
 
         <ImageButton
             android:id="@+id/magnifier_medium_button"
             android:layout_width="0dp"
-            android:layout_height="56dp"
-            android:scaleType="center"
+            android:layout_height="@dimen/magnification_setting_image_button_height"
             android:layout_weight="1"
-            android:background="@drawable/accessibility_magnification_setting_view_btn_bg"
-            android:padding="@dimen/magnification_switch_button_padding"
+            android:scaleType="fitCenter"
+            android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg"
+            android:paddingLeft="@dimen/magnification_setting_image_button_padding_horizontal"
+            android:paddingRight="@dimen/magnification_setting_image_button_padding_horizontal"
+            android:paddingTop="@dimen/magnification_setting_image_button_padding_vertical"
+            android:paddingBottom="@dimen/magnification_setting_image_button_padding_vertical"
             android:src="@drawable/ic_magnification_menu_medium"
-            android:tint="@color/accessibility_magnifier_icon_color"
+            android:tint="@color/accessibility_magnification_image_button_tint"
             android:tintMode="src_atop" />
 
         <ImageButton
             android:id="@+id/magnifier_large_button"
             android:layout_width="0dp"
-            android:layout_height="56dp"
-            android:scaleType="center"
+            android:layout_height="@dimen/magnification_setting_image_button_height"
             android:layout_weight="1"
-            android:background="@drawable/accessibility_magnification_setting_view_btn_bg"
-            android:padding="@dimen/magnification_switch_button_padding"
+            android:scaleType="fitCenter"
+            android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg"
+            android:paddingLeft="@dimen/magnification_setting_image_button_padding_horizontal"
+            android:paddingRight="@dimen/magnification_setting_image_button_padding_horizontal"
+            android:paddingTop="@dimen/magnification_setting_image_button_padding_vertical"
+            android:paddingBottom="@dimen/magnification_setting_image_button_padding_vertical"
             android:src="@drawable/ic_magnification_menu_large"
-            android:tint="@color/accessibility_magnifier_icon_color"
+            android:tint="@color/accessibility_magnification_image_button_tint"
             android:tintMode="src_atop" />
 
         <ImageButton
             android:id="@+id/magnifier_full_button"
             android:layout_width="0dp"
-            android:layout_height="56dp"
-            android:scaleType="center"
+            android:layout_height="@dimen/magnification_setting_image_button_height"
             android:layout_weight="1"
-            android:background="@drawable/accessibility_magnification_setting_view_btn_bg"
-            android:padding="@dimen/magnification_switch_button_padding"
-            android:src="@drawable/ic_open_in_new_fullscreen"
-            android:tint="@color/accessibility_magnifier_icon_color"
+            android:scaleType="fitCenter"
+            android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg"
+            android:paddingLeft
+                ="@dimen/magnification_setting_image_button_open_in_full_padding_horizontal"
+            android:paddingRight
+                ="@dimen/magnification_setting_image_button_open_in_full_padding_horizontal"
+            android:paddingTop
+                ="@dimen/magnification_setting_image_button_open_in_full_padding_vertical"
+            android:paddingBottom
+                ="@dimen/magnification_setting_image_button_open_in_full_padding_vertical"
+            android:src="@drawable/ic_open_in_full"
+            android:tint="@color/accessibility_magnification_image_button_tint"
             android:tintMode="src_atop" />
     </LinearLayout>
 
@@ -112,13 +130,19 @@
             android:layout_weight="1"
             android:singleLine="true"
             android:text="@string/accessibility_allow_diagonal_scrolling"
-            android:textAppearance="@style/TextAppearance.MagnificationSetting.Title" />
+            android:textAppearance="@style/TextAppearance.MagnificationSetting.Title"
+            android:layout_gravity="center_vertical" />
 
         <Switch
             android:id="@+id/magnifier_horizontal_lock_switch"
-            android:layout_width="wrap_content"
+            android:switchMinWidth="@dimen/settingslib_switch_track_width"
+            android:layout_gravity="right|center_vertical"
+            android:layout_width="@dimen/settingslib_switch_track_width"
             android:layout_height="wrap_content"
-            android:layout_gravity="right" />
+            android:track="@drawable/settingslib_track_selector"
+            android:thumb="@drawable/settingslib_thumb_selector"
+            android:theme="@style/MainSwitch.Settingslib"/>
+
     </LinearLayout>
 
     <TextView
@@ -128,13 +152,14 @@
         android:textAppearance="@style/TextAppearance.MagnificationSetting.Title"
         android:focusable="true" />
 
-    <SeekBar
-        android:id="@+id/magnifier_zoom_seekbar"
-        android:layout_height="wrap_content"
+    <com.android.systemui.common.ui.view.SeekBarWithIconButtonsView
+        android:id="@+id/magnifier_zoom_slider"
         android:layout_width="match_parent"
-        android:layout_marginTop="@dimen/magnification_setting_seekbar_margin"
-        android:progress="0"
-        android:max="6" />
+        android:layout_height="wrap_content"
+        app:max="6"
+        app:progress="0"
+        app:iconStartContentDescription="@string/accessibility_control_zoom_out"
+        app:iconEndContentDescription="@string/accessibility_control_zoom_in"/>
 
     <Button
         android:id="@+id/magnifier_done_button"
diff --git a/packages/SystemUI/res/layout/window_magnifier_view.xml b/packages/SystemUI/res/layout/window_magnifier_view.xml
index 0be7328..a8a048d 100644
--- a/packages/SystemUI/res/layout/window_magnifier_view.xml
+++ b/packages/SystemUI/res/layout/window_magnifier_view.xml
@@ -16,6 +16,7 @@
   -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
 
@@ -24,7 +25,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_margin="@dimen/magnification_outer_border_margin"
-        android:background="@color/magnification_border_color"/>
+        android:background="@drawable/accessibility_window_magnification_background"/>
 
     <RelativeLayout
         android:layout_width="match_parent"
@@ -66,54 +67,50 @@
 
     <ImageView
         android:id="@+id/top_right_corner"
+        android:background="@drawable/accessibility_window_magnification_drag_corner_background"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_margin="@dimen/magnification_outer_border_margin"
+        android:layout_margin="@dimen/magnification_drag_corner_margin"
         android:layout_gravity="right|top"
-        android:paddingTop="@dimen/magnifier_drag_handle_padding"
-        android:paddingEnd="@dimen/magnifier_drag_handle_padding"
         android:scaleType="center"
         android:contentDescription="@string/magnification_drag_corner_to_resize"
-        android:src="@drawable/ic_magnification_corner_top_right"
+        android:src="@drawable/ic_arrow_top_right_and_bottom_left"
         android:accessibilityTraversalAfter="@id/top_left_corner"/>
 
     <ImageView
         android:id="@+id/top_left_corner"
+        android:background="@drawable/accessibility_window_magnification_drag_corner_background"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_margin="@dimen/magnification_outer_border_margin"
+        android:layout_margin="@dimen/magnification_drag_corner_margin"
         android:layout_gravity="left|top"
-        android:paddingTop="@dimen/magnifier_drag_handle_padding"
-        android:paddingStart="@dimen/magnifier_drag_handle_padding"
         android:scaleType="center"
         android:contentDescription="@string/magnification_drag_corner_to_resize"
-        android:src="@drawable/ic_magnification_corner_top_left"
+        android:src="@drawable/ic_arrow_top_left_and_bottom_right"
         android:accessibilityTraversalAfter="@id/bottom_handle"/>
 
     <ImageView
         android:id="@+id/bottom_right_corner"
+        android:background="@drawable/accessibility_window_magnification_drag_corner_background"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_margin="@dimen/magnification_outer_border_margin"
+        android:layout_margin="@dimen/magnification_drag_corner_margin"
         android:layout_gravity="right|bottom"
-        android:paddingEnd="@dimen/magnifier_drag_handle_padding"
-        android:paddingBottom="@dimen/magnifier_drag_handle_padding"
         android:scaleType="center"
         android:contentDescription="@string/magnification_drag_corner_to_resize"
-        android:src="@drawable/ic_magnification_corner_bottom_right"
+        android:src="@drawable/ic_arrow_top_left_and_bottom_right"
         android:accessibilityTraversalAfter="@id/top_right_corner"/>
 
     <ImageView
         android:id="@+id/bottom_left_corner"
+        android:background="@drawable/accessibility_window_magnification_drag_corner_background"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_margin="@dimen/magnification_outer_border_margin"
+        android:layout_margin="@dimen/magnification_drag_corner_margin"
         android:layout_gravity="left|bottom"
-        android:paddingStart="@dimen/magnifier_drag_handle_padding"
-        android:paddingBottom="@dimen/magnifier_drag_handle_padding"
         android:scaleType="center"
         android:contentDescription="@string/magnification_drag_corner_to_resize"
-        android:src="@drawable/ic_magnification_corner_bottom_left"
+        android:src="@drawable/ic_arrow_top_right_and_bottom_left"
         android:accessibilityTraversalAfter="@id/bottom_right_corner"/>
 
     <ImageView
@@ -124,7 +121,8 @@
         android:layout_gravity="right|bottom"
         android:padding="@dimen/magnifier_drag_handle_padding"
         android:scaleType="center"
-        android:src="@drawable/ic_move_magnification"/>
+        android:src="@drawable/ic_move_magnification"
+        android:background="@drawable/accessibility_window_magnification_drag_handle_background"/>
 
     <ImageView
         android:id="@+id/close_button"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 6bb51bbb..bdbbd50 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ondergrens <xliff:g id="PERCENT">%1$d</xliff:g> persent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Linkergrens <xliff:g id="PERCENT">%1$d</xliff:g> persent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Regtergrens <xliff:g id="PERCENT">%1$d</xliff:g> persent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Werkskermskote word in die <xliff:g id="APP">%1$s</xliff:g>-app gestoor"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Gestoor in <xliff:g id="APP">%1$s</xliff:g> in die werkprofiel"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Lêers"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> het hierdie skermskoot bespeur."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> en ander oop apps het hierdie skermskoot bespeur."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Skermopnemer"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Verwerk tans skermopname"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gesig is herken. Druk die ontsluitikoon om oop te maak."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ontsluit met gesig"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Gesig is herken"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Beweeg links"</item>
-    <item msgid="5558598599408514296">"Beweeg af"</item>
-    <item msgid="4844142668312841831">"Beweeg regs"</item>
-    <item msgid="5640521437931460125">"Beweeg op"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Swiep op om weer te probeer"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontsluit om NFC te gebruik"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Hierdie toestel behoort aan jou organisasie"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Kies program om kontroles by te voeg"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrole bygevoeg.}other{# kontroles bygevoeg.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Verwyder"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Voeg <xliff:g id="APPNAME">%s</xliff:g> by?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Wanneer jy <xliff:g id="APPNAME">%s</xliff:g> byvoeg, kan dit kontroles en inhoud by hierdie paneel voeg. Jy kan in sommige apps kies watter kontroles hier verskyn."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"As gunsteling gemerk"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"As gunsteling gemerk; posisie <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"As gunsteling ontmerk"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Maak <xliff:g id="APP_LABEL">%1$s</xliff:g> oop"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Speel <xliff:g id="SONG_NAME">%1$s</xliff:g> deur <xliff:g id="ARTIST_NAME">%2$s</xliff:g> vanaf <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Speel <xliff:g id="SONG_NAME">%1$s</xliff:g> vanaf <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Vir jou"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Ontdoen"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Beweeg nader om op <xliff:g id="DEVICENAME">%1$s</xliff:g> te speel"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Beweeg nader aan <xliff:g id="DEVICENAME">%1$s</xliff:g> om hier te speel"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Fout, probeer weer"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Voeg kontroles by"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Wysig kontroles"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Voeg app by"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Voeg uitvoere by"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 toestel gekies"</string>
@@ -919,7 +915,6 @@
     <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">"Luidsprekers en skerms"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Voorgestelde toestelle"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Vereis premiumrekening"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Hoe uitsaai werk"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Saai uit"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Mense in jou omtrek met versoenbare Bluetooth-toestelle kan na die media luister wat jy uitsaai"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera is af"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofoon is af"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera en mikrofoon is af"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# kennisgewing}other{# kennisgewings}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Neem notas"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Gee eenmalige toegang"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Moenie toelaat nie"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Toestelloglêers teken aan wat op jou toestel gebeur. Apps kan hierdie loglêers gebruik om kwessies op te spoor en reg te stel.\n\nSommige loglêers bevat dalk sensitiewe inligting, en daarom moet jy toegang tot alle toestelloglêers net gee aan apps wat jy vertrou. \n\nHierdie app het steeds toegang tot sy eie loglêers as jy nie vir hierdie app toegang tot alle toestelloglêers gee nie. Jou toestelvervaardiger het dalk steeds toegang tot sommige loglêers of inligting op jou toestel."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Maak <xliff:g id="APPNAME">%1$s</xliff:g> oop"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Die app opgestel is"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Minstens een kaart by Wallet gevoeg is"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Jou werkbeleid laat jou toe om slegs van die werkprofiel af foonoproepe te maak"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skakel oor na werkprofiel"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Maak toe"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Sluitskerminstellings"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 45e83c0..ece0036 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"የታች ወሰን <xliff:g id="PERCENT">%1$d</xliff:g> በመቶ"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"የግራ ወሰን <xliff:g id="PERCENT">%1$d</xliff:g> በመቶ"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"የቀኝ ወሰን <xliff:g id="PERCENT">%1$d</xliff:g> በመቶ"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"የሥራ ቅጽበታዊ ገጽ እይታዎች በ<xliff:g id="APP">%1$s</xliff:g> መተግበሪያ ውስጥ ይቀመጣሉ"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"<xliff:g id="APP">%1$s</xliff:g> ውስጥ የስራ መገለጫው ውስጥ ተቀምጧል"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ፋይሎች"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ይህን ቅጽበታዊ ገጽ እይታ ለይቷል።"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> እና ሌሎች ክፍት መተግበሪያዎች ይህን ቅጽበታዊ ገጽ እይታ ለይተዋል።"</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"የማያ መቅጃ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"የማያ ገጽ ቀረጻን በማሰናዳት ላይ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ለአንድ የማያ ገጽ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"መልክ ተለይቶ ታውቋል። ለመክፈት የመክፈቻ አዶውን ይጫኑ።"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"በመልክ ተከፍቷል"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"መልክ ተለይቶ ታውቋል"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ወደ ግራ ውሰድ"</item>
-    <item msgid="5558598599408514296">"ወደ ታች ውሰድ"</item>
-    <item msgid="4844142668312841831">"ወደ ቀኝ ውሰድ"</item>
-    <item msgid="5640521437931460125">"ወደ ላይ ውሰድ"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"እንደገና ለመሞከር ወደ ላይ ይጥረጉ"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCን ለመጠቀም ይክፈቱ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ይህ መሣሪያ የድርጅትዎ ነው"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"መቆጣጠሪያዎችን ለማከል መተግበሪያ ይምረጡ"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ቁጥጥር ታክሏል።}one{# ቁጥጥር ታክሏል።}other{# ቁጥጥሮች ታክለዋል።}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ተወግዷል"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ይታከል?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g>ን ሲያክሉ መቆጣጠሪያዎችን እና ይዘትን ወደዚህ ፓነል ሊያክል ይችላል። በአንዳንድ መተግበሪያዎች ውስጥ የትኛዎቹ መቆጣጠሪያዎች እዚህ ላይ እንደሚታዩ መምረጥ ይችላሉ።"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ተወዳጅ የተደረገ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ተወዳጅ ተደርጓል፣ አቋም <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ተወዳጅ አልተደረገም"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ክፈት"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> በ<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ከ<xliff:g id="APP_LABEL">%3$s</xliff:g> ያጫውቱ"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ከ<xliff:g id="APP_LABEL">%2$s</xliff:g> ያጫውቱ"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"ለእርስዎ"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"ቀልብስ"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"በ<xliff:g id="DEVICENAME">%1$s</xliff:g> ላይ ለማጫወት ጠጋ ያድርጉ"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"እዚህ ለማጫወት ወደ <xliff:g id="DEVICENAME">%1$s</xliff:g> ጠጋ ይበሉ"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"ስህተት፣ እንደገና ይሞክሩ"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"መቆጣጠሪያዎችን አክል"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"መቆጣጠሪያዎችን ያርትዑ"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"መተግበሪያ አክል"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ውጽዓቶችን ያክሉ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ቡድን"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 መሣሪያ ተመርጧል"</string>
@@ -919,7 +915,6 @@
     <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">"ድምጽ ማውጫዎች እና ማሳያዎች"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"የተጠቆሙ መሣሪያዎች"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"ፕሪሚየም መለያ ይጠይቃል"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ማሰራጨት እንዴት እንደሚሠራ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ስርጭት"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ተኳሃኝ የብሉቱዝ መሣሪያዎች ያላቸው በአቅራቢያዎ ያሉ ሰዎች እርስዎ እያሰራጩት ያሉትን ሚዲያ ማዳመጥ ይችላሉ"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"ካሜራ ጠፍቷል"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"ማይክሮፎን ጠፍቷል"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ካሜራ እና ማይክሮፎን ጠፍተዋል"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ማሳወቂያ}one{# ማሳወቂያዎች}other{# ማሳወቂያዎች}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>፣ <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"የአንድ ጊዜ መዳረሻን ፍቀድ"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"አትፍቀድ"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"የመሣሪያ ምዝግብ ማስታወሻዎች በመሣሪያዎ ላይ ምን እንደሚከሰት ይመዘግባሉ። መተግበሪያዎች ችግሮችን ለማግኘት እና ለማስተካከል እነዚህን ምዝግብ ማስታወሻዎች መጠቀም ይችላሉ።\n\nአንዳንድ ምዝግብ ማስታወሻዎች ልዩ ጥንቃቄ የሚያስፈልገው መረጃ ሊይዙ ይችላሉ ስለዚህ ለሚያምኗቸው መተግበሪያዎች ብቻ ሁሉንም የመሣሪያ ምዝግብ ማስታወሻዎች እንዲደርሱ ይፍቀዱላቸው። \n\nይህ መተግበሪያ ሁሉንም የመሣሪያ ምዝግብ ማስታወሻዎች እንዲደርስ ካልፈቀዱለት አሁንም የራሱን ምዝግብ ማስታወሻዎች መድረስ ይችላል። የእርስዎ መሣሪያ አምራች አሁንም በመሣሪያዎ ላይ አንዳንድ ምዝግብ ማስታወሻዎችን ወይም መረጃዎችን ሊደርስ ይችላል።"</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ይክፈቱ"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• መተግበሪያው ተዋቅሯል"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ቢያንስ አንድ ካርድ ወደ Wallet ታክሏል"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"የሥራ መመሪያዎ እርስዎ ከሥራ መገለጫው ብቻ ጥሪ እንዲያደርጉ ይፈቅድልዎታል"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ወደ የሥራ መገለጫ ቀይር"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ዝጋ"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"የማያ ገጽ ቁልፍ ቅንብሮች"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index eeaf5d7..f0c5909 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"الحد السفلى <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"الحد الأيسر <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"الحد الأيمن <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"يتم حفظ لقطات الشاشة الخاصة بالعمل في تطبيق \"<xliff:g id="APP">%1$s</xliff:g>\"."</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"الملفات"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"مسجّل الشاشة"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"جارٍ معالجة تسجيل الشاشة"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"تم التعرّف على الوجه. اضغط على رمز فتح القفل لفتح الجهاز."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"تم فتح قفل جهازك عند تقريبه من وجهك."</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"تم التعرّف على الوجه."</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"نقل لليسار"</item>
-    <item msgid="5558598599408514296">"نقل للأسفل"</item>
-    <item msgid="4844142668312841831">"نقل لليمين"</item>
-    <item msgid="5640521437931460125">"نقل للأعلى"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"مرِّر سريعًا للأعلى لإعادة المحاولة."</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏افتح قفل الشاشة لاستخدام تقنية NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"هذا الجهاز يخص مؤسستك."</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"اختيار تطبيق لإضافة عناصر التحكّم"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{تمت إضافة عنصر تحكّم واحد.}zero{تمت إضافة # عنصر تحكّم.}two{تمت إضافة عنصرَي تحكّم.}few{تمت إضافة # عناصر تحكّم.}many{تمت إضافة # عنصر تحكّم.}other{تمت إضافة # عنصر تحكّم.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"تمت الإزالة"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"هل تريد إضافة \"<xliff:g id="APPNAME">%s</xliff:g>\"؟"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"عند إضافة تطبيق \"<xliff:g id="APPNAME">%s</xliff:g>\"، يمكنه إضافة عناصر تحكّم ومحتوى إلى هذه اللوحة. في بعض التطبيقات، يمكنك اختيار عناصر التحكّم التي تظهر هنا."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"تمت الإضافة إلى المفضّلة"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"تمت الإضافة إلى المفضّلة، الموضع <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"تمت الإزالة من المفضّلة"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"فتح <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"تشغيل <xliff:g id="SONG_NAME">%1$s</xliff:g> للفنان <xliff:g id="ARTIST_NAME">%2$s</xliff:g> من تطبيق <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"تشغيل <xliff:g id="SONG_NAME">%1$s</xliff:g> من تطبيق <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"اقتراحات لك"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"تراجع"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"عليك الاقتراب لتشغيل الوسائط على <xliff:g id="DEVICENAME">%1$s</xliff:g>."</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"للتشغيل هنا، عليك الاقتراب من \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\"."</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"حدث خطأ، يُرجى إعادة المحاولة."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"إضافة عناصر تحكّم"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"تعديل عناصر التحكّم"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"إضافة تطبيق"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"إضافة مخرجات"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"مجموعة"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"تم اختيار جهاز واحد."</string>
@@ -919,7 +918,6 @@
     <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">"مكبّرات الصوت والشاشات"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"الأجهزة المقترَحة"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"يجب استخدام حساب مدفوع."</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"كيفية عمل البث"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"البث"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"يمكن للأشخاص القريبين منك الذين لديهم أجهزة متوافقة تتضمّن بلوتوث الاستماع إلى الوسائط التي تبثها."</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"الكاميرا غير مفعّلة"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"الميكروفون غير مفعّل"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"الكاميرا والميكروفون غير مفعّلين."</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{إشعار واحد}zero{# إشعار}two{إشعاران}few{# إشعارات}many{# إشعارًا}other{# إشعار}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>، <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"تدوين الملاحظات"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"السماح بالوصول إلى السجلّ لمرة واحدة"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"عدم السماح"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"ترصد سجلّات الجهاز ما يحدث على جهازك. يمكن أن تستخدم التطبيقات هذه السجلّات لتحديد المشاكل وحلّها.\n\nقد تحتوي بعض السجلّات على معلومات حساسة، ولذلك يجب عدم السماح بالوصول إلى جميع سجلّات الجهاز إلا للتطبيقات التي تثق بها. \n\nإذا لم تسمح بوصول هذا التطبيق إلى جميع سجلّات الجهاز، يظل بإمكان التطبيق الوصول إلى سجلّاته. ويظل بإمكان الشركة المصنِّعة لجهازك الوصول إلى بعض السجلّات أو المعلومات المتوفّرة على جهازك."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"فتح \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• إعداد التطبيق"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"‏• إضافة بطاقة واحدة على الأقل إلى \"محفظة Google\""</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"تسمح لك سياسة العمل بإجراء المكالمات الهاتفية من الملف الشخصي للعمل فقط."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"التبديل إلى الملف الشخصي للعمل"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"إغلاق"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"إعدادات شاشة القفل"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 56f7e8e..5103b13 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"তলৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"বাওঁফালৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"সোঁফালৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"<xliff:g id="APP">%1$s</xliff:g> এপ্‌টোত কৰ্মস্থানৰ স্ক্ৰীনশ্বটসমূহ ছেভ কৰা হয়"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"<xliff:g id="APP">%1$s</xliff:g> কৰ্মস্থানৰ প্ৰ’ফাইলত ছেভ কৰা হৈছে"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ফাইল"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>এ এই স্ক্ৰীনশ্বটটো চিনাক্ত কৰিছে।"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> আৰু আন খোলা এপ্‌সমূহে এই স্ক্ৰীনশ্বটটো চিনাক্ত কৰিছে।"</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রীন ৰেকৰ্ডিঙৰ প্ৰক্ৰিয়াকৰণ হৈ আছে"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীন ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। খুলিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"মুখাৱয়ব চিনাক্ত কৰা হৈছে"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"বাওঁফাললৈ নিয়ক"</item>
-    <item msgid="5558598599408514296">"তললৈ নিয়ক"</item>
-    <item msgid="4844142668312841831">"সোঁফাললৈ নিয়ক"</item>
-    <item msgid="5640521437931460125">"ওপৰলৈ নিয়ক"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"পুনৰ চেষ্টা কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"নিয়ন্ত্ৰণসমূহ যোগ কৰিবলৈ এপ্‌ বাছনি কৰক"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# টা নিয়ন্ত্ৰণ যোগ দিয়া হৈছে।}one{# টা নিয়ন্ত্ৰণ যোগ দিয়া হৈছে।}other{# টা নিয়ন্ত্ৰণ যোগ দিয়া হৈছে।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"আঁতৰোৱা হ’ল"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> যোগ দিবনে?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"আপুনি <xliff:g id="APPNAME">%s</xliff:g> যোগ দিলে, ই এই পেনেলত নিয়ন্ত্ৰণ আৰু সমল যোগ দিব পাৰে। কিছুমান এপত আপুনি কোনবোৰ নিয়ন্ত্ৰণ ইয়াত দেখা পোৱা যাব সেয়া বাছনি কৰিব পাৰে।"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"প্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"প্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল, স্থান <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"অপ্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> খোলক"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ত <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ৰ <xliff:g id="SONG_NAME">%1$s</xliff:g> গীতটো প্লে’ কৰক"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g>ত <xliff:g id="SONG_NAME">%1$s</xliff:g> গীতটো প্লে’ কৰক"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"আপোনাৰ বাবে"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"আনডু কৰক"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ত প্লে’ কৰিবলৈ ওচৰলৈ যাওক"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ইয়াত প্লে’ কৰিবলৈ, <xliff:g id="DEVICENAME">%1$s</xliff:g>ৰ ওচৰলৈ যাওক"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"আসোঁৱাহ হৈছে, আকৌ চেষ্টা কৰক"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"নিয়ন্ত্ৰণসমূহ যোগ দিয়ক"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"নিয়ন্ত্ৰণসমূহ সম্পাদনা কৰক"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"এপ্‌ যোগ দিয়ক"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"আউটপুটসমূহ যোগ দিয়ক"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"গোট"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"১ টা ডিভাইচ বাছনি কৰা হৈছে"</string>
@@ -919,7 +915,6 @@
     <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">"স্পীকাৰ আৰু ডিছপ্লে’"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"পৰামৰ্শ হিচাপে পোৱা ডিভাইচ"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Premium একাউণ্টৰ আৱশ্যক"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"সম্প্ৰচাৰ কৰাটোৱে কেনেকৈ কাম কৰে"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"সম্প্ৰচাৰ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"সমিল ব্লুটুথ ডিভাইচৰ সৈতে আপোনাৰ নিকটৱৰ্তী স্থানত থকা লোকসকলে আপুনি সম্প্ৰচাৰ কৰা মিডিয়াটো শুনিব পাৰে"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"কেমেৰা অফ আছে"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"মাইক অফ আছে"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"কেমেৰা আৰু মাইক অফ হৈ আছে"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# টা জাননী}one{# টা জাননী}other{# টা জাননী}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"টোকাগ্ৰহণ"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"কেৱল এবাৰ এক্সেছ কৰাৰ অনুমতি দিয়ক"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"অনুমতি নিদিব"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"আপোনাৰ ডিভাইচত কি কি ঘটে সেয়া ডিভাইচ লগে ৰেকৰ্ড কৰে। এপ্‌সমূহে সমস্যা বিচাৰিবলৈ আৰু সমাধান কৰিবলৈ এই লগসমূহ ব্যৱহাৰ কৰিব পাৰে।\n\nকিছুমান লগত সংবেদনশীল তথ্য থাকিব পাৰে, গতিকে কেৱল আপুনি বিশ্বাস কৰা এপকহে আটাইবোৰ ডিভাইচ লগ এক্সেছ কৰাৰ অনুমতি দিয়ক। \n\nআপুনি যদি এই এপ্‌টোক আটাইবোৰ ডিভাইচ লগ এক্সেছ কৰাৰ অনুমতি নিদিয়ে, তথাপিও ই নিজৰ লগসমূহ এক্সেছ কৰিব পাৰিব। আপোনাৰ ডিভাইচৰ নিৰ্মাতাই তথাপিও হয়তো আপোনাৰ ডিভাইচটোত থকা কিছু লগ অথবা তথ্য এক্সেছ কৰিব পাৰিব।"</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> খোলক"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• এপ্‌টো ছেট আপ কৰা হৈছে"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Walletত অতি কমেও এখন কাৰ্ড যোগ দিয়া হৈছে"</string>
@@ -1054,11 +1055,11 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• অতি কমেও এটা ডিভাইচ উপলব্ধ"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"শ্বৰ্টকাটটোত স্পৰ্শ কৰি ধৰি ৰাখক"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"বাতিল কৰক"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"এতিয়াই লুটিয়াই দিয়ক"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"এতিয়াই ফ্লিপ কৰক"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"উন্নত ছেল্ফিৰ বাবে ফ’নটো আনফ’ল্ড কৰক"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"উন্নত ছেল্ফিৰ বাবে সন্মুখৰ ডিছপ্লে’ লুটিয়াই দিবনে?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"উন্নত ছেল্ফিৰ বাবে সন্মুখৰ ডিছপ্লে’ ফ্লিপ কৰিবনে?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"অধিক ৰিজ’লিউশ্বনৰ বহল ফট’ৰ বাবে পিছফালে থকা কেমেৰাটো ব্যৱহাৰ কৰক।"</string>
-    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ই স্ক্ৰীনখন অফ হ’ব"</b></string>
+    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ এই স্ক্ৰীনখন অফ হ’ব"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"জপাব পৰা ডিভাইচৰ জাপ খুলি থকা হৈছে"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"জপাব পৰা ডিভাইচৰ ওলোটাই থকা হৈছে"</string>
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> বেটাৰী বাকী আছে"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"আপোনাৰ কৰ্মস্থানৰ নীতিয়ে আপোনাক কেৱল কৰ্মস্থানৰ প্ৰ’ফাইলৰ পৰা ফ’ন কল কৰিবলৈ দিয়ে"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"কৰ্মস্থানৰ প্ৰ’ফাইললৈ সলনি কৰক"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ কৰক"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"লক স্ক্ৰীনৰ ছেটিং"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 6b5ad2a..a6e6b06 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Aşağı sərhəd <xliff:g id="PERCENT">%1$d</xliff:g> faiz"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Sol sərhəd <xliff:g id="PERCENT">%1$d</xliff:g> faiz"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Sağ sərhəd <xliff:g id="PERCENT">%1$d</xliff:g> faiz"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"İş skrinşotları <xliff:g id="APP">%1$s</xliff:g> tətbiqində saxlanılır"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"İş profilində <xliff:g id="APP">%1$s</xliff:g> tətbiqində saxlanıb"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fayllar"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> bu skrinşotu aşkarladı."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> və digər açıq tətbiqlər bu skrinşotu aşkarladı."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekran Yazıcısı"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran çəkilişi emal edilir"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb açın."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Üz ilə kiliddən çıxarılıb"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Üz tanınıb"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Sola köçürün"</item>
-    <item msgid="5558598599408514296">"Aşağı köçürün"</item>
-    <item msgid="4844142668312841831">"Sağa köçürün"</item>
-    <item msgid="5640521437931460125">"Yuxarı köçürün"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Yenidən cəhd etmək üçün yuxarı sürüşdürün"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC istifadə etmək üçün kiliddən çıxarın"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz təşkilatınıza məxsusdur"</string>
@@ -645,7 +643,7 @@
     <item msgid="2681220472659720036">"Mübadilə buferi"</item>
     <item msgid="4795049793625565683">"Açar kodu"</item>
     <item msgid="80697951177515644">"Çevirin, klaviatura dəyişdirici"</item>
-    <item msgid="7626977989589303588">"Heç bir"</item>
+    <item msgid="7626977989589303588">"Heç biri"</item>
   </string-array>
   <string-array name="nav_bar_layouts">
     <item msgid="9156773083127904112">"Normal"</item>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Kontrol əlavə etmək üçün tətbiq seçin"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# nizamlayıcı əlavə edilib.}other{# nizamlayıcı əlavə edilib.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Silinib"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> əlavə edilsin?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> əlavə etdiyiniz zaman, o, bu panelə nizamlayıcılar və məzmun əlavə edə bilər. Bəzi tətbiqlərdə burada hansı nizamlayıcıların göstərilməsini seçə bilərsiniz."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Sevimlilərə əlavə edilib"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Sevimlilərə əlavə edilib, sıra: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Sevimlilərdən silinib"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> tətbiqini açın"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> tərəfindən <xliff:g id="SONG_NAME">%1$s</xliff:g> mahnısını <xliff:g id="APP_LABEL">%3$s</xliff:g> tətbiqindən oxudun"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> mahnısını <xliff:g id="APP_LABEL">%2$s</xliff:g> tətbiqindən oxudun"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Sizin üçün"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Geri qaytarın"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> cihazında oxutmaq üçün yaxınlaşın"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Burada oxutmaq üçün <xliff:g id="DEVICENAME">%1$s</xliff:g> cihazına yaxınlaşdırın"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Xəta, yenidən cəhd edin"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Vidcet əlavə edin"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Vidcetlərə düzəliş edin"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tətbiq əlavə edin"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Nəticələri əlavə edin"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Qrup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçilib"</string>
@@ -919,7 +915,6 @@
     <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">"Dinamiklər &amp; Displeylər"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Təklif olunan Cihazlar"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Premium hesab tələb edilir"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayım necə işləyir"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Yayım"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Uyğun Bluetooth cihazları olan yaxınlığınızdakı insanlar yayımladığınız medianı dinləyə bilər"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera deaktivdir"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon deaktivdir"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera və mikrofon deaktivdir"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# bildiriş}other{# bildiriş}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Qeyd tutma"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Birdəfəlik girişə icazə verin"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"İcazə verməyin"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Cihaz qeydləri cihazınızda baş verənləri qeyd edir. Tətbiqlər problemləri tapmaq və həll etmək üçün bu qeydlərdən istifadə edə bilər.\n\nBəzi qeydlərdə həssas məlumatlar ola bilər, ona görə də yalnız etibar etdiyiniz tətbiqlərin bütün cihaz qeydlərinə giriş etməsinə icazə verin. \n\nBu tətbiqin bütün cihaz qeydlərinə girişinə icazə verməsəniz, o, hələ də öz qeydlərinə giriş edə bilər. Cihaz istehsalçınız hələ də cihazınızda bəzi qeydlərə və ya məlumatlara giriş edə bilər."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> tətbiqini açın"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Tətbiq ayarlanmalıdır"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Pulqabına ən azı bir kart əlavə edilməlidir"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"İş siyasətiniz yalnız iş profilindən telefon zəngləri etməyə imkan verir"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"İş profilinə keçin"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Bağlayın"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Kilid ekranı ayarları"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 3f9f3ec..ad3e7b5 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Donja ivica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Leva ivica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Desna ivica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Snimci ekrana za posao se čuvaju u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Sačuvano je u aplikaciji <xliff:g id="APP">%1$s</xliff:g> na poslovnom profilu"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fajlovi"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> je otkrila ovaj snimak ekrana."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije su otkrile ovaj snimak ekrana."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađujemo video snimka ekrana"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice prepoznato. Pritisnite ikonu otključavanja da biste otvorili."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Otključano je licem"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Lice je prepoznato"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Pomerite nalevo"</item>
-    <item msgid="5558598599408514296">"Pomerite nadole"</item>
-    <item msgid="4844142668312841831">"Pomerite nadesno"</item>
-    <item msgid="5640521437931460125">"Pomerite nagore"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Prevucite nagore da biste probali ponovo"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste koristili NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada organizaciji"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Odaberite aplikaciju za dodavanje kontrola"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrola je dodata.}one{# kontrola je dodata.}few{# kontrole su dodate.}other{# kontrola je dodato.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Želite li da dodate <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kada dodate aplikaciju <xliff:g id="APPNAME">%s</xliff:g>, ona može da dodaje kontrole i sadržaj u ovo okno. U nekim aplikacijama možete da izaberete koje će se kontrole ovde prikazivati."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Označeno je kao omiljeno"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Označeno je kao omiljeno, <xliff:g id="NUMBER">%d</xliff:g>. pozicija"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno je iz omiljenih"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvorite <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Za vas"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Opozovi"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Približite da biste puštali muziku na: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Da biste puštali sadržaj ovde, približite uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Greška. Probajte ponovo"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Izmeni kontrole"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikaciju"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajte izlaze"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izabran je 1 uređaj"</string>
@@ -919,7 +915,6 @@
     <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">"Zvučnici i ekrani"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Predloženi uređaji"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Zahteva premijum nalog"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcioniše emitovanje"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emitovanje"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ljudi u blizini sa kompatibilnim Bluetooth uređajima mogu da slušaju medijski sadržaj koji emitujete"</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera je isključena"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon je isključen"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera i mikrofon su isključeni"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Pomoćnik sluša"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obaveštenje}one{# obaveštenje}few{# obaveštenja}other{# obaveštenja}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Pravljenje beležaka"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Dozvoli jednokratan pristup"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ne dozvoli"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Evidencije uređaja registruju šta se dešava na uređaju. Aplikacije mogu da koriste te evidencije da bi pronašle i rešile probleme.\n\nNeke evidencije mogu da sadrže osetljive informacije, pa pristup svim evidencijama uređaja treba da dozvoljavate samo aplikacijama u koje imate poverenja. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim evidencijama uređaja, ona i dalje može da pristupa sopstvenim evidencijama. Proizvođač uređaja će možda i dalje moći da pristupa nekim evidencijama ili informacijama na uređaju."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saznajte više"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saznajte više na <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvorite: <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• da je aplikacija podešena"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• da je u Novčanik dodata barem jedna kartica"</string>
@@ -1054,7 +1052,7 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• da je dostupan barem jedan uređaj"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Dodirnite i zadržite prečicu"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Otkaži"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Obrnite"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Obrni"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Otvorite telefon za bolji selfi"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Želite da obrnete na prednji ekran za bolji selfi?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Koristite zadnju kameru da biste snimili širu sliku sa višom rezolucijom."</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Smernice za posao vam omogućavaju da telefonirate samo sa poslovnog profila"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređi na poslovni profil"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Podešavanja zaključanog ekrana"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index d4dc17b..87fd271 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ніжняя граніца: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Левая граніца: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Правая граніца: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Працоўныя здымкі экрана захаваны ў праграме \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Файлы"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Запіс экрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Апрацоўваецца запіс экрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Бягучае апавяшчэнне для сеанса запісу экрана"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Твар распазнаны. Для адкрыцця націсніце значок разблакіроўкі."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Разблакіравана распазнаваннем твару"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Твар распазнаны"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Перамясціце палец улева"</item>
-    <item msgid="5558598599408514296">"Перамясціце палец ніжэй"</item>
-    <item msgid="4844142668312841831">"Перамясціце палец управа"</item>
-    <item msgid="5640521437931460125">"Перамясціце палец уверх"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Прагартайце ўверх, каб паўтарыць спробу"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Разблакіруйце, каб выкарыстоўваць NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Гэта прылада належыць вашай арганізацыі"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Выберыце праграму для дадавання элементаў кіравання"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Дададзены # элемент кіравання.}one{Дададзена # элемента кіравання.}few{Дададзена # элементы кіравання.}many{Дададзена # элементаў кіравання.}other{Дададзена # элемента кіравання.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Выдалена"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Дадаць праграму \"<xliff:g id="APPNAME">%s</xliff:g>\"?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Калі вы дадасце праграму \"<xliff:g id="APPNAME">%s</xliff:g>\", яна зможа дадаваць на гэту панэль налады і змесціва. Для некаторых праграм вы зможаце выбраць, якія налады будуць тут паказвацца."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Дададзена ў абранае"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Дададзена ў абранае, пазіцыя <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Выдалена з абранага"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Адкрыйце праграму \"<xliff:g id="APP_LABEL">%1$s</xliff:g>\""</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Прайграйце кампазіцыю \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" (выканаўца – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) з дапамогай праграмы \"<xliff:g id="APP_LABEL">%3$s</xliff:g>\""</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Прайграйце кампазіцыю \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" з дапамогай праграмы \"<xliff:g id="APP_LABEL">%2$s</xliff:g>\""</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Для вас"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Адрабіць"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Каб прайграць мультымедыя на прыладзе \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\", наблізьцеся да яе"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Каб прайграць тут, падыдзіце бліжэй да прылады \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\""</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Памылка, паўтарыце спробу"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Дадаць элементы кіравання"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Змяніць элементы кіравання"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Дадаць праграму"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Дадайце прылады вываду"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрана 1 прылада"</string>
@@ -919,7 +918,6 @@
     <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">"Дынамікі і дысплэі"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Прылады, якія падтрымліваюцца"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Патрабуецца платны ўліковы запіс"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як адбываецца трансляцыя"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляцыя"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Людзі паблізу, у якіх ёсць прылады з Bluetooth, змогуць праслухваць мультымедыйнае змесціва, якое вы трансліруеце"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Камера выключана"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Мікрафон выключаны"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера і мікрафон выключаны"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# апавяшчэнне}one{# апавяшчэнне}few{# апавяшчэнні}many{# апавяшчэнняў}other{# апавяшчэння}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Стварэнне нататак"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Дазволіць аднаразовы доступ"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Не дазваляць"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Журналы прылад запісваюць усё, што адбываецца на вашай прыладзе. Праграмы выкарыстоўваюць гэтыя журналы для пошуку і выпраўлення памылак.\n\nУ некаторых журналах можа ўтрымлівацца канфідэнцыяльная інфармацыя, таму дазваляйце доступ да ўсіх журналаў прылады толькі тым праграмам, якім вы давяраеце. \n\nКалі вы не дасцё гэтай праграме доступу да ўсіх журналаў прылад, у яе ўсё роўна застанецца доступ да ўласных журналаў. Для вытворцы вашай прылады будуць даступнымі некаторыя журналы і інфармацыя на вашай прыладзе."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Адкрыць праграму \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Праграма наладжана."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• У Кашалёк дададзена хаця б адна картка."</string>
@@ -1056,7 +1060,7 @@
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Скасаваць"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Пераключыць"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Каб атрымаць лепшае сэлфі, раскрыйце тэлефон"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Пераключыць на пярэднюю камеру для лепшага сэлфі?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Пераключыць на пярэдні дысплэй для лепшага сэлфі?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Каб зрабіць шырэйшае фота з больш высокай раздзяляльнасцю, скарыстайце заднюю камеру."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Гэты экран будзе выключаны"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складная прылада ў раскладзеным выглядзе"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Згодна з палітыкай вашай арганізацыі, рабіць тэлефонныя выклікі дазволена толькі з працоўнага профілю"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Пераключыцца на працоўны профіль"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрыць"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Налады экрана блакіроўкі"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 2141a47..1f2d035 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Долна граница: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Лява граница: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Дясна граница: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Екранните снимки, направени в служебния потребителски профил, се запазват в приложението „<xliff:g id="APP">%1$s</xliff:g>“"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Запис на екрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Записът на екрана се обработва"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицето бе разпознато. Отворете чрез иконата за отключване."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Отключено с лице"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лицето бе разпознато"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Преместване наляво"</item>
-    <item msgid="5558598599408514296">"Преместване надолу"</item>
-    <item msgid="4844142668312841831">"Преместване надясно"</item>
-    <item msgid="5640521437931460125">"Преместване нагоре"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Плъзнете бързо нагоре, за да опитате отново"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отключете, за да използвате NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Това устройство принадлежи на организацията ви"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Изберете приложение, за да добавите контроли"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Добавена е # контрола.}other{Добавени са # контроли.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Премахнато"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Да се добави ли <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Когато добавите <xliff:g id="APPNAME">%s</xliff:g>, приложението може да добави контроли и съдържание към този панел. Някои приложения ви дават възможност да избирате кои контроли да се показват тук."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Означено като любимо"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Означено като любимо – позиция <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Не е означено като любимо"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Отваряне на <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Пускане на <xliff:g id="SONG_NAME">%1$s</xliff:g> на <xliff:g id="ARTIST_NAME">%2$s</xliff:g> от <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Пускане на <xliff:g id="SONG_NAME">%1$s</xliff:g> от <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"За вас"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Отмяна"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Преместете се по-близо, за да се възпроизведе на <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"За възпроизвеждане тук се приближете до <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Грешка. Опитайте отново"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Добавяне на контроли"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Редактиране на контролите"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Добавяне на приложение"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Добавяне на изходящи устройства"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 избрано устройство"</string>
@@ -919,7 +918,6 @@
     <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">"Високоговорители и екрани"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Предложени устройства"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Необходим е платен профил"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работи предаването"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Предаване"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Хората в близост със съвместими устройства с Bluetooth могат да слушат мултимедията, която предавате"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Камерата е изключена"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Микрофонът е изключен"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камерата и микрофонът са изключени"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# известие}other{# известия}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Водене на бележки"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Разрешаване на еднократен достъп"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Забраняване"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"В регистрационните файлове за устройството се записва какво се извършва на него. Приложенията могат да използват тези регистрационни файлове, за да откриват и отстраняват проблеми.\n\nНякои регистрационни файлове за устройството може да съдържат поверителна информация, затова разрешавайте достъп до всички тях само на приложения, на които имате доверие. \n\nАко не разрешите на това приложение достъп до всички регистрационни файлове за устройството, то пак може да осъществява достъп до собствените си регистрационни файлове. Възможно е производителят на устройството да продължи да има достъп до някои регистрационни файлове или информация на устройството ви."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Отваряне на <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Приложението е настроено."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• В Wallet е добавена поне една карта."</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Служебните правила ви дават възможност да извършвате телефонни обаждания само от служебния потребителски профил"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Превключване към служебния потребителски профил"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Затваряне"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Настройки за заключения екран"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 691293c..d9824ba 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"নিচের প্রান্ত থেকে <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"বাঁ প্রান্ত থেকে <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ডান প্রান্ত থেকে <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"অফিসের স্ক্রিনশট <xliff:g id="APP">%1$s</xliff:g> অ্যাপে সেভ করা হয়"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"অফিস প্রোফাইলের মধ্যে <xliff:g id="APP">%1$s</xliff:g>-এ সেভ করা হয়েছে"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ফাইল"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>, এই স্ক্রিনশট শনাক্ত করেছে।"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> এবং খোলা থাকা অন্য অ্যাপ এই স্ক্রিনশট শনাক্ত করেছে।"</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"স্ক্রিন রেকর্ডার"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রিন রেকর্ডিং প্রসেস হচ্ছে"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ফেস শনাক্ত করা হয়েছে। খোলার জন্য আনলক আইকন প্রেস করুন।"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ফেস দেখিয়ে আনলক করা হয়েছে"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ফেস চিনে নেওয়া হয়েছে"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"বাঁদিকে সরান"</item>
-    <item msgid="5558598599408514296">"নিচে নামান"</item>
-    <item msgid="4844142668312841831">"ডানদিকে সরান"</item>
-    <item msgid="5640521437931460125">"উপরে তুলুন"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"আবার চেষ্টা করতে উপরের দিকে সোয়াইপ করুন"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ব্যবহার করতে আনলক করুন"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"এই ডিভাইসটি আপনার প্রতিষ্ঠানের"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"কন্ট্রোল যোগ করতে অ্যাপ বেছে নিন"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{#টি কন্ট্রোল যোগ করা হয়েছে।}one{#টি কন্ট্রোল যোগ করা হয়েছে।}other{#টি কন্ট্রোল যোগ করা হয়েছে।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"সরানো হয়েছে"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> যোগ করবেন?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"আপনি <xliff:g id="APPNAME">%s</xliff:g> যোগ করলে, এই প্যানেলে এটি কন্ট্রোল ও কন্টেন্ট যোগ করতে পারবে। কিছু অ্যাপের ক্ষেত্রে, এখানে কোন কোন কন্ট্রোল দেখা যাবে আপনি তা নিয়ন্ত্রণ করতে পারবেন।"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"পছন্দসই হিসেবে চিহ্নিত করেছেন"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"পছন্দসই হিসেবে চিহ্নিত করেছেন, অবস্থান <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"পছন্দসই থেকে সরিয়ে দিয়েছেন"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> অ্যাপ খুলুন"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>-এর <xliff:g id="SONG_NAME">%1$s</xliff:g> গানটি <xliff:g id="APP_LABEL">%3$s</xliff:g> অ্যাপে চালান"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> গানটি <xliff:g id="APP_LABEL">%2$s</xliff:g> অ্যাপে চালান"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"আপনার জন্য"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"আগের অবস্থায় ফিরুন"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>-এ চালাতে আরও কাছে আনুন"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"এখানে চালানোর জন্য আপনার ডিভাইস <xliff:g id="DEVICENAME">%1$s</xliff:g>-এর কাছে নিয়ে যান"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"সমস্যা হয়েছে, আবার চেষ্টা করুন"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"কন্ট্রোল যোগ করুন"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"কন্ট্রোল এডিট করুন"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"অ্যাপ যোগ করুন"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"আউটপুট যোগ করুন"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"গ্রুপ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"১টি ডিভাইস বেছে নেওয়া হয়েছে"</string>
@@ -919,7 +915,6 @@
     <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">"স্পিকার &amp; ডিসপ্লে"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"সাজেস্ট করা ডিভাইস"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"প্রিমিয়াম অ্যাকাউন্ট প্রয়োজন"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ব্রডকাস্ট কীভাবে কাজ করে"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"সম্প্রচার করুন"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"আশপাশে লোকজন যাদের মানানসই ব্লুটুথ ডিভাইস আছে, তারা আপনার ব্রডকাস্ট করা মিডিয়া শুনতে পারবেন"</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"ক্যামেরা বন্ধ করা আছে"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"মাইক্রোফোন বন্ধ করা আছে"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ক্যামেরা ও মাইক্রোফোন বন্ধ আছে"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant শুনছে"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{#টি বিজ্ঞপ্তি}one{#টি বিজ্ঞপ্তি}other{#টি বিজ্ঞপ্তি}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"এককালীন অ্যাক্সেসের অনুমতি দিন"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"অনুমতি দেবেন না"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"ডিভাইস লগে আপনার ডিভাইসে করা অ্যাক্টিভিটি রেকর্ড করা হয়। অ্যাপ সমস্যা খুঁজে তা সমাধান করতে এইসব লগ ব্যবহার করতে পারে।\n\nকিছু লগে সংবেদনশীল তথ্য থাকতে পারে, তাই বিশ্বাস করেন শুধুমাত্র এমন অ্যাপকেই সব ডিভাইসের লগ অ্যাক্সেসের অনুমতি দিন। \n\nআপনি এই অ্যাপকে ডিভাইসের সব লগ অ্যাক্সেস করার অনুমতি না দিলেও, এটি নিজে লগ অ্যাক্সেস করতে পারবে। ডিভাইস প্রস্তুতকারকও আপনার ডিভাইসের কিছু লগ বা তথ্য হয়ত অ্যাক্সেস করতে পারবে।"</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"আরও জানুন"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"আরও জানতে <xliff:g id="URL">%s</xliff:g>-এ যান"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> খুলুন"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• অ্যাপ সেট-আপ করা হয়ে গেছে"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• অন্তত একটি কার্ড Wallet-এ যোগ করা হয়েছে"</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"কাজ সংক্রান্ত নীতি, আপনাকে শুধুমাত্র অফিস প্রোফাইল থেকে কল করার অনুমতি দেয়"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"অফিস প্রোফাইলে পাল্টে নিন"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ করুন"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"লক স্ক্রিন সেটিংস"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 57c0a23..1771a37 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Donja granica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Lijeva granica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Desna granica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Poslovni snimci ekrana se pohranjuju u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Sačuvano je u aplikaciji <xliff:g id="APP">%1$s</xliff:g> na radnom profilu"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fajlovi"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> je otkrila ovaj snimak ekrana."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije su otkrile ovaj snimak ekrana."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađivanje snimka ekrana"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice prepoznato. Pritisnite ikonu za otklj. da otvorite."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Otključano je licem"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Lice je prepoznato"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Pomjeranje ulijevo"</item>
-    <item msgid="5558598599408514296">"Pomjeranje nadolje"</item>
-    <item msgid="4844142668312841831">"Pomjeranje udesno"</item>
-    <item msgid="5640521437931460125">"Pomjeranje nagore"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Prevucite prema gore da pokušate ponovo"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da koristite NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string>
@@ -832,8 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Odaberite aplikaciju da dodate kontrole"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Dodana je # kontrola.}one{Dodana je # kontrola.}few{Dodane su # kontrole.}other{Dodano je # kontrola.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
-    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Želite li dodati aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kada dodate aplikaciju <xliff:g id="APPNAME">%s</xliff:g>, može dodati kontrole i sadržaj na ovu ploču. U nekim aplikacijama možete odabrati koje se kontrole prikazuju ovdje."</string>
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Dodati aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kada dodate aplikaciju <xliff:g id="APPNAME">%s</xliff:g>, ona može dodavati kontrole i sadržaj na ovu ploču. U nekim aplikacijama možete odabrati koje kontrole se prikazuju ovdje."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano u omiljeno"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano u omiljeno, pozicija <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno iz omiljenog"</string>
@@ -884,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvorite aplikaciju <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproducirajte pjesmu <xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> pomoću aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproducirajte pjesmu <xliff:g id="SONG_NAME">%1$s</xliff:g> pomoću aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Za vas"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Poništi"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Približite da reproducirate na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Da reproducirate ovdje, približite se uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -900,7 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Greška, pokušajte ponovo"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Uredi kontrole"</string>
-    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodavanje aplikacije"</string>
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikaciju"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajte izlaze"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Odabran je 1 uređaj"</string>
@@ -916,7 +915,6 @@
     <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">"Zvučnici i ekrani"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Predloženi uređaji"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Zahtijeva premijum račun"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcionira emitiranje"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emitirajte"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u vašoj blizini s kompatibilnim Bluetooth uređajima mogu slušati medijske sadržaje koje emitirate"</string>
@@ -1028,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera je isključena"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon je isključen"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera i mikrofon su isključeni"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistent sluša"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obavještenje}one{# obavještenje}few{# obavještenja}other{# obavještenja}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Pisanje bilješki"</string>
@@ -1043,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Dozvoli jednokratan pristup"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Nemoj dozvoliti"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Zapisnici uređaja bilježe šta se dešava na uređaju. Aplikacije mogu koristiti te zapisnike da pronađu i isprave probleme.\n\nNeki zapisnici mogu sadržavati osjetljive podatke, zato pristup svim zapisnicima uređaja dozvolite samo aplikacijama kojima vjerujete. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač uređaja će možda i dalje biti u stanju pristupiti nekim zapisnicima ili podacima na uređaju."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saznajte više"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saznajte više na <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvori aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacija je postavljena"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Najmanje jedna kartica je dodana u Novčanik"</string>
@@ -1054,7 +1055,7 @@
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Obrni sada"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Raširite telefon za bolji selfi"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Obrnuti na prednji ekran radi boljeg selfija?"</string>
-    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Koristite stražnju kameru za širu fotografiju veće rezolucije."</string>
+    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Koristite zadnju kameru za širu fotografiju veće rezolucije."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ekran će se isključiti"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Sklopivi uređaj se rasklapa"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Sklopivi uređaj se obrće"</string>
@@ -1066,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Radna pravila vam dozvoljavaju upućivanje telefonskih poziva samo s radnog profila"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređite na radni profil"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Postavke zaključavanja ekrana"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e5563c0..db76e00 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Marge inferior <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Marge esquerre <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Marge dret <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Les captures de pantalla de treball es desen a l\'aplicació <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fitxers"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravació de pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processant gravació de pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"S\'ha reconegut la cara. Prem la icona per obrir."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"S\'ha desbloquejat amb la cara"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"S\'ha reconegut la cara"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Mou cap a l\'esquerra"</item>
-    <item msgid="5558598599408514296">"Mou cap avall"</item>
-    <item msgid="4844142668312841831">"Mou cap a la dreta"</item>
-    <item msgid="5640521437931460125">"Mou cap amunt"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Llisca cap a dalt per tornar-ho a provar"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueja per utilitzar l\'NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Aquest dispositiu pertany a la teva organització"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Selecciona l\'aplicació per afegir controls"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{S\'ha afegit # control.}many{# controls added.}other{S\'han afegit # controls.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Suprimit"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vols afegir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"En afegir <xliff:g id="APPNAME">%s</xliff:g>, podrà afegir controls i contingut en aquest tauler. En algunes aplicacions, pots triar quins controls es mostren aquí."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Afegit als preferits"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Afegit als preferits, posició <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Suprimit dels preferits"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Obre <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reprodueix <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) des de l\'aplicació <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reprodueix <xliff:g id="SONG_NAME">%1$s</xliff:g> des de l\'aplicació <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Per a tu"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Desfés"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Mou més a prop per reproduir a <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Per reproduir contingut aquí, apropa\'l a <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Error; torna-ho a provar"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Afegeix controls"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edita els controls"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Afegeix una aplicació"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Afegeix sortides"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositiu seleccionat"</string>
@@ -919,7 +918,6 @@
     <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">"Altaveus i pantalles"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositius suggerits"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Requereix un compte prèmium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Com funciona l\'emissió"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emet"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les persones properes amb dispositius Bluetooth compatibles poden escoltar el contingut multimèdia que emets"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"La càmera està desactivada"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"El micròfon està desactivat"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Càmera i micròfon desactivats"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificació}many{# notifications}other{# notificacions}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Presa de notes"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permet l\'accés únic"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"No permetis"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Els registres del dispositiu inclouen informació sobre tot allò que passa al teu dispositiu. Les aplicacions poden utilitzar aquests registres per detectar i corregir problemes.\n\nÉs possible que alguns registres continguin informació sensible; per això només has de donar-hi accés a les aplicacions de confiança. \n\nEncara que no permetis que aquesta aplicació pugui accedir a tots els registres del dispositiu, podrà accedir als seus propis registres. És possible que el fabricant del dispositiu també tingui accés a alguns registres o a informació del teu dispositiu."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Obre <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• L\'aplicació està configurada."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Almenys s\'ha afegit una targeta a Wallet."</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"La teva política de treball et permet fer trucades només des del perfil de treball"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Canvia al perfil de treball"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Tanca"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Configuració pantalla de bloqueig"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c099f66..018ad0c 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Dolní okraj <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Levý okraj <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Pravý okraj <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Pracovní snímky obrazovky se ukládají do aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Soubory"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Záznam obrazovky se zpracovává"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odemknuto obličejem"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Obličej rozpoznán"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Přesunout doleva"</item>
-    <item msgid="5558598599408514296">"Přesunout dolů"</item>
-    <item msgid="4844142668312841831">"Přesunout doprava"</item>
-    <item msgid="5640521437931460125">"Přesunout nahoru"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Přejetím nahoru to zkusíte znovu"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC vyžaduje odemknutou obrazovku"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zařízení patří vaší organizaci"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Vyberte aplikaci, pro kterou chcete přidat ovládací prvky"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Byl přidán # ovládací prvek.}few{Byly přidány # ovládací prvky.}many{Bylo přidáno # ovládacího prvku.}other{Bylo přidáno # ovládacích prvků.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Odstraněno"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Přidat aplikaci <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Když přidáte aplikaci <xliff:g id="APPNAME">%s</xliff:g>, může do tohoto panelu přidat ovládací prvky a obsah. V některých aplikacích si můžete vybrat, které ovládací prvky se zde zobrazí."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Přidáno do oblíbených"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Přidáno do oblíbených na pozici <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odebráno z oblíbených"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otevřít aplikaci <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Přehrát skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> z aplikace <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Přehrát skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> z aplikace <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Pro vás"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Vrátit zpět"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Pokud chcete přehrávat na zařízení <xliff:g id="DEVICENAME">%1$s</xliff:g>, přibližte se k němu"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Pokud obsah chcete přehrát na tomto zařízení, přesuňte ho blíže k zařízení <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Chyba, zkuste to znovu"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Přidat ovládací prvky"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Upravit ovládací prvky"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Přidat aplikaci"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Přidání výstupů"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Je vybráno 1 zařízení"</string>
@@ -919,7 +918,6 @@
     <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">"Reproduktory a displeje"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Navrhovaná zařízení"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Vyžaduje prémiový účet"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak vysílání funguje"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Vysílání"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lidé ve vašem okolí s kompatibilními zařízeními Bluetooth mohou poslouchat média, která vysíláte"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera je vypnutá"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon je vypnutý"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotoaparát a mikrofon jsou vypnuté"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# oznámení}few{# oznámení}many{# oznámení}other{# oznámení}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g> <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Poznámky"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Povolit jednorázový přístup"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Nepovolovat"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Do protokolů zařízení se zaznamenává, co se na zařízení děje. Aplikace tyto protokoly mohou používat k vyhledání a odstranění problémů.\n\nNěkteré protokoly mohou zahrnovat citlivé údaje. Přístup k protokolům zařízení proto povolte pouze aplikacím, kterým důvěřujete. \n\nPokud této aplikaci nepovolíte přístup ke všem protokolům zařízení, bude mít stále přístup ke svým vlastním protokolům. Výrobce zařízení může mít stále přístup k některým protokolům nebo informacím na vašem zařízení."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otevřít <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikace je nastavena"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Do Peněženky byla přidána alespoň jedna karta"</string>
@@ -1056,7 +1060,7 @@
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Zrušit"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Otočit"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Rozložte telefon, selfie bude lepší"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Otočit na přední fotoaparát pro lepší selfie?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Otočit na přední displej pro lepší selfie?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Pomocí zadního fotoaparátu pořiďte širší fotku s vyšším rozlišením."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Tato obrazovka se vypne"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozkládání rozkládacího zařízení"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Vaše pracovní zásady vám umožňují telefonovat pouze z pracovního profilu"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Přepnout na pracovní profil"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zavřít"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Nastavení obrazovky uzamčení"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index c50202d..767fee7 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Nederste kant: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Venstre kant: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Højre kant: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Screenshots, der tages via arbejdsprofilen, gemmer i appen <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Gemt i <xliff:g id="APP">%1$s</xliff:g> på arbejdsprofilen"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Filer"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> har registreret dette screenshot."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og andre åbne apps har registreret dette screenshot."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Skærmoptagelse"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skærmoptagelse"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansigt genkendt. Tryk på oplåsningsikonet for at åbne."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Låst op via ansigtsgenkendelse"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansigtet er genkendt"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Flyt til venstre"</item>
-    <item msgid="5558598599408514296">"Flyt ned"</item>
-    <item msgid="4844142668312841831">"Flyt til højre"</item>
-    <item msgid="5640521437931460125">"Flyt op"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Stryg opad for at prøve igen"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås op for at bruge NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enhed tilhører din organisation"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Vælg en app for at tilføje styring"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# styringselement er tilføjet.}one{# styringselement er tilføjet.}other{# styringselementer er tilføjet.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Fjernet"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vil du tilføje <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Når du tilføjer <xliff:g id="APPNAME">%s</xliff:g>, kan den føje styringselementer og indhold til dette panel. I nogle apps kan du vælge, hvilke styringselementer der vises her."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Angivet som favorit"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Angivet som favorit. Position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjernet fra favoritter"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Åbn <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Afspil <xliff:g id="SONG_NAME">%1$s</xliff:g> af <xliff:g id="ARTIST_NAME">%2$s</xliff:g> via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Afspil <xliff:g id="SONG_NAME">%1$s</xliff:g> via <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Til dig"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Fortryd"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Ryk tættere på for at afspille på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"For at afspille her skal enheden tættere på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Der opstod en fejl. Prøv igen"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Tilføj styring"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Rediger styring"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tilføj app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tilføj medieudgange"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Der er valgt 1 enhed"</string>
@@ -919,7 +915,6 @@
     <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">"Højttalere og skærme"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Foreslåede enheder"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Kræver Premium-konto"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Sådan fungerer udsendelser"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Udsendelse"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i nærheden, som har kompatible Bluetooth-enheder, kan lytte til det medie, du udsender"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kameraet er slukket"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofonen er slået fra"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera og mikrofon er slået fra"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifikation}one{# notifikation}other{# notifikationer}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notetagning"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Tillad engangsadgang"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Tillad ikke"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Enhedslogs registrerer, hvad der sker på din enhed. Apps kan bruge disse logs til at finde og løse problemer.\n\nNogle logs kan indeholde følsomme oplysninger, så giv kun apps, du har tillid til, adgang til alle enhedslogs. \n\nSelvom du ikke giver denne app adgang til alle enhedslogs, kan den stadig tilgå sine egne logs. Producenten af din enhed kan muligvis fortsat tilgå visse logs eller oplysninger på din enhed."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Åbn <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Appen er konfigureret"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Mindst ét kort er føjet til Wallet"</string>
@@ -1058,7 +1059,7 @@
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Fold telefonen ud for at tage en bedre selfie"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vil du bruge frontkameraet for at få bedre selfie?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Brug bagsidekameraet for at få et bredere billede med højere opløsning."</string>
-    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ *Denne skærm slukkes"</b></string>
+    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Denne skærm slukkes"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldbar enhed foldes ud"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldbar enhed vendes om"</string>
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteri tilbage"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Din arbejdspolitik tillader kun, at du kan foretage telefonopkald fra arbejdsprofilen"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skift til arbejdsprofil"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Luk"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Indstillinger for låseskærm"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 0ac3f4b..e2cd41d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Unterer Rand <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Linker Rand <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Rechter Rand <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Mit einem Arbeitsprofil aufgenommene Screenshots werden in der App „<xliff:g id="APP">%1$s</xliff:g>“ gespeichert"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Dateien"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Bildschirmaufzeichnung"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Bildschirmaufzeichnung…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string>
@@ -183,9 +190,9 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flugmodus"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN an."</string>
     <string name="accessibility_battery_level" msgid="5143715405241138822">"Akku bei <xliff:g id="NUMBER">%d</xliff:g> Prozent."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Akku bei <xliff:g id="PERCENTAGE">%1$d</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Akku bei <xliff:g id="PERCENTAGE">%1$d</xliff:g> Prozent, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Akku wird aufgeladen, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> Prozent."</string>
-    <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Akku bei <xliff:g id="PERCENTAGE">%d</xliff:g>. Zum Schutz des Akkus wurde das Laden pausiert."</string>
+    <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Akku bei <xliff:g id="PERCENTAGE">%d</xliff:g> Prozent. Zum Schutz des Akkus wurde das Laden pausiert."</string>
     <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Akku bei <xliff:g id="PERCENTAGE">%1$d</xliff:g>. <xliff:g id="TIME">%2$s</xliff:g>. Zum Schutz des Akkus wurde das Laden pausiert."</string>
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"Alle Benachrichtigungen ansehen"</string>
     <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Schreibtelefonie aktiviert"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gesicht erkannt. Tippe zum Öffnen auf das Symbol „Entsperren“."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Gerät mit Gesicht entsperrt"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Gesicht erkannt"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Nach links bewegen"</item>
-    <item msgid="5558598599408514296">"Nach unten bewegen"</item>
-    <item msgid="4844142668312841831">"Nach rechts bewegen"</item>
-    <item msgid="5640521437931460125">"Nach oben bewegen"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Zum Wiederholen nach oben wischen"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Zur Verwendung von NFC entsperren"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Dieses Gerät gehört deiner Organisation"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"App zum Hinzufügen von Steuerelementen auswählen"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# Steuerelement hinzugefügt.}other{# Steuerelemente hinzugefügt.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Entfernt"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> hinzufügen?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Wenn du <xliff:g id="APPNAME">%s</xliff:g> hinzufügst, kann diese App Einstellungen und Inhalte zu diesem Bereich hinzufügen. In einigen Apps kannst du festlegen, welche Einstellungen hier angezeigt werden sollen."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Zu Favoriten hinzugefügt"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Zu Favoriten hinzugefügt, Position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Aus Favoriten entfernt"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> öffnen"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> von <xliff:g id="ARTIST_NAME">%2$s</xliff:g> über <xliff:g id="APP_LABEL">%3$s</xliff:g> wiedergeben"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> über <xliff:g id="APP_LABEL">%2$s</xliff:g> wiedergeben"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Für mich"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Rückgängig machen"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Gehe für die Wiedergabe näher an „<xliff:g id="DEVICENAME">%1$s</xliff:g>“ heran"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Für eine Wiedergabe auf diesem Gerät muss es näher bei <xliff:g id="DEVICENAME">%1$s</xliff:g> sein"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Fehler – versuch es noch mal"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Steuerelemente hinzufügen"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Steuerelemente bearbeiten"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"App hinzufügen"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ausgabegeräte hinzufügen"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ein Gerät ausgewählt"</string>
@@ -919,7 +918,6 @@
     <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">"Lautsprecher &amp; Displays"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Vorgeschlagene Geräte"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Premium-Konto erforderlich"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Funktionsweise von Nachrichten an alle"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Nachricht an alle"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personen, die in der Nähe sind und kompatible Bluetooth-Geräten haben, können sich die Medien anhören, die du per Nachricht an alle sendest"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera ist deaktiviert"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon ist deaktiviert"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera und Mikrofon ausgeschaltet"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# Benachrichtigung}other{# Benachrichtigungen}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notizen machen"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Einmaligen Zugriff erlauben"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Nicht erlauben"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"In Geräteprotokollen wird aufgezeichnet, welche Aktionen auf deinem Gerät ausgeführt werden. Apps können diese Protokolle verwenden, um Probleme zu finden und zu beheben.\n\nEinige Protokolle enthalten unter Umständen vertrauliche Informationen. Daher solltest du nur vertrauenswürdigen Apps den Zugriff auf alle Geräteprotokolle erlauben. \n\nWenn du dieser App keinen Zugriff auf alle Geräteprotokolle gewährst, kann sie trotzdem auf ihre eigenen Protokolle zugreifen. Dein Gerätehersteller hat möglicherweise auch Zugriff auf einige Protokolle oder Informationen auf deinem Gerät."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> öffnen"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Die App ist eingerichtet"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet wurde mindestens eine Karte hinzugefügt"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Gemäß den Arbeitsrichtlinien darfst du nur über dein Arbeitsprofil telefonieren"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Zum Arbeitsprofil wechseln"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Schließen"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Sperrbildschirm-Einstellungen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index eb0abea..68ad194 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Κάτω όριο <xliff:g id="PERCENT">%1$d</xliff:g> τοις εκατό"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Αριστερό όριο <xliff:g id="PERCENT">%1$d</xliff:g> τοις εκατό"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Δεξί όριο <xliff:g id="PERCENT">%1$d</xliff:g> τοις εκατό"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Τα στιγμιότυπα οθόνης εργασίας αποθηκεύονται στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Αποθηκεύτηκε στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> στο προφίλ εργασίας"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Αρχεία"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"Η εφαρμογή <xliff:g id="APPNAME">%1$s</xliff:g> εντόπισε αυτό το στιγμιότυπο οθόνης."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Η εφαρμογή <xliff:g id="APPNAME">%1$s</xliff:g> και άλλες ανοικτές εφαρμογές εντόπισαν το στιγμιότυπο οθόνης."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Εγγραφή οθόνης"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Επεξεργασία εγγραφής οθόνης"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ειδοποίηση σε εξέλιξη για μια περίοδο λειτουργίας εγγραφής οθόνης"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Το πρόσωπο αναγνωρ. Πατήστ. το εικον. ξεκλειδ. για άνοιγμα."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ξεκλείδωμα με αναγνώριση προσώπου"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Το πρόσωπο αναγνωρίστηκε"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Μετακίνηση αριστερά"</item>
-    <item msgid="5558598599408514296">"Μετακίνηση κάτω"</item>
-    <item msgid="4844142668312841831">"Μετακίνηση δεξιά"</item>
-    <item msgid="5640521437931460125">"Μετακίνηση επάνω"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Σύρετε προς τα πάνω για να δοκιμάσετε ξανά"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ξεκλείδωμα για χρήση του NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Αυτή η συσκευή ανήκει στον οργανισμό σας."</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Επιλογή εφαρμογής για προσθήκη στοιχείων ελέγχου"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Προστέθηκε # στοιχείο ελέγχου.}other{Προστέθηκαν # στοιχεία ελέγχου.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Καταργήθηκε"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Προσθήκη <xliff:g id="APPNAME">%s</xliff:g>;"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Όταν προσθέσετε την εφαρμογή <xliff:g id="APPNAME">%s</xliff:g>, μπορεί να προσθέσει στοιχεία ελέγχου και περιεχόμενο σε αυτό το πλαίσιο. Σε ορισμένες εφαρμογές, μπορείτε να επιλέξετε ποια στοιχεία ελέγχου θα εμφανίζονται εδώ."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Προστέθηκε στα αγαπημένα"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Προστέθηκε στα αγαπημένα, στη θέση <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Αφαιρέθηκε από τα αγαπημένα"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Άνοιγμα της εφαρμογής <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Αναπαραγωγή του <xliff:g id="SONG_NAME">%1$s</xliff:g> από <xliff:g id="ARTIST_NAME">%2$s</xliff:g> στην εφαρμογή <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Αναπαραγωγή του <xliff:g id="SONG_NAME">%1$s</xliff:g> στην εφαρμογή <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Για εσάς"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Αναίρεση"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Πλησιάστε για αναπαραγωγή στη συσκευή <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Για να γίνει αναπαραγωγή εδώ, μετακινηθείτε πιο κοντά στη συσκευή <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Σφάλμα, προσπαθήστε ξανά."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Προσθήκη στοιχείων ελέγχου"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Επεξεργασία στοιχείων ελέγχου"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Προσθήκη εφαρμογής"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Προσθήκη εξόδων"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Ομάδα"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Επιλέχτηκε 1 συσκευή"</string>
@@ -919,7 +915,6 @@
     <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">"Ηχεία και οθόνες"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Προτεινόμενες συσκευές"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Απαιτεί λογαριασμό premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Πώς λειτουργεί η μετάδοση"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Μετάδοση"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Οι άνθρωποι με συμβατές συσκευές Bluetooth που βρίσκονται κοντά σας μπορούν να ακούσουν το μέσο που μεταδίδετε."</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Η κάμερα είναι απενεργοποιημένη"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Το μικρόφωνο είναι απενεργοποιημένο"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Η κάμερα και το μικρόφωνο έχουν απενεργοποιηθεί"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Ο Βοηθός ακούει"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ειδοποίηση}other{# ειδοποιήσεις}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Δημιουργία σημειώσεων"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Να επιτρέπεται η πρόσβαση για μία φορά"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Να μην επιτρέπεται"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Τα αρχεία καταγραφής συσκευής καταγράφουν ό,τι συμβαίνει στη συσκευή σας. Οι εφαρμογές μπορούν να χρησιμοποιούν αυτά τα αρχεία καταγραφής για να εντοπίζουν και να διορθώνουν ζητήματα.\n\nΟρισμένα αρχεία καταγραφής ενδέχεται να περιέχουν ευαίσθητες πληροφορίες. Ως εκ τούτου, επιτρέψτε την πρόσβαση σε όλα τα αρχεία καταγραφής συσκευής μόνο στις εφαρμογές που εμπιστεύεστε. \n\nΕάν δεν επιτρέψετε σε αυτήν την εφαρμογή την πρόσβαση σε όλα τα αρχεία καταγραφής συσκευής, η εφαρμογή εξακολουθεί να έχει πρόσβαση στα δικά της αρχεία καταγραφής. Ο κατασκευαστής της συσκευής σας ενδέχεται να εξακολουθεί να έχει πρόσβαση σε ορισμένα αρχεία καταγραφής ή ορισμένες πληροφορίες στη συσκευή σας."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Μάθετε περισσότερα"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Μάθετε περισσότερα στο <xliff:g id="URL">%s</xliff:g>."</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Άνοιγμα <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Η εφαρμογή έχει ρυθμιστεί"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Έχει προστεθεί τουλάχιστον μία κάρτα στο Πορτοφόλι"</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Η πολιτική εργασίας σάς επιτρέπει να πραγματοποιείτε τηλεφωνικές κλήσεις μόνο από το προφίλ εργασίας σας."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Εναλλαγή σε προφίλ εργασίας"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Κλείσιμο"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Ρυθμίσεις κλειδώματος οθόνης"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index cad3b47..6babfe9 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Work screenshots are saved in the <xliff:g id="APP">%1$s</xliff:g> app"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the work profile"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detected this screenshot."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Move left"</item>
-    <item msgid="5558598599408514296">"Move down"</item>
-    <item msgid="4844142668312841831">"Move right"</item>
-    <item msgid="5640521437931460125">"Move up"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string>
@@ -884,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Open <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"For you"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Undo"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Move closer to play on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"To play here, move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -916,7 +915,6 @@
     <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_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Requires premium account"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string>
@@ -1028,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Camera is off"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mic is off"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant is listening"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
@@ -1043,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Allow one-time access"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Don’t allow"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Learn more"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Learn more at <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• The app is set up"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• At least one card has been added to Wallet"</string>
@@ -1066,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Your work policy allows you to make phone calls only from the work profile"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index c41a164..1aa3e56 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -91,8 +91,11 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Work screenshots are saved in the <xliff:g id="APP">%1$s</xliff:g> app"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the work profile"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detected this screenshot."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
+    <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -339,12 +342,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognized. Press the unlock icon to open."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognized"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Move left"</item>
-    <item msgid="5558598599408514296">"Move down"</item>
-    <item msgid="4844142668312841831">"Move right"</item>
-    <item msgid="5640521437931460125">"Move up"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organization"</string>
@@ -884,6 +881,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Open <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"For You"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Undo"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Move closer to play on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"To play here, move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -916,7 +914,6 @@
     <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_suggested_device" msgid="4157186235837903826">"Suggested Devices"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Requires premium account"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media you\'re broadcasting"</string>
@@ -1028,6 +1025,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Camera is off"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mic is off"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant is listening"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
@@ -1043,6 +1041,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Allow one-time access"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Don’t allow"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Learn more"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Learn more at <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• The app is set up"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• At least one card has been added to Wallet"</string>
@@ -1066,6 +1066,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Your work policy allows you to make phone calls only from the work profile"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index cad3b47..6babfe9 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Work screenshots are saved in the <xliff:g id="APP">%1$s</xliff:g> app"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the work profile"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detected this screenshot."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Move left"</item>
-    <item msgid="5558598599408514296">"Move down"</item>
-    <item msgid="4844142668312841831">"Move right"</item>
-    <item msgid="5640521437931460125">"Move up"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string>
@@ -884,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Open <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"For you"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Undo"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Move closer to play on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"To play here, move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -916,7 +915,6 @@
     <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_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Requires premium account"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string>
@@ -1028,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Camera is off"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mic is off"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant is listening"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
@@ -1043,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Allow one-time access"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Don’t allow"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Learn more"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Learn more at <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• The app is set up"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• At least one card has been added to Wallet"</string>
@@ -1066,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Your work policy allows you to make phone calls only from the work profile"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index cad3b47..6babfe9 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Work screenshots are saved in the <xliff:g id="APP">%1$s</xliff:g> app"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Saved in <xliff:g id="APP">%1$s</xliff:g> in the work profile"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detected this screenshot."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Face recognised. Press the unlock icon to open."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Unlocked by face"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Face recognised"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Move left"</item>
-    <item msgid="5558598599408514296">"Move down"</item>
-    <item msgid="4844142668312841831">"Move right"</item>
-    <item msgid="5640521437931460125">"Move up"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Swipe up to try again"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Unlock to use NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"This device belongs to your organisation"</string>
@@ -884,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Open <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> by <xliff:g id="ARTIST_NAME">%2$s</xliff:g> from <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"For you"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Undo"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Move closer to play on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"To play here, move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -916,7 +915,6 @@
     <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_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Requires premium account"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string>
@@ -1028,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Camera is off"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mic is off"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera and mic are off"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant is listening"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
@@ -1043,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Allow one-time access"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Don’t allow"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps that you trust to access all device logs. \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Learn more"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Learn more at <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• The app is set up"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• At least one card has been added to Wallet"</string>
@@ -1066,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Your work policy allows you to make phone calls only from the work profile"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 059a5fa..d2604fd 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -91,8 +91,11 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‏‎‏‎‏‎‏‏‏‎‎Bottom boundary ‎‏‎‎‏‏‎<xliff:g id="PERCENT">%1$d</xliff:g>‎‏‎‎‏‏‏‎ percent‎‏‎‎‏‎"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‏‎‏‏‎‏‎Left boundary ‎‏‎‎‏‏‎<xliff:g id="PERCENT">%1$d</xliff:g>‎‏‎‎‏‏‏‎ percent‎‏‎‎‏‎"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎Right boundary ‎‏‎‎‏‏‎<xliff:g id="PERCENT">%1$d</xliff:g>‎‏‎‎‏‏‏‎ percent‎‏‎‎‏‎"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎Work screenshots are saved in the ‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ app‎‏‎‎‏‎"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‎Saved in ‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ in the work profile‎‏‎‎‏‎"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎Files‎‏‎‎‏‎"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APPNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ detected this screenshot.‎‏‎‎‏‎"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APPNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and other open apps detected this screenshot.‎‏‎‎‏‎"</string>
+    <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎Add to note‎‏‎‎‏‎"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎Screen Recorder‎‏‎‎‏‎"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎Processing screen recording‎‏‎‎‏‎"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎Ongoing notification for a screen record session‎‏‎‎‏‎"</string>
@@ -339,12 +342,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‎Face recognized. Press the unlock icon to open.‎‏‎‎‏‎"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎Unlocked by face‎‏‎‎‏‎"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎Face recognized‎‏‎‎‏‎"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‎‏‎Move left‎‏‎‎‏‎"</item>
-    <item msgid="5558598599408514296">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎Move down‎‏‎‎‏‎"</item>
-    <item msgid="4844142668312841831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‎Move right‎‏‎‎‏‎"</item>
-    <item msgid="5640521437931460125">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‏‏‎‏‎Move up‎‏‎‎‏‎"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎Swipe up to try again‎‏‎‎‏‎"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‏‎Unlock to use NFC‎‏‎‎‏‎"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎This device belongs to your organization‎‏‎‎‏‎"</string>
@@ -884,6 +881,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎Open ‎‏‎‎‏‏‎<xliff:g id="APP_LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎Play ‎‏‎‎‏‏‎<xliff:g id="SONG_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ by ‎‏‎‎‏‏‎<xliff:g id="ARTIST_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ from ‎‏‎‎‏‏‎<xliff:g id="APP_LABEL">%3$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‏‎Play ‎‏‎‎‏‏‎<xliff:g id="SONG_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ from ‎‏‎‎‏‏‎<xliff:g id="APP_LABEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎For You‎‏‎‎‏‎"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎Undo‎‏‎‎‏‎"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‎‏‏‏‏‎‏‏‏‎‎‎‎Move closer to play on ‎‏‎‎‏‏‎<xliff:g id="DEVICENAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎To play here, move closer to ‎‏‎‎‏‏‎<xliff:g id="DEVICENAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
@@ -916,7 +914,6 @@
     <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_suggested_device" msgid="4157186235837903826">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎Suggested Devices‎‏‎‎‏‎"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎Requires premium account‎‏‎‎‏‎"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‎How broadcasting works‎‏‎‎‏‎"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎Broadcast‎‏‎‎‏‎"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‎‎People near you with compatible Bluetooth devices can listen to the media you\'re broadcasting‎‏‎‎‏‎"</string>
@@ -1028,6 +1025,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎Camera is off‎‏‎‎‏‎"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎Mic is off‎‏‎‎‏‎"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‏‎Camera and mic are off‎‏‎‎‏‎"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‏‏‎‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎Assistant is listening‎‏‎‎‏‎"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎# notification‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎# notifications‎‏‎‎‏‎}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TEMPERATURE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎Notetaking‎‏‎‎‏‎"</string>
@@ -1043,6 +1041,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‎‎Allow one-time access‎‏‎‎‏‎"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎Don’t allow‎‏‎‎‏‎"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎Device logs record what happens on your device. Apps can use these logs to find and fix issues.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Some logs may contain sensitive info, so only allow apps you trust to access all device logs. ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎If you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device.‎‏‎‎‏‎"</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎Learn more‎‏‎‎‏‎"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‏‎Learn more at ‎‏‎‎‏‏‎<xliff:g id="URL">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‎Open ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‎• The app is set up‎‏‎‎‏‎"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‎• At least one card has been added to Wallet‎‏‎‎‏‎"</string>
@@ -1066,6 +1066,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎Your work policy allows you to make phone calls only from the work profile‎‏‎‎‏‎"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎Switch to work profile‎‏‎‎‏‎"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎Close‎‏‎‎‏‎"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎Lock screen settings‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 706248b..2da6220 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Límite inferior: <xliff:g id="PERCENT">%1$d</xliff:g> por ciento"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Límite izquierdo: <xliff:g id="PERCENT">%1$d</xliff:g> por ciento"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Límite derecho: <xliff:g id="PERCENT">%1$d</xliff:g> por ciento"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Las capturas de pantalla de trabajo se guardan en la app de <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Se guardó en <xliff:g id="APP">%1$s</xliff:g> en el perfil de trabajo"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> detectó que tomaste una captura de pantalla."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> y otras apps en ejecución detectaron que tomaste una captura de pantalla."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Grabadora de pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación constante para una sesión de grabación de pantalla"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rostro reconocido. Presiona el desbloqueo para abrir."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Se desbloqueó con el rostro"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Se reconoció el rostro"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Mover hacia la izquierda"</item>
-    <item msgid="5558598599408514296">"Mover hacia abajo"</item>
-    <item msgid="4844142668312841831">"Mover hacia la derecha"</item>
-    <item msgid="5640521437931460125">"Mover hacia arriba"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volver a intentarlo"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea el dispositivo para usar NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Elige la app para agregar los controles"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Se agregó # control.}many{Se agregaron # controles.}other{Se agregaron # controles.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Quitados"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"¿Quieres agregar <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Si agregas la app de <xliff:g id="APPNAME">%s</xliff:g>, se incluirán controles y contenido en este panel. Algunas apps te permiten elegir qué controles mostrar aquí."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Está en favoritos"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Está en favoritos en la posición <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"No está en favoritos"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abre <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproduce <xliff:g id="SONG_NAME">%1$s</xliff:g>, de <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproducir <xliff:g id="SONG_NAME">%1$s</xliff:g> en <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Para ti"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Deshacer"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Acércate para reproducir en <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Para reproducir aquí, acércate a <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Error. Vuelve a intentarlo."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Agregar controles"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Agregar app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Agregar salidas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Se seleccionó 1 dispositivo"</string>
@@ -919,7 +915,6 @@
     <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">"Bocinas y pantallas"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Requiere una cuenta premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la transmisión"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmisión"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que transmites"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"La cámara está desactivada"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"El micrófono está desactivado"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"La cámara y el micrófono están apagados"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}many{# notificaciones}other{# notificaciones}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Tomar notas"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir acceso por única vez"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"No permitir"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Los registros del dispositivo permiten documentar lo que sucede en él. Las apps pueden usar estos registros para encontrar y solucionar problemas.\n\nEs posible que algunos registros del dispositivo contengan información sensible, por lo que solo permitimos que accedan a todos ellos apps de tu confianza. \n\nSi no permites que esta app acceda a todos los registros del dispositivo, aún puede acceder a sus propios registros. Además, es posible que el fabricante del dispositivo acceda a algunos registros o información en tu dispositivo."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Se configuró la app."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Se agregó al menos una tarjeta a la Billetera."</string>
@@ -1056,7 +1057,7 @@
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Girar ahora"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Despliega el teléfono para tomar una selfie mejor"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"¿Cambiar a pantalla frontal para mejores selfies?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"¿Girar a pantalla frontal para mejores selfies?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Usa la cámara trasera para tomar una foto más amplia y con mejor resolución."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta pantalla se apagará"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable siendo desplegado"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Tu política del trabajo te permite hacer llamadas telefónicas solo desde el perfil de trabajo"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Config. de pantalla de bloqueo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 458cd38..6cee547 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"<xliff:g id="PERCENT">%1$d</xliff:g> por ciento del límite inferior"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> por ciento del límite izquierdo"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> por ciento del límite derecho"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Las capturas de pantalla de trabajo se guardan en la aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Archivos"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Grabación de pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación de pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Cara reconocida. Pulsa el icono de desbloquear para abrir."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado con la cara"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Cara reconocida"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Mover hacia la izquierda"</item>
-    <item msgid="5558598599408514296">"Mover hacia abajo"</item>
-    <item msgid="4844142668312841831">"Mover hacia la derecha"</item>
-    <item msgid="5640521437931460125">"Mover hacia arriba"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Desliza el dedo hacia arriba para volverlo a intentar"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea para usar el NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertenece a tu organización"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Elige una aplicación para añadir controles"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control añadido.}many{# controles añadidos.}other{# controles añadidos.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Quitado"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"¿Añadir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Si añades <xliff:g id="APPNAME">%s</xliff:g>, podrá añadir controles y contenido a este panel. En algunas aplicaciones, puedes elegir qué controles aparecen aquí."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Añadido a favoritos"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Añadido a favoritos (posición <xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Quitado de favoritos"</string>
@@ -886,9 +885,10 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abrir <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Poner <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Poner <xliff:g id="SONG_NAME">%1$s</xliff:g> en <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Para ti"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Deshacer"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Acércate a <xliff:g id="DEVICENAME">%1$s</xliff:g> para reproducir contenido ahí"</string>
-    <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Para reproducirlo, acércate al dispositivo (<xliff:g id="DEVICENAME">%1$s</xliff:g>)"</string>
+    <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Para reproducirlo aquí, acércate al dispositivo (<xliff:g id="DEVICENAME">%1$s</xliff:g>)"</string>
     <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproduciendo en <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_transfer_failed" msgid="7955354964610603723">"Se ha producido un error. Inténtalo de nuevo."</string>
     <string name="media_transfer_loading" msgid="5544017127027152422">"Cargando"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Error: Vuelve a intentarlo"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Añadir controles"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Añadir aplicación"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Añadir dispositivos de salida"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo seleccionado"</string>
@@ -919,7 +918,6 @@
     <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_status_require_premium" msgid="5691200962588753380">"Requiere una cuenta premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la emisión"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emisión"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que emites"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"La cámara está desactivada"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"El micrófono está desactivado"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"La cámara y el micrófono están desactivados"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}many{# notificaciones}other{# notificaciones}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Tomar notas"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir el acceso una vez"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"No permitir"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Los registros del dispositivo documentan lo que sucede en tu dispositivo. Las aplicaciones pueden usar estos registros para encontrar y solucionar problemas.\n\nComo algunos registros pueden contener información sensible, es mejor que solo permitas que accedan a ellos las aplicaciones en las que confíes. \n\nAunque no permitas que esta aplicación acceda a todos los registros del dispositivo, aún podrá acceder a sus propios registros. El fabricante de tu dispositivo aún puede acceder a algunos registros o información de tu dispositivo."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• La aplicación debe estar configurada"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Se debe haber añadido al menos una tarjeta a Wallet"</string>
@@ -1054,10 +1058,10 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Al menos un dispositivo debe estar disponible"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantén pulsado el acceso directo"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Girar ahora"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Usar ahora"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Despliega el teléfono para hacer un selfie mejor"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"¿Usar pantalla frontal para hacer mejores selfies?"</string>
-    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Usa la cámara trasera para hacer una foto más amplia y con mayor resolución."</string>
+    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Usa la cámara trasera para hacer fotos más amplias y con mayor resolución."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta pantalla se apagará"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable desplegándose"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable mostrado desde varios ángulos"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Tu política del trabajo solo te permite hacer llamadas telefónicas desde el perfil de trabajo"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Ajustes de pantalla de bloqueo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 82bb481..6e7efa4 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Alapiir: <xliff:g id="PERCENT">%1$d</xliff:g> protsenti"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vasak piir: <xliff:g id="PERCENT">%1$d</xliff:g> protsenti"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Parem piir: <xliff:g id="PERCENT">%1$d</xliff:g> protsenti"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Töö ekraanipildid salvestatakse rakendusse <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekraanisalvesti"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekraanisalvestuse töötlemine"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Nägu tuvastati. Avamiseks vajutage avamise ikooni."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Avati näoga"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Nägu tuvastati"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Teisalda vasakule"</item>
-    <item msgid="5558598599408514296">"Teisalda alla"</item>
-    <item msgid="4844142668312841831">"Teisalda paremale"</item>
-    <item msgid="5640521437931460125">"Teisalda üles"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Uuesti proovimiseks pühkige üles"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC kasutamiseks avage."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"See seade kuulub teie organisatsioonile"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Valige juhtelementide lisamiseks rakendus"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Lisati # juhtnupp.}other{Lisati # juhtnuppu.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Eemaldatud"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Kas lisada <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kui lisate rakenduse <xliff:g id="APPNAME">%s</xliff:g>, saab see sellele paneelile lisada juhtelemendid ja sisu. Mõnes rakenduses saate valida, millised juhtelemendid siin kuvatakse."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Lisatud lemmikuks"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Lisatud lemmikuks, positsioon <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Eemaldatud lemmikute hulgast"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Rakenduse <xliff:g id="APP_LABEL">%1$s</xliff:g> avamine"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Esita lugu <xliff:g id="SONG_NAME">%1$s</xliff:g> esitajalt <xliff:g id="ARTIST_NAME">%2$s</xliff:g> rakenduses <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Esita lugu <xliff:g id="SONG_NAME">%1$s</xliff:g> rakenduses <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Teile"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Võta tagasi"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Liikuge lähemale, et seadmes <xliff:g id="DEVICENAME">%1$s</xliff:g> esitada"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Siin esitamiseks minge seadmele <xliff:g id="DEVICENAME">%1$s</xliff:g> lähemale"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Ilmnes viga, proovige uuesti"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Lisa juhtelemente"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Muuda juhtelemente"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Rakenduse lisamine"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Väljundite lisamine"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 seade on valitud"</string>
@@ -919,7 +918,6 @@
     <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">"Kõlarid ja ekraanid"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Soovitatud seadmed"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Vajalik on tasuline konto"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kuidas ülekandmine toimib?"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Ülekanne"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Teie läheduses olevad inimesed, kellel on ühilduvad Bluetooth-seadmed, saavad kuulata teie ülekantavat meediat"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kaamera on välja lülitatud"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon on välja lülitatud"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kaamera ja mikrofon on välja lülitatud"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# märguanne}other{# märguannet}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Märkmete tegemine"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Luba ühekordne juurdepääs"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ära luba"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Seadmelogid jäädvustavad, mis teie seadmes toimub. Rakendused saavad neid logisid kasutada probleemide tuvastamiseks ja lahendamiseks.\n\nMõned logid võivad sisaldada tundlikku teavet, seega lubage juurdepääs kõigile seadmelogidele ainult rakendustele, mida usaldate. \n\nKui te ei luba sellel rakendusel kõigile seadmelogidele juurde pääseda, pääseb see siiski juurde oma logidele. Teie seadme tootja võib teie seadmes siiski teatud logidele või teabele juurde pääseda."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ava <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Rakendus on seadistatud"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Vähemalt üks kaart on Walletisse lisatud"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Teie töökoha eeskirjad lubavad teil helistada ainult tööprofiililt"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Lülitu tööprofiilile"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Sule"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Lukustuskuva seaded"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index ebbc8db..557434b 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Beheko ertza: ehuneko <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Ezkerreko ertza: ehuneko <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Eskuineko ertza: ehuneko <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Laneko pantaila-argazkiak <xliff:g id="APP">%1$s</xliff:g> aplikazioan gordetzen dira"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fitxategiak"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Pantaila-grabagailua"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pantaila-grabaketa prozesatzen"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ezagutu da aurpegia. Irekitzeko, sakatu desblokeatzeko ikonoa."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Aurpegiaren bidez desblokeatu da"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ezagutu da aurpegia"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Eraman ezkerrera"</item>
-    <item msgid="5558598599408514296">"Eraman behera"</item>
-    <item msgid="4844142668312841831">"Eraman eskuinera"</item>
-    <item msgid="5640521437931460125">"Eraman gora"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Berriro saiatzeko, pasatu hatza gora"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desblokea ezazu NFCa erabiltzeko"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Gailu hau zure erakundearena da"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Aukeratu aplikazio bat kontrolatzeko aukerak gehitzeko"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Kontrolatzeko # aukera gehitu da.}other{Kontrolatzeko # aukera gehitu dira.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Kenduta"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> gehitu nahi duzu?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> gehitzen duzunean, kontrolatzeko aukerak eta edukia gehi ditzake panelean. Aplikazio batzuetan, hemen zein kontrolatzeko aukera agertzen diren aukera dezakezu."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Gogokoetan dago"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>. gogokoa da"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Ez dago gogokoetan"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Ireki <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Erreproduzitu <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) <xliff:g id="APP_LABEL">%3$s</xliff:g> bidez"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Erreproduzitu <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%2$s</xliff:g> bidez"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Zuretzat"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Desegin"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Gertura ezazu <xliff:g id="DEVICENAME">%1$s</xliff:g> gailuan erreproduzitzeko"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Hemen erreproduzitzeko, hurbildu <xliff:g id="DEVICENAME">%1$s</xliff:g> gailura"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Errorea. Saiatu berriro."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Gehitu aukerak"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editatu aukerak"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Gehitu aplikazio bat"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Gehitu irteerak"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Taldea"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 gailu hautatu da"</string>
@@ -919,7 +918,6 @@
     <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">"Bozgorailuak eta pantailak"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Iradokitako gailuak"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Premium kontu bat behar da"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Nola funtzionatzen dute iragarpenek?"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Iragarri"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Bluetooth bidezko gailu bateragarriak dituzten inguruko pertsonek iragartzen ari zaren multimedia-edukia entzun dezakete"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera desaktibatuta dago"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofonoa desaktibatuta dago"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera eta mikrofonoa desaktibatuta daude"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# jakinarazpen}other{# jakinarazpen}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Oharrak idaztea"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Eman behin erabiltzeko baimena"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ez eman baimenik"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Gailuko erregistroetan gailuan gertatzen den guztia gordetzen da. Arazoak bilatu eta konpontzeko erabil ditzakete aplikazioek erregistro horiek.\n\nBaliteke erregistro batzuek kontuzko informazioa edukitzea. Beraz, eman gailuko erregistro guztiak atzitzeko baimena fidagarritzat jotzen dituzun aplikazioei bakarrik. \n\nNahiz eta gailuko erregistro guztiak atzitzeko baimena ez eman aplikazio honi, aplikazioak hari dagozkion erregistroak atzitu ahalko ditu. Gainera, baliteke gailuaren fabrikatzaileak gailuko erregistro edo datu batzuk atzitu ahal izatea."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ireki <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikazioa konfiguratuta dago."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Diru-zorroa zerbitzuan gutxienez txartel bat gehitu da."</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Deiak laneko profiletik soilik egiteko baimena ematen dizute laneko gidalerroek"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Aldatu laneko profilera"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Itxi"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Pantaila blokeatuaren ezarpenak"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index ab78224..efc8c2c 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"مرز پایین <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"مرز سمت چپ <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"مرز سمت راست <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"نماگرفت‌های نمایه کاری در برنامه <xliff:g id="APP">%1$s</xliff:g> ذخیره می‌شوند"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"ضبط‌کننده صفحه‌نمایش"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"درحال پردازش ضبط صفحه‌نمایش"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"اعلان درحال انجام برای جلسه ضبط صفحه‌نمایش"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"چهره شناسایی شد. برای باز کردن، نماد قفل‌گشایی را فشار دهید."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"قفل با چهره باز شد"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"چهره شناسایی شد"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"انتقال به‌چپ"</item>
-    <item msgid="5558598599408514296">"انتقال به‌پایین"</item>
-    <item msgid="4844142668312841831">"انتقال به‌راست"</item>
-    <item msgid="5640521437931460125">"انتقال به‌بالا"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"برای امتحان مجدد، انگشتتان را تند به‌بالا بکشید"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏برای استفاده از NFC، قفل را باز کنید"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"این دستگاه به سازمان شما تعلق دارد"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"انتخاب برنامه برای افزودن کنترل‌ها"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# کنترل اضافه شد.}one{# کنترل اضافه شد.}other{# کنترل اضافه شد.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"حذف شد"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> افزوده شود؟"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"وقتی <xliff:g id="APPNAME">%s</xliff:g> را اضافه می‌کنید، می‌تواند کنترل‌ها و محتوا را به این پانل اضافه کند. در برخی‌از برنامه‌ها می‌توانید انتخاب کنید چه کنترل‌هایی در اینجا نشان داده شود."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"به موارد دلخواه اضافه شد"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"اضافه‌شده به موارد دلخواه، جایگاه <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"حذف‌شده از موارد دلخواه"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"باز کردن <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> از <xliff:g id="ARTIST_NAME">%2$s</xliff:g> را ازطریق <xliff:g id="APP_LABEL">%3$s</xliff:g> پخش کنید"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> را ازطریق <xliff:g id="APP_LABEL">%2$s</xliff:g> پخش کنید"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"برای شما"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"واگرد"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"برای پخش در <xliff:g id="DEVICENAME">%1$s</xliff:g> به دستگاه نزدیک‌تر شوید"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"برای پخش در اینجا، به <xliff:g id="DEVICENAME">%1$s</xliff:g> نزدیک‌تر شوید"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"خطا، دوباره امتحان کنید"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"افزودن کنترل‌ها"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ویرایش کنترل‌ها"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"افزودن برنامه"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"افزودن خروجی"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"گروه"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"۱ دستگاه انتخاب شد"</string>
@@ -919,7 +918,6 @@
     <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">"بلندگوها و نمایشگرها"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"دستگاه‌های پیشنهادی"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"حساب ممتاز لازم است"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"همه‌فرتستی چطور کار می‌کند"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"همه‌فرستی"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"‏افرادی که در اطرافتان دستگاه‌های Bluetooth سازگار دارند می‌توانند به رسانه‌ای که همه‌فرستی می‌کنید گوش کنند"</string>
@@ -984,7 +982,7 @@
     <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"موقتاً متصل است"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"اتصال ضعیف"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"داده تلفن همراه به‌طور خودکار متصل نخواهد شد"</string>
-    <string name="mobile_data_no_connection" msgid="1713872434869947377">"اتصال برقرار نیست"</string>
+    <string name="mobile_data_no_connection" msgid="1713872434869947377">"اتصال اینترنت موجود نیست"</string>
     <string name="non_carrier_network_unavailable" msgid="770049357024492372">"شبکه دیگری وجود ندارد"</string>
     <string name="all_network_unavailable" msgid="4112774339909373349">"شبکه‌ای در دسترس نیست"</string>
     <string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"دوربین خاموش است"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"میکروفون خاموش است"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"دوربین و میکروفون خاموش هستند"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# اعلان}one{# اعلان}other{# اعلان}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>، <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"یادداشت‌برداری"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"مجاز کردن دسترسی یک‌باره"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"اجازه نمی‌دهم"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"گزارش‌های دستگاه آنچه را در دستگاهتان رخ می‌دهد ثبت می‌کند. برنامه‌ها می‌توانند از این گزارش‌ها برای پیدا کردن مشکلات و رفع آن‌ها استفاده کنند.\n\nبرخی‌از گزارش‌ها ممکن است حاوی اطلاعات حساس باشند، بنابراین فقط به برنامه‌های مورداعتمادتان اجازه دسترسی به همه گزارش‌های دستگاه را بدهید. \n\nاگر به این برنامه اجازه ندهید به همه گزارش‌های دستگاه دسترسی داشته باشد، همچنان می‌تواند به گزارش‌های خودش دسترسی داشته باشد. سازنده دستگاه نیز ممکن است همچنان بتواند به برخی‌از گزارش‌ها یا اطلاعات دستگاهتان دسترسی داشته باشد."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"باز کردن <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• برنامه راه‌اندازی شده باشد"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• حداقل یک کارت به «کیف پول» اضافه شده باشد"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"خط‌مشی کاری شما فقط به برقراری تماس ازطریق نمایه کاری اجازه می‌دهد"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"رفتن به نمایه کاری"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"بستن"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"تنظیمات صفحه قفل"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index b84ca4f..0abde9d 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Alareuna <xliff:g id="PERCENT">%1$d</xliff:g> prosenttia"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vasen reuna <xliff:g id="PERCENT">%1$d</xliff:g> prosenttia"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Oikea reuna <xliff:g id="PERCENT">%1$d</xliff:g> prosenttia"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Työprofiilin kuvakaappaukset tallennetaan sovellukseen: <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Näytön tallentaja"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Näytön tallennusta käsitellään"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Avattu kasvojen avulla"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Kasvot tunnistettu"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Siirrä vasemmalle"</item>
-    <item msgid="5558598599408514296">"Siirrä alas"</item>
-    <item msgid="4844142668312841831">"Siirrä oikealle"</item>
-    <item msgid="5640521437931460125">"Siirrä ylös"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Yritä uudelleen pyyhkäisemällä ylös"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Avaa lukitus, jotta voit käyttää NFC:tä"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Organisaatiosi omistaa tämän laitteen"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Valitse sovellus lisätäksesi säätimiä"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# säädin lisätty.}other{# säädintä lisätty.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Poistettu"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Lisätäänkö <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kun <xliff:g id="APPNAME">%s</xliff:g> lisätään, se voi lisätä asetuksia ja sisältöä tähän paneeliin. Joissakin sovelluksissa voit valita, mitä asetukset näkyvät täällä."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Lisätty suosikkeihin"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Lisätty suosikkeihin sijalle <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Poistettu suosikeista"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Avaa <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Soita <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) sovelluksessa <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Soita <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="APP_LABEL">%2$s</xliff:g>)"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Sinulle"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Kumoa"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Siirry lähemmäs, jotta <xliff:g id="DEVICENAME">%1$s</xliff:g> voi toistaa tämän"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Siirry lähemmäs laitetta (<xliff:g id="DEVICENAME">%1$s</xliff:g>) toistaaksesi täällä"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Virhe, yritä uudelleen"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Lisää säätimiä"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Muokkaa säätimiä"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Lisää sovellus"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Lisää toistotapoja"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Ryhmä"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 laite valittu"</string>
@@ -919,7 +918,6 @@
     <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">"Kaiuttimet ja näytöt"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Ehdotetut laitteet"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Edellyttää premium-tiliä"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Miten lähetys toimii"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Lähetys"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lähistöllä olevat ihmiset, joilla on yhteensopiva Bluetooth-laite, voivat kuunnella lähettämääsi mediaa"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera on poissa päältä"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofoni on poissa päältä"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera ja mikrofoni ovat pois päältä"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ilmoitus}other{# ilmoitusta}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Muistiinpanojen tekeminen"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Salli kertaluonteinen pääsy"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Älä salli"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Laitteen tapahtumat tallentuvat laitelokeihin. Niiden avulla sovellukset voivat löytää ja korjata ongelmia.\n\nJotkin lokit voivat sisältää arkaluontoista tietoa, joten salli pääsy kaikkiin laitelokeihin vain sovelluksille, joihin luotat. \n\nJos et salli tälle sovellukselle pääsyä kaikkiin laitelokeihin, sillä on kuitenkin pääsy sen omiin lokeihin. Laitteen valmistajalla voi olla pääsy joihinkin lokeihin tai tietoihin laitteella."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Avaa <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Sovellus on otettu käyttöön"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Ainakin yksi kortti on lisätty Walletiin"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Työkäytäntö sallii sinun soittaa puheluita vain työprofiilista"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Vaihda työprofiiliin"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Sulje"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Lukitusnäytön asetukset"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a60d961..0bf02a9 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Limite inférieure : <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite gauche : <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite droite : <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Les captures d\'écran du profil professionnel sont enregistrées dans l\'application <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fichiers"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Enregistreur d\'écran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Trait. de l\'enregist. d\'écran…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement d\'écran"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Visage reconnu. Appuyez sur Déverrouiller pour ouvrir."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Déverrouillé avec le visage"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Visage reconnu"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Déplacer vers la gauche"</item>
-    <item msgid="5558598599408514296">"Déplacer vers le bas"</item>
-    <item msgid="4844142668312841831">"Déplacer vers la droite"</item>
-    <item msgid="5640521437931460125">"Déplacer vers le haut"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour utiliser la CCP"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Sélectionnez l\'application pour laquelle ajouter des commandes"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}many{# de commandes ajoutées.}other{# commandes ajoutées.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Ajouter <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Lorsque vous ajoutez <xliff:g id="APPNAME">%s</xliff:g>, elle peut ajouter des commandes et du contenu à ce panneau. Dans certaines applications, vous pouvez choisir les commandes qui s\'affichent ici."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Supprimé des favoris"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Ouvrez <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Lecture de <xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> à partir de <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Lecture de <xliff:g id="SONG_NAME">%1$s</xliff:g> à partir de <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Pour vous"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Annuler"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Rapprochez-vous pour faire jouer le contenu sur <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Pour faire jouer le contenu ici, rapprochez-vous de <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Erreur. Veuillez réessayer."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Ajouter des commandes"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Modifier des commandes"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ajouter une application"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ajouter des sorties"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Un appareil sélectionné"</string>
@@ -919,7 +918,6 @@
     <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">"Haut-parleurs et écrans"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Appareils suggérés"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Nécessite un compte payant"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement de la diffusion"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Diffusion"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité disposant d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"L\'appareil photo est désactivé"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Le micro est désactivé"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"L\'appareil photo et le micro sont désactivés"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}many{# de notifications}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Prise de note"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Autoriser un accès unique"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ne pas autoriser"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Les journaux de l\'appareil enregistrent ce qui se passe sur celui-ci. Les applications peuvent utiliser ces journaux pour trouver et résoudre des problèmes.\n\nCertains journaux peuvent contenir des renseignements confidentiels. N\'autorisez donc que les applications auxquelles vous faites confiance puisque celles-ci pourront accéder à l\'ensemble des journaux de l\'appareil. \n\nMême si vous n\'autorisez pas cette application à accéder à l\'ensemble des journaux de l\'appareil, elle aura toujours accès à ses propres journaux. Le fabricant de votre appareil pourrait toujours être en mesure d\'accéder à certains journaux ou renseignements sur votre appareil."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ouvrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• que cette application est configurée;"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• qu\'au moins une carte a été ajoutée à Portefeuille."</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Votre politique de l\'entreprise vous autorise à passer des appels téléphoniques uniquement à partir de votre profil professionnel"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1a37657..1208668 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Limite inférieure : <xliff:g id="PERCENT">%1$d</xliff:g> pour cent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite gauche : <xliff:g id="PERCENT">%1$d</xliff:g> pour cent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite droite : <xliff:g id="PERCENT">%1$d</xliff:g> pour cent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Les captures d\'écran du profil professionnel sont enregistrées dans l\'appli <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fichiers"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Enregistreur d\'écran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Enregistrement de l\'écran…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour ouvrir."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Déverrouillé par le visage"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Visage reconnu"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Déplacer vers la gauche"</item>
-    <item msgid="5558598599408514296">"Déplacer vers le bas"</item>
-    <item msgid="4844142668312841831">"Déplacer vers la droite"</item>
-    <item msgid="5640521437931460125">"Déplacer vers le haut"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Balayez l\'écran vers le haut pour réessayer"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Déverrouillez l\'écran pour pouvoir utiliser le NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Cet appareil appartient à votre organisation"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Sélectionnez l\'appli pour laquelle ajouter des commandes"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}many{# commandes ajoutées.}other{# commandes ajoutées.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Ajouter <xliff:g id="APPNAME">%s</xliff:g> ?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Lorsque vous ajoutez l\'appli <xliff:g id="APPNAME">%s</xliff:g>, elle peut ajouter des commandes et contenus dans ce panneau. Dans certaines applis, vous pouvez choisir les commandes à afficher ici."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Supprimé des favoris"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Ouvre <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Mets <xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> depuis <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Mets <xliff:g id="SONG_NAME">%1$s</xliff:g> depuis <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Pour vous"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Annuler"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Rapprochez-vous de votre <xliff:g id="DEVICENAME">%1$s</xliff:g> pour y lire le contenu"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Pour lancer la lecture ici, rapprochez-vous de <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Erreur. Veuillez réessayer."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Ajouter des commandes"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Modifier des commandes"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ajouter une appli"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ajouter des sorties"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 appareil sélectionné"</string>
@@ -919,7 +918,6 @@
     <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">"Enceintes et écrans"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Appareils suggérés"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Nécessite un compte premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement des annonces"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Annonce"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité équipées d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Caméra désactivée"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Micro désactivé"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Appareil photo et micro désactivés"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}many{# notifications}other{# notifications}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Prendre des notes"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Autoriser un accès unique"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ne pas autoriser"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Les journaux enregistrent ce qui se passe sur votre appareil. Les applis peuvent les utiliser pour rechercher et résoudre des problèmes.\n\nCertains journaux pouvant contenir des infos sensibles, autorisez uniquement les applis de confiance à accéder à tous les journaux de l\'appareil. \n\nSi vous refusez à cette appli l\'accès à tous les journaux de l\'appareil, elle a quand même accès aux siens. Le fabricant de l\'appareil peut accéder à certains journaux ou certaines infos sur votre appareil."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ouvrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• L\'appli est configurée"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Au moins une carte a été ajoutée à Wallet"</string>
@@ -1054,11 +1058,11 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Au moins un appareil est disponible"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Appuyez de manière prolongée sur raccourci"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuler"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Retourner maintenant"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Retourner"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Déplier le téléphone pour un meilleur selfie"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Passer à l\'écran frontal pour un meilleur selfie ?"</string>
-    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilisez la caméra arrière pour prendre une photo plus large avec une résolution supérieure."</string>
-    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Cet écran sera désactivé"</b></string>
+    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilisez la caméra arrière pour prendre une photo plus large d\'une résolution supérieure."</string>
+    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Cet écran s\'éteindra"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable qui est déplié"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable qui est retourné"</string>
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de batterie restante"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Votre règle professionnelle ne vous permet de passer des appels que depuis le profil professionnel"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index cb1a8cb..50f07db 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bordo inferior: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Bordo esquerdo: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Bordo dereito: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"As capturas de pantalla do perfil de traballo gárdanse na aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Ficheiros"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravadora da pantalla"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando gravación pantalla"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación en curso sobre unha sesión de gravación de pantalla"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Recoñeceuse a cara. Preme a icona de desbloquear para abrir."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Usouse o desbloqueo facial"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Recoñeceuse a cara"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Mover cara á esquerda"</item>
-    <item msgid="5558598599408514296">"Mover cara abaixo"</item>
-    <item msgid="4844142668312841831">"Mover cara á dereita"</item>
-    <item msgid="5640521437931460125">"Mover cara arriba"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Pasa o dedo cara arriba para tentalo de novo"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquea o dispositivo para utilizar a NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence á túa organización."</string>
@@ -543,10 +544,8 @@
     <string name="notification_automatic_title" msgid="3745465364578762652">"Automática"</string>
     <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sen son nin vibración"</string>
     <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sen son nin vibración, e aparecen máis abaixo na sección de conversas"</string>
-    <!-- no translation found for notification_channel_summary_default (777294388712200605) -->
-    <skip />
-    <!-- no translation found for notification_channel_summary_default_with_bubbles (3482483084451555344) -->
-    <skip />
+    <string name="notification_channel_summary_default" msgid="777294388712200605">"Poderían facer que o dispositivo soe ou vibre en función da súa configuración"</string>
+    <string name="notification_channel_summary_default_with_bubbles" msgid="3482483084451555344">"Poderían facer que o dispositivo soe ou vibre en función da súa configuración. As conversas de <xliff:g id="APP_NAME">%1$s</xliff:g> móstranse en burbullas de forma predeterminada."</string>
     <string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Fai que o sistema determine se a notificación debe emitir un son ou unha vibración"</string>
     <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"&lt;b&gt;Estado:&lt;/b&gt; ascendeuse a Predeterminada"</string>
     <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"&lt;b&gt;Estado:&lt;/b&gt; o nivel diminuíuse a Silencioso"</string>
@@ -834,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Escolle unha aplicación para engadir controis"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Engadiuse # control.}other{Engadíronse # controis.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Quitouse"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Queres engadir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Cando engadas a aplicación <xliff:g id="APPNAME">%s</xliff:g>, poderá incluír controis e contido neste panel Nalgunhas aplicacións, podes escoller os controis que se mostrarán aquí."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Está entre os controis favoritos"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Está entre os controis favoritos (posición: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Non está entre os controis favoritos"</string>
@@ -888,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abre <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproduce <xliff:g id="SONG_NAME">%1$s</xliff:g>, de <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproduce <xliff:g id="SONG_NAME">%1$s</xliff:g> en <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Para ti"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Desfacer"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Achega o dispositivo para reproducir o contido en: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Para reproducir o contido aquí, achégate ao dispositivo (<xliff:g id="DEVICENAME">%1$s</xliff:g>)"</string>
@@ -904,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Erro. Téntao de novo"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Engadir controis"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controis"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Engadir aplicación"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Engadir saídas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Seleccionouse 1 dispositivo"</string>
@@ -921,8 +918,6 @@
     <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">"Altofalantes e pantallas"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos suxeridos"</string>
-    <!-- no translation found for media_output_status_require_premium (5691200962588753380) -->
-    <skip />
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funcionan as difusións?"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Difusión"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As persoas que estean preto de ti e que dispoñan de dispositivos Bluetooth compatibles poden escoitar o contido multimedia que difundas"</string>
@@ -1034,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"A cámara está apagada"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"O micrófono está desactivado"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A cámara e o micrófono están desactivados"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}other{# notificacións}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Toma de notas"</string>
@@ -1049,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir acceso unha soa vez"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Non permitir"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Os rexistros do dispositivo dan conta do que ocorre neste. As aplicacións poden usalos para buscar problemas e solucionalos.\n\nAlgúns poden conter información confidencial, polo que che recomendamos que só permitas que accedan a todos os rexistros do dispositivo as aplicacións nas que confíes. \n\nEsta aplicación pode acceder aos seus propios rexistros aínda que non lle permitas acceder a todos. É posible que o fabricante do dispositivo teña acceso a algúns rexistros ou á información do teu dispositivo."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• A aplicación debe estar configurada"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Ten que haber polo menos unha tarxeta engadida a Wallet"</string>
@@ -1067,16 +1068,10 @@
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batería restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Conecta o lapis óptico a un cargador"</string>
     <string name="stylus_battery_low" msgid="7134370101603167096">"O lapis óptico ten pouca batería"</string>
-    <!-- no translation found for video_camera (7654002575156149298) -->
-    <skip />
-    <!-- no translation found for call_from_work_profile_title (6991157106804289643) -->
-    <skip />
-    <!-- no translation found for call_from_work_profile_text (3458704745640229638) -->
-    <skip />
-    <!-- no translation found for call_from_work_profile_action (2937701298133010724) -->
-    <skip />
-    <!-- no translation found for call_from_work_profile_close (7927067108901068098) -->
-    <skip />
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="video_camera" msgid="7654002575156149298">"Videocámara"</string>
+    <string name="call_from_work_profile_title" msgid="6991157106804289643">"Non se pode chamar desde este perfil"</string>
+    <string name="call_from_work_profile_text" msgid="3458704745640229638">"A política do teu traballo só che permite facer chamadas de teléfono desde o perfil de traballo"</string>
+    <string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar ao perfil de traballo"</string>
+    <string name="call_from_work_profile_close" msgid="7927067108901068098">"Pechar"</string>
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Configuración pantalla bloqueo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 78aa0f5..3d974d0 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"નીચેની સીમા <xliff:g id="PERCENT">%1$d</xliff:g> ટકા"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ડાબી બાજુની સીમા <xliff:g id="PERCENT">%1$d</xliff:g> ટકા"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"જમણી બાજુની સીમા <xliff:g id="PERCENT">%1$d</xliff:g> ટકા"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"ઑફિસના સ્ક્રીનશૉટ <xliff:g id="APP">%1$s</xliff:g> ઍપમાં સાચવવામાં આવે છે"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ફાઇલો"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"સ્ક્રીન રેકોર્ડર"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"સ્ક્રીન રેકૉર્ડિંગ ચાલુ છે"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"સ્ક્રીન રેકોર્ડિંગ સત્ર માટે ચાલુ નોટિફિકેશન"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ચહેરો ઓળખ્યો. ખોલવા માટે \'અનલૉક કરો\' આઇકન દબાવો."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ચહેરા દ્વારા અનલૉક કર્યું"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ચહેરો ઓળખ્યો"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ડાબે ખસેડો"</item>
-    <item msgid="5558598599408514296">"નીચે ખસેડો"</item>
-    <item msgid="4844142668312841831">"જમણે ખસેડો"</item>
-    <item msgid="5640521437931460125">"ઉપર ખસેડો"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"ફરી પ્રયાસ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCનો ઉપયોગ કરવા માટે અનલૉક કરો"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"આ ડિવાઇસ તમારી સંસ્થાની માલિકીનું છે"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"નિયંત્રણો ઉમેરવા માટે ઍપ પસંદ કરો"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# નિયંત્રણ ઉમેર્યું.}one{# નિયંત્રણ ઉમેર્યું.}other{# નિયંત્રણ ઉમેર્યા.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"કાઢી નાખ્યું"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ઉમેરીએ?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"જ્યારે તમે <xliff:g id="APPNAME">%s</xliff:g> ઉમેરો, ત્યારે તે આ પૅનલમાં નિયંત્રણો અને કન્ટેન્ટ ઉમેરી શકે છે. કેટલીક ઍપમાં, અહીં કયા નિયંત્રણો દેખાય તે તમે પસંદ કરી શકો છો."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"મનપસંદમાં ઉમેર્યું"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"મનપસંદમાં ઉમેર્યું, સ્થાન <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"મનપસંદમાંથી કાઢી નાખ્યું"</string>
@@ -853,7 +852,7 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"અન્ય"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ડિવાઇસનાં નિયંત્રણોમાં ઉમેરો"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ઉમેરો"</string>
-    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> દ્વારા સૂચન કરેલા"</string>
+    <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> દ્વારા સૂચવેલા"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"ડિવાઇસ લૉક કરેલું છે"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"લૉક સ્ક્રીનમાંથી ડિવાઇસ બતાવીએ અને નિયંત્રિત કરીએ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"તમે તમારા બાહ્ય ડિવાઇસ માટેના નિયંત્રણો લૉક સ્ક્રીન પર ઉમેરી શકો છો.\n\nતમારી ડિવાઇસ ઍપ કદાચ તમને તમારો ફોન કે ટૅબ્લેટ અનલૉક કર્યા વિના અમુક ડિવાઇસ નિયંત્રિત કરવાની મંજૂરી આપી શકે.\n\nતમે ગમે ત્યારે સેટિંગમાં જઈને ફેરફાર કરી શકો છો."</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ખોલો"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> પર <xliff:g id="ARTIST_NAME">%2$s</xliff:g>નું <xliff:g id="SONG_NAME">%1$s</xliff:g> ગીત ચલાવો"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> પર <xliff:g id="SONG_NAME">%1$s</xliff:g> ગીત ચલાવો"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"તમારા માટે"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"છેલ્લો ફેરફાર રદ કરો"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> પર ચલાવવા માટે વધુ નજીક ખસેડો"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"અહીં ચલાવવા માટે, <xliff:g id="DEVICENAME">%1$s</xliff:g>ની નજીક લાવો"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"ભૂલ, ફરીથી પ્રયાસ કરો"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"નિયંત્રણો ઉમેરો"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"નિયંત્રણોમાં ફેરફાર કરો"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ઍપ ઉમેરો"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"આઉટપુટ ઉમેરો"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ગ્રૂપ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ડિવાઇસ પસંદ કર્યું"</string>
@@ -919,7 +918,6 @@
     <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">"સ્પીકર અને ડિસ્પ્લે"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"સૂચવેલા ડિવાઇસ"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Premium એકાઉન્ટ જરૂરી છે"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"બ્રોડકાસ્ટ પ્રક્રિયાની કામ કરવાની રીત"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"બ્રોડકાસ્ટ કરો"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"સુસંગત બ્લૂટૂથ ડિવાઇસ ધરાવતા નજીકના લોકો તમે જે મીડિયા બ્રોડકાસ્ટ કરી રહ્યાં છો તે સાંભળી શકે છે"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"કૅમેરા બંધ છે"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"માઇક્રોફોન બંધ છે"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"કૅમેરા અને માઇક બંધ છે"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# નોટિફિકેશન}one{# નોટિફિકેશન}other{# નોટિફિકેશન}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"નોંધ લેવી"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"એક-વખતના ઍક્સેસની મંજૂરી આપો"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"મંજૂરી આપશો નહીં"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"તમારા ડિવાઇસ પર થતી કામગીરીને ડિવાઇસ લૉગ રેકોર્ડ કરે છે. ઍપ આ લૉગનો ઉપયોગ સમસ્યાઓ શોધી તેનું નિરાકરણ કરવા માટે કરી શકે છે.\n\nઅમુક લૉગમાં સંવેદનશીલ માહિતી હોઈ શકે, આથી ડિવાઇસનો બધો લૉગ ઍક્સેસ કરવાની મંજૂરી માત્ર તમારી વિશ્વાસપાત્ર ઍપને જ આપો. \n\nજો તમે આ ઍપને ડિવાઇસનો બધો લૉગ ઍક્સેસ કરવાની મંજૂરી ન આપો, તો પણ તે તેના પોતાના લૉગ ઍક્સેસ કરી શકે છે. તમારા ડિવાઇસના નિર્માતા હજી પણ કદાચ તમારા ડિવાઇસ પર અમુક લૉગ અથવા માહિતી ઍક્સેસ કરી શકે છે."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ખોલો"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ઍપનું સેટઅપ કરેલું છે"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ઓછામાં ઓછું એક કાર્ડ વૉલેટમાં ઉમેરેલું છે"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"તમારી ઑફિસની પૉલિસી તમને માત્ર ઑફિસની પ્રોફાઇલ પરથી જ ફોન કૉલ કરવાની મંજૂરી આપે છે"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ઑફિસની પ્રોફાઇલ પર સ્વિચ કરો"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"બંધ કરો"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"લૉક સ્ક્રીનના સેટિંગ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c0d89f9..5a316c1 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"निचले किनारे से <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"बाएं किनारे से <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"दाएं किनारे से <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"वर्क प्रोफ़ाइल से लिए गए स्क्रीनशॉट, <xliff:g id="APP">%1$s</xliff:g> ऐप्लिकेशन में सेव किए गए हैं"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रिकॉर्डर"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रिकॉर्डिंग को प्रोसेस किया जा रहा है"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"चेहरे की पहचान हो गई. डिवाइस खोलने के लिए अनलॉक आइकॉन को टैप करें."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"चेहरे से अनलॉक किया गया"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"चेहरे की पहचान हो गई"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"बाईं ओर ले जाएं"</item>
-    <item msgid="5558598599408514296">"नीचे ले जाएं"</item>
-    <item msgid="4844142668312841831">"दाईं ओर ले जाएं"</item>
-    <item msgid="5640521437931460125">"ऊपर ले जाएं"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"फिर से कोशिश करने के लिए ऊपर की ओर स्वाइप करें"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"एनएफ़सी इस्तेमाल करने के लिए स्क्रीन को अनलॉक करें"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"कंट्रोल जोड़ने के लिए ऐप्लिकेशन चुनें"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# कंट्रोल जोड़ा गया.}one{# कंट्रोल जोड़ा गया.}other{# कंट्रोल जोड़े गए.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"हटाया गया"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> को जोड़ना है?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> को जोड़ने पर, वह इस पैनल पर कुछ कंट्रोल और कॉन्टेंट दिखा सकता है. कुछ ऐप्लिकेशन के लिए यह चुना जा सकता है कि वे इस पैनल पर कौनसे कंट्रोल दिखाएं."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"पसंदीदा बनाया गया"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"पसंदीदा बनाया गया, क्रम संख्या <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"पसंदीदा से हटाया गया"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> खोलें"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> पर, <xliff:g id="ARTIST_NAME">%2$s</xliff:g> का <xliff:g id="SONG_NAME">%1$s</xliff:g> चलाएं"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> पर, <xliff:g id="SONG_NAME">%1$s</xliff:g> चलाएं"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"आपके लिए सुझाव"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"पहले जैसा करें"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> पर मीडिया चलाने के लिए, अपने डिवाइस को उसके पास ले जाएं"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"मीडिया ट्रांसफ़र करने के लिए, <xliff:g id="DEVICENAME">%1$s</xliff:g> के करीब जाएं"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"गड़बड़ी हुई, फिर से कोशिश करें"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"कंट्राेल जोड़ें"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"कंट्रोल में बदलाव करें"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ऐप्लिकेशन जोड़ें"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट जोड़ें"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ग्रुप"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिवाइस चुना गया"</string>
@@ -919,7 +918,6 @@
     <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">"स्पीकर और डिसप्ले"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"सुझाए गए डिवाइस"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"प्रीमियम खाता होना ज़रूरी है"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ब्रॉडकास्ट करने की सुविधा कैसे काम करती है"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ब्रॉडकास्ट करें"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"आपके आस-पास मौजूद लोग, ब्रॉडकास्ट किए जा रहे मीडिया को सुन सकते हैं. हालांकि, इसके लिए उनके पास ऐसे ब्लूटूथ डिवाइस होने चाहिए जिन पर मीडिया चलाया जा सके"</string>
@@ -1031,6 +1029,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"कैमरा बंद है"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"माइक्रोफ़ोन बंद है"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"कैमरा और माइक बंद हैं"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant सुन रही है"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# सूचना}one{# सूचना}other{# सूचनाएं}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"नोट बनाएं"</string>
@@ -1046,6 +1045,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"एक बार ऐक्सेस करने की अनुमति दें"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"अनुमति न दें"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"डिवाइस लॉग में आपके डिवाइस पर की गई कार्रवाइयां रिकॉर्ड होती हैं. ऐप्लिकेशन, इन लॉग का इस्तेमाल गड़बड़ियां ढूंढने और उन्हें सही करने के लिए करता है.\n\nकुछ लॉग में संवेदनशील जानकारी हो सकती है. इसलिए, सिर्फ़ भरोसेमंद ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस दें. \n\nअगर इस ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस नहीं दिया जाता है, तब भी यह डिवाइस पर मौजूद अपने लॉग ऐक्सेस कर सकता है. डिवाइस को बनाने वाली कंपनी अब भी डिवाइस के कुछ लॉग या जानकारी को ऐक्सेस कर सकती है."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ज़्यादा जानें"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"ज़्यादा जानने के लिए <xliff:g id="URL">%s</xliff:g> पर जाएं"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> खोलें"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ऐप्लिकेशन को सेट अप किया गया है"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet में कम से कम एक कार्ड जोड़ा गया है"</string>
@@ -1054,7 +1055,7 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• कम से कम एक डिवाइस उपलब्ध है"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"शॉर्टकट को दबाकर रखें"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द करें"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"कैमरा अभी स्विच करें"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"अभी स्विच करें"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"बेहतर सेल्फ़ी के लिए फ़ोन को अनफ़ोल्ड करें"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"बेहतर सेल्फ़ी के लिए फ़्रंट डिसप्ले पर स्विच करें?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"वाइड ऐंगल में हाई रिज़ॉल्यूशन वाली फ़ोटो लेने के लिए, पीछे का कैमरा इस्तेमाल करें."</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"ऑफ़िस की नीति के तहत, वर्क प्रोफ़ाइल होने पर ही फ़ोन कॉल किए जा सकते हैं"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"वर्क प्रोफ़ाइल पर स्विच करें"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करें"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"लॉक स्क्रीन की सेटिंग"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index cdf6e57..e5dd4d1 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Donji rub <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Lijevi rub <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Desni rub <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Snimke zaslona s poslovnog profila spremaju se u aplikaciju <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Spremljeno u aplikaciju <xliff:g id="APP">%1$s</xliff:g> u poslovnom profilu"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Datoteke"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> otkrila je ovu snimku zaslona."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije otkrile su ovu snimku zaslona."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Snimač zaslona"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrada snimanja zaslona"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Tekuća obavijest za sesiju snimanja zaslona"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste otvorili."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Otključano licem"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Lice je prepoznato"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Pomicanje ulijevo"</item>
-    <item msgid="5558598599408514296">"Pomicanje prema dolje"</item>
-    <item msgid="4844142668312841831">"Pomicanje udesno"</item>
-    <item msgid="5640521437931460125">"Pomicanje prema gore"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Prijeđite prstom prema gore za ponovni pokušaj"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Otključajte da biste upotrijebili NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ovaj uređaj pripada vašoj organizaciji"</string>
@@ -884,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvori <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g> putem aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g> putem aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Za vas"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Poništi"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Približite se radi reprodukcije na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Da biste reproducirali ovdje, približite se uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -916,7 +915,6 @@
     <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">"Zvučnici i zasloni"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Predloženi uređaji"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Zahtijeva račun s naplatom"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako emitiranje funkcionira"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Emitiranje"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u blizini s kompatibilnim Bluetooth uređajima mogu slušati medije koje emitirate"</string>
@@ -1028,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera je isključena"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon je isključen"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotoaparat i mikrofon su isključeni"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistent sluša"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obavijest}one{# obavijest}few{# obavijesti}other{# obavijesti}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Pisanje bilježaka"</string>
@@ -1043,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Omogući jednokratni pristup"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Nemoj dopustiti"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"U zapisnicima uređaja bilježi se što se događa na uređaju. Aplikacije mogu koristiti te zapisnike kako bi pronašle i riješile poteškoće.\n\nNeki zapisnici mogu sadržavati osjetljive podatke, pa pristup svim zapisnicima uređaja odobrite samo pouzdanim aplikacijama. \n\nAko ne dopustite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač vašeg uređaja i dalje može pristupati nekim zapisnicima ili podacima na vašem uređaju."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saznajte više"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saznajte više na <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvorite <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacija je postavljena"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Najmanje jedna kartica dodana je u Wallet"</string>
@@ -1051,7 +1052,7 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Dostupan je najmanje jedan uređaj"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Prečac za dodirnuti i zadržati"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Odustani"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Okreni odmah"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Prebaci"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Otvorite telefon da biste snimili bolji selfie"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Prebaciti na prednji zaslon za bolji selfie?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Upotrijebite stražnji fotoaparat za širu fotografiju s višom razlučivošću."</string>
@@ -1066,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Vaša pravila za poslovne uređaje omogućuju vam upućivanje poziva samo s poslovnog profila"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Prijeđite na poslovni profil"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Postavke zaključanog zaslona"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index c411a0a..cd0eb81 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Alsó rész <xliff:g id="PERCENT">%1$d</xliff:g> százaléka"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Bal oldali rész <xliff:g id="PERCENT">%1$d</xliff:g> százaléka"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Jobb oldali rész <xliff:g id="PERCENT">%1$d</xliff:g> százaléka"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"A munkahelyi képernyőképeket a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazásba menti a rendszer"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Mentve a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazás munkaprofiljába"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fájlok"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> észlelte ezt a képernyőképet."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> és más nyitott alkalmazások észlelték ezt a képernyőképet."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Képernyőrögzítő"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Képernyőrögzítés feldolgozása"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Arc felismerve. Eszköz használata: Feloldás ikon."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Zárolás arccal feloldva"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Arc felismerve"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Mozgatás balra"</item>
-    <item msgid="5558598599408514296">"Mozgatás lefelé"</item>
-    <item msgid="4844142668312841831">"Mozgatás jobbra"</item>
-    <item msgid="5640521437931460125">"Mozgatás felfelé"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Az újrapróbálkozáshoz csúsztassa felfelé az ujját"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Az NFC használatához oldja fel a képernyőzárat"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ez az eszköz az Ön szervezetének tulajdonában van"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Válasszon alkalmazást a vezérlők hozzáadásához"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# vezérlő hozzáadva.}other{# vezérlő hozzáadva.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Eltávolítva"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Hozzáadja a(z) <xliff:g id="APPNAME">%s</xliff:g> alkalmazást?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"A(z) <xliff:g id="APPNAME">%s</xliff:g> hozzáadását követően az alkalmazás vezérlőelemeket és tartalmakat adhat hozzá ehhez a panelhez. Egyes alkalmazásokban kiválasztható, hogy mely vezérlőelemek jelenjenek meg itt."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Hozzáadva a kedvencekhez"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Hozzáadva a kedvencekhez <xliff:g id="NUMBER">%d</xliff:g>. helyen"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Eltávolítva a kedvencek közül"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> megnyitása"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> <xliff:g id="SONG_NAME">%1$s</xliff:g> című számának lejátszása innen: <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> lejátszása innen: <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Neked"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Visszavonás"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Menjen közelebb, ha itt szeretné lejátszani: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Ha szeretné itt lejátszani, helyezkedjen közelebb a következőhöz: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Hiba történt. Próbálja újra."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Vezérlők hozzáadása"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Vezérlők szerkesztése"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Alkalmazás hozzáadása"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Kimenetek hozzáadása"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Csoport"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 eszköz kiválasztva"</string>
@@ -919,7 +915,6 @@
     <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">"Hangfalak és kijelzők"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Javasolt eszközök"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Prémiumfiók szükséges"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"A közvetítés működése"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Közvetítés"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"A közelben tartózkodó, kompatibilis Bluetooth-eszközzel rendelkező személyek meghallgathatják az Ön közvetített médiatartalmait"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"A kamera ki van kapcsolva"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"A mikrofon ki van kapcsolva"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A kamera és a mikrofon ki vannak kapcsolva"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# értesítés}other{# értesítés}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Jegyzetelés"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Egyszeri hozzáférés engedélyezése"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Tiltás"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Az eszköznaplók rögzítik, hogy mi történik az eszközén. Az alkalmazások ezeket a naplókat használhatják a problémák megkeresésére és kijavítására.\n\nBizonyos naplók bizalmas adatokat is tartalmazhatnak, ezért csak olyan alkalmazások számára engedélyezze az összes eszköznaplóhoz való hozzáférést, amelyekben megbízik. \n\nHa nem engedélyezi ennek az alkalmazásnak, hogy hozzáférjen az összes eszköznaplójához, az app továbbra is hozzáférhet a saját naplóihoz. Előfordulhat, hogy az eszköz gyártója továbbra is hozzáfér az eszközön található bizonyos naplókhoz és adatokhoz."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> megnyitása"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Az alkalmazás be van állítva"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Legalább egy kártya hozzá lett adva a Wallethez"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"A munkahelyi házirend csak munkaprofilból kezdeményezett telefonhívásokat engedélyez"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Váltás munkaprofilra"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Bezárás"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Lezárási képernyő beállításai"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 9186f12..2219e48 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ներքևի սահմանագիծը՝ <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Ձախ կողմի սահմանագիծը՝ <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Աջ կողմի սահմանագիծը՝ <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Աշխատանքային սքրինշոթները պահվում են «<xliff:g id="APP">%1$s</xliff:g>» հավելվածում"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Ֆայլեր"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Էկրանի տեսագրիչ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Էկրանի տեսագրության մշակում"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Դեմքը ճանաչվեց։ Բացելու համար սեղմեք ապակողպման պատկերակը։"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ապակողպվեց դեմքով"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Դեմքը ճանաչվեց"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Տեղափոխել ձախ"</item>
-    <item msgid="5558598599408514296">"Տեղափոխել ներքև"</item>
-    <item msgid="4844142668312841831">"Տեղափոխել աջ"</item>
-    <item msgid="5640521437931460125">"Տեղափոխել վերև"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Սահեցրեք վերև՝ նորից փորձելու համար"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ապակողպեք՝ NFC-ն օգտագործելու համար"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Այս սարքը պատկանում է ձեր կազմակերպությանը"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Ընտրեք հավելված` կառավարման տարրեր ավելացնելու համար"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Ավելացվեց կառավարման # տարր։}one{Ավելացվեց կառավարման # տարր։}other{Ավելացվեց կառավարման # տարր։}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Հեռացված է"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Ավելացնե՞լ <xliff:g id="APPNAME">%s</xliff:g> հավելվածը"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Եթե ավելացնեք <xliff:g id="APPNAME">%s</xliff:g> հավելվածը, այն կարող է կարգավորումներ և բովանդակություն ավելացնել այս վահանակում։ Որոշ հավելվածներում դուք կարող եք ընտրել, թե որ կարգավորումները ցուցադրվեն այստեղ։"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ավելացված է ընտրանիում"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ավելացված է ընտրանիում, դիրքը՝ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Հեռացված է ընտրանուց"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Բացեք <xliff:g id="APP_LABEL">%1$s</xliff:g> հավելվածը"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Նվագարկել <xliff:g id="SONG_NAME">%1$s</xliff:g> երգը <xliff:g id="ARTIST_NAME">%2$s</xliff:g>-ի կատարմամբ <xliff:g id="APP_LABEL">%3$s</xliff:g> հավելվածից"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Նվագարկել <xliff:g id="SONG_NAME">%1$s</xliff:g> երգը <xliff:g id="APP_LABEL">%2$s</xliff:g> հավելվածից"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Ձեզ համար"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Հետարկել"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Ավելի մոտ եկեք՝ <xliff:g id="DEVICENAME">%1$s</xliff:g> սարքում նվագարկելու համար"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Այստեղ նվագարկելու համար մոտեցեք <xliff:g id="DEVICENAME">%1$s</xliff:g> սարքին"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Սխալ առաջացավ։ Նորից փորձեք։"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Ավելացնել կառավարման տարրեր"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Փոփոխել կառավարման տարրերը"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ավելացնել հավելված"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ավելացրեք մուտքագրման սարքեր"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Խումբ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ընտրված է 1 սարք"</string>
@@ -919,7 +918,6 @@
     <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">"Բարձրախոսներ և էկրաններ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Առաջարկվող սարքեր"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Պահանջվում է պրեմիում հաշիվ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ինչպես է աշխատում հեռարձակումը"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Հեռարձակում"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ձեր մոտակայքում գտնվող՝ համատեղելի Bluetooth սարքերով մարդիկ կարող են լսել մեդիա ֆայլերը, որոնք դուք հեռարձակում եք։"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Տեսախցիկն անջատված է"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Խոսափողն անջատված է"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Տեսախցիկը և խոսափողն անջատված են"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ծանուցում}one{# ծանուցում}other{# ծանուցում}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Նշումների ստեղծում"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Թույլատրել մեկանգամյա մուտքը"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Չթույլատրել"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Այն, ինչ տեղի է ունենում ձեր սարքում, գրանցվում է սարքի մատյաններում։ Հավելվածները կարող են դրանք օգտագործել անսարքությունները հայտնաբերելու և վերացնելու նպատակով։\n\nՔանի որ որոշ մատյաններ անձնական տեղեկություններ են պարունակում, խորհուրդ ենք տալիս հասանելի դարձնել ձեր սարքի բոլոր մատյանները միայն այն հավելվածներին, որոնց վստահում եք։ \n\nԵթե այս հավելվածին նման թույլտվություն չեք տվել, դրան նախկինի պես հասանելի կլինեն իր մատյանները։ Հնարավոր է՝ ձեր սարքի արտադրողին ևս հասանելի լինեն սարքի որոշ մատյաններ և տեղեկություններ։"</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Բացել <xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Հավելվածը կարգավորված է"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Առնվազն մեկ քարտ ավելացված է Wallet-ում"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Ձեր աշխատանքային կանոնների համաձայն՝ դուք կարող եք զանգեր կատարել աշխատանքային պրոֆիլից"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Անցնել աշխատանքային պրոֆիլ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Փակել"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Կողպէկրանի կարգավորումներ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 1d0d3d6..941accc 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Batas bawah <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Batas kiri <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Batas kanan <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Screenshot dengan profil kerja disimpan di aplikasi <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Disimpan di <xliff:g id="APP">%1$s</xliff:g> di profil kerja"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"File"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> mendeteksi screenshot ini."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dan aplikasi terbuka lainnya mendeteksi screenshot ini."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Perekam Layar"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses perekaman layar"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Wajah dikenali. Tekan ikon buka kunci untuk membuka."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Kunci dibuka dengan wajah"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Wajah dikenali"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Pindah ke kiri"</item>
-    <item msgid="5558598599408514296">"Pindah ke bawah"</item>
-    <item msgid="4844142668312841831">"Pindah ke kanan"</item>
-    <item msgid="5640521437931460125">"Pindah ke atas"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Geser ke atas untuk mencoba lagi"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Perangkat ini milik organisasi Anda"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Pilih aplikasi untuk menambahkan kontrol"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrol ditambahkan.}other{# kontrol ditambahkan.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Dihapus"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Tambahkan <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Jika Anda menambahkannya, <xliff:g id="APPNAME">%s</xliff:g> dapat menambahkan kontrol dan konten ke panel ini. Di beberapa aplikasi, Anda dapat memilih kontrol yang akan muncul di sini."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Difavoritkan"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Difavoritkan, posisi <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Batal difavoritkan"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Buka <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Putar <xliff:g id="SONG_NAME">%1$s</xliff:g> oleh <xliff:g id="ARTIST_NAME">%2$s</xliff:g> dari <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Putar <xliff:g id="SONG_NAME">%1$s</xliff:g> dari <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Untuk Anda"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Urungkan"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Dekatkan untuk memutar di <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Untuk memutar di sini, dekatkan ke <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Error, coba lagi"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Tambahkan kontrol"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edit kontrol"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tambahkan aplikasi"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tambahkan output"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 perangkat dipilih"</string>
@@ -919,7 +915,6 @@
     <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">"Speaker &amp; Layar"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Perangkat yang Disarankan"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Memerlukan akun premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cara kerja siaran"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Siaran"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Orang di dekat Anda dengan perangkat Bluetooth yang kompatibel dapat mendengarkan media yang sedang Anda siarkan"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera nonaktif"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon nonaktif"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera dan mikrofon nonaktif"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifikasi}other{# notifikasi}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Pembuatan catatan"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Izinkan akses satu kali"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Jangan izinkan"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Log perangkat merekam hal-hal yang terjadi di perangkat Anda. Aplikasi dapat menggunakan log ini untuk menemukan dan memperbaiki masalah.\n\nBeberapa log mungkin berisi info sensitif, jadi hanya izinkan aplikasi yang Anda percayai untuk mengakses semua log perangkat. \n\nJika Anda tidak mengizinkan aplikasi ini mengakses semua log perangkat, aplikasi masih dapat mengakses log-nya sendiri. Produsen perangkat masih dapat mengakses beberapa log atau info di perangkat Anda."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Buka <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikasi disiapkan"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Minimal satu kartu telah ditambahkan ke Wallet"</string>
@@ -1056,7 +1057,7 @@
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Batal"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Balik sekarang"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Bentangkan ponsel untuk selfie yang lebih baik"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Gunakan layar depan untuk selfie yang lebih baik?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Balik ke layar depan untuk selfie yang lebih bagus?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gunakan kamera belakang untuk foto dengan resolusi lebih tinggi dan lebih lebar."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Layar ini akan dinonaktifkan"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Perangkat foldable sedang dibentangkan"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Kebijakan kantor mengizinkan Anda melakukan panggilan telepon hanya dari profil kerja"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Beralih ke profil kerja"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Setelan layar kunci"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index aabae2f..e96a63d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Neðri mörk <xliff:g id="PERCENT">%1$d</xliff:g> prósent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vinstri mörk <xliff:g id="PERCENT">%1$d</xliff:g> prósent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Hægri mörk <xliff:g id="PERCENT">%1$d</xliff:g> prósent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Vinnuskjámyndir eru vistaðar í forritinu <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Skrár"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Skjáupptaka"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Vinnur úr skjáupptöku"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Andlitið var greint. Ýttu á opnunartáknið til að opna."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Opnað með andliti"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Andlitið var greint"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Færa til vinstri"</item>
-    <item msgid="5558598599408514296">"Færa niður"</item>
-    <item msgid="4844142668312841831">"Færa til hægri"</item>
-    <item msgid="5640521437931460125">"Færa upp"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Strjúktu upp til að reyna aftur"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Taktu úr lás til að nota NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Þetta tæki tilheyrir fyrirtækinu þínu"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Veldu forrit til að bæta við stýringum"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# stýringu bætt við.}one{# stýringu bætt við.}other{# stýringum bætt við.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Fjarlægt"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Viltu bæta <xliff:g id="APPNAME">%s</xliff:g> við?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Þegar þú bætir <xliff:g id="APPNAME">%s</xliff:g> við getur það bætt stýringum og efni við þetta svæði. Í sumum forritum geturðu valið hvaða stýringar birtast hér."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Eftirlæti"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Eftirlæti, staða <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjarlægt úr eftirlæti"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Opna <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Spila <xliff:g id="SONG_NAME">%1$s</xliff:g> með <xliff:g id="ARTIST_NAME">%2$s</xliff:g> í <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Spila <xliff:g id="SONG_NAME">%1$s</xliff:g> í <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Fyrir þig"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Afturkalla"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Færðu nær til að spila í <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Farðu nær <xliff:g id="DEVICENAME">%1$s</xliff:g> til að spila hér"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Villa, reyndu aftur"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Bæta við stýringum"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Breyta stýringum"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Bæta við forriti"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Bæta við úttaki"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Hópur"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 tæki valið"</string>
@@ -919,7 +918,6 @@
     <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">"Hátalarar og skjáir"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Tillögur að tækjum"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Krefst úrvalsreiknings"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Svona virkar útsending"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Útsending"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Fólk nálægt þér með samhæf Bluetooth-tæki getur hlustað á efnið sem þú sendir út"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Slökkt er á myndavél"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Slökkt er á hljóðnema"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Slökkt á myndavél og hljóðnema"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# tilkynning}one{# tilkynning}other{# tilkynningar}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Glósugerð"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Leyfa aðgang í eitt skipti"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ekki leyfa"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Annálar tækisins skrá það sem gerist í tækinu. Forrit geta notað þessa annála til að finna og lagfæra vandamál.\n\nTilteknir annálar innihalda viðkvæmar upplýsingar og því skaltu einungis veita forritum sem þú treystir aðgang að öllum annálum tækisins. \n\nEf þú veitir þessu forriti ekki aðgang að öllum annálum tækisins hefur það áfram aðgang að eigin annálum. Framleiðandi tækisins getur þó hugsanlega opnað tiltekna annála eða upplýsingar í tækinu."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Opna <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Forritið er uppsett"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Að minnsta kosti einu korti var bætt við Veski"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Vinnureglur gera þér aðeins kleift að hringja símtöl úr vinnusniði"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skipta yfir í vinnusnið"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Loka"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Stillingar fyrir lásskjá"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index ced316f..f2ffd7e 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Limite inferiore, <xliff:g id="PERCENT">%1$d</xliff:g> percento"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite sinistro, <xliff:g id="PERCENT">%1$d</xliff:g> percento"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite destro, <xliff:g id="PERCENT">%1$d</xliff:g> percento"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Gli screenshot acquisiti nel profilo di lavoro sono salvati nell\'app <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Salvato nell\'app <xliff:g id="APP">%1$s</xliff:g> nel profilo di lavoro"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"File"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ha rilevato questo screenshot."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e altre app aperte hanno rilevato questo screenshot."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Registrazione dello schermo"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Elaboraz. registraz. schermo"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Volto riconosciuto. Premi l\'icona Sblocca per aprire."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Sbloccato con il volto"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Volto riconosciuto"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Sposta a sinistra"</item>
-    <item msgid="5558598599408514296">"Sposta giù"</item>
-    <item msgid="4844142668312841831">"Sposta a destra"</item>
-    <item msgid="5640521437931460125">"Sposta su"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Scorri verso l\'alto per riprovare"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Sblocca per usare NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Questo dispositivo appartiene alla tua organizzazione"</string>
@@ -884,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Apri <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Riproduci <xliff:g id="SONG_NAME">%1$s</xliff:g> di <xliff:g id="ARTIST_NAME">%2$s</xliff:g> da <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Riproduci <xliff:g id="SONG_NAME">%1$s</xliff:g> da <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Per te"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Annulla"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Avvicinati per riprodurre su <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Per riprodurre qui i contenuti, avvicinati a <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -916,7 +915,6 @@
     <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">"Speaker e display"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivi consigliati"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Occorre un account premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Come funziona la trasmissione"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Annuncio"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Le persone vicine a te che hanno dispositivi Bluetooth compatibili possono ascoltare i contenuti multimediali che stai trasmettendo"</string>
@@ -1028,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"La fotocamera è disattivata"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Il microfono è disattivato"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotocamera e microfono non attivi"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"L\'assistente è in ascolto"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifica}many{# notifiche}other{# notifiche}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Aggiunta di note"</string>
@@ -1043,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Consenti accesso una tantum"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Non consentire"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"I log del dispositivo registrano tutto ciò che succede sul tuo dispositivo. Le app possono usare questi log per individuare problemi e correggerli.\n\nAlcuni log potrebbero contenere informazioni sensibili, quindi concedi l\'accesso a tutti i log del dispositivo soltanto alle app attendibili. \n\nSe le neghi l\'accesso a tutti i log del dispositivo, questa app può comunque accedere ai propri log. Il produttore del tuo dispositivo potrebbe essere comunque in grado di accedere ad alcuni log o informazioni sul dispositivo."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Scopri di più"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Scopri di più all\'indirizzo <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Apri <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• L\'app sia configurata"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Sia stata aggiunta almeno una carta a Wallet"</string>
@@ -1053,9 +1054,9 @@
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annulla"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Gira ora"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Apri il telefono per un selfie migliore"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Girare su display frontale per un selfie migliore?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Passare al display frontale per un selfie migliore?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilizza la fotocamera posteriore per una foto più ampia con maggiore risoluzione."</string>
-    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Questo schermo verrà disattivato"</b></string>
+    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Questo schermo verrà spento"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pieghevole che viene aperto"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pieghevole che viene capovolto"</string>
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteria rimanente"</string>
@@ -1066,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Le norme di lavoro ti consentono di fare telefonate soltanto dal profilo di lavoro"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passa a profilo di lavoro"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Chiudi"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Impostazioni schermata di blocco"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index dba7c4e..f04cf4d 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"<xliff:g id="PERCENT">%1$d</xliff:g> אחוז מהשוליים התחתונים"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> אחוז מהשוליים השמאליים"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> אחוז מהשוליים הימניים"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"צילומי מסך בפרופיל העבודה נשמרים באפליקציה <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"קבצים"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"מקליט המסך"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"מתבצע עיבוד של הקלטת מסך"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"הפנים זוהו. יש ללחוץ על סמל ביטול הנעילה כדי לפתוח."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"הנעילה בוטלה באמצעות זיהוי הפנים"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"הפנים זוהו"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"הזזה שמאלה"</item>
-    <item msgid="5558598599408514296">"הזזה למטה"</item>
-    <item msgid="4844142668312841831">"הזזה ימינה"</item>
-    <item msgid="5640521437931460125">"הזזה למעלה"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"יש להחליק למעלה כדי לנסות שוב"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏יש לבטל את הנעילה כדי להשתמש ב-NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"המכשיר הזה שייך לארגון שלך"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"יש לבחור אפליקציה כדי להוסיף פקדים"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{נוסף אמצעי בקרה אחד (#).}one{נוספו # אמצעי בקרה.}two{נוספו # אמצעי בקרה.}other{נוספו # אמצעי בקרה.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"הוסר"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"להוסיף את <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"כשמוסיפים את האפליקציה <xliff:g id="APPNAME">%s</xliff:g>, היא תוכל להוסיף אמצעי בקרה ותוכן לחלונית הזו. חלק מהאפליקציות מאפשרות לבחור אילו אמצעי בקרה יוצגו כאן."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"סומן כמועדף"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"סומן כמועדף, במיקום <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"הוסר מהמועדפים"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"פתיחה של <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"הפעלת <xliff:g id="SONG_NAME">%1$s</xliff:g> של <xliff:g id="ARTIST_NAME">%2$s</xliff:g> מ-<xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"הפעלת <xliff:g id="SONG_NAME">%1$s</xliff:g> מ-<xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"בשבילך"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"ביטול"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"צריך להתקרב כדי להפעיל מדיה במכשיר <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"כדי להפעיל במכשיר הזה, יש להתקרב אל <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"שגיאה, יש לנסות שוב"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"הוספת פקדים"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"עריכת פקדים"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"הוספת אפליקציה"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"הוספת מכשירי פלט"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"קבוצה"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"נבחר מכשיר אחד"</string>
@@ -919,7 +918,6 @@
     <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">"רמקולים ומסכים"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"הצעות למכשירים"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"נדרש חשבון פרימיום"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"הסבר על שידורים"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"שידור"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"‏אנשים בקרבת מקום עם מכשירי Bluetooth תואמים יכולים להאזין למדיה שמשודרת על ידך"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"המצלמה כבויה"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"המיקרופון כבוי"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"המצלמה והמיקרופון כבויים"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{התראה אחת}one{# התראות}two{# התראות}other{# התראות}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"כתיבת הערות"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"הרשאת גישה חד-פעמית"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"אין אישור"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"ביומני המכשיר מתועדת הפעילות במכשיר. האפליקציות יכולות להשתמש ביומנים האלה כדי למצוא בעיות ולפתור אותן.\n\nהמידע בחלק מהיומנים יכול להיות רגיש, לכן יש לתת הרשאת גישה לכל היומנים של המכשיר רק לאפליקציות שסומכים עליהן. \n\nגם אם האפליקציה הזו לא תקבל הרשאת גישה לכל יומני המכשיר, היא תוכל לגשת ליומנים שלה. יכול להיות שליצרן המכשיר עדיין תהיה גישה לחלק מהיומנים או למידע במכשיר שלך."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"פתיחת <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• האפליקציה מוגדרת"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"‏• לפחות כרטיס אחד נוסף ל-Wallet"</string>
@@ -1054,7 +1058,7 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• יש לפחות מכשיר אחד זמין"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"מקש קיצור ללחיצה ארוכה"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ביטול"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"הפכת את המכשיר"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"אני רוצה להפוך"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"כדי לצלם תמונת סלפי טובה יותר, פותחים את הטלפון"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"להפוך למסך הקדמי כדי לצלם תמונת סלפי טובה יותר?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"במצלמה האחורית אפשר לצלם תמונה רחבה יותר ברזולוציה גבוהה יותר."</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"המדיניות של מקום העבודה מאפשרת לך לבצע שיחות טלפון רק מפרופיל העבודה"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"מעבר לפרופיל עבודה"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"סגירה"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"הגדרות מסך הנעילה"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index f88eb8b..680490d 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -91,8 +91,11 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"下部の境界線 <xliff:g id="PERCENT">%1$d</xliff:g> パーセント"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左の境界線 <xliff:g id="PERCENT">%1$d</xliff:g> パーセント"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右の境界線 <xliff:g id="PERCENT">%1$d</xliff:g> パーセント"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"仕事用のスクリーンショットは <xliff:g id="APP">%1$s</xliff:g> アプリに保存されます"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"仕事用プロファイルで <xliff:g id="APP">%1$s</xliff:g> に保存しました"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ファイル"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> がこのスクリーンショットを検出しました。"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> とその他の開いているアプリがこのスクリーンショットを検出しました。"</string>
+    <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"メモに追加"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"スクリーン レコーダー"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"画面の録画を処理しています"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"画面の録画セッション中の通知"</string>
@@ -339,12 +342,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"顔を認識しました。ロック解除アイコンを押して開きます。"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"顔でロック解除しました"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"顔を認識しました"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"左に移動"</item>
-    <item msgid="5558598599408514296">"下に移動"</item>
-    <item msgid="4844142668312841831">"右に移動"</item>
-    <item msgid="5640521437931460125">"上に移動"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"上にスワイプしてもう一度お試しください"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC を使用するには、ロックを解除してください"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"これは組織が所有するデバイスです"</string>
@@ -458,7 +455,7 @@
     <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"字幕のオーバーレイ"</string>
     <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"有効にする"</string>
     <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"無効にする"</string>
-    <string name="sound_settings" msgid="8874581353127418308">"サウンドとバイブレーション"</string>
+    <string name="sound_settings" msgid="8874581353127418308">"音とバイブレーション"</string>
     <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string>
     <string name="screen_pinning_title" msgid="9058007390337841305">"アプリは固定されています"</string>
     <string name="screen_pinning_description" msgid="8699395373875667743">"固定を解除するまで画面が常に表示されるようになります。[戻る] と [最近] を同時に押し続けると固定が解除されます。"</string>
@@ -884,6 +881,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> を開く"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g>(アーティスト名: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>)を <xliff:g id="APP_LABEL">%3$s</xliff:g> で再生"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> を <xliff:g id="APP_LABEL">%2$s</xliff:g> で再生"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"おすすめ"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"元に戻す"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>で再生するにはもっと近づけてください"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"このデバイスで再生するには、<xliff:g id="DEVICENAME">%1$s</xliff:g> にもっと近づけてください"</string>
@@ -916,7 +914,6 @@
     <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">"スピーカーとディスプレイ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"デバイスの候補"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"プレミアム アカウントが必要です"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ブロードキャストの仕組み"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ブロードキャスト"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Bluetooth 対応デバイスを持っている付近のユーザーは、あなたがブロードキャストしているメディアを聴けます"</string>
@@ -1028,6 +1025,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"カメラは OFF です"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"マイクは OFF です"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"カメラとマイクが OFF です"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"アシスタントが音声認識中です"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 件の通知}other{# 件の通知}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>、<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"メモ"</string>
@@ -1043,6 +1041,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"1 回限りのアクセスを許可"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"許可しない"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"デバイスのログに、このデバイスで発生したことが記録されます。アプリは問題を検出、修正するためにこれらのログを使用することができます。\n\nログによっては機密性の高い情報が含まれている可能性があるため、すべてのデバイスログへのアクセスは信頼できるアプリにのみ許可してください。\n\nすべてのデバイスログへのアクセスを許可しなかった場合も、このアプリはアプリ独自のログにアクセスできます。また、デバイスのメーカーもデバイスの一部のログや情報にアクセスできる可能性があります。"</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"詳細"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"詳しくは、<xliff:g id="URL">%s</xliff:g> をご覧ください"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> を開く"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• アプリが設定されている"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ウォーレットに追加されているカードが 1 枚以上ある"</string>
@@ -1051,7 +1051,7 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 利用できるデバイスが 1 台以上ある"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ショートカットの長押しが必要です"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"キャンセル"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"切り替えましょう"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"切り替える"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"高画質で撮るにはスマートフォンを開いてください"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"前面ディスプレイに切り替えて綺麗に撮りましょう"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"高解像度で広い範囲を撮影するには、背面カメラを使用してください。"</string>
@@ -1066,6 +1066,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"仕事用ポリシーでは、通話の発信を仕事用プロファイルからのみに制限できます"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"仕事用プロファイルに切り替える"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"閉じる"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"ロック画面の設定"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index dd4f03dc..01c5be9 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ქვედა ზღვარი: <xliff:g id="PERCENT">%1$d</xliff:g> პროცენტი"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"მარცხენა ზღვარი: <xliff:g id="PERCENT">%1$d</xliff:g> პროცენტი"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"მარჯვენა ზღვარი: <xliff:g id="PERCENT">%1$d</xliff:g> პროცენტი"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"სამუშაო ეკრანის ანაბეჭდები ინახება <xliff:g id="APP">%1$s</xliff:g> აპში"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"შენახულია <xliff:g id="APP">%1$s</xliff:g>-ში სამსახურის პროფილში"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ფაილები"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>-მა აღმოაჩინა ეკრანის ეს ანაბეჭდი"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>-მა და სხვა გახსნილმა აპებმა აღმოაჩინეს ეკრანის ეს ანაბეჭდი."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"ეკრანის ჩამწერი"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ეკრანის ჩანაწერი მუშავდება"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"უწყვეტი შეტყობინება ეკრანის ჩაწერის სესიისთვის"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ამოცნობილია სახით. გასახსნელად დააჭირეთ განბლოკვის ხატულას."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"განიბლოკა სახით"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"სახე ამოცნობილია"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"მარცხნივ გადატანა"</item>
-    <item msgid="5558598599408514296">"ქვემოთ გადატანა"</item>
-    <item msgid="4844142668312841831">"მარჯვნივ გადატანა"</item>
-    <item msgid="5640521437931460125">"ზემოთ გადატანა"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"ხელახლა საცდელად გადაფურცლეთ ზემოთ"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"განბლოკეთ NFC-ის გამოსაყენებლად"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"აირჩიეთ აპი მართვის საშუალებების დასამატებლად"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{დაემატა მართვის # საშუალება.}other{დაემატა მართვის # საშუალება.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ამოიშალა"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"გსურთ <xliff:g id="APPNAME">%s</xliff:g>-ის დამატება?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"როდესაც <xliff:g id="APPNAME">%s</xliff:g>-ს ამატებთ, მან შეიძლება დაამატოს მართვის საშუალებები და კონტენტი მოცემულ არეში. ზოგიერთ აპში შეგიძლიათ აირჩიოთ, რომელი მართვის საშუალებები უნდა გამოჩნდეს აქ."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"რჩეულებშია"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"რჩეულებშია, პოზიციაზე <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"რჩეულებიდან ამოღებულია"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"გახსენით <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"დაუკარით <xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, <xliff:g id="APP_LABEL">%3$s</xliff:g>-დან"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"დაუკარით <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%2$s</xliff:g>-დან"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"თქვენთვის"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"მოქმედ.გაუქმება"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"მიიტანეთ უფრო ახლოს, რომ დაუკრათ <xliff:g id="DEVICENAME">%1$s</xliff:g>-ზე"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"აქ სათამაშოდ, მიუახლოვდით <xliff:g id="DEVICENAME">%1$s</xliff:g>-ს"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"შეცდომა, ისევ ცადეთ"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"მართვის საშუალებების დამატება"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"მართვის საშუალებათა რედაქტირება"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"აპის დამატება"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"მედია-გამოსავლების დამატება"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ჯგუფი"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"არჩეულია 1 მოწყობილობა"</string>
@@ -919,7 +915,6 @@
     <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">"დინამიკები და დისპლეები"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"შემოთავაზებული მოწყობილობები"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"საჭიროა პრემიუმ-ანგარიში"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ტრანსლირების მუშაობის პრინციპი"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ტრანსლაცია"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"თქვენთან ახლოს მყოფ ხალხს თავსებადი Bluetooth მოწყობილობით შეუძლიათ თქვენ მიერ ტრანსლირებული მედიის მოსმენა"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"კამერა გამორთულია"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"მიკროფონი გამორთულია"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"კამერა და მიკროფონი გამორთულია"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# შეტყობინება}other{# შეტყობინება}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"შენიშვნების ჩაწერა"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"ერთჯერადი წვდომის დაშვება"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"არ დაიშვას"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"მოწყობილობის ჟურნალში იწერება, რა ხდება ამ მოწყობილობაზე. აპებს შეუძლია ამ ჟურნალების გამოყენება პრობლემების აღმოსაჩენად და მოსაგვარებლად.\n\nზოგი ჟურნალი შეიძლება სენსიტიური ინფორმაციის მატარებელი იყოს, ამიტომაც მოწყობილობის ყველა ჟურნალზე წვდომა მხოლოდ სანდო აპებს მიანიჭეთ. \n\nთუ ამ აპს მოწყობილობის ყველა ჟურნალზე წვდომას არ მიანიჭებთ, მას მაინც ექნება წვდომა თქვენს ჟურნალებზე. თქვენი მოწყობილობის მწარმოებელს მაინც შეეძლება თქვენი მოწყობილობის ზოგიერთ ჟურნალსა თუ ინფორმაციაზე წვდომა."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> აპის გახსნა"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• აპი დაყენებულია"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• საფულეში დამატებულია მინიმუმ ერთი ბარათი"</string>
@@ -1054,9 +1055,9 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ხელმისაწვდომია მინიმუმ ერთი მოწყობილობა"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"შეხების დაamp; მოცდის მალსახმობი"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"გაუქმება"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"გადაატრიალეთ ახლა"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ახლა გადატრიალება"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"გაშალეთ ტელეფონი უკეთესი სელფისთვის"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"გადააბრუნეთ წინა ეკრანზე უკეთესი სელფის მისაღებად?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"გამოვიყენოთ წინა ეკრანი უკეთესი სელფის მისაღებად?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"გამოიყენეთ უკანა კამერა უფრო ფართო ფოტოს გადასაღებად მაღალი გარჩევადობით."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ეს ეკრანი გამოირთვება"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"დასაკეცი მოწყობილობა იხსნება"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"თქვენი სამსახურის წესები საშუალებას გაძლევთ, სატელეფონო ზარები განახორციელოთ მხოლოდ სამსახურის პროფილიდან"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"სამსახურის პროფილზე გადართვა"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"დახურვა"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"ჩაკეტილი ეკრანის პარამეტრები"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index f4575f0..0229d5c 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Төменгі шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Сол жақ шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Оң жақ шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Жұмыс профилінен алынған скриншоттар <xliff:g id="APP">%1$s</xliff:g> қолданбасында сақталады."</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Жұмыс профиліндегі <xliff:g id="APP">%1$s</xliff:g> қолданбасында сақталған."</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> қолданбасы осы скриншотты анықтады."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> және басқа да ашық қолданбалар осы скриншотты анықтады."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Экран жазғыш"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экран жазғыш бейнесін өңдеу"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Бет танылды. Ашу үшін құлыпты ашу белгішесін басыңыз."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Бетпен ашылды."</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Бет танылды."</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Солға жылжыту"</item>
-    <item msgid="5558598599408514296">"Төмен жылжыту"</item>
-    <item msgid="4844142668312841831">"Оңға жылжыту"</item>
-    <item msgid="5640521437931460125">"Жоғары жылжыту"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Әрекетті қайталау үшін жоғары сырғытыңыз."</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC пайдалану үшін құлыпты ашыңыз."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Бұл құрылғы ұйымыңызға тиесілі."</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Басқару элементтері қосылатын қолданбаны таңдаңыз"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# басқару элементі қосылды.}other{# басқару элементі қосылды.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Өшірілді"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> қолданбасын қосу керек пе?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> қолданбасын қосқан кезде, басқару элементтері мен контент осы панельге енгізіледі. Кейбір қолданбада басқару элементтерінің қайсысы осы жерде көрсетілетінін таңдай аласыз."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Таңдаулыларға қосылды"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Таңдаулыларға қосылды, <xliff:g id="NUMBER">%d</xliff:g>-позиция"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Таңдаулылардан алып тасталды"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> қолданбасын ашу"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> қолданбасында <xliff:g id="ARTIST_NAME">%2$s</xliff:g> орындайтын \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" әнін ойнату"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> қолданбасында \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" әнін ойнату"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Сіз үшін"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Қайтару"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> құрылғысында музыка ойнату үшін оған жақындаңыз."</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Осы жерде ойнату үшін <xliff:g id="DEVICENAME">%1$s</xliff:g> құрылғысына жақындаңыз."</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Қате шықты. Қайталап көріңіз."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Басқару элементтерін қосу"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Басқару элементтерін өзгерту"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Қолданба қосу"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Шығыс сигналдарды қосу"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 құрылғы таңдалды."</string>
@@ -919,7 +915,6 @@
     <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">"Динамиктер мен дисплейлер"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Ұсынылған құрылғылар"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Премиум аккаунт қажет"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Тарату қалай жүзеге асады"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Тарату"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Үйлесімді Bluetooth құрылғылары бар маңайдағы адамдар сіз таратып жатқан медиамазмұнды тыңдай алады."</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Камера өшірулі."</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Микрофон өшірулі."</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера мен микрофон өшірулі"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# хабарландыру}other{# хабарландыру}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Ескертпе жазу"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Бір рет рұқсат беру"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Рұқсат бермеу"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Журналдарға құрылғыда не болып жатқаны жазылады. Қолданбалар бұл журналдарды қате тауып, түзету үшін пайдаланады.\n\nКейбір журналдарда құпия ақпарат болуы мүмкін. Сондықтан құрылғының барлық журналын пайдалану рұқсаты тек сенімді қолданбаларға берілуі керек. \n\nБұл қолданбаға құрылғының барлық журналын пайдалануға рұқсат бермесеңіз де, ол өзінің журналдарын пайдалана береді. Құрылғы өндірушісі де құрылғыдағы кейбір журналдарды немесе ақпаратты пайдалануы мүмкін."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ашу"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Қолданба реттелген"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet-ке кемінде бір карта қосылған"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Жұмыс саясатыңызға сәйкес тек жұмыс профилінен қоңырау шалуға болады."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Жұмыс профиліне ауысу"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Жабу"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Экран құлпының параметрлері"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index d5e31aa..6ac7238 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"បន្ទាត់បែងចែក​ខាងក្រោម <xliff:g id="PERCENT">%1$d</xliff:g> ភាគរយ"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"បន្ទាត់បែងចែក​ខាងឆ្វេង <xliff:g id="PERCENT">%1$d</xliff:g> ភាគរយ"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"បន្ទាត់បែងចែក​ខាងស្ដាំ <xliff:g id="PERCENT">%1$d</xliff:g> ភាគរយ"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"រូបថតអេក្រង់​ក្នុងកម្រងព័ត៌មានការងារ​ត្រូវបានរក្សាទុកនៅក្នុងកម្មវិធី <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ឯកសារ"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"មុខងារថត​វីដេអូអេក្រង់"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"កំពុង​ដំណើរការ​ការថតអេក្រង់"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ការជូនដំណឹង​ដែល​កំពុង​ដំណើរការ​សម្រាប់​រយៈពេលប្រើ​ការថត​សកម្មភាព​អេក្រង់"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"បានស្គាល់មុខ។ សូមចុចរូបដោះសោ ដើម្បីបើក។"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"បានដោះសោដោយប្រើមុខ"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"បានស្គាល់មុខ"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ផ្លាស់ទី​ទៅ​ឆ្វេង"</item>
-    <item msgid="5558598599408514296">"ផ្លាស់ទី​ចុះ​ក្រោម"</item>
-    <item msgid="4844142668312841831">"ផ្លាស់ទីទៅ​ស្តាំ"</item>
-    <item msgid="5640521437931460125">"ផ្លាស់ទី​ឡើង​លើ"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"អូសឡើងលើ ដើម្បី​ព្យាយាម​ម្ដងទៀត"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ដោះសោ ដើម្បីប្រើ NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ឧបករណ៍​នេះគឺជា​កម្មសិទ្ធិរបស់​ស្ថាប័ន​អ្នក"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"ជ្រើសរើស​កម្មវិធីដែលត្រូវបញ្ចូល​ផ្ទាំងគ្រប់គ្រង"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{បានបញ្ចូល​ការគ្រប់គ្រង #។}other{បានបញ្ចូល​ការគ្រប់គ្រង #។}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"បានដកចេញ"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"បញ្ចូល <xliff:g id="APPNAME">%s</xliff:g> ឬ?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"នៅពេលអ្នកបញ្ចូល <xliff:g id="APPNAME">%s</xliff:g> កម្មវិធីនេះអាចបញ្ចូលការគ្រប់គ្រង និងខ្លឹមសារទៅផ្ទាំងនេះបាន។ ក្នុងកម្មវិធីមួយចំនួន អ្នកអាចជ្រើសរើសឱ្យការគ្រប់គ្រងណាខ្លះបង្ហាញនៅទីនេះបាន។"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"បានដាក់ជា​សំណព្វ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"បានដាក់ជា​សំណព្វ ទីតាំង​ទី <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"បានដកចេញ​ពី​សំណព្វ"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"បើក <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"ចាក់ <xliff:g id="SONG_NAME">%1$s</xliff:g> ច្រៀងដោយ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ពី <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"ចាក់ <xliff:g id="SONG_NAME">%1$s</xliff:g> ពី <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"សម្រាប់អ្នក"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"ត្រឡប់វិញ"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"រំកិលឱ្យកាន់តែជិត ដើម្បីចាក់នៅលើ <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ដើម្បីចាក់នៅទីនេះ សូមខិតទៅជិត <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"មានបញ្ហា សូម​ព្យាយាម​ម្តងទៀត"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"បញ្ចូល​ផ្ទាំងគ្រប់គ្រង"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"កែ​ផ្ទាំងគ្រប់គ្រង"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"បញ្ចូល​កម្មវិធី"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"បញ្ចូល​ឧបករណ៍​មេឌៀ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ក្រុម"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"បានជ្រើសរើស​ឧបករណ៍ 1"</string>
@@ -919,7 +918,6 @@
     <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">"ឧបករណ៍បំពងសំឡេង និងផ្ទាំងអេក្រង់"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"ឧបករណ៍​ដែលបានណែនាំ"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"ត្រូវការគណនីលំដាប់ខ្ពស់"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"របៀបដែលការផ្សាយដំណើរការ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ការ​ផ្សាយ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"មនុស្សនៅជិត​អ្នកដែលមាន​ឧបករណ៍ប៊្លូធូស​ត្រូវគ្នា​អាចស្តាប់​មេឌៀ​ដែលអ្នកកំពុងផ្សាយបាន"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"កាមេរ៉ា​ត្រូវបានបិទ"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"មីក្រូហ្វូន​ត្រូវ​បាន​បិទ"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"កាមេរ៉ា និង​មីក្រូហ្វូន​ត្រូវបានបិទ"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{ការ​ជូន​ដំណឹង #}other{ការ​ជូនដំណឹង #}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"ការកត់ត្រា​"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"អនុញ្ញាតឱ្យចូលប្រើ​ប្រាស់តែមួយលើក"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"មិនអនុញ្ញាត"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"កំណត់ហេតុឧបករណ៍កត់ត្រាអ្វីដែលកើតឡើងនៅលើឧបករណ៍របស់អ្នក។ កម្មវិធីអាចប្រើកំណត់ហេតុទាំងនេះ ដើម្បីស្វែងរក និងដោះស្រាយបញ្ហាបាន។\n\nកំណត់ហេតុមួយចំនួនអាចមានព័ត៌មានរសើប ដូច្នេះសូមអនុញ្ញាតឱ្យចូលប្រើកំណត់ហេតុឧបករណ៍ទាំងអស់សម្រាប់តែកម្មវិធីដែលអ្នកទុកចិត្តប៉ុណ្ណោះ។ \n\nប្រសិនបើអ្នកមិនអនុញ្ញាតឱ្យកម្មវិធីនេះចូលប្រើកំណត់ហេតុឧបករណ៍ទាំងអស់ទេ កម្មវិធីនេះនៅតែអាចចូលប្រើកំណត់ហេតុរបស់ខ្លួនផ្ទាល់បាន។ ក្រុមហ៊ុន​ផលិត​ឧបករណ៍របស់អ្នក​ប្រហែលជា​នៅតែអាចចូលប្រើ​កំណត់ហេតុ ឬព័ត៌មានមួយចំនួន​នៅលើឧបករណ៍​របស់អ្នក​បានដដែល។"</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"បើក <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• កម្មវិធីត្រូវបានរៀបចំ"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• កាតយ៉ាងតិចមួយត្រូវបានបញ្ចូលទៅក្នុង Wallet"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"គោលការណ៍ការងាររបស់អ្នកអនុញ្ញាតឱ្យអ្នកធ្វើការហៅទូរសព្ទបានតែពីកម្រងព័ត៌មានការងារប៉ុណ្ណោះ"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ប្ដូរ​ទៅ​កម្រង​ព័ត៌មាន​ការងារ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"បិទ"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"ការកំណត់​អេក្រង់ចាក់សោ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 687fa28..b8749f4 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ಕೆಳಗಿನ ಬೌಂಡರಿ ಶೇಕಡಾ <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ಎಡಭಾಗದ ಬೌಂಡರಿ ಶೇಕಡಾ <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ಬಲಭಾಗದ ಬೌಂಡರಿ ಶೇಕಡಾ <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"<xliff:g id="APP">%1$s</xliff:g> ಆ್ಯಪ್‌ನಲ್ಲಿ ಉಳಿಸಲಾದ ಕೆಲಸದ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳು"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌ನಲ್ಲಿನ <xliff:g id="APP">%1$s</xliff:g> ನಲ್ಲಿ ಉಳಿಸಲಾಗಿದೆ"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ಫೈಲ್‌ಗಳು"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"ಈ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು <xliff:g id="APPNAME">%1$s</xliff:g> ಪತ್ತೆಹಚ್ಚಿದೆ."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ಹಾಗೂ ತೆರೆದಿರುವ ಇತರ ಆ್ಯಪ್‌ಗಳು ಈ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ಪತ್ತೆಹಚ್ಚಿವೆ."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡರ್"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್‌ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಅಧಿಸೂಚನೆ"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ತೆರೆಯಲು ಅನ್‌ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ಮುಖದ ಮೂಲಕ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ಎಡಕ್ಕೆ ಸರಿಸಿ"</item>
-    <item msgid="5558598599408514296">"ಕೆಳಗೆ ಸರಿಸಿ"</item>
-    <item msgid="4844142668312841831">"ಬಲಕ್ಕೆ ಸರಿಸಿ"</item>
-    <item msgid="5640521437931460125">"ಮೇಲಕ್ಕೆ ಸರಿಸಿ"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ಬಳಸಲು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲು ಆ್ಯಪ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ನಿಯಂತ್ರಣವನ್ನು ಸೇರಿಸಲಾಗಿದೆ.}one{# ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.}other{# ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ಅನ್ನು ಸೇರಿಸಬೇಕೆ?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"ನೀವು <xliff:g id="APPNAME">%s</xliff:g> ಅನ್ನು ಸೇರಿಸಿದಾಗ, ಅದು ಈ ಪ್ಯಾನೆಲ್‌ಗೆ ನಿಯಂತ್ರಣಗಳು ಮತ್ತು ವಿಷಯವನ್ನು ಸೇರಿಸಬಹುದು. ಕೆಲವು ಆ್ಯಪ್‌ಗಳಲ್ಲಿ, ಇಲ್ಲಿ ಯಾವ ನಿಯಂತ್ರಣಗಳು ಕಾಣಿಸಬೇಕು ಎಂಬುದನ್ನು ನೀವು ಆಯ್ಕೆಮಾಡಬಹುದು."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ಮೆಚ್ಚಲಾಗಿರುವುದು"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ಮೆಚ್ಚಲಾಗಿರುವುದು, ಸ್ಥಾನ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ಮೆಚ್ಚಿನದಲ್ಲದ್ದು"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ಅವರ <xliff:g id="SONG_NAME">%1$s</xliff:g> ಹಾಡನ್ನು <xliff:g id="APP_LABEL">%3$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ಹಾಡನ್ನು <xliff:g id="APP_LABEL">%2$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"ನಿಮಗಾಗಿ"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"ರದ್ದುಗೊಳಿಸಿ"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಅದರ ಹತ್ತಿರಕ್ಕೆ ಸರಿಯಿರಿ"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ಇಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು, <xliff:g id="DEVICENAME">%1$s</xliff:g> ಸಮೀಪಕ್ಕೆ ಸರಿಯಿರಿ"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"ದೋಷ, ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಿ"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ನಿಯಂತ್ರಣಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ಆ್ಯಪ್ ಅನ್ನು ಸೇರಿಸಿ"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ಔಟ್‌ಪುಟ್‌ಗಳನ್ನು ಸೇರಿಸಿ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ಗುಂಪು"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ಸಾಧನವನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
@@ -919,7 +915,6 @@
     <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">"ಸ್ಪೀಕರ್‌ಗಳು ಮತ್ತು ಡಿಸ್‌ಪ್ಲೇಗಳು"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"ಸೂಚಿಸಿದ ಸಾಧನಗಳು"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"ಪ್ರೀಮಿಯಂ ಖಾತೆಯ ಅಗತ್ಯವಿದೆ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ಪ್ರಸಾರವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ಪ್ರಸಾರ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ಹೊಂದಾಣಿಕೆಯಾಗುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಹೊಂದಿರುವ ಸಮೀಪದಲ್ಲಿರುವ ಜನರು ನೀವು ಪ್ರಸಾರ ಮಾಡುತ್ತಿರುವ ಮಾಧ್ಯಮವನ್ನು ಆಲಿಸಬಹುದು"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"ಕ್ಯಾಮರಾ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"ಮೈಕ್ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ ಆಫ್ ಆಗಿದೆ"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ಅಧಿಸೂಚನೆ}one{# ಅಧಿಸೂಚನೆಗಳು}other{# ಅಧಿಸೂಚನೆಗಳು}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"ಟಿಪ್ಪಣಿಗಳನ್ನು ಬರೆದುಕೊಳ್ಳುವುದು"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"ಒಂದು ಬಾರಿಯ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"ಅನುಮತಿಸಬೇಡಿ"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಸಾಧನದ ಲಾಗ್‌ಗಳು ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತವೆ. ಸಮಸ್ಯೆಗಳನ್ನು ಪತ್ತೆಹಚ್ಚಲು ಮತ್ತು ಪರಿಹರಿಸಲು ಆ್ಯಪ್‌ಗಳು ಈ ಲಾಗ್ ಅನ್ನು ಬಳಸಬಹುದು.\n\nಕೆಲವು ಲಾಗ್‌ಗಳು ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಿರಬಹುದು, ಆದ್ದರಿಂದ ನಿಮ್ಮ ವಿಶ್ವಾಸಾರ್ಹ ಆ್ಯಪ್‌ಗಳಿಗೆ ಮಾತ್ರ ಸಾಧನದ ಎಲ್ಲಾ ಲಾಗ್‌ಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸಿ. \n\nಎಲ್ಲಾ ಸಾಧನ ಲಾಗ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ನೀವು ಈ ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸದಿದ್ದರೆ, ಅದು ಆಗಲೂ ತನ್ನದೇ ಆದ ಲಾಗ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ನಿಮ್ಮ ಸಾಧನ ತಯಾರಕರಿಗೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಕೆಲವು ಲಾಗ್‌ಗಳು ಅಥವಾ ಮಾಹಿತಿಯನ್ನು ಪ್ರವೇಶಿಸಲು ಈಗಲೂ ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ಆ್ಯಪ್ ಅನ್ನು ಸೆಟಪ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ವಾಲೆಟ್‌ಗೆ ಕನಿಷ್ಠ ಒಂದು ಕಾರ್ಡ್ ಅನ್ನು ಸೇರಿಸಲಾಗಿದೆ"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"ನಿಮ್ಮ ಕೆಲಸದ ನೀತಿಯು ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ನಿಂದ ಮಾತ್ರ ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ಗೆ ಬದಲಿಸಿ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ಮುಚ್ಚಿರಿ"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3631973..0b448e4 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"하단 가장자리 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"왼쪽 가장자리 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"오른쪽 가장자리 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"직장 프로필의 스크린샷은 <xliff:g id="APP">%1$s</xliff:g> 앱에 저장됩니다."</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"직장 프로필의 <xliff:g id="APP">%1$s</xliff:g>에 저장되었습니다."</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"파일"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>에서 이 스크린샷을 감지했습니다."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 및 기타 공개 앱에서 이 스크린샷을 감지했습니다."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"화면 녹화"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"화면 녹화 처리 중"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"얼굴이 인식되었습니다. 열려면 잠금 해제 아이콘을 누르세요."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"얼굴 인식으로 잠금 해제되었습니다."</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"얼굴이 인식되었습니다."</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"왼쪽으로 이동"</item>
-    <item msgid="5558598599408514296">"아래로 이동"</item>
-    <item msgid="4844142668312841831">"오른쪽으로 이동"</item>
-    <item msgid="5640521437931460125">"위로 이동"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"위로 스와이프하여 다시 시도해 주세요"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"잠금 해제하여 NFC 사용"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"내 조직에 속한 기기입니다."</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"컨트롤을 추가할 앱을 선택하세요"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{설정이 #개 추가되었습니다.}other{설정이 #개 추가되었습니다.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"삭제됨"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>을(를) 추가할까요?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> 앱을 추가하면 이 패널에 컨트롤과 콘텐츠가 추가됩니다. 일부 앱에서는 여기 표시되는 컨트롤을 선택할 수 있습니다."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"즐겨찾기에 추가됨"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"즐겨찾기에 추가됨, 위치 <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"즐겨찾기에서 삭제됨"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> 열기"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g>에서 <xliff:g id="ARTIST_NAME">%2$s</xliff:g>의 <xliff:g id="SONG_NAME">%1$s</xliff:g> 재생"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g>에서 <xliff:g id="SONG_NAME">%1$s</xliff:g> 재생"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"추천"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"실행취소"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>에서 재생하려면 기기를 더 가까이로 옮기세요."</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"여기에서 재생하려면 <xliff:g id="DEVICENAME">%1$s</xliff:g>에 더 가까이 이동하세요."</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"오류. 다시 시도하세요."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"컨트롤 추가"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"컨트롤 수정"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"앱 추가"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"출력 추가"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"그룹"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"기기 1대 선택됨"</string>
@@ -919,7 +915,6 @@
     <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">"스피커 및 디스플레이"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"추천 기기"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"프리미엄 계정 필요"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"브로드캐스팅 작동 원리"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"브로드캐스트"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"호환되는 블루투스 기기를 가진 근처의 사용자가 내가 브로드캐스트 중인 미디어를 수신 대기할 수 있습니다."</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"카메라 꺼짐"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"마이크 꺼짐"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"카메라 및 마이크가 사용 중지되었습니다."</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{알림 #개}other{알림 #개}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"메모"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"일회성 액세스 허용"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"허용 안함"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"기기 로그에 기기에서 발생한 상황이 기록됩니다. 앱은 문제를 찾고 해결하는 데 이 로그를 사용할 수 있습니다.\n\n일부 로그는 민감한 정보를 포함할 수 있으므로 신뢰할 수 있는 앱만 모든 기기 로그에 액세스하도록 허용하세요. \n\n앱에 전체 기기 로그에 대한 액세스 권한을 부여하지 않아도 앱이 자체 로그에는 액세스할 수 있습니다. 기기 제조업체에서 일부 로그 또는 기기 내 정보에 액세스할 수도 있습니다."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> 열기"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• 앱이 설정되어 있습니다."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• 1개 이상의 카드가 월렛에 추가되어 있습니다."</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"직장 정책이 직장 프로필에서만 전화를 걸도록 허용합니다."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"직장 프로필로 전환"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"닫기"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"잠금 화면 설정"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index f5b4a26..3edbbf2 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ылдый жагы <xliff:g id="PERCENT">%1$d</xliff:g> пайызга"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Сол жагы <xliff:g id="PERCENT">%1$d</xliff:g> пайызга"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Оң жагы <xliff:g id="PERCENT">%1$d</xliff:g> пайызга"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Жумуш скриншоттору <xliff:g id="APP">%1$s</xliff:g> колдонмосунда сакталат"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Жумуш профилиндеги <xliff:g id="APP">%1$s</xliff:g> колдонмосуна сакталды"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ушул скриншотту аныктады."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> жана ачылып турган башка колдонмолор ушул скриншотту аныктады."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"экрандан видео жаздырып алуу"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экрандан жаздырылып алынган видео иштетилүүдө"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды жаздыруу сеансы боюнча учурдагы билдирме"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Жүз таанылды. Эми кулпуну ачуу сүрөтчөсүн басыңыз."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Түзмөгүңүздү жүзүңүз менен ачтыңыз"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Жүз таанылды"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Солго жылдыруу"</item>
-    <item msgid="5558598599408514296">"Төмөн жылдыруу"</item>
-    <item msgid="4844142668312841831">"Оңго жылдыруу"</item>
-    <item msgid="5640521437931460125">"Жогору жылдыруу"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Кайталоо үчүн экранды өйдө сүрүңүз"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC колдонуу үчүн түзмөктүн кулпусун ачыңыз"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Бул түзмөк уюмуңузга таандык"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Башкаруу элементтери кошула турган колдонмону тандоо"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# көзөмөл кошулду.}other{# көзөмөл кошулду.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Өчүрүлдү"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> кошулсунбу?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> колдонмосун кошсоңуз, ал бул панелге башкаруу элементтерин жана контентти кошо алат. Айрым колдонмолордо бул жерде көрүнүүчү башкаруу элементтерин тандай аласыз."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Сүйүктүүлөргө кошулду"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Сүйүктүүлөргө <xliff:g id="NUMBER">%d</xliff:g>-позицияга кошулду"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Сүйүктүүлөрдөн чыгарылды"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> колдонмосун ачуу"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ырын (аткаруучу: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) <xliff:g id="APP_LABEL">%3$s</xliff:g> колдонмосунан ойнотуу"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ырын <xliff:g id="APP_LABEL">%2$s</xliff:g> колдонмосунан ойнотуу"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Сизге"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Кайтаруу"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> түзмөгүндө ойнотуу үчүн жакындатыңыз"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Ушул жерде ойнотуу үчүн <xliff:g id="DEVICENAME">%1$s</xliff:g> түзмөгүнө жакындаңыз"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Ката, кайталап көрүңүз"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Башкаруу элементтерин кошуу"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Башкаруу элементтерин түзөтүү"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Колдонмо кошуу"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Медиа түзмөктөрдү кошуу"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 түзмөк тандалды"</string>
@@ -919,7 +915,6 @@
     <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">"Динамиктер жана дисплейлер"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Сунушталган түзмөктөр"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Премиум аккаунт талап кылынат"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Кабарлоо кантип иштейт"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Кабарлоо"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Шайкеш Bluetooth түзмөктөрү болгон жакын жердеги кишилер кабарлап жаткан медиаңызды уга алышат"</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Камера өчүк"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Микрофон өчүк"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера жана микрофон өчүк"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Жардамчы угуп жатат"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# билдирме}other{# билдирме}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Эскертме жазуу"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Бир жолу жеткиликтүү кылуу"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Тыюу салуу"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Түзмөктө аткарылган бардык аракеттер түзмөктүн таржымалдарында сакталып калат. Колдонмолор бул таржымалдарды колдонуп, маселелерди оңдошот.\n\nАйрым таржымалдарда купуя маалымат болушу мүмкүн, андыктан ишенимдүү колдонмолорго гана түзмөктөгү бардык таржымалдарды пайдаланууга уруксат бериңиз. \n\nЭгер бул колдонмого түзмөктөгү бардык таржымалдарга кирүүгө тыюу салсаңыз, ал өзүнүн таржымалдарын пайдалана берет. Түзмөктү өндүрүүчү түзмөгүңүздөгү айрым таржымалдарды же маалыматты көрө берет."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Кеңири маалымат"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Кеңири маалымат: <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ачуу"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Колдонмо туураланды"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Капчыкка кеминде бир карта кошулду"</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Жумуш саясатыңызга ылайык, жумуш профилинен гана чалууларды аткара аласыз"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Жумуш профилине которулуу"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Жабуу"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Кулпуланган экран параметрлери"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index fff2544..ac81dcc 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -64,4 +64,6 @@
 
     <dimen name="qs_panel_padding_top">@dimen/qqs_layout_margin_top</dimen>
     <dimen name="qs_panel_padding_top_combined_headers">@dimen/qs_panel_padding_top</dimen>
+
+    <dimen name="controls_padding_horizontal">16dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 8754166..e6edcff 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ຂອບເຂດທາງລຸ່ມ <xliff:g id="PERCENT">%1$d</xliff:g> ເປີເຊັນ"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ຂອບເຂດທາງຊ້າຍ <xliff:g id="PERCENT">%1$d</xliff:g> ເປີເຊັນ"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ຂອບເຂດທາງຂວາ <xliff:g id="PERCENT">%1$d</xliff:g> ເປີເຊັນ"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"ຮູບໜ້າຈໍວຽກຖືກບັນທຶກຢູ່ໃນແອັບ <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"ບັນທຶກໃນ <xliff:g id="APP">%1$s</xliff:g> ໃນໂປຣໄຟລ໌ບ່ອນເຮັດວຽກແລ້ວ"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ໄຟລ໌"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ກວດພົບຮູບໜ້າຈໍນີ້."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ແລະ ແອັບອື່ນໆທີ່ເປີດຢູ່ກວດພົບຮູບໜ້າຈໍນີ້."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"ໂປຣແກຣມບັນທຶກໜ້າຈໍ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ກຳລັງປະມວນຜົນການບັນທຶກໜ້າຈໍ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ການແຈ້ງເຕືອນສຳລັບເຊດຊັນການບັນທຶກໜ້າຈໍໃດໜຶ່ງ"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອເປີດ."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ປົດລັອກດ້ວຍໃບໜ້າແລ້ວ"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ຈຳແນກໜ້າໄດ້ແລ້ວ"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ຍ້າຍໄປຊ້າຍ"</item>
-    <item msgid="5558598599408514296">"ຍ້າຍລົງ"</item>
-    <item msgid="4844142668312841831">"ຍ້າຍໄປຂວາ"</item>
-    <item msgid="5640521437931460125">"ຍ້າຍຂຶ້ນ"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"ປັດຂຶ້ນເພື່ອລອງໃໝ່"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ປົດລັອກເພື່ອໃຊ້ NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"ເລືອກແອັບເພື່ອເພີ່ມການຄວບຄຸມ"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{ເພີ່ມ # ການຄວບຄຸມແລ້ວ.}other{ເພີ່ມ # ການຄວບຄຸມແລ້ວ.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ລຶບອອກແລ້ວ"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"ເພີ່ມ <xliff:g id="APPNAME">%s</xliff:g> ບໍ?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"ເມື່ອທ່ານເພີ່ມ <xliff:g id="APPNAME">%s</xliff:g>, ມັນຈະສາມາດເພີ່ມການຄວບຄຸມ ແລະ ເນື້ອຫາໃສ່ແຜງນີ້ໄດ້. ໃນບາງແອັບ, ທ່ານສາມາດເລືອກວ່າຈະໃຫ້ສ່ວນຄວບຄຸມໃດສະແດງຂຶ້ນຢູ່ບ່ອນນີ້ໄດ້."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ເພີ່ມລາຍການທີ່ມັກແລ້ວ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ເພີ່ມລາຍການທີ່ມັກແລ້ວ, ຕຳແໜ່ງ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ຍົກເລີກລາຍການທີ່ມັກແລ້ວ"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"ເປີດ <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"ຫຼິ້ນ <xliff:g id="SONG_NAME">%1$s</xliff:g> ໂດຍ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ຈາກ <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"ຫຼິ້ນ <xliff:g id="SONG_NAME">%1$s</xliff:g> ຈາກ <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"ສຳລັບທ່ານ"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"ຍົກເລີກ"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"ຍ້າຍໄປໃກ້ຂຶ້ນເພື່ອຫຼິ້ນຢູ່ <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ເພື່ອຫຼິ້ນຢູ່ບ່ອນນີ້, ໃຫ້ເຂົ້າໃກ້ <xliff:g id="DEVICENAME">%1$s</xliff:g> ຫຼາຍຂຶ້ນ"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"​ຜິດ​ພາດ​, ກະລຸນາລອງໃໝ່"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"ເພີ່ມການຄວບຄຸມ"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ແກ້ໄຂການຄວບຄຸມ"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ເພີ່ມແອັບ"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ເພີ່ມເອົ້າພຸດ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ກຸ່ມ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"ເລືອກ 1 ອຸປະກອນແລ້ວ"</string>
@@ -919,7 +915,6 @@
     <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">"ລຳໂພງ ແລະ ຈໍສະແດງຜົນ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"ອຸປະກອນທີ່ແນະນຳ"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"ຕ້ອງໃຊ້ບັນຊີພຣີມຽມ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ການອອກອາກາດເຮັດວຽກແນວໃດ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ອອກອາກາດ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ຄົນທີ່ຢູ່ໃກ້ທ່ານທີ່ມີອຸປະກອນ Bluetooth ທີ່ເຂົ້າກັນໄດ້ຈະສາມາດຟັງມີເດຍທີ່ທ່ານກຳລັງອອກອາກາດຢູ່ໄດ້"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"ກ້ອງປິດຢູ່"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"ໄມປິດຢູ່"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ປິດກ້ອງຖ່າຍຮູບ ແລະ ໄມແລ້ວ"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ການແຈ້ງເຕືອນ}other{# ການແຈ້ງເຕືອນ}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"ການຈົດບັນທຶກ"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"ອະນຸຍາດສິດເຂົ້າເຖິງແບບເທື່ອດຽວ"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"ບໍ່ອະນຸຍາດ"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"ບັນທຶກຂອງອຸປະກອນຈະບັນທຶກສິ່ງທີ່ເກີດຂຶ້ນຢູ່ອຸປະກອນຂອງທ່ານ. ແອັບສາມາດໃຊ້ບັນທຶກເຫຼົ່ານີ້ເພື່ອຊອກຫາ ແລະ ແກ້ໄຂບັນຫາໄດ້.\n\nບັນທຶກບາງຢ່າງອາດມີຂໍ້ມູນທີ່ລະອຽດອ່ອນ, ດັ່ງນັ້ນໃຫ້ອະນຸຍາດສະເພາະແອັບທີ່ທ່ານເຊື່ອຖືໄດ້ໃຫ້ເຂົ້າເຖິງບັນທຶກທັງໝົດຂອງອຸປະກອນເທົ່ານັ້ນ. \n\nຫາກທ່ານບໍ່ອະນຸຍາດໃຫ້ແອັບນີ້ເຂົ້າເຖິງບັນທຶກທັງໝົດຂອງອຸປະກອນ, ມັນຈະຍັງຄົງສາມາດເຂົ້າເຖິງບັນທຶກຂອງຕົວມັນເອງໄດ້ຢູ່. ຜູ້ຜະລິດອຸປະກອນຂອງທ່ານອາດຍັງຄົງສາມາດເຂົ້າເຖິງບັນທຶກ ຫຼື ຂໍ້ມູນບາງຢ່າງຢູ່ອຸປະກອນຂອງທ່ານໄດ້."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"ເປີດ <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ແອັບໄດ້ຮັບການຕັ້ງຄ່າແລ້ວ"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ມີການເພີ່ມຢ່າງໜ້ອຍ 1 ບັດໃສ່ໃນ Wallet"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"ນະໂຍບາຍບ່ອນເຮັດວຽກຂອງທ່ານອະນຸຍາດໃຫ້ທ່ານໂທລະສັບໄດ້ຈາກໂປຣໄຟລ໌ບ່ອນເຮັດວຽກເທົ່ານັ້ນ"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ສະຫຼັບໄປໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ປິດ"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"ການຕັ້ງຄ່າໜ້າຈໍລັອກ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d42fc7a..514e28a 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -91,8 +91,14 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Apatinė riba – <xliff:g id="PERCENT">%1$d</xliff:g> proc."</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Kairioji riba – <xliff:g id="PERCENT">%1$d</xliff:g> proc."</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Dešinioji riba – <xliff:g id="PERCENT">%1$d</xliff:g> proc."</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Ekrano kopijos, užfiksuotos naudojantis darbo profiliu, išsaugomos programoje „<xliff:g id="APP">%1$s</xliff:g>“"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Failai"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pridėti prie užrašo"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrano vaizdo įrašytuvas"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Apdorojam. ekrano vaizdo įraš."</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string>
@@ -339,12 +345,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Veidas atpažintas. Atidarykite paspaudę atrakin. piktogramą."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Atrakinta pagal veidą"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Veidas atpažintas"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Perkelti kairėn"</item>
-    <item msgid="5558598599408514296">"Perkelti žemyn"</item>
-    <item msgid="4844142668312841831">"Perkelti dešinėn"</item>
-    <item msgid="5640521437931460125">"Perkelti aukštyn"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Jei norite bandyti dar kartą, perbraukite aukštyn"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Norėdami naudoti NFC, atrakinkite"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Šis įrenginys priklauso jūsų organizacijai"</string>
@@ -884,6 +884,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Atidaryti „<xliff:g id="APP_LABEL">%1$s</xliff:g>“"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Leisti <xliff:g id="ARTIST_NAME">%2$s</xliff:g> – „<xliff:g id="SONG_NAME">%1$s</xliff:g>“ iš „<xliff:g id="APP_LABEL">%3$s</xliff:g>“"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Leisti „<xliff:g id="SONG_NAME">%1$s</xliff:g>“ iš „<xliff:g id="APP_LABEL">%2$s</xliff:g>“"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Jums"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Anuliuoti"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Prieikite arčiau, kad galėtumėte leisti įrenginyje „<xliff:g id="DEVICENAME">%1$s</xliff:g>“"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Jei norite leisti čia, eikite arčiau įrenginio „<xliff:g id="DEVICENAME">%1$s</xliff:g>“"</string>
@@ -916,7 +917,6 @@
     <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">"Garsiakalbiai ir ekranai"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Siūlomi įrenginiai"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Reikalinga mokama paskyra"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kaip veikia transliacija"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transliacija"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Netoliese esantys žmonės, turintys suderinamus „Bluetooth“ įrenginius, gali klausyti jūsų transliuojamos medijos"</string>
@@ -1028,6 +1028,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Fotoaparatas išjungtas"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofonas išjungtas"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Vaizdo kamera ir mikrofonas išjungti"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Padėjėjas klausosi"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# pranešimas}one{# pranešimas}few{# pranešimai}many{# pranešimo}other{# pranešimų}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Užrašų kūrimas"</string>
@@ -1043,6 +1044,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Leisti vienkartinę prieigą"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Neleisti"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Įrenginio žurnaluose įrašoma, kas įvyksta įrenginyje. Programos gali naudoti šiuos žurnalus, kai reikia surasti ir išspręsti problemas.\n\nKai kuriuose žurnaluose gali būti neskelbtinos informacijos, todėl visus įrenginio žurnalus leiskite pasiekti tik programoms, kuriomis pasitikite. \n\nJei neleisite šiai programai pasiekti visų įrenginio žurnalų, ji vis tiek galės pasiekti savo žurnalus. Įrenginio gamintojui vis tiek gali būti leidžiama pasiekti tam tikrus žurnalus ar informaciją jūsų įrenginyje."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Sužinokite daugiau"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Sužinokite daugiau adresu <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Atidaryti „<xliff:g id="APPNAME">%1$s</xliff:g>“"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Programa nustatyta"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Prie „Wallet“ pridėta bent viena kortelė"</string>
@@ -1066,6 +1069,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Pagal jūsų darbo politiką galite skambinti telefonu tik iš darbo profilio"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Perjungti į darbo profilį"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Uždaryti"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Užrakinimo ekrano nustatymai"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index d01cab9..1d9c413 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Apakšmala: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Kreisā mala: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Labā mala: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Darba profila ekrānuzņēmumi tiek saglabāti lietotnē <xliff:g id="APP">%1$s</xliff:g>."</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Faili"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrāna ierakstītājs"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekrāna ieraksta apstrāde"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Seja atpazīta. Lai atvērtu, nospiediet atbloķēšanas ikonu."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ierīce atbloķēta pēc sejas"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Seja atpazīta"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Pārvietojiet pirkstu pa kreisi"</item>
-    <item msgid="5558598599408514296">"Pārvietojiet pirkstu lejup"</item>
-    <item msgid="4844142668312841831">"Pārvietojiet pirkstu pa labi"</item>
-    <item msgid="5640521437931460125">"Pārvietojiet pirkstu augšup"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Velciet augšup, lai mēģinātu vēlreiz"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Atbloķējiet ierīci, lai izmantotu NFC."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Šī ierīce pieder jūsu organizācijai."</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Izvēlieties lietotni, lai pievienotu vadīklas"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Pievienota # vadīkla.}zero{Pievienotas # vadīklas.}one{Pievienota # vadīkla.}other{Pievienotas # vadīklas.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Noņemta"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vai pievienot lietotni <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Ja pievienosiet lietotni <xliff:g id="APPNAME">%s</xliff:g>, tā varēs pievienot vadīklas un saturu šim panelim. Dažās lietotnēs varat izvēlēties, kuras vadīklas šeit rādīt."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Pievienota izlasei"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Pievienota izlasei, <xliff:g id="NUMBER">%d</xliff:g>. pozīcija"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Noņemta no izlases"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Atveriet lietotni <xliff:g id="APP_LABEL">%1$s</xliff:g>."</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Atskaņojiet failu “<xliff:g id="SONG_NAME">%1$s</xliff:g>” (izpildītājs: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) no lietotnes <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Atskaņojiet failu “<xliff:g id="SONG_NAME">%1$s</xliff:g>” no lietotnes <xliff:g id="APP_LABEL">%2$s</xliff:g>."</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Tieši jums"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Atsaukt"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Pārvietojiet savu ierīci tuvāk, lai atskaņotu mūziku ierīcē “<xliff:g id="DEVICENAME">%1$s</xliff:g>”."</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Lai atskaņotu šeit, jums jāatrodas tuvāk šai ierīcei: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Radās kļūda. Mēģiniet vēlreiz."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Pievienot vadīklas"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Rediģēt vadīklas"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Pievienot lietotni"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Izejas ierīču pievienošana"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Atlasīta viena ierīce"</string>
@@ -919,7 +918,6 @@
     <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">"Skaļruņi un displeji"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Ieteiktās ierīces"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Nepieciešams maksas konts"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kā darbojas apraide"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Apraide"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Tuvumā esošās personas ar saderīgām Bluetooth ierīcēm var klausīties jūsu apraidīto multivides saturu."</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera ir izslēgta"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofons ir izslēgts"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera un mikrofons ir izslēgti"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# paziņojums}zero{# paziņojumu}one{# paziņojums}other{# paziņojumi}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Piezīmju pierakstīšana"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Atļaut vienreizēju piekļuvi"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Neatļaut"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Ierīces žurnālos tiek reģistrēti ierīces procesi un notikumi. Lietotņu izstrādātāji var izmantot šos žurnālus, lai atrastu un novērstu problēmas savās lietotnēs.\n\nDažos žurnālos var būt ietverta sensitīva informācija, tāpēc atļaujiet tikai uzticamām lietotnēm piekļūt visiem ierīces žurnāliem. \n\nJa neatļausiet šai lietotnei piekļūt visiem ierīces žurnāliem, lietotnes izstrādātājs joprojām varēs piekļūt pašas lietotnes žurnāliem. Iespējams, ierīces ražotājs joprojām varēs piekļūt noteiktiem žurnāliem vai informācijai jūsu ierīcē."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Atvērt lietotni <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Lietotne ir iestatīta."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Makam ir pievienota vismaz viena karte."</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Saskaņā ar jūsu darba politiku tālruņa zvanus drīkst veikt tikai no darba profila"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Pārslēgties uz darba profilu"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Aizvērt"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Bloķēšanas ekrāna iestatījumi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index f8e0151..969a098 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Долна граница <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Лева граница <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Десна граница <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Сликите од екранот во работниот профил се зачувуваат во апликацијата <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Зачувано во <xliff:g id="APP">%1$s</xliff:g> во работниот профил"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Датотеки"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ја откри оваа слика од екранот."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и други отворени апликации ја открија оваа слика од екранот."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Снимач на екран"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Се обработува снимка од екран"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Тековно известување за сесија за снимање на екранот"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицето е препознаено. Притиснете ја иконата за отклучување за да отворите."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Отклучено со лице"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лицето е препознаено"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Премести налево"</item>
-    <item msgid="5558598599408514296">"Премести надолу"</item>
-    <item msgid="4844142668312841831">"Премести надесно"</item>
-    <item msgid="5640521437931460125">"Премести нагоре"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Повлечете нагоре за да се обидете повторно"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Отклучете за да користите NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Уредов е во сопственост на организацијата"</string>
@@ -884,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Отворете <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Пуштете <xliff:g id="SONG_NAME">%1$s</xliff:g> од <xliff:g id="ARTIST_NAME">%2$s</xliff:g> на <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Пуштете <xliff:g id="SONG_NAME">%1$s</xliff:g> на <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"За вас"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Врати"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Приближете се за да пуштите на <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"За да пуштате овде, приближете се до <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -916,7 +915,6 @@
     <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">"Звучници и екрани"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Предложени уреди"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Потребна е премиум сметка"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционира емитувањето"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Емитување"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Луѓето во ваша близина со компатибилни уреди со Bluetooth може да ги слушаат аудиозаписите што ги емитувате"</string>
@@ -1028,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Камерата е исклучена"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Микрофонот е исклучен"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камерата и микрофонот се исклучени"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"„Помошникот“ слуша"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# известување}one{# известување}other{# известувања}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Фаќање белешки"</string>
@@ -1043,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Дозволи еднократен пристап"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Не дозволувај"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Дневниците за евиденција на уредот снимаат што се случува на вашиот уред. Апликациите може да ги користат овие дневници за евиденција за да наоѓаат и поправаат проблеми.\n\nНекои дневници за евиденција може да содржат чувствителни податоци, па затоа дозволете им пристап до сите дневници за евиденција на уредот само на апликациите во кои имате доверба. \n\nАко не ѝ дозволите на апликацијава да пристапува до сите дневници за евиденција на уредот, таа сепак ќе може да пристапува до сопствените дневници за евиденција. Производителот на вашиот уред можеби сепак ќе може да пристапува до некои дневници за евиденција или податоци на уредот."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Дознајте повеќе"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Дознајте повеќе на <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Отворете ја <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• апликацијата е поставена"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• најмалку една картичка е додадена во Wallet"</string>
@@ -1066,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Вашето работно правило ви дозволува да упатувате повици само од работниот профил"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Префрли се на работен профил"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Поставки за заклучен екран"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 96ebfd0..676af95 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"താഴെയുള്ള അതിർത്തി <xliff:g id="PERCENT">%1$d</xliff:g> ശതമാനം"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ഇടത് വശത്തെ അതിർത്തി <xliff:g id="PERCENT">%1$d</xliff:g> ശതമാനം"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"വലത് വശത്തെ അതിർത്തി <xliff:g id="PERCENT">%1$d</xliff:g> ശതമാനം"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"ഔദ്യോഗിക പ്രൊഫൈലിന്റെ സ്ക്രീന്‍ഷോട്ടുകൾ <xliff:g id="APP">%1$s</xliff:g> ആപ്പിൽ സംരക്ഷിച്ചു"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"ഔദ്യോഗിക പ്രൊഫൈലിൽ <xliff:g id="APP">%1$s</xliff:g> ആപ്പിൽ സംരക്ഷിച്ചു"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ഫയലുകൾ"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ഈ സ്ക്രീൻഷോട്ട് തിരിച്ചറിഞ്ഞു."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> എന്ന ആപ്പും തുറന്നിരിക്കുന്ന മറ്റ് ആപ്പും ഈ സ്ക്രീൻഷോട്ട് തിരിച്ചറിഞ്ഞു."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"സ്ക്രീൻ റെക്കോർഡർ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"സ്ക്രീൻ റെക്കോർഡിംഗ് പ്രോസസുചെയ്യുന്നു"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"മുഖം തിരിച്ചറിഞ്ഞു. തുറക്കാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്‌തു"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"മുഖം തിരിച്ചറിഞ്ഞു"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ഇടത്തേക്ക് നീക്കുക"</item>
-    <item msgid="5558598599408514296">"താഴേക്ക് നീക്കുക"</item>
-    <item msgid="4844142668312841831">"വലത്തേക്ക് നീക്കുക"</item>
-    <item msgid="5640521437931460125">"മുകളിലേക്ക് നീക്കുക"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"വീണ്ടും ശ്രമിക്കാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റേതാണ്"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"നിയന്ത്രണങ്ങൾ ചേർക്കാൻ ആപ്പ് തിരഞ്ഞെടുക്കുക"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# നിയന്ത്രണം ചേർത്തു.}other{# നിയന്ത്രണങ്ങൾ ചേർത്തു.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"നീക്കം ചെയ്‌തു"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ചേർക്കണോ?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"നിങ്ങൾ <xliff:g id="APPNAME">%s</xliff:g> ചേർത്താൽ, അതിന് ഈ പാനലിലേക്ക് നിയന്ത്രണങ്ങളും ഉള്ളടക്കവും ചേർക്കാനാകും. ചില ആപ്പുകളിൽ, ഇവിടെ ഏത് നിയന്ത്രണങ്ങൾ ദൃശ്യമാകണമെന്ന് നിങ്ങൾക്ക് തിരഞ്ഞെടുക്കാനാകും."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"പ്രിയപ്പെട്ടതാക്കി"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"പ്രിയപ്പെട്ടതാക്കി, സ്ഥാനം <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"പ്രിയപ്പെട്ടതല്ലാതാക്കി"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> തുറക്കുക"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> എന്ന ആർട്ടിസ്റ്റിന്റെ <xliff:g id="SONG_NAME">%1$s</xliff:g> എന്ന ഗാനം <xliff:g id="APP_LABEL">%3$s</xliff:g> ആപ്പിൽ പ്ലേ ചെയ്യുക"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> എന്ന ഗാനം <xliff:g id="APP_LABEL">%2$s</xliff:g> ആപ്പിൽ പ്ലേ ചെയ്യുക"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"നിങ്ങൾക്കുള്ളവ"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"പഴയപടിയാക്കുക"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> എന്നതിൽ പ്ലേ ചെയ്യാൻ അടുത്തേക്ക് നീക്കുക"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ഇവിടെ പ്ലേ ചെയ്യാൻ <xliff:g id="DEVICENAME">%1$s</xliff:g> എന്നതിനടുത്തേക്ക് നീക്കുക"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"പിശക്, വീണ്ടും ശ്രമിക്കുക"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"നിയന്ത്രണങ്ങൾ ചേർക്കുക"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"നിയന്ത്രണങ്ങൾ എഡിറ്റ് ചെയ്യുക"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ആപ്പ് ചേർക്കുക"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ഔട്ട്പുട്ടുകൾ ചേർക്കുക"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ഗ്രൂപ്പ്"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"ഒരു ഉപകരണം തിരഞ്ഞെടുത്തു"</string>
@@ -919,7 +915,6 @@
     <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">"സ്‌പീക്കറുകളും ഡിസ്പ്ലേകളും"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"നിർദ്ദേശിച്ച ഉപകരണങ്ങൾ"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"പ്രീമിയം അക്കൗണ്ട് ആവശ്യമാണ്"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ബ്രോഡ്‌കാസ്‌റ്റ് എങ്ങനെയാണ് പ്രവർത്തിക്കുന്നത്"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ബ്രോഡ്‌കാസ്റ്റ്"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"അനുയോജ്യമായ Bluetooth ഉപകരണങ്ങളോടെ സമീപമുള്ള ആളുകൾക്ക് നിങ്ങൾ ബ്രോഡ്‌കാസ്‌റ്റ് ചെയ്യുന്ന മീഡിയ കേൾക്കാനാകും"</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"ക്യാമറ ഓഫാണ്"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"മൈക്ക് ഓഫാണ്"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ക്യാമറയും മൈക്കും ഓഫാണ്"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant കേൾക്കുന്നു"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# അറിയിപ്പ്}other{# അറിയിപ്പുകൾ}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"കുറിപ്പ് രേഖപ്പെടുത്തൽ"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"ഒറ്റത്തവണ ആക്‌സസ് അനുവദിക്കുക"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"അനുവദിക്കരുത്"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"നിങ്ങളുടെ ഉപകരണത്തിൽ സംഭവിക്കുന്ന കാര്യങ്ങൾ ഉപകരണ ലോഗുകൾ റെക്കോർഡ് ചെയ്യുന്നു. പ്രശ്‌നങ്ങൾ കണ്ടെത്തി പരിഹരിക്കുന്നതിന് ആപ്പുകൾക്ക് ഈ ലോഗുകൾ ഉപയോഗിക്കാൻ കഴിയും.\n\nചില ലോഗുകളിൽ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട വിവരങ്ങൾ അടങ്ങിയിരിക്കാൻ സാധ്യതയുള്ളതിനാൽ, എല്ലാ ഉപകരണ ലോഗുകളും ആക്സസ് ചെയ്യാനുള്ള അനുമതി നിങ്ങൾക്ക് വിശ്വാസമുള്ള ആപ്പുകൾക്ക് മാത്രം നൽകുക. \n\nഎല്ലാ ഉപകരണ ലോഗുകളും ആക്‌സസ് ചെയ്യാനുള്ള അനുവാദം നൽകിയില്ലെങ്കിലും, ഈ ആപ്പിന് അതിന്റെ സ്വന്തം ലോഗുകൾ ആക്‌സസ് ചെയ്യാനാകും. നിങ്ങളുടെ ഉപകരണ നിർമ്മാതാവിന് തുടർന്നും നിങ്ങളുടെ ഉപകരണത്തിലെ ചില ലോഗുകളോ വിവരങ്ങളോ ആക്‌സസ് ചെയ്യാനായേക്കും."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"കൂടുതലറിയുക"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> എന്നതിൽ കൂടുതലറിയുക"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> തുറക്കുക"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ആപ്പ് സജ്ജീകരിച്ചിട്ടുണ്ട്"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet-ലേക്ക് ഒരു കാർഡെങ്കിലും ചേർത്തിട്ടുണ്ട്"</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"ഔദ്യോഗിക പ്രൊഫൈലിൽ നിന്ന് മാത്രം ഫോൺ കോളുകൾ ചെയ്യാനാണ് നിങ്ങളുടെ ഔദ്യോഗിക നയം അനുവദിക്കുന്നത്"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് മാറുക"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"അടയ്ക്കുക"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"ലോക്ക് സ്ക്രീൻ ക്രമീകരണം"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 5a552ad..1d40c6b 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Доод талын хязгаар <xliff:g id="PERCENT">%1$d</xliff:g> хувь"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Зүүн талын хязгаар <xliff:g id="PERCENT">%1$d</xliff:g> хувь"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Баруун талын хязгаар <xliff:g id="PERCENT">%1$d</xliff:g> хувь"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Ажлын дэлгэцийн агшнуудыг <xliff:g id="APP">%1$s</xliff:g> апп дээр хадгалсан"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Ажлын профайл дахь <xliff:g id="APP">%1$s</xliff:g>-д хадгалсан"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Файлс"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> энэ дэлгэцийн агшныг илрүүлсэн."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> болон бусад нээлттэй апп энэ дэлгэцийн агшныг илрүүлсэн."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Дэлгэцийн үйлдэл бичигч"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Дэлгэц бичлэг боловсруулж байна"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Царайг таньсан. Нээх бол түгжээг тайлах дүрсийг дарна уу."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Царайгаар түгжээг тайлсан"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Царайг таньсан"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Зүүн тийш зөөх"</item>
-    <item msgid="5558598599408514296">"Доош зөөх"</item>
-    <item msgid="4844142668312841831">"Баруун тийш зөөх"</item>
-    <item msgid="5640521437931460125">"Дээш зөөх"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Дахин оролдохын тулд дээш шударна уу"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC-г ашиглахын тулд түгжээг тайлна уу"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Энэ төхөөрөмж танай байгууллагад харьяалагддаг"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Хяналтууд нэмэхийн тулд аппыг сонгоно уу"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# хяналт нэмсэн.}other{# хяналт нэмсэн.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Хассан"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>-г нэмэх үү?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Та <xliff:g id="APPNAME">%s</xliff:g>-г нэмэх үед энэ нь уг түр зуурын самбарт тохиргоо болон контент нэмэх боломжтой. Зарим аппад та энд ямар тохиргоог харуулахыг сонгох боломжтой."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Дуртай гэж тэмдэглэсэн"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>-р байршилд дуртай гэж тэмдэглэсэн"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Дургүй гэж тэмдэглэсэн"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g>-г нээх"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>-н <xliff:g id="SONG_NAME">%1$s</xliff:g>-г <xliff:g id="APP_LABEL">%3$s</xliff:g> дээр тоглуулах"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g>-г <xliff:g id="APP_LABEL">%2$s</xliff:g> дээр тоглуулах"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Танд зориулсан"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Болих"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> дээр тоглуулахын тулд төхөөрөмжөө ойртуулна уу"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Энд тоглуулахын тулд <xliff:g id="DEVICENAME">%1$s</xliff:g> руу ойртуулна уу"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Алдаа гарав, дахин оролдоно уу"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Хяналт нэмэх"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Хяналтыг өөрчлөх"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Апп нэмэх"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Гаралт нэмэх"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Бүлэг"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 төхөөрөмж сонгосон"</string>
@@ -919,7 +915,6 @@
     <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">"Чанга яригч ба дэлгэц"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Санал болгосон төхөөрөмжүүд"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Тусгай бүртгэл шаарддаг"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Нэвтрүүлэлт хэрхэн ажилладаг вэ?"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Нэвтрүүлэлт"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Тохиромжтой Bluetooth төхөөрөмжүүдтэй таны ойролцоох хүмүүс таны нэвтрүүлж буй медиаг сонсох боломжтой"</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Камер унтраалттай байна"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Микрофон унтраалттай байна"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камер болон микрофон унтраалттай байна"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Туслах сонсож байна"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# мэдэгдэл}other{# мэдэгдэл}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Тэмдэглэл хөтлөх"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Нэг удаагийн хандалтыг зөвшөөрөх"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Бүү зөвшөөр"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Төхөөрөмжийн лог нь таны төхөөрөмж дээр юу болж байгааг бичдэг. Аппууд эдгээр логийг асуудлыг олох болон засахад ашиглах боломжтой.\n\nЗарим лог эмзэг мэдээлэл агуулж байж магадгүй тул та зөвхөн итгэдэг аппууддаа төхөөрөмжийн бүх логт хандахыг зөвшөөрнө үү. \n\nХэрэв та энэ аппад төхөөрөмжийн бүх логт хандахыг зөвшөөрөхгүй бол энэ нь өөрийн логт хандах боломжтой хэвээр байх болно. Tаны төхөөрөмжийн үйлдвэрлэгч таны төхөөрөмж дээрх зарим лог эсвэл мэдээлэлд хандах боломжтой хэвээр байж магадгүй."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Нэмэлт мэдээлэл авах"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>-с нэмэлт мэдээлэл авна уу"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g>-г нээх"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Аппыг тохируулсан"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Дор хаяж нэг картыг Wallet-д нэмсэн"</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Таны ажлын бодлого танд зөвхөн ажлын профайлаас утасны дуудлага хийхийг зөвшөөрдөг"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Ажлын профайл руу сэлгэх"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Хаах"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Түгжигдсэн дэлгэцийн тохиргоо"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index a9e57f7..04948f5 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"खालील सीमेपासून <xliff:g id="PERCENT">%1$d</xliff:g> टक्के"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"डाव्या सीमेपासून <xliff:g id="PERCENT">%1$d</xliff:g> टक्के"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"उजव्या सीमेपासून <xliff:g id="PERCENT">%1$d</xliff:g> टक्के"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"ऑफिससंबंधित स्क्रीनशॉट <xliff:g id="APP">%1$s</xliff:g> अ‍ॅपमध्ये सेव्ह केले आहेत"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"<xliff:g id="APP">%1$s</xliff:g> मधील कार्य प्रोफाइलमध्ये सेव्ह केला"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"फाइल"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ने हा स्क्रीनशॉट डिटेक्ट केला."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> आणि उघडलेल्या इतर अ‍ॅप्सनी हा स्क्रीनशॉट डिटेक्ट केला."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रेकॉर्डर"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रेकॉर्डिंग प्रोसेस सुरू"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"चेहरा ओळखला आहे. उघडण्यासाठी अनलॉक करा आयकन दाबा."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"चेहऱ्याने अनलॉक केले आहे"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"चेहरा ओळखला आहे"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"डावीकडे हलवा"</item>
-    <item msgid="5558598599408514296">"खाली हलवा"</item>
-    <item msgid="4844142668312841831">"उजवीकडे हलवा"</item>
-    <item msgid="5640521437931460125">"वर हलवा"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"पुन्हा प्रयत्न करण्यासाठी वर स्‍वाइप करा"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC वापरण्यासाठी स्क्रीन अनलॉक करा"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"हे डिव्हाइस तुमच्या संस्थेचे आहे"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"नियंत्रणे जोडण्यासाठी ॲप निवडा"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# नियंत्रण जोडले आहे.}other{# नियंत्रणे जोडली आहेत.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"काढून टाकले"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> जोडायचे आहे का?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"तुम्ही <xliff:g id="APPNAME">%s</xliff:g> जोडता, तेव्हा ते या पॅनलमध्ये नियंत्रणे आणि आशय जोडू शकते. येथे कोणती नियंत्रणे दाखवावीत ते तुम्ही काही अ‍ॅप्समध्ये निवडू शकता."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"आवडले"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"आवडले, स्थान <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"नावडले"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> उघडा"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> मध्ये <xliff:g id="ARTIST_NAME">%2$s</xliff:g> चे <xliff:g id="SONG_NAME">%1$s</xliff:g> प्ले करा"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> मध्ये <xliff:g id="SONG_NAME">%1$s</xliff:g> प्ले करा"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"तुमच्यासाठी"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"पहिल्यासारखे करा"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> वर प्ले करण्यासाठी जवळ जा"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"येथे प्ले करण्यासाठी, <xliff:g id="DEVICENAME">%1$s</xliff:g> च्या जवळ जा"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"एरर, पुन्हा प्रयत्न करा"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"नियंत्रणे जोडा"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"नियंत्रणे संपादित करा"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"अ‍ॅप जोडा"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट जोडा"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"गट"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिव्हाइस निवडले"</string>
@@ -919,7 +915,6 @@
     <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">"स्पीकर आणि डिस्प्ले"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"सुचवलेली डिव्हाइस"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"प्रीमियम खाते आवश्यक आहे"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ब्रॉडकास्टिंग कसे काम करते"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ब्रॉडकास्ट करा"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"कंपॅटिबल ब्लूटूथ डिव्‍हाइस असलेले तुमच्या जवळपासचे लोक हे तुम्ही ब्रॉडकास्ट करत असलेला मीडिया ऐकू शकतात"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"कॅमेरा बंद आहे"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"माइक बंद आहे"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"कॅमेरा आणि माइक बंद आहेत"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# सूचना}other{# सूचना}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"नोटटेकिंग"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"एक वेळ अ‍ॅक्सेसची अनुमती द्या"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"अनुमती देऊ नका"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"तुमच्या डिव्हाइसवर काय होते ते डिव्हाइस लॉग रेकॉर्ड करते. समस्या शोधण्यासाठी आणि त्यांचे निराकरण करण्यासाठी ॲप्स हे लॉग वापरू शकतात.\n\nकाही लॉगमध्ये संवेदनशील माहिती असू शकते, त्यामुळे फक्त तुमचा विश्वास असलेल्या ॲप्सना सर्व डिव्हाइस लॉग अ‍ॅक्सेस करण्याची अनुमती द्या. \n\nतुम्ही या ॲपला सर्व डिव्हाइस लॉग अ‍ॅक्सेस करण्याची अनुमती न दिल्यास, ते तरीही त्याचा स्वतःचा लॉग अ‍ॅक्सेस करू शकते. तुमच्या डिव्हाइसचा उत्पादक तरीही काही लॉग किंवा तुमच्या डिव्हाइसवरील माहिती अ‍ॅक्सेस करू शकतो."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> उघडा"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• अ‍ॅप सेट करणे"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet मध्ये किमान एक कार्ड जोडणे"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"तुमचे कामाशी संबंधित धोरण तुम्हाला फक्त कार्य प्रोफाइलवरून फोन कॉल करन्याची अनुमती देते"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइलवर स्विच करा"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करा"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"लॉक स्क्रीन सेटिंग्ज"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 9ffe823..6c5389a 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Sempadan bawah <xliff:g id="PERCENT">%1$d</xliff:g> peratus"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Sempadan kiri <xliff:g id="PERCENT">%1$d</xliff:g> peratus"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Sempadan kanan <xliff:g id="PERCENT">%1$d</xliff:g> peratus"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Tangkapan skrin tugasan disimpan dalam apl <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Disimpan dalam <xliff:g id="APP">%1$s</xliff:g> dalam profil kerja"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fail"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> telah mengesan tangkapan skrin ini."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dan apl lain yang dibuka telah mengesan tangkapan skrin ini."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Perakam Skrin"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses rakaman skrin"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pemberitahuan breterusan untuk sesi rakaman skrin"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Wajah dicam. Tekan ikon buka kunci untuk membuka."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Dibuka kunci dengan wajah"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Wajah dicam"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Alih ke kiri"</item>
-    <item msgid="5558598599408514296">"Alih ke bawah"</item>
-    <item msgid="4844142668312841831">"Alih ke kanan"</item>
-    <item msgid="5640521437931460125">"Alih ke atas"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Leret ke atas untuk mencuba lagi"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Buka kunci untuk menggunakan NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Peranti ini milik organisasi anda"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Pilih apl untuk menambahkan kawalan"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kawalan ditambah.}other{# kawalan ditambah.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Dialih keluar"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Tambahkan <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Apabila anda menambahkan <xliff:g id="APPNAME">%s</xliff:g>, apl ini boleh menambahkan kawalan dan kandungan pada panel ini. Dalam sesetengah apl, anda boleh memilih kawalan yang muncul di sini."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Digemari"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Digemari, kedudukan <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Dinyahgemari"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Buka <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Mainkan <xliff:g id="SONG_NAME">%1$s</xliff:g> oleh <xliff:g id="ARTIST_NAME">%2$s</xliff:g> daripada <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Mainkan <xliff:g id="SONG_NAME">%1$s</xliff:g> daripada <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Untuk Anda"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Buat asal"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Alihkan lebih dekat untuk bermain pada<xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Untuk bermain di sini, bergerak lebih dekat kepada <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Ralat, cuba lagi"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Tambah kawalan"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edit kawalan"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tambahkan apl"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tambah output"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Kumpulan"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 peranti dipilih"</string>
@@ -919,7 +915,6 @@
     <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">"Pembesar Suara &amp; Paparan"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Peranti yang Dicadangkan"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Memerlukan akaun premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cara siaran berfungsi"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Siarkan"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Orang berdekatan anda dengan peranti Bluetooth yang serasi boleh mendengar media yang sedang anda siarkan"</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera dimatikan"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon dimatikan"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera dan mikrofon dimatikan"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Pembantu sedang mendengar"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# pemberitahuan}other{# pemberitahuan}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Pengambilan nota"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Benarkan akses satu kali"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Jangan benarkan"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Log peranti merekodkan perkara yang berlaku pada peranti anda. Apl boleh menggunakan log ini untuk menemukan dan membetulkan masalah.\n\nSesetengah log mungkin mengandungi maklumat sensitif, jadi hanya benarkan apl yang anda percaya untuk mengakses semua log peranti. \n\nJika anda tidak membenarkan apl ini mengakses semua log peranti, apl ini masih boleh mengakses log sendiri. Pengilang peranti anda mungkin masih dapat mengakses sesetengah log atau maklumat pada peranti anda."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Ketahui lebih lanjut"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Ketahui lebih lanjut di <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Buka <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Apl disediakan"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Sekurang-kurangnya satu kad telah ditambahkan pada Wallet"</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Dasar kerja anda membenarkan anda membuat panggilan telefon hanya daripada profil kerja"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Tukar kepada profil kerja"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Tetapan skrin kunci"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 3ccac95..775abd4 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"အောက်ခြေအနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ဘယ်ဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ညာဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"အလုပ်နှင့်ဆိုင်သော ဖန်သားပြင်ဓာတ်ပုံများကို <xliff:g id="APP">%1$s</xliff:g> အက်ပ်တွင် သိမ်းသည်"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"အလုပ်ပရိုဖိုင်ရှိ <xliff:g id="APP">%1$s</xliff:g> တွင် သိမ်းထားသည်"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ဖိုင်များ"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> က ဤဖန်သားပြင်ဓာတ်ပုံကို တွေ့ရှိသည်။"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> နှင့် အခြားဖွင့်ထားသော အက်ပ်များက ဤဖန်သားပြင်ဓာတ်ပုံကို တွေ့ရှိသည်။"</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"ဖန်သားပြင် ရိုက်ကူးမှု"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"စကရင်ရိုက်ကူးမှု အပြီးသတ်နေသည်"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"မျက်နှာ မှတ်မိသည်။ ဖွင့်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"မျက်နှာဖြင့် ဖွင့်လိုက်သည်"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"မျက်နှာ မှတ်မိသည်"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ဘယ်ဘက်သို့ရွှေ့ရန်"</item>
-    <item msgid="5558598599408514296">"အောက်သို့ရွှေ့ရန်"</item>
-    <item msgid="4844142668312841831">"ညာဘက်သို့ရွှေ့ရန်"</item>
-    <item msgid="5640521437931460125">"အပေါ်သို့ရွှေ့ရန်"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"ထပ်စမ်းကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲပါ"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ကို အသုံးပြုရန် လော့ခ်ဖွင့်ပါ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"ထိန်းချုပ်မှုများထည့်ရန် အက်ပ်ရွေးခြင်း"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{ထိန်းချုပ်ခလုတ် # ခု ထည့်ထားသည်။}other{ထိန်းချုပ်ခလုတ် # ခု ထည့်ထားသည်။}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ဖယ်ရှားထားသည်"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ထည့်မလား။"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> ထည့်သောအခါ ၎င်းသည် ဤအကန့်တွင် သတ်မှတ်ချက်များနှင့် အကြောင်းအရာကို ထည့်နိုင်သည်။ အက်ပ်အချို့၌ မြင်ရမည့် သတ်မှတ်ချက်များကို ဤနေရာတွင် ရွေးနိုင်သည်။"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"အကြိုက်ဆုံးတွင် ထည့်ထားသည်"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"အကြိုက်ဆုံးတွင် ထည့်ထားသည်၊ အဆင့် <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"အကြိုက်ဆုံးမှ ဖယ်ရှားထားသည်"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ကို ဖွင့်ပါ"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ၏ <xliff:g id="SONG_NAME">%1$s</xliff:g> ကို <xliff:g id="APP_LABEL">%3$s</xliff:g> တွင် ဖွင့်ပါ"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ကို <xliff:g id="APP_LABEL">%2$s</xliff:g> တွင် ဖွင့်ပါ"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"သင့်အတွက်"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"နောက်ပြန်ရန်"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> တွင်ဖွင့်ရန် အနီးသို့ရွှေ့ပါ"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ဤနေရာတွင် ဖွင့်ရန် <xliff:g id="DEVICENAME">%1$s</xliff:g> အနီးသို့ ရွှေ့ပါ"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"မှားသွားသည်၊ ပြန်စမ်းကြည့်ပါ"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"ထိန်းချုပ်မှုများ ထည့်ရန်"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ထိန်းချုပ်မှုများ ပြင်ရန်"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"အက်ပ်ထည့်ရန်"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"မီဒီယာအထွက်များ ထည့်ရန်"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"အုပ်စု"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"စက်ပစ္စည်း ၁ ခုကို ရွေးချယ်ထားသည်"</string>
@@ -919,7 +915,6 @@
     <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">"စပီကာနှင့် ဖန်သားပြင်များ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"အကြံပြုထားသော စက်ပစ္စည်းများ"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"ပရီမီယံအကောင့် လိုအပ်သည်"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ထုတ်လွှင့်မှုဆောင်ရွက်ပုံ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ထုတ်လွှင့်ခြင်း"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"အနီးရှိတွဲသုံးနိုင်သော ဘလူးတုသ်သုံးစက် အသုံးပြုသူများက သင်ထုတ်လွှင့်နေသော မီဒီယာကို နားဆင်နိုင်သည်"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"ကင်မရာ ပိတ်ထားသည်"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"မိုက်ပိတ်ထားသည်"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ကင်မရာနှင့် မိုက် ပိတ်ထားသည်"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{အကြောင်းကြားချက် # ခု}other{အကြောင်းကြားချက် # ခု}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>၊ <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"မှတ်စုလိုက်ခြင်း"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"တစ်ခါသုံး ဝင်ခွင့်ပေးရန်"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"ခွင့်မပြုပါ"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"သင့်စက်ရှိ အဖြစ်အပျက်များကို စက်မှတ်တမ်းများက မှတ်တမ်းတင်သည်။ အက်ပ်များက ပြဿနာများ ရှာဖွေပြီးဖြေရှင်းရန် ဤမှတ်တမ်းများကို သုံးနိုင်သည်။\n\nအချို့မှတ်တမ်းများတွင် သတိထားရမည့်အချက်အလက်များ ပါဝင်နိုင်သဖြင့် ယုံကြည်ရသည့် အက်ပ်များကိုသာ စက်မှတ်တမ်းအားလုံး သုံးခွင့်ပြုပါ။ \n\nဤအက်ပ်ကို စက်မှတ်တမ်းအားလုံး သုံးခွင့်မပြုသော်လည်း ၎င်းက ကိုယ်ပိုင်မှတ်တမ်းများ သုံးနိုင်သေးသည်။ သင့်စက်ရှိ အချို့မှတ်တမ်းများ (သို့) အချက်အလက်များကို သင့်စက်ထုတ်လုပ်သူက သုံးနိုင်ပါသေးသည်။"</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ဖွင့်ရန်"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• အက်ပ်ကို စနစ်ထည့်သွင်းထားရမည်"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet တွင် အနည်းဆုံးကတ်တစ်ခု ထည့်ထားရမည်"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"သင့်အလုပ်မူဝါဒသည် သင့်အား အလုပ်ပရိုဖိုင်မှသာ ဖုန်းခေါ်ဆိုခွင့် ပြုသည်"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"အလုပ်ပရိုဖိုင်သို့ ပြောင်းရန်"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ပိတ်ရန်"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"လော့ခ်မျက်နှာပြင် ဆက်တင်များ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 44d97aa..c212096 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Nedre grense <xliff:g id="PERCENT">%1$d</xliff:g> prosent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Venstre grense <xliff:g id="PERCENT">%1$d</xliff:g> prosent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Høyre grense <xliff:g id="PERCENT">%1$d</xliff:g> prosent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Jobbrelaterte skjermdumper lagres i <xliff:g id="APP">%1$s</xliff:g>-appen"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Filer"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Skjermopptaker"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skjermopptaket"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Låst opp med ansiktet"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansiktet er gjenkjent"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Flytt til venstre"</item>
-    <item msgid="5558598599408514296">"Flytt ned"</item>
-    <item msgid="4844142668312841831">"Flytt til høyre"</item>
-    <item msgid="5640521437931460125">"Flytt opp"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Sveip opp for å prøve igjen"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås opp for å bruke NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Denne enheten tilhører organisasjonen din"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Velg en app for å legge til kontroller"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontroll er lagt til.}other{# kontroller er lagt til.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Fjernet"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vil du legge til <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Når du legger til <xliff:g id="APPNAME">%s</xliff:g>, kan den legge til kontroller og innhold i dette panelet. I noen apper kan du velge hvilke kontroller som vises her."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favoritt"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favoritt, posisjon <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjernet som favoritt"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Åpne <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Spill av <xliff:g id="SONG_NAME">%1$s</xliff:g> av <xliff:g id="ARTIST_NAME">%2$s</xliff:g> fra <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Spill av <xliff:g id="SONG_NAME">%1$s</xliff:g> fra <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"For deg"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Angre"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Flytt nærmere for å spille av på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"For å spille av her, gå nærmere <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"En feil oppsto. Prøv på nytt"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Legg til kontroller"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Endre kontroller"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Legg til app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Legg til utenheter"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet er valgt"</string>
@@ -919,7 +918,6 @@
     <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">"Høyttalere og skjermer"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Foreslåtte enheter"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Krever en premium-konto"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Slik fungerer kringkasting"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Kringkasting"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Folk i nærheten med kompatible Bluetooth-enheter kan lytte til mediene du kringkaster"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kameraet er av"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofonen er av"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera og mikrofon er av"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# varsel}other{# varsler}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notatskriving"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Gi éngangstilgang"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ikke tillat"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Enhetslogger registrerer det som skjer på enheten din. Apper kan bruke disse loggene til å finne og løse problemer.\n\nNoen logger kan inneholde sensitiv informasjon, så du bør bare gi tilgang til alle enhetslogger til apper du stoler på. \n\nHvis du ikke gir denne appen tilgang til alle enhetslogger, har den fortsatt tilgang til sine egne logger. Enhetsprodusenten kan fortsatt ha tilgang til visse logger eller noe informasjon på enheten din."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Åpne <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• appen er konfigurert"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• minst ett kort er lagt til i Wallet"</string>
@@ -1056,7 +1060,7 @@
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Avbryt"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Vend nå"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Brett ut telefonen for å ta bedre selfier"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vil du bytte til frontskjermen for bedre selfier?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vil du bruke frontkameraet for bedre selfier?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Bruk det bakovervendte kameraet for å ta bredere bilder med høyere oppløsning."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Denne skjermen slås av"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En sammenleggbar enhet blir brettet ut"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Som følge av jobbreglene dine kan du bare starte telefonanrop fra jobbprofilen."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Bytt til jobbprofilen"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Lukk"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Innstillinger for låseskjermen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index b5ffc21..377ac45 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"फेदबाट <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"बायाँ किनाराबाट <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"दायाँ किनाराबाट <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"कार्य प्रोफाइल प्रयोग गरी लिइएका स्क्रिनसटहरू <xliff:g id="APP">%1$s</xliff:g> एपमा सेभ गरिन्छन्"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"कार्य प्रोफाइलअन्तर्गत <xliff:g id="APP">%1$s</xliff:g> मा सेभ गरियो"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ले यो स्क्रिनसट भेट्टाएको छ।"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> र खुला रहेका अन्य एपहरूले यो स्क्रिनसट भेट्टाएका छन्।"</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"स्क्रिन रेकर्डर"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रिन रेकर्डिङको प्रक्रिया अघि बढाइँदै"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"अनुहार पहिचान गरियो। डिभाइस खोल्न अनलक आइकनमा थिच्नुहोस्।"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"अनुहार प्रयोग गरी अनलक गरियो"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"अनुहार पहिचान गरियो"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"बायाँ सार्नुहोस्"</item>
-    <item msgid="5558598599408514296">"तल सार्नुहोस्"</item>
-    <item msgid="4844142668312841831">"दायाँ सार्नुहोस्"</item>
-    <item msgid="5640521437931460125">"माथि सार्नुहोस्"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"फेरि प्रयास गर्न माथितिर स्वाइप गर्नुहोस्"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC प्रयोग गर्न स्क्रिन अनलक गर्नुहोस्"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"यो डिभाइस तपाईंको सङ्गठनको स्वामित्वमा छ"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"कन्ट्रोल थप्नु पर्ने एप छान्नुहोस्"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# कन्ट्रोल हालियो।}other{# वटा कन्ट्रोल हालियो।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"हटाइएको"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> हाल्ने हो?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"तपाईंले <xliff:g id="APPNAME">%s</xliff:g> हाल्नुभयो भने यसले यो प्यानलमा सेटिङ र सामग्री हाल्न सक्छ। तपाईं केही एपहरूमा यहाँ कुन कुन सेटिङ देखाउने भन्ने कुरा छनौट गर्न सक्नुहुन्छ।"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"मनपराइएको"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"मन पराइएका कुराहरूको <xliff:g id="NUMBER">%d</xliff:g> औँ स्थानमा"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"मन पर्ने कुराहरूको सूचीमा नराखिएको"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> खोल्नुहोस्"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> को <xliff:g id="SONG_NAME">%1$s</xliff:g> बोलको गीत <xliff:g id="APP_LABEL">%3$s</xliff:g> मा बजाउनुहोस्"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> बोलको गीत <xliff:g id="APP_LABEL">%2$s</xliff:g> मा बजाउनुहोस्"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"तपाईंको लागि सिफारिस गरिएका"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"अन्डू गर्नुहोस्"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> मा प्ले गर्न आफ्नो डिभाइस नजिकै लैजानुहोस्"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"यो डिभाइसमा प्ले गर्न <xliff:g id="DEVICENAME">%1$s</xliff:g> को अझ नजिक जानुहोस्"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"त्रुटि भयो, फेरि प्रयास गर्नु…"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"कन्ट्रोल थप्नुहोस्"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"कन्ट्रोल सम्पादन गर्नुहोस्"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"एप हाल्नुहोस्"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट यन्त्रहरू थप्नुहोस्"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"समूह"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"१ यन्त्र चयन गरियो"</string>
@@ -919,7 +915,6 @@
     <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">"स्पिकर तथा डिस्प्लेहरू"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"सिफारिस गरिएका डिभाइसहरू"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"प्रिमियम खाता चाहिन्छ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"प्रसारण गर्ने सुविधाले कसरी काम गर्छ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"प्रसारण"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"कम्प्याटिबल ब्लुटुथ डिभाइस भएका नजिकैका मान्छेहरू तपाईंले प्रसारण गरिरहनुभएको मिडिया सुन्न सक्छन्"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"क्यामेरा अफ छ"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"माइक अफ छ"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"क्यामेरा र माइक अफ छन्"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# वटा सूचना}other{# वटा सूचनाहरू}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"टिपोट गर्ने कार्य"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"एक पटक प्रयोग गर्ने अनुमति दिनुहोस्"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"अनुमति नदिनुहोस्"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"डिभाइसका लगले तपाईंको डिभाइसमा भएका विभिन्न गतिविधिको अभिलेख राख्छन्। एपहरू यी लगका आधारमा समस्या पत्ता लगाउन र तिनको समाधान गर्न सक्छन्।\n\nकेही लगहरूमा संवेदनशील जानकारी समावेश हुन सक्ने भएकाले आफूले भरोसा गर्ने एपलाई मात्र डिभाइसका सबै लग हेर्ने अनुमति दिनुहोस्। \n\nतपाईंले यो एपलाई डिभाइसका सबै लग हेर्ने अनुमति दिनुभएन भने पनि यसले आफ्नै लग भने हेर्न सक्छ। तपाईंको डिभाइसका उत्पादकले पनि तपाईंको डिभाइसमा भएका केही लग वा जानकारी हेर्न सक्ने सम्भावना हुन्छ।"</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> खोल्नुहोस्"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• एप सेटअप गरिएको छ"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet मा कम्तीमा एउटा कार्ड हालिएको छ"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"तपाईंको कामसम्बन्धी नीतिअनुसार कार्य प्रोफाइलबाट मात्र फोन कल गर्न सकिन्छ"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइल प्रयोग गर्नुहोस्"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"बन्द गर्नुहोस्"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"लक स्क्रिनसम्बन्धी सेटिङ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 221a9d8..ba251e7 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ondergrens <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Linkergrens <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Rechtergrens <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Werkscreenshots worden opgeslagen in de <xliff:g id="APP">%1$s</xliff:g>-app"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Bestanden"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Schermopname"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Schermopname verwerken"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Doorlopende melding voor een schermopname-sessie"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Gezicht herkend. Druk op het ontgrendelicoon."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Ontgrendeld via gezicht"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Gezicht herkend"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Naar links verplaatsen"</item>
-    <item msgid="5558598599408514296">"Omlaag verplaatsen"</item>
-    <item msgid="4844142668312841831">"Naar rechts verplaatsen"</item>
-    <item msgid="5640521437931460125">"Omhoog verplaatsen"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Swipe omhoog om het opnieuw te proberen"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ontgrendel het apparaat om NFC te gebruiken"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Dit apparaat is eigendom van je organisatie"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Kies de app waaraan je bedieningselementen wilt toevoegen"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# bedieningselement toegevoegd.}other{# bedieningselementen toegevoegd.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Verwijderd"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> toevoegen?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Als je <xliff:g id="APPNAME">%s</xliff:g> toevoegt, kan deze app bedieningselementen en content aan dit deelvenster toevoegen. In sommige apps kun je kiezen welke bedieningselementen hier worden getoond."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Gemarkeerd als favoriet"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Gemarkeerd als favoriet, positie <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Verwijderd als favoriet"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> openen"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> van <xliff:g id="ARTIST_NAME">%2$s</xliff:g> afspelen via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> afspelen via <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Voor jou"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Ongedaan maken"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Houd dichter bij <xliff:g id="DEVICENAME">%1$s</xliff:g> om af te spelen"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Ga dichter naar <xliff:g id="DEVICENAME">%1$s</xliff:g> toe om hier af te spelen"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Fout, probeer het opnieuw"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Bedieningselementen toevoegen"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Bedieningselementen bewerken"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"App toevoegen"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Uitvoer toevoegen"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Eén apparaat geselecteerd"</string>
@@ -919,7 +918,6 @@
     <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 en schermen"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Voorgestelde apparaten"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Je hebt een premium account nodig"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Hoe uitzenden werkt"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Uitzending"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Mensen bij jou in de buurt met geschikte bluetooth-apparaten kunnen luisteren naar de media die je uitzendt"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Camera staat uit"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Microfoon staat uit"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera en microfoon staan uit"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# melding}other{# meldingen}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Aantekeningen maken"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Eenmalige toegang toestaan"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Niet toestaan"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Apparaatlogboeken leggen vast wat er op je apparaat gebeurt. Apps kunnen deze logboeken gebruiken om problemen op te sporen en te verhelpen.\n\nSommige logboeken kunnen gevoelige informatie bevatten, dus geef alleen apps die je vertrouwt toegang tot alle apparaatlogboeken. \n\nAls je deze app geen toegang tot alle apparaatlogboeken geeft, heeft de app nog wel toegang tot de eigen logboeken. De fabrikant van je apparaat heeft misschien nog steeds toegang tot bepaalde logboeken of informatie op je apparaat."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> openen"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• De app is ingesteld"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Er is ten minste één kaart aan Wallet toegevoegd"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Op basis van je werkbeleid kun je alleen bellen vanuit het werkprofiel"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Overschakelen naar werkprofiel"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Sluiten"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Instellingen vergrendelscherm"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index e3314b3..6acf3b9 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ନିମ୍ନ ସୀମାରେଖା <xliff:g id="PERCENT">%1$d</xliff:g> ଶତକଡ଼ା"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ବାମ ସୀମାରେଖା <xliff:g id="PERCENT">%1$d</xliff:g> ଶତକଡ଼ା"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ଡାହାଣ ସୀମାରେଖା <xliff:g id="PERCENT">%1$d</xliff:g> ଶତକଡ଼ା"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"ୱାର୍କ ସ୍କ୍ରିନସଟଗୁଡ଼ିକୁ <xliff:g id="APP">%1$s</xliff:g> ଆପରେ ସେଭ କରାଯାଇଛି"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"ୱାର୍କ ପ୍ରୋଫାଇଲରେ ଥିବା <xliff:g id="APP">%1$s</xliff:g>ରେ ସେଭ କରାଯାଇଛି"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ଫାଇଲଗୁଡ଼ିକ"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ଏହି ସ୍କ୍ରିନସଟକୁ ଚିହ୍ନଟ କରିଛି।"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ଏବଂ ଅନ୍ୟ ଓପନ ଆପ୍ସ ଏହି ସ୍କ୍ରିନସଟକୁ ଚିହ୍ନଟ କରିଛି।"</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"ସ୍କ୍ରିନ୍ ରେକର୍ଡର୍"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ସ୍କ୍ରିନ ରେକର୍ଡିଂର ପ୍ରକ୍ରିୟାକରଣ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରି‍ନ୍‍ ରେକର୍ଡ୍‍ ସେସନ୍‍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଖୋଲିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ବାମକୁ ମୁଭ କରନ୍ତୁ"</item>
-    <item msgid="5558598599408514296">"ତଳକୁ ମୁଭ କରନ୍ତୁ"</item>
-    <item msgid="4844142668312841831">"ଡାହାଣକୁ ମୁଭ କରନ୍ତୁ"</item>
-    <item msgid="5640521437931460125">"ଉପରକୁ ମୁଭ କରନ୍ତୁ"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"ପୁଣି ଚେଷ୍ଟା କରିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଯୋଗ କରିବାକୁ ଆପ୍ ବାଛନ୍ତୁ"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{#ଟି ନିୟନ୍ତ୍ରଣ ଯୋଗ କରାଯାଇଛି।}other{#ଟି ନିୟନ୍ତ୍ରଣ ଯୋଗ କରାଯାଇଛି।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"କାଢ଼ି ଦିଆଯାଇଛି"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>କୁ ଯୋଗ କରିବେ?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"ଯେତେବେଳେ ଆପଣ <xliff:g id="APPNAME">%s</xliff:g>କୁ ଯୋଗ କରନ୍ତି, ସେତେବେଳେ ଏହି ପେନେଲରେ ଏହା ନିୟନ୍ତ୍ରଣ ଏବଂ ବିଷୟବସ୍ତୁ ଯୋଗ କରିପାରିବ। କିଛି ଆପ୍ସରେ, ଏଠାରେ କେଉଁ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଦେଖାଯିବ ତାହା ଆପଣ ବାଛିପାରିବେ।"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ପସନ୍ଦ କରାଯାଇଛି"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ପସନ୍ଦ କରାଯାଇଛି, ସ୍ଥିତି <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ନାପସନ୍ଦ କରାଯାଇଛି"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ଖୋଲନ୍ତୁ"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ରୁ <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ଙ୍କ <xliff:g id="SONG_NAME">%1$s</xliff:g> ଚଲାନ୍ତୁ"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g>ରୁ <xliff:g id="SONG_NAME">%1$s</xliff:g> ଚଲାନ୍ତୁ"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"ଆପଣଙ୍କ ପାଇଁ"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"ପୂର୍ବବତ୍ କରନ୍ତୁ"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ରେ ପ୍ଲେ କରିବା ପାଇଁ ପାଖକୁ ମୁଭ କରନ୍ତୁ"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ଏଠାରେ ପ୍ଲେ କରିବା ପାଇଁ <xliff:g id="DEVICENAME">%1$s</xliff:g> ପାଖକୁ ମୁଭ କରନ୍ତୁ"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"ତ୍ରୁଟି ହୋଇଛି, ପୁଣି ଚେଷ୍ଟା କର"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଏଡିଟ କରନ୍ତୁ"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ଆପ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ଆଉଟପୁଟ୍ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ଗୋଷ୍ଠୀ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1ଟି ଡିଭାଇସ୍ ଚୟନ କରାଯାଇଛି"</string>
@@ -919,7 +915,6 @@
     <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">"ସ୍ପିକର ଏବଂ ଡିସପ୍ଲେଗୁଡ଼ିକ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"ପ୍ରସ୍ତାବିତ ଡିଭାଇସଗୁଡ଼ିକ"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"ପ୍ରିମିୟମ ଆକାଉଣ୍ଟ ଆବଶ୍ୟକ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ବ୍ରଡକାଷ୍ଟିଂ କିପରି କାମ କରେ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ବ୍ରଡକାଷ୍ଟ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ଆପଣଙ୍କ ଆଖପାଖର କମ୍ପାଟିବଲ ବ୍ଲୁଟୁଥ ଡିଭାଇସ ଥିବା ଲୋକମାନେ ଆପଣ ବ୍ରଡକାଷ୍ଟ କରୁଥିବା ମିଡିଆ ଶୁଣିପାରିବେ"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"କ୍ୟାମେରା ବନ୍ଦ ଅଛି"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"ମାଇକ ବନ୍ଦ ଅଛି"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"କ୍ୟାମେରା ଏବଂ ମାଇକ ବନ୍ଦ ଅଛି"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{#ଟି ବିଜ୍ଞପ୍ତି}other{#ଟି ବିଜ୍ଞପ୍ତି}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"ନୋଟଟେକିଂ"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"ଗୋଟିଏ-ଥର ଆକ୍ସେସ ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"ଆପଣଙ୍କ ଡିଭାଇସରେ ଯାହା ହୁଏ ତାହା ଡିଭାଇସ ଲଗଗୁଡ଼ିକ ରେକର୍ଡ କରେ। ସମସ୍ୟାଗୁଡ଼ିକୁ ଖୋଜି ସମାଧାନ କରିବାକୁ ଆପ୍ସ ଏହି ଲଗଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିପାରିବ।\n\nକିଛି ଲଗରେ ସମ୍ବେଦନଶୀଳ ସୂଚନା ଥାଇପାରେ, ତେଣୁ ସମସ୍ତ ଡିଭାଇସ ଲଗକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଆପଣ ବିଶ୍ୱାସ କରୁଥିବା ଆପ୍ସକୁ ହିଁ କେବଳ ଅନୁମତି ଦିଅନ୍ତୁ। \n\nଯଦି ଆପଣ ସମସ୍ତ ଡିଭାଇସ ଲଗକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଏହି ଆପକୁ ଅନୁମତି ଦିଅନ୍ତି ନାହିଁ, ତେବେ ଏହା ନିଜର ଡିଭାଇସ ଲଗଗୁଡ଼ିକୁ ଏବେ ବି ଆକ୍ସେସ କରିପାରିବ। ଆପଣଙ୍କ ଡିଭାଇସର ନିର୍ମାତା ଏବେ ବି ଆପଣଙ୍କର ଡିଭାଇସରେ କିଛି ଲଗ କିମ୍ବା ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ସକ୍ଷମ ହୋଇପାରନ୍ତି।"</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ଖୋଲନ୍ତୁ"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ଆପ ସେଟ ଅପ କରାଯାଇଥିବା"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Walletରେ ଅତିକମରେ ଗୋଟିଏ କାର୍ଡ ଯୋଗ କରାଯାଇଥିବା"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"ଆପଣଙ୍କ ୱାର୍କ ନୀତି ଆପଣଙ୍କୁ କେବଳ ୱାର୍କ ପ୍ରୋଫାଇଲରୁ ଫୋନ କଲ କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ୱାର୍କ ପ୍ରୋଫାଇଲକୁ ସ୍ୱିଚ କରନ୍ତୁ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ବନ୍ଦ କରନ୍ତୁ"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"ଲକ ସ୍କ୍ରିନ ସେଟିଂସ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index be4e149..275ab57 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ਹੇਠਾਂ ਦੀ ਸੀਮਾ <xliff:g id="PERCENT">%1$d</xliff:g> ਫ਼ੀਸਦ"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ਖੱਬੇ ਪਾਸੇ ਵਾਲੀ ਸੀਮਾ <xliff:g id="PERCENT">%1$d</xliff:g> ਫ਼ੀਸਦ"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ਸੱਜੇ ਪਾਸੇ ਵਾਲੀ ਸੀਮਾ <xliff:g id="PERCENT">%1$d</xliff:g> ਫ਼ੀਸਦ"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"ਕਾਰਜ ਸਕ੍ਰੀਨਸ਼ਾਟਾਂ ਨੂੰ <xliff:g id="APP">%1$s</xliff:g> ਐਪ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ਫ਼ਾਈਲਾਂ"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਜਾਰੀ ਹੈ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਖੋਲ੍ਹਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ਖੱਬੇ ਲਿਜਾਓ"</item>
-    <item msgid="5558598599408514296">"ਹੇਠਾਂ ਲਿਜਾਓ"</item>
-    <item msgid="4844142668312841831">"ਸੱਜੇ ਲਿਜਾਓ"</item>
-    <item msgid="5640521437931460125">"ਉੱਪਰ ਲਿਜਾਓ"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਉੱਤੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਐਪ ਚੁਣੋ"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ।}one{# ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ।}other{# ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤੇ ਗਏ।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ਹਟਾਇਆ ਗਿਆ"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"ਕੀ <xliff:g id="APPNAME">%s</xliff:g> ਸ਼ਾਮਲ ਕਰਨਾ ਹੈ?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"ਜਦੋਂ ਤੁਸੀਂ <xliff:g id="APPNAME">%s</xliff:g> ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਹ ਇਸ ਪੈਨਲ ਵਿੱਚ ਕੰਟਰੋਲਾਂ ਅਤੇ ਸਮੱਗਰੀ ਨੂੰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੀ ਹੈ। ਕੁਝ ਐਪਾਂ ਲਈ, ਤੁਸੀਂ ਇਹ ਚੁਣ ਸਕਦੇ ਹੋ ਕਿ ਇੱਥੇ ਕਿਹੜੇ ਕੰਟਰੋਲ ਦਿਸਣ।"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ, ਸਥਾਨ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ਮਨਪਸੰਦ ਵਿੱਚੋਂ ਹਟਾਇਆ ਗਿਆ"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ਖੋਲ੍ਹੋ"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ਤੋਂ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ਦਾ <xliff:g id="SONG_NAME">%1$s</xliff:g> ਚਲਾਓ"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> ਤੋਂ <xliff:g id="SONG_NAME">%1$s</xliff:g> ਚਲਾਓ"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"ਤੁਹਾਡੇ ਲਈ"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"ਅਣਕੀਤਾ ਕਰੋ"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> \'ਤੇ ਚਲਾਉਣ ਲਈ ਨੇੜੇ ਲਿਜਾਓ"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ਇੱਥੇ ਚਲਾਉਣ ਲਈ, <xliff:g id="DEVICENAME">%1$s</xliff:g> ਦੇ ਨੇੜੇ ਲਿਆਓ"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"ਗੜਬੜ, ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ਕੰਟਰੋਲਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ਐਪ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ਆਊਟਪੁੱਟ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ਗਰੁੱਪ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ਡੀਵਾਈਸ ਨੂੰ ਚੁਣਿਆ ਗਿਆ"</string>
@@ -919,7 +918,6 @@
     <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">"ਸਪੀਕਰ ਅਤੇ ਡਿਸਪਲੇਆਂ"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"ਸੁਝਾਏ ਗਏ ਡੀਵਾਈਸ"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"ਪ੍ਰੀਮੀਅਮ ਖਾਤੇ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ਪ੍ਰਸਾਰਨ ਕਿਵੇਂ ਕੰਮ ਕਰਦਾ ਹੈ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ਪ੍ਰਸਾਰਨ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ਅਨੁਰੂਪ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨਾਲ ਨਜ਼ਦੀਕੀ ਲੋਕ ਤੁਹਾਡੇ ਵੱਲੋਂ ਪ੍ਰਸਾਰਨ ਕੀਤੇ ਜਾ ਰਹੇ ਮੀਡੀਆ ਨੂੰ ਸੁਣ ਸਕਦੇ ਹਨ"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"ਕੈਮਰਾ ਬੰਦ ਹੈ"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"ਮਾਈਕ ਬੰਦ ਹੈ"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ ਬੰਦ ਹਨ"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ਸੂਚਨਾ}one{# ਸੂਚਨਾ}other{# ਸੂਚਨਾਵਾਂ}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"ਨੋਟ ਬਣਾਉਣਾ"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"ਇੱਕ-ਵਾਰ ਲਈ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"ਆਗਿਆ ਨਾ ਦਿਓ"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"ਡੀਵਾਈਸ ਲੌਗਾਂ ਵਿੱਚ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀਆਂ ਕਾਰਵਾਈਆਂ ਰਿਕਾਰਡ ਹੁੰਦੀਆਂ ਹਨ। ਐਪਾਂ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਲੱਭਣ ਅਤੇ ਉਨ੍ਹਾਂ ਦਾ ਹੱਲ ਕਰਨ ਲਈ ਇਨ੍ਹਾਂ ਲੌਗਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੀਆਂ ਹਨ।\n\nਕੁਝ ਲੌਗਾਂ ਵਿੱਚ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀ ਹੈ, ਇਸ ਲਈ ਸਿਰਫ਼ ਆਪਣੀਆਂ ਭਰੋਸੇਯੋਗ ਐਪਾਂ ਨੂੰ ਹੀ ਸਾਰੇ ਡੀਵਾਈਸ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ। \n\nਜੇ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਸਾਰੇ ਡੀਵਾਈਸ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਦਿੰਦੇ ਹੋ, ਤਾਂ ਇਹ ਹਾਲੇ ਵੀ ਆਪਣੇ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ। ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਨਿਰਮਾਤਾ ਹਾਲੇ ਵੀ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਮੌਜੂਦ ਕੁਝ ਲੌਗਾਂ ਜਾਂ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ਖੋਲ੍ਹੋ"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ਐਪ ਦਾ ਸੈੱਟਅੱਪ ਹੋ ਗਿਆ ਹੈ"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ਘੱਟੋ-ਘੱਟ ਇੱਕ ਕਾਰਡ ਨੂੰ Wallet ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"ਤੁਹਾਡੀ ਕਾਰਜ ਨੀਤੀ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਹੀ ਫ਼ੋਨ ਕਾਲਾਂ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ \'ਤੇ ਜਾਓ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ਬੰਦ ਕਰੋ"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index b9c3fa6..3c29716 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Przycięcie dolnej krawędzi o <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Przycięcie lewej krawędzi o <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Przycięcie prawej krawędzi o <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Służbowe zrzuty ekranu są zapisywane w aplikacji <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Pliki"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Nagrywanie ekranu"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Przetwarzam nagrywanie ekranu"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Twarz rozpoznana. Aby otworzyć, kliknij ikonę odblokowywania."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odblokowano skanem twarzy"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Twarz rozpoznana"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Przenieś w lewo"</item>
-    <item msgid="5558598599408514296">"Przenieś w dół"</item>
-    <item msgid="4844142668312841831">"Przenieś w prawo"</item>
-    <item msgid="5640521437931460125">"Przenieś w górę"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Przesuń w górę, by spróbować ponownie"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odblokuj, by użyć komunikacji NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"To urządzenie należy do Twojej organizacji"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Wybierz aplikację, do której chcesz dodać elementy sterujące"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Dodano # element sterujący.}few{Dodano # elementy sterujące.}many{Dodano # elementów sterujących.}other{Dodano # elementu sterującego.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Usunięto"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Dodać aplikację <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Gdy dodasz aplikację <xliff:g id="APPNAME">%s</xliff:g>, będzie ona mogła dodawać elementy sterujące i treści do tego panelu. W niektórych aplikacjach można wybrać elementy sterujące, które się tu pojawią."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano do ulubionych"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano do ulubionych, pozycja <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Usunięto z ulubionych"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otwórz aplikację <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Odtwórz utwór <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) w aplikacji <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Odtwórz utwór <xliff:g id="SONG_NAME">%1$s</xliff:g> w aplikacji <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Dla Ciebie"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Cofnij"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Przysuń się bliżej, aby odtwarzać na urządzeniu <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Aby zagrać tutaj, przysuń bliżej urządzenie <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Błąd, spróbuj ponownie"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Dodaj elementy sterujące"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edytuj elementy sterujące"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikację"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodaj urządzenia wyjściowe"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Wybrano 1 urządzenie"</string>
@@ -919,7 +918,6 @@
     <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">"Głośniki i wyświetlacze"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Proponowane urządzenia"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Wymagane konto premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak działa transmitowanie"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmisja"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osoby w pobliżu ze zgodnymi urządzeniami Bluetooth mogą słuchać transmitowanych przez Ciebie multimediów"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera jest wyłączona"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon jest wyłączony"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Aparat i mikrofon są wyłączone"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# powiadomienie}few{# powiadomienia}many{# powiadomień}other{# powiadomienia}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notatki"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Zezwól na jednorazowy dostęp"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Nie zezwalaj"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Dzienniki urządzenia zapisują, co dzieje się na urządzeniu. Aplikacje mogą ich używać do wykrywania i rozwiązywania problemów.\n\nNiektóre dzienniki mogą zawierać poufne dane, dlatego na dostęp do wszystkich dzienników zezwalaj tylko aplikacjom, którym ufasz. \n\nNawet jeśli nie zezwolisz tej aplikacji na dostęp do wszystkich dzienników na urządzeniu, będzie mogła korzystać z własnych. Producent urządzenia nadal będzie mógł używać niektórych dzienników na urządzeniu."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otwórz: <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacja została skonfigurowana."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Do Portfela została dodana co najmniej 1 karta."</string>
@@ -1058,7 +1062,7 @@
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Rozłóż telefon, aby uzyskać lepszej jakości selfie"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Przełączyć na przedni wyświetlacz?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Użyj tylnego aparatu, aby zrobić szersze zdjęcie o większej rozdzielczości."</string>
-    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Ekran się wyłączy"</b></string>
+    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Ten ekran się wyłączy"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Składane urządzenie jest rozkładane"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Składane urządzenie jest obracane"</string>
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g> baterii"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Zasady obowiązujące w firmie zezwalają na nawiązywanie połączeń telefonicznych tylko w profilu służbowym"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Przełącz na profil służbowy"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zamknij"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Ustawienia ekranu blokady"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 8bb3e7d..e21d41c 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Borda inferior em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Borda esquerda em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Borda direita em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Capturas de tela do trabalho são salvas no app <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Salva no app <xliff:g id="APP">%1$s</xliff:g> no perfil de trabalho"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"O app <xliff:g id="APPNAME">%1$s</xliff:g> detectou essa captura de tela."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outros apps abertos detectaram essa captura de tela."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravador de tela"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Pressione o ícone de desbloq. para abrir."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado pelo rosto"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Rosto reconhecido"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Mais para a esquerda"</item>
-    <item msgid="5558598599408514296">"Mais para baixo"</item>
-    <item msgid="4844142668312841831">"Mais para a direita"</item>
-    <item msgid="5640521437931460125">"Mais para cima"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string>
@@ -500,7 +498,7 @@
     <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Chamadas e notificações farão o smartphone tocar (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
     <string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador System UI"</string>
     <string name="status_bar" msgid="4357390266055077437">"Barra de status"</string>
-    <string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da IU do sistema"</string>
+    <string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da interface do sistema"</string>
     <string name="enable_demo_mode" msgid="3180345364745966431">"Ativar modo de demonstração"</string>
     <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo de demonstração"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Escolha um app para adicionar controles"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar o app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Quando você adiciona o app <xliff:g id="APPNAME">%s</xliff:g>, ele pode incluir controles e conteúdo neste painel. Em alguns casos, é possível escolher quais controles aparecem aqui."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abrir <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> no app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> no app <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Para você"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Desfazer"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Aproxime os dispositivos para tocar a mídia neste: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Para abrir aqui, aproxime-se do dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Erro. Tente novamente"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controles"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adicionar app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicionar saídas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
@@ -919,7 +915,6 @@
     <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_status_require_premium" msgid="5691200962588753380">"Requer uma conta premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"A câmera está desativada"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"O microfone está desativado"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmera e o microfone estão desativados"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}many{# notificações}other{# notificações}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Anotações"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir o acesso único"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Não permitir"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Os registros do dispositivo gravam o que acontece nele. Os apps podem usar esses registros para encontrar e corrigir problemas.\n\nAlguns registros podem conter informações sensíveis, então autorize o acesso a eles apenas para os apps em que você confia. \n\nSe você não permitir que esse app acesse todos os registros do dispositivo, ele ainda vai poder acessar os próprios. O fabricante do dispositivo também pode ter acesso a alguns registros ou informações."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• O app está disponível"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Pelo menos um cartão foi adicionado à Carteira"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Sua política de trabalho só permite fazer ligações pelo perfil de trabalho"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Configurações de tela de bloqueio"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 19e9194..4effeb2 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -91,8 +91,11 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Limite inferior de <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite esquerdo de <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite direito de <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"As capturas de ecrã do trabalho são guardadas na app <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Guardada na app <xliff:g id="APP">%1$s</xliff:g> no perfil de trabalho"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Ficheiros"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"A app <xliff:g id="APPNAME">%1$s</xliff:g> detetou esta captura de ecrã."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"A app <xliff:g id="APPNAME">%1$s</xliff:g> e outras apps abertas detetaram esta captura de ecrã."</string>
+    <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Adicionar a uma nota"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravador de ecrã"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"A processar a gravação de ecrã"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação persistente de uma sessão de gravação de ecrã"</string>
@@ -339,12 +342,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Prima o ícone de desbloqueio para abrir."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado com o rosto"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Rosto reconhecido"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Mover para a esquerda"</item>
-    <item msgid="5558598599408514296">"Mover para baixo"</item>
-    <item msgid="4844142668312841831">"Mover para a direita"</item>
-    <item msgid="5640521437931460125">"Mover para cima"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Deslize rapidamente para cima para tentar novamente."</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloquear para utilizar o NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua entidade."</string>
@@ -832,10 +829,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Escolha uma app para adicionar controlos"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controlo adicionado.}many{# controlos adicionados.}other{# controlos adicionados.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Quando adicionar a app <xliff:g id="APPNAME">%s</xliff:g>, esta pode adicionar controlos e conteúdos a este painel. Em algumas apps, pode escolher que controlos são apresentados aqui."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado aos favoritos"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionados aos favoritos, posição <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
@@ -886,6 +881,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abrir <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproduzir <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> a partir da app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproduzir <xliff:g id="SONG_NAME">%1$s</xliff:g> a partir da app <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Para si"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Anular"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Aproxime-se para reproduzir no dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Para reproduzir aqui, aproxime-se do <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +898,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Erro. Tente novamente."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controlos"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controlos"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adicionar app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicione saídas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
@@ -919,7 +914,6 @@
     <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">"Altifalantes e ecrãs"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Requer uma conta premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmissão"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas de si com dispositivos Bluetooth compatíveis podem ouvir o conteúdo multimédia que está a transmitir"</string>
@@ -1031,6 +1025,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"A câmara está desativada"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"O microfone está desativado"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmara e o microfone estão desativados"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"O Assistente está a ouvir"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}many{# notificações}other{# notificações}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Tomar notas"</string>
@@ -1046,6 +1041,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir acesso único"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Não permitir"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Os registos do dispositivo documentam o que ocorre no seu dispositivo. As apps podem usar esses registos para detetar e corrigir problemas.\n\nAlguns registos podem conter informações confidenciais e, por isso, o acesso a todos os registos do dispositivo só deve ser permitido às apps nas quais confia. \n\nSe não permitir o acesso desta app a todos os registos do dispositivo, esta pode ainda assim aceder aos próprios registos. O fabricante do dispositivo pode continuar a aceder a alguns registos ou informações no seu dispositivo."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saiba mais"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saiba mais em <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• A app está configurada"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Foi adicionado, pelo menos, um cartão à Carteira"</string>
@@ -1069,6 +1066,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"A sua Política de Trabalho só lhe permite fazer chamadas telefónicas a partir do perfil de trabalho"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Mudar para perfil de trabalho"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Definições do ecrã de bloqueio"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 8bb3e7d..e21d41c 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Borda inferior em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Borda esquerda em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Borda direita em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Capturas de tela do trabalho são salvas no app <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Salva no app <xliff:g id="APP">%1$s</xliff:g> no perfil de trabalho"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"O app <xliff:g id="APPNAME">%1$s</xliff:g> detectou essa captura de tela."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outros apps abertos detectaram essa captura de tela."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Gravador de tela"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Rosto reconhecido. Pressione o ícone de desbloq. para abrir."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Desbloqueado pelo rosto"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Rosto reconhecido"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Mais para a esquerda"</item>
-    <item msgid="5558598599408514296">"Mais para baixo"</item>
-    <item msgid="4844142668312841831">"Mais para a direita"</item>
-    <item msgid="5640521437931460125">"Mais para cima"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Deslize para cima para tentar novamente"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Desbloqueie para usar a NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Este dispositivo pertence à sua organização"</string>
@@ -500,7 +498,7 @@
     <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Chamadas e notificações farão o smartphone tocar (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
     <string name="system_ui_tuner" msgid="1471348823289954729">"Sintonizador System UI"</string>
     <string name="status_bar" msgid="4357390266055077437">"Barra de status"</string>
-    <string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da IU do sistema"</string>
+    <string name="demo_mode" msgid="263484519766901593">"Modo de demonstração da interface do sistema"</string>
     <string name="enable_demo_mode" msgid="3180345364745966431">"Ativar modo de demonstração"</string>
     <string name="show_demo_mode" msgid="3677956462273059726">"Mostrar modo de demonstração"</string>
     <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Escolha um app para adicionar controles"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar o app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Quando você adiciona o app <xliff:g id="APPNAME">%s</xliff:g>, ele pode incluir controles e conteúdo neste painel. Em alguns casos, é possível escolher quais controles aparecem aqui."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abrir <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> no app <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> no app <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Para você"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Desfazer"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Aproxime os dispositivos para tocar a mídia neste: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Para abrir aqui, aproxime-se do dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Erro. Tente novamente"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controles"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adicionar app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicionar saídas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
@@ -919,7 +915,6 @@
     <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_status_require_premium" msgid="5691200962588753380">"Requer uma conta premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"A câmera está desativada"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"O microfone está desativado"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmera e o microfone estão desativados"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}many{# notificações}other{# notificações}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Anotações"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir o acesso único"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Não permitir"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Os registros do dispositivo gravam o que acontece nele. Os apps podem usar esses registros para encontrar e corrigir problemas.\n\nAlguns registros podem conter informações sensíveis, então autorize o acesso a eles apenas para os apps em que você confia. \n\nSe você não permitir que esse app acesse todos os registros do dispositivo, ele ainda vai poder acessar os próprios. O fabricante do dispositivo também pode ter acesso a alguns registros ou informações."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• O app está disponível"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Pelo menos um cartão foi adicionado à Carteira"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Sua política de trabalho só permite fazer ligações pelo perfil de trabalho"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Configurações de tela de bloqueio"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 2473153..fa7ab4d 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Marginea de jos la <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Marginea stângă la <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Marginea dreaptă la <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Capturile de ecran pentru serviciu sunt salvate în aplicația <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Salvată în <xliff:g id="APP">%1$s</xliff:g> în profilul de serviciu"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fișiere"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> a detectat această captură de ecran."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> și alte aplicații deschise au detectat această captură de ecran."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Recorder pentru ecran"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Se procesează înregistrarea"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Chip recunoscut. Apasă pictograma Deblocare ca să deschizi."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"S-a deblocat folosind fața"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Chipul a fost recunoscut"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Mută la stânga"</item>
-    <item msgid="5558598599408514296">"Mută în jos"</item>
-    <item msgid="4844142668312841831">"Mută la dreapta"</item>
-    <item msgid="5640521437931460125">"Mută în sus"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Glisează pentru a încerca din nou"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Deblochează pentru a folosi NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Dispozitivul aparține organizației tale"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Alege aplicația pentru a adăuga comenzi"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{S-a adăugat # comandă.}few{S-au adăugat # comenzi.}other{S-au adăugat # de comenzi.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Eliminată"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Adaugi <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Când adaugi <xliff:g id="APPNAME">%s</xliff:g>, aplicația poate să adauge comenzi și conținut pe acest panou. În anumite aplicații, poți să alegi comenzile care se afișează aici."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Marcată ca preferată"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Marcată ca preferată, poziția <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"S-a anulat marcarea ca preferată"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Deschide <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Redă <xliff:g id="SONG_NAME">%1$s</xliff:g> de la <xliff:g id="ARTIST_NAME">%2$s</xliff:g> în <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Redă <xliff:g id="SONG_NAME">%1$s</xliff:g> în <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Pentru tine"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Anulează"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Apropie-te pentru a reda pe <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Pentru a reda conținutul aici, apropie-te de <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Eroare, încearcă din nou"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Adaugă comenzi"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editează comenzile"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adaugă o aplicație"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adaugă ieșiri"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"S-a selectat un dispozitiv"</string>
@@ -919,7 +915,6 @@
     <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_suggested_device" msgid="4157186235837903826">"Dispozitive sugerate"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Necesită un cont premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cum funcționează transmisia"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmite"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Persoanele din apropiere cu dispozitive Bluetooth compatibile pot asculta conținutul pe care îl transmiți"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Camera foto este dezactivată"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Microfonul este dezactivat"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Camera și microfonul sunt dezactivate"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificare}few{# notificări}other{# de notificări}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Notetaking"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Permite accesul o dată"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Nu permite"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Jurnalele dispozitivului înregistrează activitatea de pe dispozitivul tău. Aplicațiile pot folosi aceste jurnale pentru a identifica și a remedia probleme.\n\nUnele jurnale pot să conțină informații sensibile, prin urmare permite accesul la toate jurnalele dispozitivului doar aplicațiilor în care ai încredere. \n\nDacă nu permiți accesul aplicației la toate jurnalele dispozitivului, aceasta poate în continuare să acceseze propriile jurnale. Este posibil ca producătorul dispozitivului să acceseze în continuare unele jurnale sau informații de pe dispozitiv."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Deschide <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplicația este configurată"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Cel puțin un card a fost adăugat în Portofel"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Politica privind activitatea îți permite să efectuezi apeluri telefonice numai din profilul de serviciu"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Comută la profilul de serviciu"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Închide"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Setările ecranului de blocare"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 830b0c1..15bb14f 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Граница снизу: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Граница слева: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Граница справа: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Скриншоты сохраняются в приложении \"<xliff:g id="APP">%1$s</xliff:g>\" в рабочем профиле"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Скриншот сохранен в рабочем профиле в приложении <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Файлы"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"Приложение \"<xliff:g id="APPNAME">%1$s</xliff:g>\" обнаружило создание скриншота."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Приложение \"<xliff:g id="APPNAME">%1$s</xliff:g>\" и другие запущенные продукты обнаружили создание скриншота."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Запись видео с экрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обработка записи с экрана…"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лицо распознано. Нажмите на значок разблокировки."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Разблокировано сканированием лица"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лицо распознано"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Переместите палец влево"</item>
-    <item msgid="5558598599408514296">"Переместите палец вниз"</item>
-    <item msgid="4844142668312841831">"Переместите палец вправо"</item>
-    <item msgid="5640521437931460125">"Переместите палец вверх"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Чтобы повторить попытку, проведите вверх"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Чтобы использовать NFC, разблокируйте устройство."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Это устройство принадлежит вашей организации"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Чтобы добавить виджеты управления, выберите приложение"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Добавлен # элемент управления.}one{Добавлен # элемент управления.}few{Добавлено # элемента управления.}many{Добавлено # элементов управления.}other{Добавлено # элемента управления.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Удалено"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Добавить приложение \"<xliff:g id="APPNAME">%s</xliff:g>\"?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Приложение \"<xliff:g id="APPNAME">%s</xliff:g>\" может добавить на эту панель элементы управления и контент. Некоторые приложения позволяют выбирать, какие элементы будут здесь показаны."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Добавлено в избранное"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Добавлено в избранное на позицию <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Не добавлено в избранное"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Открыть приложение \"<xliff:g id="APP_LABEL">%1$s</xliff:g>\""</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Воспроизвести медиафайл \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" (исполнитель: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) из приложения \"<xliff:g id="APP_LABEL">%3$s</xliff:g>\""</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Воспроизвести медиафайл \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" из приложения \"<xliff:g id="APP_LABEL">%2$s</xliff:g>\""</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Для вас"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Отменить"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Чтобы начать трансляцию на устройстве \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\", подойдите к нему ближе."</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Чтобы начать воспроизведение здесь, подойдите ближе к устройству (<xliff:g id="DEVICENAME">%1$s</xliff:g>)."</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Ошибка. Повторите попытку."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Добавить виджеты"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Изменить виджеты"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Добавить приложение"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Добавление устройств вывода"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Группа"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрано 1 устройство"</string>
@@ -919,7 +915,6 @@
     <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">"Колонки и дисплеи"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Рекомендуемые устройства"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Требуется премиум-аккаунт"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работают трансляции"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляция"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Находящиеся рядом с вами люди с совместимыми устройствами Bluetooth могут слушать медиафайлы, которые вы транслируете."</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Камера отключена"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Микрофон отключен"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера и микрофон отключены"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# уведомление}one{# уведомление}few{# уведомления}many{# уведомлений}other{# уведомления}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Создание заметок"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Разрешить разовый доступ"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Запретить"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"В журналы записывается информация о том, что происходит на устройстве. Приложения могут использовать их, чтобы находить и устранять неполадки.\n\nТак как некоторые журналы могут содержать конфиденциальную информацию, доступ ко всем журналам следует предоставлять только тем приложениям, которым вы доверяете. \n\nЕсли вы не предоставите такой доступ этому приложению, оно по-прежнему сможет просматривать свои журналы. Не исключено, что некоторые журналы или сведения на вашем устройстве будут по-прежнему доступны его производителю."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Открыть \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Приложение установлено."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• В Кошельке есть хотя бы одна карта."</string>
@@ -1056,7 +1057,7 @@
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Отмена"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Перевернуть сейчас"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Разложите телефон, чтобы селфи получилось лучше"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Перевернули телефон передним экраном к себе?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Перейти на передний экран?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Используйте основную камеру с широкоугольным объективом и высоким разрешением."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Этот экран отключится"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складное устройство в разложенном виде"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Согласно правилам вашей организации вы можете совершать телефонные звонки только из рабочего профиля."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Перейти в рабочий профиль"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрыть"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Настройки блокировки экрана"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index bee211a..31bb2ae 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"පහළ සීමාව සියයට <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"වම් සීමාව සියයට <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"දකුණු සීමාව සියයට <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"වැඩ තිර රූ <xliff:g id="APP">%1$s</xliff:g> යෙදුම තුළ සුරැකෙයි"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ගොනු"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"තිර රෙකෝඩරය"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"තිර පටිගත කිරීම සකසමින්"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"මුහුණ හඳුනා ගන්නා ලදි. විවෘත කිරීමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"මුහුණ මගින් අගුලු හරින ලදි"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"මුහුණ හඳුනා ගන්නා ලදි"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"වමට ගෙන යන්න"</item>
-    <item msgid="5558598599408514296">"පහළට ගෙන යන්න"</item>
-    <item msgid="4844142668312841831">"දකුණට ගෙන යන්න"</item>
-    <item msgid="5640521437931460125">"ඉහළට ගෙන යන්න"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"නැවත උත්සාහ කිරීමට ඉහළට ස්වයිප් කරන්න"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC භාවිත කිරීමට අගුලු හරින්න"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"පාලන එක් කිරීමට යෙදුම තෝරා ගන්න"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# පාලනයක් එක් කර ඇත.}one{පාලන #ක් එක් කර ඇත.}other{පාලන #ක් එක් කර ඇත.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ඉවත් කළා"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> එක් කරන්න ද?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"ඔබ <xliff:g id="APPNAME">%s</xliff:g> එක් කළ විට, එයට මෙම පැනලයට පාලන සහ අන්තර්ගතය එක් කළ හැක. සමහර යෙදුම්වල, ඔබට මෙහි පෙන්වන්නේ කුමන පාලන ද යන්න තෝරා ගැනීමට හැක."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ප්‍රියතම කළා"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ප්‍රියතම කළා, තත්ත්ව <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ප්‍රියතම වෙතින් ඉවත් කළා"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> විවෘත කරන්න"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>ගේ <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%3$s</xliff:g> වෙතින් වාදනය කරන්න"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%2$s</xliff:g> වෙතින් වාදනය කරන්න"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"ඔබට"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"පසුගමනය කරන්න"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> හි වාදනය කිරීමට වඩාත් ළං වන්න"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"මෙහි වාදනය කිරීම සඳහා, <xliff:g id="DEVICENAME">%1$s</xliff:g> වෙත සමීප වන්න"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"දෝෂයකි, නැවත උත්සාහ කරන්න"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"පාලන එක් කරන්න"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"පාලන සංස්කරණය කරන්න"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"යෙදුම එක් කරන්න"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ප්‍රතිදාන එක් කරන්න"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"සමූහය"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"උපාංග 1ක් තෝරන ලදී"</string>
@@ -919,7 +918,6 @@
     <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">"ස්පීකර් සහ සංදර්ශක"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"යෝජිත උපාංග"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"පාරිතෝෂික ගිණුමක් අවශ්‍යයි"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"විකාශනය ක්‍රියා කරන ආකාරය"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"විකාශනය"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ගැළපෙන බ්ලූටූත් උපාංග සහිත ඔබ අවට සිටින පුද්ගලයින්ට ඔබ විකාශනය කරන මාධ්‍යයට සවන් දිය හැකිය"</string>
@@ -1031,6 +1029,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"කැමරාව ක්‍රියා විරහිතයි"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"මයිකය ක්‍රියා විරහිතයි"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"කැමරාව සහ මයික් ක්‍රියාවිරහිතයි"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"සහයක සවන් දෙයි"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{දැනුම්දීම් #ක්}one{දැනුම්දීම් #ක්}other{දැනුම්දීම් #ක්}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"සටහන් කර ගැනීම"</string>
@@ -1046,6 +1045,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"එක් වරක් ප්‍රවේශය ඉඩ දෙන්න"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"ඉඩ නොදෙන්න"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"උපාංග ලොග ඔබේ උපාංගයෙහි සිදු වන දේ වාර්තා කරයි. ගැටලු සොයා ගැනීමට සහ නිරාකරණයට යෙදුම්වලට මෙම ලොග භාවිතා කළ හැක.\n\nසමහර ලොගවල සංවේදී තතු අඩංගු විය හැකි බැවින්, ඔබ විශ්වාස කරන යෙදුම්වලට පමණක් සියලු උපාංග ලොග වෙත ප්‍රවේශ වීමට ඉඩ දෙන්න. \n\nඔබ මෙම යෙදුමට සියලු උපාංග ලොග වෙත ප්‍රවේශ වීමට ඉඩ නොදෙන්නේ නම්, එයට තවමත් එහිම ලොග වෙත ප්‍රවේශ විය හැක. ඔබේ උපාංග නිෂ්පාදකයාට තවමත් ඔබේ උපාංගයෙහි සමහර ලොග හෝ තතු වෙත ප්‍රවේශ විය හැක."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"තව දැන ගන්න"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> තුළින් තව දැන ගන්න"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> විවෘත කරන්න"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• යෙදුම සකසා ඇත"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet වෙත අවම වශයෙන් එක කාඩ්පතක් එක් කර ඇත"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"ඔබේ වැඩ ප්‍රතිපත්තිය ඔබට කාර්යාල පැතිකඩෙන් පමණක් දුරකථන ඇමතුම් ලබා ගැනීමට ඉඩ සලසයි"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"කාර්යාල පැතිකඩ වෙත මාරු වන්න"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"වසන්න"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"අගුළු තිර සැකසීම්"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index beb0ee07..52cfd61 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -91,8 +91,14 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"<xliff:g id="PERCENT">%1$d</xliff:g> %% dolnej hranice"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> %% ľavej hranice"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> %% pravej hranice"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Pracovné snímky obrazovky sú uložené v aplikácii <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pridať do poznámky"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Spracúva sa záznam obrazovky"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string>
@@ -339,12 +345,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Tvár bola rozpoznaná. Otvorte stlačením ikony odomknutia."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odomknuté tvárou"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Tvár bola rozpoznaná"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Posunúť doľava"</item>
-    <item msgid="5558598599408514296">"Posunúť nadol"</item>
-    <item msgid="4844142668312841831">"Posunúť doprava"</item>
-    <item msgid="5640521437931460125">"Posunúť nahor"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Potiahnutím nahor to skúste znova"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ak chcete použiť NFC, odomknite"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Toto zariadenie patrí vašej organizácii"</string>
@@ -832,10 +832,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Vyberte aplikáciu, ktorej ovládače si chcete pridať"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Bol pridaný # ovládací prvok.}few{Boli pridané # ovládacie prvky.}many{# controls added.}other{Bolo pridaných # ovládacích prvkov.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Odstránené"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Chcete pridať aplikáciu <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Keď pridáte aplikáciu <xliff:g id="APPNAME">%s</xliff:g>, bude môcť pridať ovládanie a obsah na tento panel. V prípade niektorých aplikácií môžete vybrať, ktoré ovládacie prvky sa tu majú zobraziť."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Pridané medzi obľúbené"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Pridané medzi obľúbené, pozícia <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odstránené z obľúbených"</string>
@@ -886,6 +884,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvoriť <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Prehrať skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> z aplikácie <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Prehrať skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> z aplikácie <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Pre vás"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Späť"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Ak chcete prehrávať v zariadení <xliff:g id="DEVICENAME">%1$s</xliff:g>, priblížte sa k nemu"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Ak tu chcete prehrávať obsah, priblížte zariadenie k zariadeniu <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +901,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Chyba, skúste to znova"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Pridať ovládače"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Upraviť ovládače"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Pridať aplikáciu"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Pridanie výstupov"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 vybrané zariadenie"</string>
@@ -919,7 +917,6 @@
     <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">"Reproduktory a obrazovky"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Navrhované zariadenia"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Vyžaduje prémiový účet"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ako vysielanie funguje"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Vysielanie"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ľudia v okolí s kompatibilnými zariadeniami s rozhraním Bluetooth si môžu vypočuť médiá, ktoré vysielate"</string>
@@ -1031,6 +1028,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera je vypnutá"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofón je vypnutý"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera a mikrofón sú vypnuté"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Asistent počúva"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# upozornenie}few{# upozornenia}many{# notifications}other{# upozornení}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Zapisovanie poznámok"</string>
@@ -1046,6 +1044,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Povoliť jednorazový prístup"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Nepovoliť"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Denníky zariadenia zaznamenávajú, čo sa deje vo vašom zariadení. Aplikácie môžu pomocou týchto denníkov vyhľadávať a riešiť problémy.\n\nNiektoré denníky môžu obsahovať citlivé údaje, preto povoľte prístup k všetkým denníkom zariadenia iba dôveryhodným aplikáciám. \n\nAk tejto aplikácii nepovolíte prístup k všetkým denníkom zariadenia, stále bude mať prístup k vlastným denníkom. Výrobca vášho zariadenia bude mať naďalej prístup k niektorým denníkom alebo informáciám vo vašom zariadení."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Ďalšie informácie"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Viac sa dozviete na <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvoriť <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikácia je nastavená"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Do Peňaženky bola pridaná minimálne jedna karta"</string>
@@ -1054,9 +1054,9 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• K dispozícii je minimálne jedno zariadenie"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pridržte skratku"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Zrušiť"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Prevráťte"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Otočiť"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Ak chcete lepšie selfie, rozložte telefón"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Prevrátiť na pred. obrazovku pre lepšie selfie?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Otočiť na prednú obrazovku pre lepšie selfie?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Pomocou zadného fotoaparátu vytvorte širšiu fotku s vyšším rozlíšením."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Táto obrazovka sa vypne"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozloženie skladacieho zariadenia"</string>
@@ -1069,6 +1069,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Pracovné pravidlá vám umožňujú telefonovať iba v pracovnom profile"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Prepnúť na pracovný profil"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zavrieť"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Nastavenia uzamknutej obrazovky"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 72eddd3..4ec09f0 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Meja spodaj <xliff:g id="PERCENT">%1$d</xliff:g> odstotkov"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Meja levo <xliff:g id="PERCENT">%1$d</xliff:g> odstotkov"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Meja desno <xliff:g id="PERCENT">%1$d</xliff:g> odstotkov"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Posnetki zaslona v delovnem profilu so shranjeni v aplikaciji <xliff:g id="APP">%1$s</xliff:g>."</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Shranjeno v aplikaciji <xliff:g id="APP">%1$s</xliff:g> v delovnem profilu"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Datoteke"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> je zaznala ta posnetek zaslona."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> in druge odprte aplikacije so zaznale ta posnetek zaslona."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Snemalnik zaslona"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obdelava videoposnetka zaslona"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Nenehno obveščanje o seji snemanja zaslona"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Obraz je prepoznan. Za odpiranje pritisnite ikono za odklepanje."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Odklenjeno z obrazom"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Obraz je prepoznan"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Premik levo"</item>
-    <item msgid="5558598599408514296">"Premik navzdol"</item>
-    <item msgid="4844142668312841831">"Premik desno"</item>
-    <item msgid="5640521437931460125">"Premik navzgor"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Povlecite navzgor za vnovičen poskus"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Odklenite napravo, če želite uporabljati NFC."</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Ta naprava pripada vaši organizaciji"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Izberite aplikacijo za dodajanje kontrolnikov"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrolnik je dodan.}one{# kontrolnik je dodan.}two{# kontrolnika sta dodana.}few{# kontrolniki so dodani.}other{# kontrolnikov je dodanih.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Odstranjeno"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Želite dodati aplikacijo <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Ko dodate aplikacijo <xliff:g id="APPNAME">%s</xliff:g>, lahko ta doda kontrolnike in vsebino v to podokno. V nekaterih aplikacijah lahko izberete, kateri kontrolniki so prikazani tukaj."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano med priljubljene"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano med priljubljene, položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odstranjeno iz priljubljenih"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Odpri aplikacijo <xliff:g id="APP_LABEL">%1$s</xliff:g>."</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Predvajaj skladbo <xliff:g id="SONG_NAME">%1$s</xliff:g> izvajalca <xliff:g id="ARTIST_NAME">%2$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Predvajaj skladbo <xliff:g id="SONG_NAME">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>."</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Za vas"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Razveljavi"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Za predvajanje v napravi <xliff:g id="DEVICENAME">%1$s</xliff:g> bolj približajte telefon"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Če želite predvajati tukaj, se približajte napravi <xliff:g id="DEVICENAME">%1$s</xliff:g>."</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Napaka, poskusite znova"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Dodajte kontrolnike"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Uredite kontrolnike"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikacijo"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajanje izhodov"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izbrana je ena naprava"</string>
@@ -919,7 +915,6 @@
     <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">"Zvočniki in zasloni"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Predlagane naprave"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Obvezen je plačljivi račun"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako deluje oddajanje"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Oddajanje"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osebe v bližini z združljivo napravo Bluetooth lahko poslušajo predstavnost, ki jo oddajate."</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Fotoaparat je izklopljen"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon je izklopljen"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotoaparat in mikrofon sta izklopljena."</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Pomočnik posluša."</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# obvestilo}one{# obvestilo}two{# obvestili}few{# obvestila}other{# obvestil}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Ustvarjanje zapiskov"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Dovoli enkratni dostop"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ne dovoli"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"V dnevnikih naprave se beleži dogajanje v napravi. Aplikacije lahko te dnevnike uporabijo za iskanje in odpravljanje težav.\n\nNekateri dnevniki morda vsebujejo občutljive podatke, zato dostop do vseh dnevnikov naprave omogočite le aplikacijam, ki jim zaupate. \n\nČe tej aplikaciji ne dovolite dostopa do vseh dnevnikov naprave, bo aplikacija kljub temu lahko dostopala do svojih dnevnikov. Proizvajalec naprave bo morda lahko kljub temu dostopal do nekaterih dnevnikov ali podatkov v napravi."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Več o tem"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Več informacij je na voljo na strani <xliff:g id="URL">%s</xliff:g>."</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Odpri aplikacijo <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacija mora biti nastavljena."</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Vsaj ena kartica mora biti dodana v Denarnico."</string>
@@ -1054,7 +1052,7 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Na voljo mora biti vsaj ena naprava."</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pridržite bližnjico"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Prekliči"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Obrnite"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Obrni"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Razprite telefon za boljši selfi"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Obrnite telefon na sprednji zaslon za boljši selfi"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Uporabite hrbtni fotoaparat, da posnamete širšo sliko višje ločljivosti."</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Službeni pravilnik dovoljuje opravljanje telefonskih klicev le iz delovnega profila."</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Preklopi na delovni profil"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zapri"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Nastavitve zaklepanja zaslona"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 0cbd9cd..176ef6f 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Kufiri i poshtëm <xliff:g id="PERCENT">%1$d</xliff:g> për qind"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Kufiri i majtë <xliff:g id="PERCENT">%1$d</xliff:g> për qind"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Kufiri i djathtë <xliff:g id="PERCENT">%1$d</xliff:g> për qind"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Pamjet e ekranit të punës janë ruajtur në aplikacionin \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Ruajtur në <xliff:g id="APP">%1$s</xliff:g> në profilin e punës"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Skedarë"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> zbuloi këtë pamje ekrani."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dhe aplikacionet e tjera të hapura zbuluan këtë pamje ekrani."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Regjistruesi i ekranit"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Regjistrimi i ekranit po përpunohet"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Fytyra u njoh. Shtyp ikonën e shkyçjes për ta hapur."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"U shkyç me fytyrë"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Fytyra u njoh"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Lëvize majtas"</item>
-    <item msgid="5558598599408514296">"Lëvize poshtë"</item>
-    <item msgid="4844142668312841831">"Lëvize djathtas"</item>
-    <item msgid="5640521437931460125">"Lëvize lart"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Rrëshqit lart për të provuar përsëri"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Shkyçe për të përdorur NFC-në"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Kjo pajisje i përket organizatës sate"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Zgjidh aplikacionin për të shtuar kontrollet"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{U shtua # kontroll.}other{U shtuan # kontrolle.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"E hequr"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Të shtohet <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kur shton <xliff:g id="APPNAME">%s</xliff:g>, ai mund t\'i shtojë kontrolle dhe përmbajtje këtij paneli. Në disa aplikacione, mund të zgjedhësh se cilat kontrolle shfaqen këtu."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"E shtuar te të preferuarat"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"E shtuar te të preferuarat, pozicioni <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"E hequr nga të preferuarat"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Hap <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Luaj <xliff:g id="SONG_NAME">%1$s</xliff:g> nga <xliff:g id="ARTIST_NAME">%2$s</xliff:g> nga <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Luaj <xliff:g id="SONG_NAME">%1$s</xliff:g> nga <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Për ty"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Zhbëj"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Afrohu për të luajtur në <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Për ta luajtur këtu, afrohu më shumë te <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Gabim, provo sërish"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Shto kontrollet"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Modifiko kontrollet"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Shto një aplikacion"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Shto daljet"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupi"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 pajisje e zgjedhur"</string>
@@ -919,7 +915,6 @@
     <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">"Altoparlantët dhe ekranet"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Pajisjet e sugjeruara"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Kërkon llogari premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Si funksionon transmetimi"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmetimi"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personat në afërsi me ty me pajisje të përputhshme me Bluetooth mund të dëgjojnë median që ti po transmeton"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera është joaktive"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofoni është joaktiv"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera dhe mikrofoni janë joaktivë"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# njoftim}other{# njoftime}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Mbajtja e shënimeve"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Lejo qasjen vetëm për një herë"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Mos lejo"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Evidencat e pajisjes regjistrojnë çfarë ndodh në pajisjen tënde. Aplikacionet mund t\'i përdorin këto evidenca për të gjetur dhe rregulluar problemet.\n\nDisa evidenca mund të përmbajnë informacione delikate, ndaj lejo vetëm aplikacionet që u beson të kenë qasje te të gjitha evidencat e pajisjes. \n\nNëse nuk e lejon këtë aplikacion që të ketë qasje te të gjitha evidencat e pajisjes, ai mund të vazhdojë të ketë qasje tek evidencat e tij. Prodhuesi i pajisjes sate mund të jetë ende në gjendje që të ketë qasje te disa evidenca ose informacione në pajisjen tënde."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Hap \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacioni është konfiguruar"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Të paktën një kartë të jetë shtuar në \"Portofol\""</string>
@@ -1054,7 +1055,7 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ofrohet të paktën një pajisje"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Prek dhe mbaj shtypur shkurtoren"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Anulo"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"U kthye tani"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Ktheje tani"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Shpalos telefonin për një selfi më të mirë"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Të kthehet tek ekrani para për selfi më të mirë?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Përdor lenten e kamerës së pasme për një fotografi më të gjerë me rezolucion më të lartë."</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Politika jote e punës të lejon të bësh telefonata vetëm nga profili i punës"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Kalo te profili i punës"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Mbyll"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Cilësimet e ekranit të kyçjes"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 4c685a9..c141051 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Доња ивица <xliff:g id="PERCENT">%1$d</xliff:g> посто"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Лева ивица <xliff:g id="PERCENT">%1$d</xliff:g> посто"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Десна ивица <xliff:g id="PERCENT">%1$d</xliff:g> посто"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Снимци екрана за посао се чувају у апликацији <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Сачувано је у апликацији <xliff:g id="APP">%1$s</xliff:g> на пословном профилу"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Фајлови"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"Апликација <xliff:g id="APPNAME">%1$s</xliff:g> је открила овај снимак екрана."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и друге отворене апликације су откриле овај снимак екрана."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Снимач екрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обрађујемо видео снимка екрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Лице препознато. Притисните икону откључавања да бисте отворили."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Откључано је лицем"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Лице је препознато"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Померите налево"</item>
-    <item msgid="5558598599408514296">"Померите надоле"</item>
-    <item msgid="4844142668312841831">"Померите надесно"</item>
-    <item msgid="5640521437931460125">"Померите нагоре"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Превуците нагоре да бисте пробали поново"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Откључајте да бисте користили NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Овај уређај припада организацији"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Одаберите апликацију за додавање контрола"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# контрола је додата.}one{# контрола је додата.}few{# контроле су додате.}other{# контрола је додато.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Уклоњено"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Желите ли да додате <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Када додате апликацију <xliff:g id="APPNAME">%s</xliff:g>, она може да додаје контроле и садржај у ово окно. У неким апликацијама можете да изаберете које ће се контроле овде приказивати."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Означено је као омиљено"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Означено је као омиљено, <xliff:g id="NUMBER">%d</xliff:g>. позиција"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Уклоњено је из омиљених"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Отворите <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Пустите <xliff:g id="SONG_NAME">%1$s</xliff:g> извођача <xliff:g id="ARTIST_NAME">%2$s</xliff:g> из апликације <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Пустите <xliff:g id="SONG_NAME">%1$s</xliff:g> из апликације <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"За вас"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Опозови"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Приближите да бисте пуштали музику на: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Да бисте пуштали садржај овде, приближите уређају <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Грешка. Пробајте поново"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Додај контроле"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Измени контроле"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Додај апликацију"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додајте излазе"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Изабран је 1 уређај"</string>
@@ -919,7 +915,6 @@
     <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">"Звучници и екрани"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Предложени уређаји"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Захтева премијум налог"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционише емитовање"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Емитовање"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Људи у близини са компатибилним Bluetooth уређајима могу да слушају медијски садржај који емитујете"</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Камера је искључена"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Микрофон је искључен"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камера и микрофон су искључени"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Помоћник слуша"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# обавештење}one{# обавештење}few{# обавештења}other{# обавештења}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Прављење бележака"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Дозволи једнократан приступ"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Не дозволи"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Евиденције уређаја региструју шта се дешава на уређају. Апликације могу да користе те евиденције да би пронашле и решиле проблеме.\n\nНеке евиденције могу да садрже осетљиве информације, па приступ свим евиденцијама уређаја треба да дозвољавате само апликацијама у које имате поверења. \n\nАко не дозволите овој апликацији да приступа свим евиденцијама уређаја, она и даље може да приступа сопственим евиденцијама. Произвођач уређаја ће можда и даље моћи да приступа неким евиденцијама или информацијама на уређају."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Сазнајте више"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Сазнајте више на <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Отворите: <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• да је апликација подешена"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• да је у Новчаник додата барем једна картица"</string>
@@ -1054,7 +1052,7 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• да је доступан барем један уређај"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Додирните и задржите пречицу"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Откажи"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Обрните"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Обрни"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Отворите телефон за бољи селфи"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Желите да обрнете на предњи екран за бољи селфи?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Користите задњу камеру да бисте снимили ширу слику са вишом резолуцијом."</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Смернице за посао вам омогућавају да телефонирате само са пословног профила"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Пређи на пословни профил"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Подешавања закључаног екрана"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 94cd420..f352e8f 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Nedre gräns: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vänster gräns: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Höger gräns: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Jobbskärmbilder sparas i <xliff:g id="APP">%1$s</xliff:g>-appen"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Sparad i <xliff:g id="APP">%1$s</xliff:g> i jobbprofilen"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Filer"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> identifierade skärmbilden."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> och andra öppna appar identifierade skärmbilden."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Skärminspelare"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandlar skärminspelning"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Upplåst med ansiktslås"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ansiktet har identifierats"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Flytta åt vänster"</item>
-    <item msgid="5558598599408514296">"Flytta nedåt"</item>
-    <item msgid="4844142668312841831">"Flytta åt höger"</item>
-    <item msgid="5640521437931460125">"Flytta uppåt"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Svep uppåt om du vill försöka igen"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Lås upp om du vill använda NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Den här enheten tillhör organisationen"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Välj en app om du vill lägga till snabbkontroller"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontroll har lagts till.}other{# kontroller har lagts till.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Har tagits bort"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vill du lägga till <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"När du lägger till <xliff:g id="APPNAME">%s</xliff:g> kan den lägga till kontroller och innehåll i den här panelen. I vissa appar kan du styra vilka kontroller som visas här."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Har lagts till som favorit"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Har lagts till som favorit, plats <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Har tagits bort från favoriter"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Öppna <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Spela upp <xliff:g id="SONG_NAME">%1$s</xliff:g> med <xliff:g id="ARTIST_NAME">%2$s</xliff:g> från <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Spela upp <xliff:g id="SONG_NAME">%1$s</xliff:g> från <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"För dig"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Ångra"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Flytta närmare för att spela upp på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Kom närmare <xliff:g id="DEVICENAME">%1$s</xliff:g> om du vill spela upp här"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Fel, försök igen"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Lägg till snabbkontroller"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Redigera snabbkontroller"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Lägg till app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Lägg till utgångar"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet har valts"</string>
@@ -919,7 +915,6 @@
     <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">"Högtalare och skärmar"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Förslag på enheter"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Premiumkonto krävs"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Så fungerar utsändning"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Utsändning"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i närheten med kompatibla Bluetooth-enheter kan lyssna på medieinnehåll som du sänder ut"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kameran är av"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofonen är av"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kameran och mikrofonen är avstängda"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# avisering}other{# aviseringar}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Anteckningar"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Tillåt engångsåtkomst"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Tillåt inte"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"I enhetsloggar registreras vad som händer på enheten. Appar kan använda dessa loggar för att hitta och åtgärda problem.\n\nVissa loggar kan innehålla känsliga uppgifter, så du ska bara bevilja appar du litar på åtkomst till alla enhetsloggar. \n\nEn app har åtkomst till sina egna loggar även om du inte ger den åtkomst till alla enhetsloggar. Enhetens tillverkare kan fortfarande ha åtkomst till vissa loggar eller viss information på enheten."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Öppna <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• appen har konfigurerats"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• minst ett kort har lagts till i Wallet"</string>
@@ -1056,7 +1057,7 @@
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Avbryt"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Vänd nu"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Vik upp telefonen för att ta en bättre selfie"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vill du ta en bättre selfie med främre skärmen?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vill du ta en bättre selfie med främre kameran?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Använd den bakre kameran för att ta ett mer vidsträckt foto med högre upplösning."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Den här skärmen inaktiveras"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En vikbar enhet viks upp"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Jobbprincipen tillåter endast att du ringer telefonsamtal från jobbprofilen"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Byt till jobbprofilen"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Stäng"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Inställningar för låsskärm"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 9fbaf92..9a93c42 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Mpaka wa sehemu ya chini wa asilimia <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Mpaka wa sehemu ya kushoto wa asilimia <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Mpaka wa sehemu ya kulia wa asilimia <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Picha ya skrini ya kazi huhifadhiwa kwenye programu ya <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Faili"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Kinasa Skrini"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Inachakata rekodi ya skrini"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili ufungue."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Imefunguliwa kwa kutumia uso"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Uso umetambuliwa"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Sogeza kushoto"</item>
-    <item msgid="5558598599408514296">"Sogeza chini"</item>
-    <item msgid="4844142668312841831">"Sogeza kulia"</item>
-    <item msgid="5640521437931460125">"Sogeza juu"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Telezesha kidole juu ili ujaribu tena"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Fungua ili utumie NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Kifaa hiki kinamilikiwa na shirika lako"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Chagua programu ili uweke vidhibiti"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Umeweka kidhibiti #.}other{Umeweka vidhibiti #.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Kimeondolewa"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Ungependa kuweka <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Unapoweka <xliff:g id="APPNAME">%s</xliff:g>, inaweza kuweka vidhibiti na maudhui kwenye kidirisha hiki. Katika baadhi ya programu, unaweza kuchagua ni vidhibiti vipi vionekane hapa."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Kimewekwa kwenye vipendwa"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Kimewekwa kwenye vipendwa, nafasi ya <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Kimeondolewa kwenye vipendwa"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Fungua <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Cheza <xliff:g id="SONG_NAME">%1$s</xliff:g> ulioimbwa na <xliff:g id="ARTIST_NAME">%2$s</xliff:g> katika <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Cheza <xliff:g id="SONG_NAME">%1$s</xliff:g> katika <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Kwa Ajili Yako"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Tendua"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Sogeza karibu ili ucheze kwenye <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Ili ucheze maudhui kwenye kifaa hiki, sogeza karibu na <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Hitilafu, jaribu tena"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Weka vidhibiti"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Badilisha vidhibiti"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Weka programu"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Weka vifaa vya kutoa sauti"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Kikundi"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Umechagua kifaa 1"</string>
@@ -919,7 +918,6 @@
     <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">"Spika na Skrini"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Vifaa Vilivyopendekezwa"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Inahitaji akaunti ya kulipia"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jinsi utangazaji unavyofanya kazi"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Tangaza"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Watu walio karibu nawe wenye vifaa oanifu vya Bluetooth wanaweza kusikiliza maudhui unayoyatangaza"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera imezimwa"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Maikrofoni imezimwa"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera na maikrofoni zimezimwa"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{Arifa #}other{Arifa #}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Kuandika vidokezo"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Ruhusu ufikiaji wa mara moja"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Usiruhusu"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Kumbukumbu za kifaa hurekodi kinachofanyika kwenye kifaa chako. Programu zinaweza kutumia kumbukumbu hizi ili kutambua na kurekebisha hitilafu.\n\nHuenda baadhi ya kumbukumbu zikawa na taarifa nyeti, hivyo ruhusu tu programu unazoziamini kufikia kumbukumbu zote za kifaa. \n\nIwapo hutaruhusu programu hii ifikie kumbukumbu zote za kifaa, bado inaweza kufikia kumbukumbu zake yenyewe. Huenda mtengenezaji wa kifaa chako bado akaweza kufikia baadhi ya kumbukumbu au taarifa zilizopo kwenye kifaa chako."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Fungua <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Programu hii imewekewa mipangilio"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Angalau kadi moja imewekwa kwenye Pochi"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Sera ya mahali pako pa kazi inakuruhusu upige simu kutoka kwenye wasifu wa kazini pekee"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Tumia wasifu wa kazini"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Funga"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Mipangilio ya skrini iliyofungwa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index 5d78e4e..2a27b47 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -45,8 +45,6 @@
     <item name="controls_task_view_width_percentage" translatable="false" format="float" type="dimen">0.45</item>
     <dimen name="controls_task_view_right_margin">8dp</dimen>
 
-    <dimen name="status_bar_header_height_keyguard">42dp</dimen>
-
     <dimen name="lockscreen_shade_max_over_scroll_amount">32dp</dimen>
 
     <dimen name="status_view_margin_horizontal">8dp</dimen>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index db7fb48..45b137a 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -16,8 +16,9 @@
 */
 -->
 <resources>
-    <!-- Height of the status bar header bar when on Keyguard -->
-    <dimen name="status_bar_header_height_keyguard">60dp</dimen>
+    <!-- Height of the status bar header bar when on Keyguard.
+         On large screens should be the same as the regular status bar. -->
+    <dimen name="status_bar_header_height_keyguard">@dimen/status_bar_height</dimen>
 
     <!-- Size of user icon + frame in the qs user picker (incl. frame) -->
     <dimen name="qs_framed_avatar_size">60dp</dimen>
@@ -51,9 +52,6 @@
     <!-- Text size for user name in user switcher -->
     <dimen name="kg_user_switcher_text_size">18sp</dimen>
 
-    <dimen name="controls_header_bottom_margin">12dp</dimen>
-    <dimen name="controls_top_margin">24dp</dimen>
-
     <dimen name="global_actions_grid_item_layout_height">80dp</dimen>
 
     <dimen name="qs_brightness_margin_bottom">16dp</dimen>
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index 122806a..9ed9360 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -17,14 +17,11 @@
 */
 -->
 <resources>
-    <dimen name="controls_padding_horizontal">205dp</dimen>
     <dimen name="split_shade_notifications_scrim_margin_bottom">24dp</dimen>
     <dimen name="notification_panel_margin_bottom">64dp</dimen>
 
     <dimen name="keyguard_split_shade_top_margin">72dp</dimen>
 
-    <dimen name="status_bar_header_height_keyguard">56dp</dimen>
-
     <dimen name="status_view_margin_horizontal">24dp</dimen>
 
     <dimen name="qs_media_session_height_expanded">184dp</dimen>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 927059a..8f59df6 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -19,7 +19,7 @@
     <!-- gap on either side of status bar notification icons -->
     <dimen name="status_bar_icon_padding">1dp</dimen>
 
-    <dimen name="controls_padding_horizontal">75dp</dimen>
+    <dimen name="controls_padding_horizontal">40dp</dimen>
 
     <dimen name="large_screen_shade_header_height">56dp</dimen>
 
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index dd99594..b8290c3 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"கீழ் எல்லை <xliff:g id="PERCENT">%1$d</xliff:g> சதவீதம்"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"இடது எல்லை <xliff:g id="PERCENT">%1$d</xliff:g> சதவீதம்"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"வலது எல்லை <xliff:g id="PERCENT">%1$d</xliff:g> சதவீதம்"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"பணிக் கணக்கு ஸ்கிரீன்ஷாட்டுகள் <xliff:g id="APP">%1$s</xliff:g> ஆப்ஸில் சேமிக்கப்படும்"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"ஸ்கிரீன் ரெக்கார்டர்"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ஸ்க்ரீன் ரெக்கார்டிங் செயலாக்கப்படுகிறது"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"முகம் அங்கீகரிக்கப்பட்டது. திறக்க அன்லாக் ஐகானை அழுத்தவும்."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"முகத்தால் அன்லாக் செய்யப்பட்டது"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"முகம் அங்கீகரிக்கப்பட்டது"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"இடதுபுறம் நகர்த்துங்கள்"</item>
-    <item msgid="5558598599408514296">"கீழே நகர்த்துங்கள்"</item>
-    <item msgid="4844142668312841831">"வலதுபுறம் நகர்த்துங்கள்"</item>
-    <item msgid="5640521437931460125">"மேலே நகர்த்துங்கள்"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"மீண்டும் முயல மேல்நோக்கி ஸ்வைப் செய்யவும்"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCயைப் பயன்படுத்த அன்லாக் செய்யவும்"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு சொந்தமானது"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"கட்டுப்பாடுகளைச் சேர்க்க வேண்டிய ஆப்ஸைத் தேர்ந்தெடுங்கள்"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# கட்டுப்பாடு சேர்க்கப்பட்டது.}other{# கட்டுப்பாடுகள் சேர்க்கப்பட்டன.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"அகற்றப்பட்டது"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ஆப்ஸைச் சேர்க்கவா?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"இந்தப் பேனலில் <xliff:g id="APPNAME">%s</xliff:g> ஆப்ஸைச் சேர்க்கும்போது கட்டுப்பாடுகளையும் உள்ளடக்கத்தையும் அது சேர்க்கலாம். இருப்பினும், சில ஆப்ஸில் எந்தெந்தக் கட்டுப்பாடுகள் இங்கே காட்டப்பட வேண்டும் என்பதை நீங்களே தேர்வுசெய்யலாம்."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"பிடித்தவற்றில் சேர்க்கப்பட்டது"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"பிடித்தவற்றில் சேர்க்கப்பட்டது, நிலை <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"பிடித்தவற்றிலிருந்து நீக்கப்பட்டது"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ஆப்ஸைத் திறங்கள்"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> இன் <xliff:g id="SONG_NAME">%1$s</xliff:g> பாடலை <xliff:g id="APP_LABEL">%3$s</xliff:g> ஆப்ஸில் பிளேசெய்"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> பாடலை <xliff:g id="APP_LABEL">%2$s</xliff:g> ஆப்ஸில் பிளேசெய்"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"உங்களுக்கானவை"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"செயல்தவிர்"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> சாதனத்தில் இயக்க உங்கள் சாதனத்தை அருகில் எடுத்துச் செல்லுங்கள்"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"இங்கு பிளே செய்ய உங்கள் சாதனத்தை <xliff:g id="DEVICENAME">%1$s</xliff:g>அருகில் நகர்த்துங்கள்"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"பிழை, மீண்டும் முயலவும்"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"கட்டுப்பாடுகளைச் சேர்த்தல்"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"கட்டுப்பாடுகளை மாற்றுதல்"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ஆப்ஸைச் சேர்"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"அவுட்புட்களைச் சேர்த்தல்"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"குழு"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 சாதனம் தேர்ந்தெடுக்கப்பட்டுள்ளது"</string>
@@ -919,7 +918,6 @@
     <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">"ஸ்பீக்கர்கள் &amp; டிஸ்ப்ளேக்கள்"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"பரிந்துரைக்கப்படும் சாதனங்கள்"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"பிரீமியம் கணக்கு தேவை"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"பிராட்காஸ்ட் எவ்வாறு செயல்படுகிறது?"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"பிராட்காஸ்ட்"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"நீங்கள் பிராட்காஸ்ட் செய்யும் மீடியாவை அருகிலுள்ளவர்கள் இணக்கமான புளூடூத் சாதனங்கள் மூலம் கேட்கலாம்"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"கேமரா முடக்கப்பட்டுள்ளது"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"மைக் முடக்கப்பட்டுள்ளது"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"கேமராவும் மைக்கும் ஆஃப் செய்யப்பட்டுள்ளன"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# அறிவிப்பு}other{# அறிவிப்புகள்}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"குறிப்பெடுத்தல்"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"ஒருமுறை அணுகலை அனுமதி"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"அனுமதிக்க வேண்டாம்"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"உங்கள் சாதனத்தில் நடப்பவற்றைச் சாதனப் பதிவுகள் ரெக்கார்டு செய்யும். சிக்கல்களைக் கண்டறிந்து சரிசெய்ய ஆப்ஸ் இந்தப் பதிவுகளைப் பயன்படுத்தலாம்.\n\nபாதுகாக்க வேண்டிய தகவல்கள் சில பதிவுகளில் இருக்கக்கூடும் என்பதால் சாதனப் பதிவுகள் அனைத்தையும் அணுக நீங்கள் நம்பும் ஆப்ஸை மட்டுமே அனுமதிக்கவும். \n\nசாதனப் பதிவுகள் அனைத்தையும் அணுக இந்த ஆப்ஸை நீங்கள் அனுமதிக்கவில்லை என்றாலும் அதற்குச் சொந்தமான பதிவுகளை அதனால் அணுக முடியும். உங்கள் சாதனத்திலுள்ள சில பதிவுகளையோ தகவல்களையோ சாதன உற்பத்தியாளரால் தொடர்ந்து அணுக முடியும்."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸைத் திற"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• இந்த ஆப்ஸ் அமைக்கப்பட்டிருக்க வேண்டும்"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Walletடில் குறைந்தபட்சம் ஒரு கார்டாவது சேர்க்கப்பட்டிருக்க வேண்டும்"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"உங்கள் பணிக் கொள்கையின்படி நீங்கள் பணிக் கணக்கில் இருந்து மட்டுமே ஃபோன் அழைப்புகளைச் செய்ய முடியும்"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"பணிக் கணக்கிற்கு மாறு"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"மூடுக"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"பூட்டுத் திரை அமைப்புகள்"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 655f2f9..8ce144a 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"దిగువ సరిహద్దు <xliff:g id="PERCENT">%1$d</xliff:g> శాతం"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ఎడమ వైపు సరిహద్దు <xliff:g id="PERCENT">%1$d</xliff:g> శాతం"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"కుడి వైపు సరిహద్దు <xliff:g id="PERCENT">%1$d</xliff:g> శాతం"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"వర్క్ స్క్రీన్‌షాట్‌లు <xliff:g id="APP">%1$s</xliff:g> యాప్‌లో సేవ్ చేయబడతాయి"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"వర్క్ ప్రొఫైల్‌లోని <xliff:g id="APP">%1$s</xliff:g>‌లో సేవ్ చేయబడింది"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ఫైల్స్"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g>, ఈ స్క్రీన్‌షాట్‌ను గుర్తించింది."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>, ఇతర ఓపెన్ యాప్‌లు ఈ స్క్రీన్‌షాట్‌ను గుర్తించాయి."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"స్క్రీన్ రికార్డర్"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"స్క్రీన్ రికార్డింగ్ అవుతోంది"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్‌గోయింగ్ నోటిఫికేషన్"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"ముఖం గుర్తించబడింది. తెరవడానికి అన్‌లాక్ చిహ్నం నొక్కండి."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ముఖం ద్వారా అన్‌లాక్ చేయబడింది"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"ముఖం గుర్తించబడింది"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"ఎడమవైపుగా జరపండి"</item>
-    <item msgid="5558598599408514296">"కిందికి జరపండి"</item>
-    <item msgid="4844142668312841831">"కుడివైపుగా జరపండి"</item>
-    <item msgid="5640521437931460125">"పైకి జరపండి"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"మళ్ళీ ప్రయత్నించడానికి పైకి స్వైప్ చేయండి"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFCని ఉపయోగించడానికి అన్‌లాక్ చేయండి"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"ఈ పరికరం మీ సంస్థకు చెందినది"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"కంట్రోల్స్‌ను యాడ్ చేయడానికి యాప్‌ను ఎంచుకోండి"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# కంట్రోల్ జోడించబడింది.}other{# కంట్రోల్స్ జోడించబడ్డాయి.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"తీసివేయబడింది"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>ను జోడించాలా?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"మీరు <xliff:g id="APPNAME">%s</xliff:g>ను జోడించినప్పుడు, ఇది ఈ ప్యానెల్‌కు కంట్రోల్స్‌ని, కంటెంట్‌ను జోడించగలదు. కొన్ని యాప్‌లలో, ఇక్కడ ఏయే కంట్రోల్స్ కనిపించాలో మీరు ఎంచుకోవచ్చు."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ఇష్టమైనదిగా గుర్తు పెట్టబడింది"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>వ స్థానంలో ఇష్టమైనదిగా గుర్తు పెట్టబడింది"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ఇష్టమైనదిగా పెట్టిన గుర్తు తీసివేయబడింది"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g>ను తెరవండి"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> నుండి <xliff:g id="ARTIST_NAME">%2$s</xliff:g> పాడిన <xliff:g id="SONG_NAME">%1$s</xliff:g>‌ను ప్లే చేయండి"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> నుండి <xliff:g id="SONG_NAME">%1$s</xliff:g>‌ను ప్లే చేయండి"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"మీ కోసం"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"చర్య రద్దు"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>‌లో ప్లే చేయడానికి దగ్గరగా వెళ్లండి"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ఇక్కడ ఆడటానికి, <xliff:g id="DEVICENAME">%1$s</xliff:g>‌కు దగ్గరగా వెళ్లండి"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"ఎర్రర్, మళ్లీ ప్రయత్నించండి"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"కంట్రోల్స్‌ను జోడించండి"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"కంట్రోల్స్‌ను ఎడిట్ చేయండి"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"యాప్‌ను జోడించండి"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"అవుట్‌పుట్‌లను జోడించండి"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"గ్రూప్"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 పరికరం ఎంచుకోబడింది"</string>
@@ -919,7 +915,6 @@
     <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">"స్పీకర్‌లు &amp; డిస్‌ప్లేలు"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"సూచించబడిన పరికరాలు"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"ప్రీమియం ఖాతా అవసరం"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ప్రసారం కావడం అనేది ఎలా పని చేస్తుంది"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ప్రసారం"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"మీకు సమీపంలో ఉన్న వ్యక్తులు అనుకూలత ఉన్న బ్లూటూత్ పరికరాలతో మీరు ప్రసారం చేస్తున్న మీడియాను వినగలరు"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"కెమెరా ఆఫ్‌లో ఉంది"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"మైక్ ఆఫ్‌లో ఉంది"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"కెమెరా, మైక్ ఆఫ్‌లో ఉన్నాయి"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# నోటిఫికేషన్}other{# నోటిఫికేషన్‌లు}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"నోట్‌టేకింగ్"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"వన్-టైమ్ యాక్సెస్‌ను అనుమతించండి"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"అనుమతించవద్దు"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"మీ పరికరంలో జరిగే దాన్ని పరికర లాగ్‌లు రికార్డ్ చేస్తాయి. సమస్యలను కనుగొని, పరిష్కరించడానికి యాప్‌లు ఈ లాగ్‌లను ఉపయోగిస్తాయి.\n\nకొన్ని లాగ్‌లలో గోప్యమైన సమాచారం ఉండవచ్చు, కాబట్టి మీరు విశ్వసించే యాప్‌లను మాత్రమే అన్ని పరికర లాగ్‌లను యాక్సెస్ చేయడానికి అనుమతించండి. \n\nఅన్ని పరికర లాగ్‌లను యాక్సెస్ చేయడానికి మీరు ఈ యాప్‌ను అనుమతించకపోతే, అది తన స్వంత లాగ్‌లను ఇప్పటికి యాక్సెస్ చేయగలదు. మీ పరికర తయారీదారు ఇప్పటికీ మీ పరికరంలో కొన్ని లాగ్‌లు లేదా సమాచారాన్ని యాక్సెస్ చేయగలరు."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g>‌ను తెరవండి"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• యాప్ సెటప్ చేయబడి ఉందని"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Walletకు కనీసం ఒక కార్డ్ అయినా జోడించబడి ఉందని"</string>
@@ -1057,7 +1058,7 @@
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ఇప్పుడే తిప్పండి"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"మెరుగైన సెల్ఫీ కోసం ఫోన్‌ను అన్‌ఫోల్డ్ చేయండి"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"మంచి సెల్ఫీ కోసం ముందు వైపు డిస్‌ప్లేకు తిప్పాలా?"</string>
-    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"అధిక రిజల్యూషన్‌తో పెద్ద ఫోటో కోసం వెనుక వైపున ఉన్న కెమెరాను ఉపయోగించండి."</string>
+    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"వెనుక వైపున ఉన్న కెమెరాను ఉపయోగించి అధిక రిజల్యూషన్ గల, మరింత వెడల్పైన ఫోటోను పొందండి."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ఈ స్క్రీన్ ఆఫ్ అవుతుంది"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"మడవగల పరికరం విప్పబడుతోంది"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"మడవగల పరికరం చుట్టూ తిప్పబడుతోంది"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"మీ వర్క్ పాలసీ, మిమ్మల్ని వర్క్ ప్రొఫైల్ నుండి మాత్రమే ఫోన్ కాల్స్ చేయడానికి అనుమతిస్తుంది"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"వర్క్ ప్రొఫైల్‌కు మారండి"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"మూసివేయండి"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"లాక్ స్క్రీన్ సెట్టింగ్‌లు"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 375bd39..0ca154e 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -46,4 +46,7 @@
     <!-- Whether to tint the icon of the sensor hardware privacy toggle unblock dialog.
         Set to false if using a custom icon. -->
     <bool name="config_unblockHwSensorIconEnableTint">true</bool>
+
+    <!-- Configuration to set Learn more in device logs as URL link -->
+    <bool name="log_access_confirmation_learn_more_as_link">false</bool>
 </resources>
diff --git a/packages/SystemUI/res/values-television/strings.xml b/packages/SystemUI/res/values-television/strings.xml
deleted file mode 100644
index f30b73e..0000000
--- a/packages/SystemUI/res/values-television/strings.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * 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.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content for the log access confirmation dialog. [CHAR LIMIT=NONE]-->
-    <string name="log_access_confirmation_body">Device logs record what happens on your device. Apps can use these logs to find and fix issues.\n\nSome logs may contain sensitive info, so only allow apps you trust to access all device logs.
-        \n\nIf you don’t allow this app to access all device logs, it can still access its own logs. Your device manufacturer may still be able to access some logs or info on your device.\n\nLearn more at g.co/android/devicelogs.
-    </string>
-
-    <!-- Learn more URL for the log access confirmation dialog. [DO NOT TRANSLATE]-->
-    <string name="log_access_confirmation_learn_more" translatable="false"></string>
-</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 1d62202..fe6cee6 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -91,8 +91,11 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ขอบเขตด้านล่าง <xliff:g id="PERCENT">%1$d</xliff:g> เปอร์เซ็นต์"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ขอบเขตด้านซ้าย <xliff:g id="PERCENT">%1$d</xliff:g> เปอร์เซ็นต์"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ขอบเขตด้านขวา <xliff:g id="PERCENT">%1$d</xliff:g> เปอร์เซ็นต์"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"ภาพหน้าจองานจะบันทึกอยู่ในแอป <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"บันทึกไว้ที่ <xliff:g id="APP">%1$s</xliff:g> ในโปรไฟล์งาน"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ไฟล์"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> ตรวจพบภาพหน้าจอนี้"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> และแอปอื่นๆ ที่เปิดอยู่ตรวจพบภาพหน้าจอนี้"</string>
+    <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"เพิ่มลงในโน้ต"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"โปรแกรมบันทึกหน้าจอ"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"กำลังประมวลผลการอัดหน้าจอ"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string>
@@ -339,12 +342,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อเปิด"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"ปลดล็อกด้วยใบหน้าแล้ว"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"จดจำใบหน้าได้"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"เลื่อนนิ้วไปทางซ้าย"</item>
-    <item msgid="5558598599408514296">"เลื่อนนิ้วลง"</item>
-    <item msgid="4844142668312841831">"เลื่อนนิ้วไปทางขวา"</item>
-    <item msgid="5640521437931460125">"เลื่อนนิ้วขึ้น"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"เลื่อนขึ้นเพื่อลองอีกครั้ง"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"ปลดล็อกเพื่อใช้ NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้"</string>
@@ -884,6 +881,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"เปิด <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"เปิดเพลง <xliff:g id="SONG_NAME">%1$s</xliff:g> ของ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> จาก <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"เปิดเพลง <xliff:g id="SONG_NAME">%1$s</xliff:g> จาก <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"สำหรับคุณ"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"เลิกทำ"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"ขยับไปใกล้มากขึ้นเพื่อเล่นใน <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"ขยับไปใกล้ <xliff:g id="DEVICENAME">%1$s</xliff:g> มากขึ้นเพื่อเล่นที่นี่"</string>
@@ -916,7 +914,6 @@
     <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">"ลำโพงและจอแสดงผล"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"อุปกรณ์ที่แนะนำ"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"ต้องใช้บัญชี Premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"วิธีการทำงานของการออกอากาศ"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"ประกาศ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ผู้ที่อยู่ใกล้คุณและมีอุปกรณ์บลูทูธที่รองรับสามารถรับฟังสื่อที่คุณกำลังออกอากาศได้"</string>
@@ -1028,6 +1025,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"กล้องปิดอยู่"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"ไมค์ปิดอยู่"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"กล้องและไมค์ปิดอยู่"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistant กำลังฟังอยู่"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{การแจ้งเตือน # รายการ}other{การแจ้งเตือน # รายการ}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"การจดบันทึก"</string>
@@ -1043,6 +1041,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"อนุญาตสิทธิ์เข้าถึงแบบครั้งเดียว"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"ไม่อนุญาต"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"บันทึกของอุปกรณ์เก็บข้อมูลสิ่งที่เกิดขึ้นในอุปกรณ์ แอปสามารถใช้บันทึกเหล่านี้เพื่อค้นหาและแก้ไขปัญหา\n\nบันทึกบางรายการอาจมีข้อมูลที่ละเอียดอ่อน คุณจึงควรอนุญาตเฉพาะแอปที่เชื่อถือได้ให้เข้าถึงบันทึกทั้งหมดของอุปกรณ์ \n\nหากคุณไม่อนุญาตให้แอปนี้เข้าถึงบันทึกทั้งหมดของอุปกรณ์ แอปจะยังเข้าถึงบันทึกของตัวเองได้อยู่ ผู้ผลิตอุปกรณ์อาจยังเข้าถึงบันทึกหรือข้อมูลบางรายการในอุปกรณ์ของคุณได้"</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ดูข้อมูลเพิ่มเติม"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"ดูข้อมูลเพิ่มเติมที่ <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"เปิด <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• แอปได้รับการตั้งค่าแล้ว"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• มีการเพิ่มบัตรลงใน Wallet อย่างน้อย 1 รายการ"</string>
@@ -1066,6 +1066,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"นโยบายการทำงานอนุญาตให้คุณโทรออกได้จากโปรไฟล์งานเท่านั้น"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"สลับไปใช้โปรไฟล์งาน"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ปิด"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"การตั้งค่าหน้าจอล็อก"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e29fc9e..ab512e5 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -91,8 +91,11 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"<xliff:g id="PERCENT">%1$d</xliff:g> (na) porsyento sa hangganan sa ibaba"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> (na) porsyento sa hangganan sa kaliwa"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> (na) porsyento sa hangganan sa kanan"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Naka-save ang mga screenshot sa trabaho sa <xliff:g id="APP">%1$s</xliff:g> app"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Na-save sa <xliff:g id="APP">%1$s</xliff:g> sa profile sa trabaho"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Mga File"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"Na-detect ng <xliff:g id="APPNAME">%1$s</xliff:g> ang screenshot. na ito"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Na-detect ng <xliff:g id="APPNAME">%1$s</xliff:g> at ng iba pang bukas na app ang screenshot na ito."</string>
+    <string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Idagdag sa tala"</string>
     <string name="screenrecord_name" msgid="2596401223859996572">"Recorder ng Screen"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pinoproseso screen recording"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Kasalukuyang notification para sa session ng pag-record ng screen"</string>
@@ -339,12 +342,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Nakilala ang mukha. Pindutin ang icon ng unlock para buksan."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Na-unlock gamit ang mukha"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Nakilala ang mukha"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Ilipat pakaliwa"</item>
-    <item msgid="5558598599408514296">"Ibaba"</item>
-    <item msgid="4844142668312841831">"Ilipat pakanan"</item>
-    <item msgid="5640521437931460125">"Itaas"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Mag-swipe pataas para subukan ulit"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"I-unlock para magamit ang NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Pagmamay-ari ng iyong organisasyon ang device na ito"</string>
@@ -884,6 +881,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Buksan ang <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"I-play ang <xliff:g id="SONG_NAME">%1$s</xliff:g> ni/ng <xliff:g id="ARTIST_NAME">%2$s</xliff:g> mula sa <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"I-play ang <xliff:g id="SONG_NAME">%1$s</xliff:g> mula sa <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Para sa Iyo"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"I-undo"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Lumapit pa para mag-play sa <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Para mag-play dito, lumapit sa <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -916,7 +914,6 @@
     <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">"Mga Speaker at Display"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Mga Iminumungkahing Device"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Nangangailangan ng premium account"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Paano gumagana ang pag-broadcast"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Makakapakinig ang mga taong malapit sa iyo na may mga compatible na Bluetooth device sa media na bino-broadcast mo"</string>
@@ -1028,6 +1025,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Naka-off ang camera"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Naka-off ang mikropono"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Naka-off ang camera at mikropono"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}other{# na notification}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Pagtatala"</string>
@@ -1043,6 +1042,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Payagan ang isang beses na pag-access"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Huwag payagan"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Nire-record ng mga log ng device kung ano ang nangyayari sa iyong device. Magagamit ng mga app ang mga log na ito para maghanap at mag-ayos ng mga isyu.\n\nPosibleng maglaman ang ilang log ng sensitibong impormasyon, kaya ang mga app lang na pinagkakatiwalaan mo ang payagang maka-access sa lahat ng log ng device. \n\nKung hindi mo papayagan ang app na ito na i-access ang lahat ng log ng device, maa-access pa rin nito ang mga sarili nitong log. Posible pa ring ma-access ng manufacturer ng iyong device ang ilang log o impormasyon sa device mo."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Buksan ang <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Na-set up ang app"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• May kahit isang card na idinagdag sa Wallet"</string>
@@ -1066,6 +1069,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Pinapayagan ka ng iyong patakaran sa trabaho na tumawag lang mula sa profile sa trabaho"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Lumipat sa profile sa trabaho"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Isara"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Mga setting ng lock screen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d421610..8863d32 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Alt sınır yüzde <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Sol sınır yüzde <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Sağ sınır yüzde <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"İş profilindeki ekran görüntüleri <xliff:g id="APP">%1$s</xliff:g> uygulamasına kaydedilir"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Dosyalar"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekran Kaydedicisi"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran kaydı işleniyor"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Yüzünüz tanındı. Kilit açma simgesine basın."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Cihazın kilidini yüzünüzle açtınız"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Yüzünüz tanındı"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Sola taşı"</item>
-    <item msgid="5558598599408514296">"Aşağı taşı"</item>
-    <item msgid="4844142668312841831">"Sağa taşı"</item>
-    <item msgid="5640521437931460125">"Yukarı taşı"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Tekrar denemek için yukarı kaydırın"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC\'yi kullanmak için kilidi açın"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu cihaz, kuruluşunuza ait"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Denetim eklemek için uygulama seçin"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrol eklendi.}other{# kontrol eklendi.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Kaldırıldı"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> eklensin mi?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> uygulamasını eklerseniz bu panele kontrol ve içerik ekleyebilir. Bazı uygulamalarda, burada hangi kontrollerin görüneceğini seçebilirsiniz."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favoriler listesine eklendi"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favorilere eklendi, konum: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Favorilerden kaldırıldı"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> uygulamasını aç"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> uygulamasından <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, <xliff:g id="SONG_NAME">%1$s</xliff:g> şarkısını çal"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> uygulamasından <xliff:g id="SONG_NAME">%1$s</xliff:g> şarkısını çal"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Sizin İçin"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Geri al"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> cihazında oynatmak için yaklaşın"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Burada oynatmak için <xliff:g id="DEVICENAME">%1$s</xliff:g> cihazına yaklaşın"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Hata, yeniden deneyin"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Denetim ekle"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Denetimleri düzenle"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Uygulama ekle"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Çıkışlar ekleyin"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçildi"</string>
@@ -919,7 +918,6 @@
     <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">"Hoparlörler ve Ekranlar"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Önerilen Cihazlar"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Premium hesap gerekiyor"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayınlamanın işleyiş şekli"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Anons"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Yakınınızda ve uyumlu Bluetooth cihazları olan kişiler yayınladığınız medya içeriğini dinleyebilir"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera kapalı"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon kapalı"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera ve mikrofon kapalı"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# bildirim}other{# bildirim}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Not alma"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Tek seferlik erişim izni ver"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"İzin verme"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Cihaz günlükleri, cihazınızda olanları kaydeder. Uygulamalar, sorunları bulup düzeltmek için bu günlükleri kullanabilir.\n\nBazı günlükler hassas bilgiler içerebileceği için yalnızca güvendiğiniz uygulamaların tüm cihaz günlüklerine erişmesine izin verin. \n\nBu uygulamanın tüm cihaz günlüklerine erişmesine izin vermeseniz de kendi günlüklerine erişmeye devam edebilir. Ayrıca, cihaz üreticiniz de cihazınızdaki bazı günlüklere veya bilgilere erişmeye devam edebilir."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> uygulamasını aç"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Uygulama kurulmuş olmalıdır"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Cüzdan\'a en az bir kart eklenmelidir"</string>
@@ -1058,7 +1062,7 @@
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Daha iyi selfie çekmek için telefonu açın"</string>
     <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Daha iyi bir selfie için ön ekrana geçilsin mi?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Daha yüksek çözünürlüğe sahip daha büyük bir fotoğraf için arka yüz kamerasını kullanın."</string>
-    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ * Bu ekran kapatılacak"</b></string>
+    <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Bu ekran kapatılacak"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Katlanabilir cihaz açılıyor"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Katlanabilir cihaz döndürülüyor"</string>
     <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> pil kaldı"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"İşletme politikanız yalnızca iş profilinden telefon araması yapmanıza izin veriyor"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"İş profiline geç"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Kapat"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Kilit ekranı ayarları"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 43c212d..5ba8ddf 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Знизу на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Зліва на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Справа на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Робочі знімки екрана зберігаються в додатку <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Файли"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Запис відео з екрана"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обробка записування екрана"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Обличчя розпізнано. Натисніть значок розблокування."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Розблоковано (фейсконтроль)"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Обличчя розпізнано"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Перемістіть палець ліворуч"</item>
-    <item msgid="5558598599408514296">"Перемістіть палець униз"</item>
-    <item msgid="4844142668312841831">"Перемістіть палець праворуч"</item>
-    <item msgid="5640521437931460125">"Перемістіть палець угору"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Проведіть пальцем угору, щоб повторити спробу"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Розблокуйте екран, щоб скористатись NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Цей пристрій належить вашій організації"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Виберіть, для якого додатка налаштувати елементи керування"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Додано # елемент керування.}one{Додано # елемент керування.}few{Додано # елементи керування.}many{Додано # елементів керування.}other{Додано # елемента керування.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Вилучено"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Долучити додаток <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Якщо ви долучите додаток <xliff:g id="APPNAME">%s</xliff:g>, він зможе розміщувати елементи керування й контент на цій панелі. У деяких додатках можна вибрати, які елементи керування тут відображатимуться."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Додано у вибране"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Додано у вибране, позиція <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Видалено з вибраного"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Відкрити додаток <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Увімкнути пісню \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\", яку виконує <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, у додатку <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Увімкнути пісню \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" у додатку <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Для вас"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Відмінити"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Щоб відтворити контент на пристрої <xliff:g id="DEVICENAME">%1$s</xliff:g>, наблизьтеся до нього"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Щоб відтворити на цьому пристрої, перемістіть його ближче до пристрою \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\""</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Помилка. Спробуйте знову"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Додати елементи керування"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Змінити елементи керування"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Долучити додаток"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додати пристрої виводу"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Вибрано 1 пристрій"</string>
@@ -919,7 +918,6 @@
     <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">"Колонки й екрани"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Пропоновані пристрої"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Потрібен платний обліковий запис"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як працює трансляція"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Трансляція"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Люди поблизу, які мають сумісні пристрої з Bluetooth, можуть слухати медіаконтент, який ви транслюєте."</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Камеру вимкнено"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Мікрофон вимкнено"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Камеру й мікрофон вимкнено"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# сповіщення}one{# сповіщення}few{# сповіщення}many{# сповіщень}other{# сповіщення}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Створення нотаток"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Надати доступ лише цього разу"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Не надавати"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"У журналах пристрою реєструється все, що відбувається на ньому. За допомогою цих журналів додатки можуть виявляти й усувати проблеми.\n\nДеякі журнали можуть містити конфіденційні дані, тому надавати доступ до всіх журналів пристрою слід лише надійним додаткам. \n\nЯкщо додаток не має доступу до всіх журналів пристрою, він усе одно може використовувати власні журнали. Виробник вашого пристрою все одно може використовувати деякі журнали чи інформацію на ньому."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Відкрити <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Додаток налаштовано"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Принаймні одну картку додано в Гаманець"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Відповідно до правил організації ви можете телефонувати лише з робочого профілю"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Перейти в робочий профіль"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрити"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Параметри заблокованого екрана"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index c9e1ee4..230454b 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"نیچے کا احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"بایاں احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"دایاں احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"دفتری اسکرین شاٹس کو <xliff:g id="APP">%1$s</xliff:g> ایپ میں محفوظ کیا جاتا ہے"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"فائلز"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"اسکرین ریکارڈر"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"سکرین ریکارڈنگ پروسیس ہورہی ہے"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"چہرے کی شناخت ہو گئی۔ کھولنے کیلئے انلاک آئیکن دبائیں۔"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"چہرے سے غیر مقفل کیا گیا"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"چہرے کی شناخت ہو گئی"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"دائیں منتقل کریں"</item>
-    <item msgid="5558598599408514296">"نیچے منتقل کریں"</item>
-    <item msgid="4844142668312841831">"بائیں منتقل کریں"</item>
-    <item msgid="5640521437931460125">"اوپر منتقل کریں"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"دوبارہ کوشش کرنے کے لیے اوپر سوائپ کريں"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"‏NFC استعمال کرنے کیلئے غیر مقفل کریں"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"یہ آلہ آپ کی تنظیم کا ہے"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"کنٹرولز شامل کرنے کے لیے ایپ منتخب کریں"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# کنٹرول کو شامل کیا گیا۔}other{# کنٹرولز کو شامل کیا گیا۔}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ہٹا دیا گیا"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> کو شامل کریں؟"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"جب آپ <xliff:g id="APPNAME">%s</xliff:g> کو شامل کرتے ہیں، تو یہ اس پینل میں کنٹرولز اور مواد کو شامل کر سکتا ہے۔ کچھ ایپس میں، آپ یہ منتخب کر سکتے ہیں کہ کون سے کنٹرولز یہاں ظاہر ہوں۔"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"پسند کردہ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"پسند کردہ، پوزیشن <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ناپسند کردہ"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> کھولیں"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> سے <xliff:g id="ARTIST_NAME">%2$s</xliff:g> کا <xliff:g id="SONG_NAME">%1$s</xliff:g> چلائیں"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> سے <xliff:g id="SONG_NAME">%1$s</xliff:g> چلائیں"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"آپ کیلئے"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"کالعدم کریں"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"‫<xliff:g id="DEVICENAME">%1$s</xliff:g> پر چلانے کے لیے قریب کریں"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"یہاں چلانے کے لیے، <xliff:g id="DEVICENAME">%1$s</xliff:g> کے زیادہ جائیں"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"خرابی، دوبارہ کوشش کریں"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"کنٹرولز شامل کریں"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"کنٹرولز میں ترمیم کریں"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ایپ شامل کریں"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"آؤٹ پٹس شامل کریں"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"گروپ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 آلہ منتخب کیا گیا"</string>
@@ -919,7 +918,6 @@
     <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">"اسپیکرز اور ڈسپلیز"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"تجویز کردہ آلات"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"پریمئیم اکاؤنٹ درکار ہے"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"براڈکاسٹنگ کیسے کام کرتا ہے"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"براڈکاسٹ"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"موافق بلوٹوتھ آلات کے ساتھ آپ کے قریبی لوگ آپ کے نشر کردہ میڈیا کو سن سکتے ہیں"</string>
@@ -1031,6 +1029,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"کیمرا آف ہے"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"مائیک آف ہے"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"کیمرا اور مائیک آف ہیں"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"اسسٹنٹ سن رہی ہے"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# اطلاع}other{# اطلاعات}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>، <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"نوٹ لینا"</string>
@@ -1046,6 +1045,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"یک وقتی رسائی کی اجازت دیں"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"اجازت نہ دیں"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"آپ کے آلے پر جو ہوتا ہے آلے کے لاگز اسے ریکارڈ کر لیتے ہیں۔ ایپس ان لاگز کا استعمال مسائل کو تلاش کرنے اور ان کو حل کرنے کے لیے کر سکتی ہیں۔\n\nکچھ لاگز میں حساس معلومات شامل ہو سکتی ہیں، اس لیے صرف اپنی بھروسے مند ایپس کو ہی آلے کے تمام لاگز تک رسائی کی اجازت دیں۔ \n\nاگر آپ اس ایپ کو آلے کے تمام لاگز تک رسائی کی اجازت نہیں دیتے ہیں تب بھی یہ اپنے لاگز تک رسائی حاصل کر سکتی ہے۔ آپ کے آلے کا مینوفیکچرر اب بھی آپ کے آلے پر کچھ لاگز یا معلومات تک رسائی حاصل کر سکتا ہے۔"</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"مزید جانیں"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> پر مزید جانیں"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> کھولیں"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ایپ سیٹ اپ ہو گئی ہے"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• والٹ میں کم از کم ایک کارڈ شامل کیا گیا ہے"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"آپ کے کام سے متعلق پالیسی آپ کو صرف دفتری پروفائل سے فون کالز کرنے کی اجازت دیتی ہے"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"دفتری پروفائل پر سوئچ کریں"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"بند کریں"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"مقفل اسکرین کی ترتیبات"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index d31f3f8..72e5553 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Quyi chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Chap chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Oʻng chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Ish skrinshotlari <xliff:g id="APP">%1$s</xliff:g> ilovasida saqlanadi"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fayllar"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Ekrandan yozib olish"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Yuz aniqlandi. Ochish uchun ochish belgisini bosing."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Yuz bilan ochildi"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Yuz aniqlandi"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Chapga siljitish"</item>
-    <item msgid="5558598599408514296">"Pastga siljitish"</item>
-    <item msgid="4844142668312841831">"Oʻngga siljitish"</item>
-    <item msgid="5640521437931460125">"Tepaga siljitish"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Qayta urinish uchun tepaga suring"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC ishlatish uchun qurilma qulfini oching"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Bu qurilma tashkilotingizga tegishli"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Boshqaruv elementlarini kiritish uchun ilovani tanlang"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ta boshqaruv elementi kiritildi.}other{# ta boshqaruv elementi kiritildi.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Olib tashlandi"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> qoʻshilsinmi?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> bu panelga boshqaruv elementlari va kontent qoʻshishi mumkin. Ayrim ilovalarda bu yerda qaysi elementlar chiqishini tanlashingiz mumkin."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Saralanganlarga kiritilgan"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Saralanganlarga kiritilgan, <xliff:g id="NUMBER">%d</xliff:g>-joy"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Saralanganlardan olib tashlangan"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ilovasini ochish"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ilovasida ijro etish: <xliff:g id="SONG_NAME">%1$s</xliff:g> – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> ilovasida ijro etilmoqda: <xliff:g id="SONG_NAME">%1$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Siz uchun"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Qaytarish"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> qurilmasida ijro qilish uchun unga yaqinlashing"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Shu yerda ijro qilish uchun <xliff:g id="DEVICENAME">%1$s</xliff:g>ga yaqinroq suring"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Xato, qayta urining"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Element kiritish"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Elementlarni tahrirlash"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ilova kiritish"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Chiquvchi qurilmani kiritish"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Guruh"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ta qurilma tanlandi"</string>
@@ -919,7 +918,6 @@
     <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">"Karnaylar va displeylar"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Taklif qilingan qurilmalar"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Premium hisob talab etiladi"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Translatsiya qanday ishlaydi"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Translatsiya"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Atrofingizdagi mos Bluetooth qurilmasiga ega foydalanuvchilar siz translatsiya qilayotgan mediani tinglay olishadi"</string>
@@ -1031,6 +1029,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Kamera yoqilmagan"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Mikrofon yoqilmagan"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Kamera va mikrofon yoqilmagan"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Assistent tinglamoqda"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# ta bildirishnoma}other{# ta bildirishnoma}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Eslatma yozish"</string>
@@ -1046,6 +1045,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Bir matalik foydalanishga ruxsat berish"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Rad etish"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Qurilma jurnaliga qurilma bilan yuz bergan hodisalar qaydlari yoziladi. Ilovalar bu jurnal qaydlari yordamida muammolarni topishi va bartaraf qilishi mumkin.\n\nAyrim jurnal qaydlarida maxfiy axborotlar yozilishi mumkin, shu sababli qurilmadagi barcha jurnal qaydlariga ruxsatni faqat ishonchli ilovalarga bering. \n\nBu ilovaga qurilmadagi barcha jurnal qaydlariga ruxsat berilmasa ham, u oʻzining jurnalini ocha oladi. Qurilma ishlab chiqaruvchisi ham ayrim jurnallar yoki qurilma haqidagi axborotlarni ocha oladi."</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Batafsil"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Batafsil: <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ochish: <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Ilova sozlangan"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Kamida bitta kartochka Wallet xizmatiga qoʻshilgan"</string>
@@ -1054,10 +1055,10 @@
     <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Kamida bitta qurilma mavjud"</string>
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Bosib turish yorligʻi"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Bekor qilish"</string>
-    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Hozir aylantirish"</string>
+    <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Almashtirish"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Yaxshiroq selfi olish uchun telefonni yoying"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Old ekran sizga qaragan holda aylantirdingizmi?"</string>
-    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Keng va yuqori tiniqlikdagi suratga olish uchun orqa kameradan foydalaning."</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Yaxshiroq selfi uchun old ekranga almashilsinmi?"</string>
+    <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Keng burchakli va yuqori aniqlikda suratga olish uchun orqa kameradan foydalaning."</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Bu ekran oʻchiriladi"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Buklanadigan qurilma ochilmoqda"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Buklanadigan qurilma aylantirilmoqda"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Ishga oid siyosatingiz faqat ish profilidan telefon chaqiruvlarini amalga oshirish imkonini beradi"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Ish profiliga almashish"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Yopish"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Qulflangan ekran sozlamalari"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 2a4989a..29ccf23 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Cạnh dưới cùng <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Cạnh trái <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Cạnh phải <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Ảnh chụp màn hình công việc được lưu trong ứng dụng <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Đã lưu vào <xliff:g id="APP">%1$s</xliff:g> trong hồ sơ công việc"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> đã phát hiện thấy ảnh chụp màn hình này."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> và các ứng dụng đang mở khác đã phát hiện thấy ảnh chụp màn hình này."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Trình ghi màn hình"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Đang xử lý video ghi màn hình"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Thông báo đang diễn ra về phiên ghi màn hình"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Đã nhận diện khuôn mặt. Nhấn biểu tượng mở khoá để mở."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Đã mở khoá bằng khuôn mặt."</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Đã nhận diện khuôn mặt."</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Di chuyển sang trái"</item>
-    <item msgid="5558598599408514296">"Di chuyển xuống"</item>
-    <item msgid="4844142668312841831">"Di chuyển sang phải"</item>
-    <item msgid="5640521437931460125">"Di chuyển lên"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Vuốt lên để thử lại"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Mở khóa để sử dụng NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Thiết bị này thuộc về tổ chức của bạn"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Chọn ứng dụng để thêm các tùy chọn điều khiển"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Đã thêm # chế độ điều khiển.}other{Đã thêm # chế độ điều khiển.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Đã xóa"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Thêm <xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Khi bạn thêm <xliff:g id="APPNAME">%s</xliff:g>, ứng dụng có thể bổ sung các chế độ điều khiển và nội dung vào bảng điều khiển này. Trong một số ứng dụng, bạn có thể chọn chế độ điều khiển nào sẽ hiển thị tại đây."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Được yêu thích"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Được yêu thích, vị trí số <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Không được yêu thích"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Mở <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Phát <xliff:g id="SONG_NAME">%1$s</xliff:g> của <xliff:g id="ARTIST_NAME">%2$s</xliff:g> trên <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Phát <xliff:g id="SONG_NAME">%1$s</xliff:g> trên <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Dành cho bạn"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Hủy"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Đưa thiết bị đến gần hơn để phát trên <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Để phát ở đây, vui lòng lại gần <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Lỗi, hãy thử lại"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Thêm các tùy chọn điều khiển"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Chỉnh sửa tùy chọn điều khiển"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Thêm ứng dụng"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Thêm thiết bị đầu ra"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Nhóm"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Đã chọn 1 thiết bị"</string>
@@ -919,7 +915,6 @@
     <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">"Loa và màn hình"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Thiết bị được đề xuất"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Yêu cầu tài khoản trả phí"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cách tính năng truyền hoạt động"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Truyền"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Những người ở gần có thiết bị Bluetooth tương thích có thể nghe nội dung nghe nhìn bạn đang truyền"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Camera đang tắt"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Micrô đã bị tắt"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Máy ảnh và micrô đang tắt"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# thông báo}other{# thông báo}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Ghi chú"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Cho phép truy cập một lần"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Không cho phép"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Nhật ký thiết bị ghi lại những hoạt động diễn ra trên thiết bị của bạn. Các ứng dụng có thể dùng nhật ký này để tìm và khắc phục vấn đề.\n\nMột số nhật ký có thể chứa thông tin nhạy cảm, vì vậy, bạn chỉ nên cấp quyền truy cập vào mọi nhật ký thiết bị cho những ứng dụng mà mình tin tưởng. \n\nNếu bạn không cho phép ứng dụng này truy cập vào mọi nhật ký thiết bị, thì ứng dụng này vẫn có thể truy cập vào nhật ký của chính nó. Nhà sản xuất thiết bị vẫn có thể truy cập vào một số nhật ký hoặc thông tin trên thiết bị của bạn."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Mở <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Ứng dụng được thiết lập"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Thêm ít nhất một thẻ vào Wallet"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Chính sách của nơi làm việc chỉ cho phép bạn gọi điện thoại từ hồ sơ công việc"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Chuyển sang hồ sơ công việc"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Đóng"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Cài đặt màn hình khoá"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 431146b..2c3f941 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -91,8 +91,15 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"底部边界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左侧边界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右侧边界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"工作屏幕截图保存在“<xliff:g id="APP">%1$s</xliff:g>”应用中"</string>
+    <!-- no translation found for screenshot_work_profile_notification (203041724052970693) -->
+    <skip />
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"文件"</string>
+    <!-- no translation found for screenshot_detected_template (7940376642921719915) -->
+    <skip />
+    <!-- no translation found for screenshot_detected_multiple_template (7644827792093819241) -->
+    <skip />
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"屏幕录制器"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在处理屏幕录制视频"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string>
@@ -339,12 +346,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"识别出面孔。按下解锁图标即可打开。"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"已用面孔解锁"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"已识别出面孔"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"左移"</item>
-    <item msgid="5558598599408514296">"下移"</item>
-    <item msgid="4844142668312841831">"右移"</item>
-    <item msgid="5640521437931460125">"上移"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"向上滑动即可重试"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"需要解锁才能使用 NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"此设备归贵单位所有"</string>
@@ -832,10 +833,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"选择要添加控制器的应用"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{已添加 # 个控件。}other{已添加 # 个控件。}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"添加“<xliff:g id="APPNAME">%s</xliff:g>”?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"当您添加“<xliff:g id="APPNAME">%s</xliff:g>”后,它可以将控件和内容添加到此面板。在某些应用中,您可以选择在此处显示哪些控件。"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"已收藏"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"已收藏,位置:<xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"已取消收藏"</string>
@@ -886,6 +885,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"打开<xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"通过<xliff:g id="APP_LABEL">%3$s</xliff:g>播放<xliff:g id="ARTIST_NAME">%2$s</xliff:g>的《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"通过<xliff:g id="APP_LABEL">%2$s</xliff:g>播放《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"为您推荐"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"撤消"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"若要在“<xliff:g id="DEVICENAME">%1$s</xliff:g>”上播放,请靠近这台设备"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"若要在此设备上播放,请再靠近<xliff:g id="DEVICENAME">%1$s</xliff:g>一点"</string>
@@ -902,8 +902,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"出现错误,请重试"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"添加控制器"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"修改控制器"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"添加应用"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"添加输出设备"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"群组"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"已选择 1 个设备"</string>
@@ -919,7 +918,6 @@
     <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">"音箱和显示屏"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"建议的设备"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"需要使用付费帐号"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"广播的运作方式"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"广播"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近使用兼容蓝牙设备的用户可以收听您广播的媒体内容"</string>
@@ -1031,6 +1029,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"摄像头已关闭"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"麦克风已关闭"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"摄像头和麦克风已关闭"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 条通知}other{# 条通知}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>,<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"记录"</string>
@@ -1046,6 +1046,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"允许访问一次"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"不允许"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"设备日志会记录设备上发生的活动。应用可以使用这些日志查找和修复问题。\n\n部分日志可能包含敏感信息,因此请仅允许您信任的应用访问所有设备日志。\n\n如果您不授予此应用访问所有设备日志的权限,它仍然可以访问自己的日志。您的设备制造商可能仍然能够访问设备上的部分日志或信息。"</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"打开<xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• 应用已设置完毕"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• 至少已将一张银行卡添加到钱包"</string>
@@ -1056,7 +1060,7 @@
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"立即翻转"</string>
     <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"展开手机可拍出更好的自拍照"</string>
-    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"要翻转到外屏以拍出更好的自拍照吗?"</string>
+    <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"翻转到外屏后自拍效果更好,要试试吗?"</string>
     <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"您可以使用后置摄像头拍摄视角更广、分辨率更高的照片。"</string>
     <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 此屏幕将会关闭"</b></string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展开可折叠设备"</string>
@@ -1069,6 +1073,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"根据您的工作政策,您只能通过工作资料拨打电话"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"切换到工作资料"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"关闭"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"锁屏设置"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index ac27be2..48d6c65 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"下方邊界 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左方邊界 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右方邊界 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"工作的螢幕截圖會儲存在「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"已儲存在工作資料夾的「<xliff:g id="APP">%1$s</xliff:g>」中"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"檔案"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"「<xliff:g id="APPNAME">%1$s</xliff:g>」偵測到這張螢幕截圖。"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"「<xliff:g id="APPNAME">%1$s</xliff:g>」和其他開啟的應用程式偵測到這張螢幕截圖。"</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"螢幕畫面錄影工具"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在處理螢幕錄影內容"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"已識別面孔。按解鎖圖示即可開啟。"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"已使用面孔解鎖"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"已識別面孔"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"向左移"</item>
-    <item msgid="5558598599408514296">"向下移"</item>
-    <item msgid="4844142668312841831">"向右移"</item>
-    <item msgid="5640521437931460125">"向上移"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"請向上滑動以再試一次"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"解鎖方可使用 NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"此裝置屬於您的機構"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"選擇要新增控制項的應用程式"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{已新增 # 個控制項。}other{已新增 # 個控制項。}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"要新增「<xliff:g id="APPNAME">%s</xliff:g>」嗎?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"如果您新增「<xliff:g id="APPNAME">%s</xliff:g>」,應用程式可將控制項和內容新增至此面板。部份應用程式可讓您選擇要在這裡顯示的控制項。"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"已加入收藏"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"已加入至收藏位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"已取消收藏"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"開啟 <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"在 <xliff:g id="APP_LABEL">%3$s</xliff:g> 播放 <xliff:g id="ARTIST_NAME">%2$s</xliff:g> 的《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"在 <xliff:g id="APP_LABEL">%2$s</xliff:g> 播放《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"為您推薦"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"復原"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"如要在「<xliff:g id="DEVICENAME">%1$s</xliff:g>」上播放,請靠近一點"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"如要在這部裝置播放,請靠近「<xliff:g id="DEVICENAME">%1$s</xliff:g>」一點"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"發生錯誤,請重試"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"新增控制項"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"編輯控制項"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"新增應用程式"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"新增輸出裝置"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
@@ -919,7 +915,6 @@
     <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">"喇叭和螢幕"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"建議的裝置"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"需要付費帳戶"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播運作方式"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近有兼容藍牙裝置的人可收聽您正在廣播的媒體內容"</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"相機已關閉"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"麥克風已關閉"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"相機和麥克風已關閉"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Google 助理正在聆聽"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 則通知}other{# 則通知}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>,<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"做筆記"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"允許存取一次"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"不允許"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"裝置記錄會記下裝置的活動。應用程式可透過這些記錄找出並修正問題。\n\n部分記錄可能包含敏感資料,因此請只允許信任的應用程式存取所有裝置記錄。\n\n如果不允許此應用程式存取所有裝置記錄,此應用程式仍能存取自己的記錄,且裝置製造商可能仍可存取裝置上的部分記錄或資料。"</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"瞭解詳情"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"如要瞭解詳情,請前往 <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"開啟「<xliff:g id="APPNAME">%1$s</xliff:g>」"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• 應用程式已完成設定"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• 已新增至少一張卡至「錢包」"</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"您的公司政策只允許透過工作設定檔撥打電話"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"切換至工作設定檔"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"關閉"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"上鎖畫面設定"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 56fc01d..adf98fc 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"下方邊界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左側邊界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右側邊界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"工作的螢幕截圖會儲存在「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"已儲存在工作資料夾的「<xliff:g id="APP">%1$s</xliff:g>」中"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"檔案"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"「<xliff:g id="APPNAME">%1$s</xliff:g>」偵測到這張螢幕截圖。"</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"「<xliff:g id="APPNAME">%1$s</xliff:g>」和其他開啟的應用程式偵測到這張螢幕截圖。"</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"螢幕錄影器"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"處理螢幕錄影內容"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示螢幕畫面錄製工作階段通知"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"臉孔辨識完成,按下「解鎖」圖示即可開啟。"</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"裝置已透過你的臉解鎖"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"臉孔辨識完成"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"向左移"</item>
-    <item msgid="5558598599408514296">"向下移"</item>
-    <item msgid="4844142668312841831">"向右移"</item>
-    <item msgid="5640521437931460125">"向上移"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"向上滑動即可重試"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"如要使用 NFC,請先解鎖"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"這部裝置的擁有者為貴機構"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"選擇應用程式以新增控制項"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{已新增 # 個控制項。}other{已新增 # 個控制項。}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"要新增「<xliff:g id="APPNAME">%s</xliff:g>」嗎?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"當你新增「<xliff:g id="APPNAME">%s</xliff:g>」時,應用程式也可將控制選項及內容新增到這個面板。某些應用程式可讓你選擇要顯示在這裡的控制選項。"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"已加入收藏"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"已加入收藏,位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"從收藏中移除"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"開啟「<xliff:g id="APP_LABEL">%1$s</xliff:g>」"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"透過「<xliff:g id="APP_LABEL">%3$s</xliff:g>」播放<xliff:g id="ARTIST_NAME">%2$s</xliff:g>的〈<xliff:g id="SONG_NAME">%1$s</xliff:g>〉"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"透過「<xliff:g id="APP_LABEL">%2$s</xliff:g>」播放〈<xliff:g id="SONG_NAME">%1$s</xliff:g>〉"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"為你推薦"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"復原"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"如要在「<xliff:g id="DEVICENAME">%1$s</xliff:g>」上播放,請靠近一點"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"如要在這部裝置播放,請移到更靠近「<xliff:g id="DEVICENAME">%1$s</xliff:g>」的位置"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"發生錯誤,請再試一次"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"新增控制項"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"編輯控制項"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"新增應用程式"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"新增輸出裝置"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
@@ -919,7 +915,6 @@
     <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">"喇叭和螢幕"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"建議的裝置"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"必須有付費帳戶"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播功能的運作方式"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"如果附近的人有相容的藍牙裝置,就可以聽到你正在廣播的媒體內容"</string>
@@ -1031,6 +1026,7 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"相機已關閉"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"麥克風已關閉"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"已關閉相機和麥克風"</string>
+    <string name="dream_overlay_status_bar_assistant_attention_indicator" msgid="4712565923771372690">"Google 助理正在聆聽"</string>
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# 則通知}other{# 則通知}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>,<xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"做筆記"</string>
@@ -1046,6 +1042,8 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"允許一次性存取"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"不允許"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"系統會透過裝置記錄記下裝置上的活動。應用程式可以根據這些記錄找出問題並修正。\n\n某些記錄可能含有機密資訊,因此請勿讓不信任的應用程式存取所有裝置記錄。\n\n即使你不允許這個應用程式存取所有裝置記錄,這個應用程式仍能存取自己的記錄,而且裝置製造商或許仍可存取裝置的某些記錄或資訊。"</string>
+    <string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"瞭解詳情"</string>
+    <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"如要瞭解詳情,請前往 <xliff:g id="URL">%s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"開啟「<xliff:g id="APPNAME">%1$s</xliff:g>」"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• 完成應用程式設定"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• 錢包中至少要有一張卡片"</string>
@@ -1069,6 +1067,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"貴公司政策僅允許透過工作資料夾撥打電話"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"切換至工作資料夾"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"關閉"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"螢幕鎖定設定"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index eda7571..89be2cb 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -91,8 +91,12 @@
     <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Iphesenti elingu-<xliff:g id="PERCENT">%1$d</xliff:g> lomngcele ophansi"</string>
     <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Iphesenti elingu-<xliff:g id="PERCENT">%1$d</xliff:g> lomngcele ongakwesobunxele"</string>
     <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Iphesenti elingu-<xliff:g id="PERCENT">%1$d</xliff:g> lomngcele ongakwesokudla"</string>
-    <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Izithombe-skrini zomsebenzi zigcinwa ku-app ye-<xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="screenshot_work_profile_notification" msgid="203041724052970693">"Kulondolozwe ku-<xliff:g id="APP">%1$s</xliff:g> kuphrofayela yomsebenzi"</string>
     <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Amafayela"</string>
+    <string name="screenshot_detected_template" msgid="7940376642921719915">"I-<xliff:g id="APPNAME">%1$s</xliff:g> ithole lesi sithombe-skrini."</string>
+    <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"I-<xliff:g id="APPNAME">%1$s</xliff:g> namanye ama-app avuliwe athole lesi sithombe-skrini."</string>
+    <!-- no translation found for app_clips_save_add_to_note (3460200751278069445) -->
+    <skip />
     <string name="screenrecord_name" msgid="2596401223859996572">"Irekhoda yesikrini"</string>
     <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Icubungula okokuqopha iskrini"</string>
     <string name="screenrecord_channel_description" msgid="4147077128486138351">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string>
@@ -339,12 +343,6 @@
     <string name="keyguard_face_successful_unlock_press_alt_3" msgid="7219030481255573962">"Ubuso buyaziwa. Cindezela isithonjana sokuvula ukuze uvule."</string>
     <string name="keyguard_face_successful_unlock" msgid="4203999851465708287">"Vula ngobuso"</string>
     <string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Ubuso buyaziwa"</string>
-  <string-array name="udfps_accessibility_touch_hints">
-    <item msgid="1901953991150295169">"Yisa kwesokunxele"</item>
-    <item msgid="5558598599408514296">"Yehlisa"</item>
-    <item msgid="4844142668312841831">"Yisa kwesokudla"</item>
-    <item msgid="5640521437931460125">"Khuphula"</item>
-  </string-array>
     <string name="keyguard_retry" msgid="886802522584053523">"Swayiphela phezulu ukuze uzame futhi"</string>
     <string name="require_unlock_for_nfc" msgid="1305686454823018831">"Vula ukuze usebenzise i-NFC"</string>
     <string name="do_disclosure_generic" msgid="4896482821974707167">"Le divayisi eyenhlangano yakho"</string>
@@ -832,10 +830,8 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Khetha uhlelo lokusebenza ukwengeza izilawuli"</string>
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{ulawulo olu-# olwengeziwe.}one{ukulawulwa okungu-# okwengeziwe.}other{ukulawulwa okungu-# okwengeziwe.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Isusiwe"</string>
-    <!-- no translation found for controls_panel_authorization_title (267429338785864842) -->
-    <skip />
-    <!-- no translation found for controls_panel_authorization (4540047176861801815) -->
-    <skip />
+    <string name="controls_panel_authorization_title" msgid="267429338785864842">"Engeza i-<xliff:g id="APPNAME">%s</xliff:g>?"</string>
+    <string name="controls_panel_authorization" msgid="4540047176861801815">"Uma wengeza i-<xliff:g id="APPNAME">%s</xliff:g>, ingangeza izilawuli nokuqukethwe kuleli phaneli. Kwamanye ama-app, ungakhetha ukuthi yiziphi izilawuli eziboniswa lapha."</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Kwenziwe intandokazi"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Kwenziwe intandokazi, isimo esiyi-<xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Akwenziwanga intandokazi"</string>
@@ -886,6 +882,7 @@
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Vula i-<xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Dlala i-<xliff:g id="SONG_NAME">%1$s</xliff:g> ka-<xliff:g id="ARTIST_NAME">%2$s</xliff:g> kusuka ku-<xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Dlala i-<xliff:g id="SONG_NAME">%1$s</xliff:g> kusuka ku-<xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
+    <string name="controls_media_smartspace_rec_header" msgid="5053461390357112834">"Okwenzelwe wena"</string>
     <string name="media_transfer_undo" msgid="1895606387620728736">"Hlehlisa"</string>
     <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Sondeza eduze ukudlala ku-<xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
     <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Ukuze udlale lapha, sondela ku-<xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
@@ -902,8 +899,7 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Iphutha, zama futhi"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Engeza Izilawuli"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Hlela izilawuli"</string>
-    <!-- no translation found for controls_menu_add_another_app (8661172304650786705) -->
-    <skip />
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Engeza i-app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Engeza okukhiphayo"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Iqembu"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"idivayisi ekhethiwe e-1"</string>
@@ -919,7 +915,6 @@
     <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">"Izipikha Neziboniso"</string>
     <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Amadivayisi Aphakanyisiwe"</string>
-    <string name="media_output_status_require_premium" msgid="5691200962588753380">"Idinga i-akhawunti ye-premium"</string>
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Indlela ukusakaza okusebenza ngayo"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Sakaza"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Abantu abaseduze nawe abanamadivayisi e-Bluetooth ahambisanayo bangalalela imidiya oyisakazayo"</string>
@@ -1031,6 +1026,8 @@
     <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Ikhamera ivaliwe"</string>
     <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Imakrofoni ivaliwe"</string>
     <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Ikhamera nemakrofoni kuvaliwe"</string>
+    <!-- no translation found for dream_overlay_status_bar_assistant_attention_indicator (4712565923771372690) -->
+    <skip />
     <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{Isaziso esingu-#}one{Izaziso ezingu-#}other{Izaziso ezingu-#}}"</string>
     <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string>
     <string name="note_task_button_label" msgid="8718616095800343136">"Ukuthatha amanothi"</string>
@@ -1046,6 +1043,10 @@
     <string name="log_access_confirmation_allow" msgid="752147861593202968">"Vumela ukufinyelela kwesikhathi esisodwa"</string>
     <string name="log_access_confirmation_deny" msgid="2389461495803585795">"Ungavumeli"</string>
     <string name="log_access_confirmation_body" msgid="6883031912003112634">"Amalogu edivayisi arekhoda okwenzekayo kudivayisi yakho. Ama-app angasebenzisa lawa malogu ukuze athole futhi alungise izinkinga.\n\nAmanye amalogu angase aqukathe ulwazi olubucayi, ngakho vumela ama-app owathembayo kuphela ukuthi afinyelele wonke amalogu edivayisi. \n\nUma ungayivumeli le app ukuthi ifinyelele wonke amalogu wedivayisi, isengakwazi ukufinyelela amalogu wayo. Umkhiqizi wedivayisi yakho usengakwazi ukufinyelela amanye amalogu noma ulwazi kudivayisi yakho."</string>
+    <!-- no translation found for log_access_confirmation_learn_more (3134565480986328004) -->
+    <skip />
+    <!-- no translation found for log_access_confirmation_learn_more_at (5635666259505215905) -->
+    <skip />
     <string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Vula i-<xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• I-app isethiwe"</string>
     <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Okungenani ikhadi elilodwa lengeziwe ku-Wallet"</string>
@@ -1069,6 +1070,5 @@
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Inqubomgomo yakho yomsebenzi ikuvumela ukuthi wenze amakholi wefoni kuphela ngephrofayela yomsebenzi"</string>
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Shintshela kuphrofayela yomsebenzi"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Vala"</string>
-    <!-- no translation found for lock_screen_settings (9197175446592718435) -->
-    <skip />
+    <string name="lock_screen_settings" msgid="9197175446592718435">"Amasethingi okukhiya isikrini"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 5b6c9d3..b3256ef 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -219,5 +219,12 @@
         <attr name="biometricsEnrollProgressHelp" format="reference|color" />
         <attr name="biometricsEnrollProgressHelpWithTalkback" format="reference|color" />
     </declare-styleable>
+
+    <declare-styleable name="SeekBarWithIconButtonsView_Layout">
+        <attr name="max" format="integer" />
+        <attr name="progress" format="integer" />
+        <attr name="iconStartContentDescription" format="reference" />
+        <attr name="iconEndContentDescription" format="reference" />
+    </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 5bb96c4..7360c79 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -168,10 +168,11 @@
     <color name="GM2_yellow_200">#FDE293</color>
 
     <!-- Window magnification colors -->
-    <color name="magnification_border_color">#FF9900</color>
-    <color name="magnification_border_color_change">#0000FF</color>
+    <color name="magnification_border_color">#F29900</color>
     <color name="magnification_switch_button_color">#7F000000</color>
+    <color name="magnification_drag_corner_background">#E5FFFFFF</color>
     <color name="magnification_drag_handle_color">#B3000000</color>
+    <color name="magnification_drag_handle_tint">#111111</color>
     <color name="accessibility_magnifier_bg">#FCFCFC</color>
     <color name="accessibility_magnifier_bg_stroke">#E0E0E0</color>
     <color name="accessibility_magnifier_icon_color">#252525</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index f5db5ec..050b1e1 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -445,6 +445,13 @@
          screenshot has been saved to work profile. If blank, a default icon will be shown. -->
     <string name="config_sceenshotWorkProfileFilesApp" translatable="false"></string>
 
+    <!-- The component name of the screenshot editing activity that provides the App Clips flow.
+         The App Clips flow includes taking a screenshot, showing user screenshot cropping activity
+         and finally letting user send the screenshot to the calling notes app. This activity
+         should not send the screenshot to the calling activity without user consent. -->
+    <string name="config_screenshotAppClipsActivityComponent" translatable="false"
+            >com.android.systemui/com.android.systemui.screenshot.AppClipsActivity</string>
+
     <!-- Remote copy default activity.  Must handle REMOTE_COPY_ACTION intents.
      This name is in the ComponentName flattened format (package/class)  -->
     <string name="config_remoteCopyPackage" translatable="false"></string>
@@ -835,4 +842,7 @@
     <!-- Whether the floating rotation button should be on the left/right in the device's natural
          orientation -->
     <bool name="floating_rotation_button_position_left">true</bool>
+
+    <!-- Configuration to set Learn more in device logs as URL link -->
+    <bool name="log_access_confirmation_learn_more_as_link">true</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9e001e0..2df2513 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -43,12 +43,18 @@
     <dimen name="navigation_edge_panel_height">268dp</dimen>
     <!-- The threshold to drag to trigger the edge action -->
     <dimen name="navigation_edge_action_drag_threshold">16dp</dimen>
+    <!-- The drag distance to consider evaluating gesture -->
+    <dimen name="navigation_edge_action_min_distance_to_start_animation">24dp</dimen>
     <!-- The threshold to progress back animation for edge swipe -->
     <dimen name="navigation_edge_action_progress_threshold">412dp</dimen>
     <!-- The minimum display position of the arrow on the screen -->
     <dimen name="navigation_edge_arrow_min_y">64dp</dimen>
     <!-- The amount by which the arrow is shifted to avoid the finger-->
     <dimen name="navigation_edge_finger_offset">64dp</dimen>
+    <!-- The threshold to dynamically activate the edge action -->
+    <dimen name="navigation_edge_action_reactivation_drag_threshold">32dp</dimen>
+    <!-- The threshold to dynamically deactivate the edge action -->
+    <dimen name="navigation_edge_action_deactivation_drag_threshold">32dp</dimen>
 
     <!-- The thickness of the arrow -->
     <dimen name="navigation_edge_arrow_thickness">4dp</dimen>
@@ -56,37 +62,61 @@
     <dimen name="navigation_edge_minimum_x_delta_for_switch">32dp</dimen>
 
     <!-- entry state -->
+    <item name="navigation_edge_entry_scale" format="float" type="dimen">0.98</item>
     <dimen name="navigation_edge_entry_margin">4dp</dimen>
-    <dimen name="navigation_edge_entry_background_width">8dp</dimen>
-    <dimen name="navigation_edge_entry_background_height">60dp</dimen>
-    <dimen name="navigation_edge_entry_edge_corners">30dp</dimen>
-    <dimen name="navigation_edge_entry_far_corners">30dp</dimen>
-    <dimen name="navigation_edge_entry_arrow_length">10dp</dimen>
-    <dimen name="navigation_edge_entry_arrow_height">7dp</dimen>
+    <item name="navigation_edge_entry_background_alpha" format="float" type="dimen">1.0</item>
+    <dimen name="navigation_edge_entry_background_width">0dp</dimen>
+    <dimen name="navigation_edge_entry_background_height">48dp</dimen>
+    <dimen name="navigation_edge_entry_edge_corners">6dp</dimen>
+    <dimen name="navigation_edge_entry_far_corners">6dp</dimen>
+    <item name="navigation_edge_entry_arrow_alpha" format="float" type="dimen">0.0</item>
+    <dimen name="navigation_edge_entry_arrow_length">8.6dp</dimen>
+    <dimen name="navigation_edge_entry_arrow_height">5dp</dimen>
 
     <!-- pre-threshold -->
     <dimen name="navigation_edge_pre_threshold_margin">4dp</dimen>
-    <dimen name="navigation_edge_pre_threshold_background_width">64dp</dimen>
-    <dimen name="navigation_edge_pre_threshold_background_height">60dp</dimen>
-    <dimen name="navigation_edge_pre_threshold_edge_corners">22dp</dimen>
-    <dimen name="navigation_edge_pre_threshold_far_corners">26dp</dimen>
+    <item name="navigation_edge_pre_threshold_background_alpha" format="float" type="dimen">1.0
+    </item>
+    <item name="navigation_edge_pre_threshold_scale" format="float" type="dimen">0.98</item>
+    <dimen name="navigation_edge_pre_threshold_background_width">51dp</dimen>
+    <dimen name="navigation_edge_pre_threshold_background_height">46dp</dimen>
+    <dimen name="navigation_edge_pre_threshold_edge_corners">16dp</dimen>
+    <dimen name="navigation_edge_pre_threshold_far_corners">20dp</dimen>
+    <item name="navigation_edge_pre_threshold_arrow_alpha" format="float" type="dimen">1.0</item>
+    <dimen name="navigation_edge_pre_threshold_arrow_length">8dp</dimen>
+    <dimen name="navigation_edge_pre_threshold_arrow_height">5.6dp</dimen>
 
-    <!-- post-threshold / active -->
+    <!-- active (post-threshold) -->
+    <item name="navigation_edge_active_scale" format="float" type="dimen">1.0</item>
     <dimen name="navigation_edge_active_margin">14dp</dimen>
-    <dimen name="navigation_edge_active_background_width">60dp</dimen>
-    <dimen name="navigation_edge_active_background_height">60dp</dimen>
-    <dimen name="navigation_edge_active_edge_corners">30dp</dimen>
-    <dimen name="navigation_edge_active_far_corners">30dp</dimen>
-    <dimen name="navigation_edge_active_arrow_length">8dp</dimen>
-    <dimen name="navigation_edge_active_arrow_height">9dp</dimen>
+    <item name="navigation_edge_active_background_alpha" format="float" type="dimen">1.0</item>
+    <dimen name="navigation_edge_active_background_width">48dp</dimen>
+    <dimen name="navigation_edge_active_background_height">48dp</dimen>
+    <dimen name="navigation_edge_active_edge_corners">24dp</dimen>
+    <dimen name="navigation_edge_active_far_corners">24dp</dimen>
+    <item name="navigation_edge_active_arrow_alpha" format="float" type="dimen">1.0</item>
+    <dimen name="navigation_edge_active_arrow_length">6.4dp</dimen>
+    <dimen name="navigation_edge_active_arrow_height">7.2dp</dimen>
 
+    <!-- committed -->
+    <item name="navigation_edge_committed_scale" format="float" type="dimen">0.85</item>
+    <item name="navigation_edge_committed_alpha" format="float" type="dimen">0</item>
+
+    <!-- cancelled -->
+    <dimen name="navigation_edge_cancelled_background_width">0dp</dimen>
+
+    <item name="navigation_edge_stretch_scale" format="float" type="dimen">1.0</item>
     <dimen name="navigation_edge_stretch_margin">18dp</dimen>
-    <dimen name="navigation_edge_stretch_background_width">74dp</dimen>
-    <dimen name="navigation_edge_stretch_background_height">60dp</dimen>
-    <dimen name="navigation_edge_stretch_edge_corners">30dp</dimen>
-    <dimen name="navigation_edge_stretch_far_corners">30dp</dimen>
-    <dimen name="navigation_edge_stretched_arrow_length">7dp</dimen>
-    <dimen name="navigation_edge_stretched_arrow_height">10dp</dimen>
+    <dimen name="navigation_edge_stretch_background_width">60dp</dimen>
+    <item name="navigation_edge_stretch_background_alpha" format="float" type="dimen">
+        @dimen/navigation_edge_entry_background_alpha
+    </item>
+    <dimen name="navigation_edge_stretch_background_height">48dp</dimen>
+    <dimen name="navigation_edge_stretch_edge_corners">24dp</dimen>
+    <dimen name="navigation_edge_stretch_far_corners">24dp</dimen>
+    <item name="navigation_edge_strech_arrow_alpha" format="float" type="dimen">1.0</item>
+    <dimen name="navigation_edge_stretched_arrow_length">5.6dp</dimen>
+    <dimen name="navigation_edge_stretched_arrow_height">8dp</dimen>
 
     <dimen name="navigation_edge_cancelled_arrow_length">12dp</dimen>
     <dimen name="navigation_edge_cancelled_arrow_height">0dp</dimen>
@@ -1099,6 +1129,7 @@
     <dimen name="magnification_outer_border_margin">15dp</dimen>
     <dimen name="magnification_inner_border_margin">17dp</dimen>
     <dimen name="magnification_mirror_surface_margin">20dp</dimen>
+    <dimen name="magnification_drag_corner_margin">8dp</dimen>
     <dimen name="magnification_frame_move_short">5dp</dimen>
     <dimen name="magnification_frame_move_long">25dp</dimen>
     <dimen name="magnification_drag_view_size">36dp</dimen>
@@ -1111,6 +1142,15 @@
     <dimen name="magnifier_left_right_controls_height">45dp</dimen>
     <dimen name="magnifier_up_down_controls_width">45dp</dimen>
     <dimen name="magnifier_up_down_controls_height">40dp</dimen>
+    <dimen name="magnifier_outer_corner_radius">30dp</dimen>
+    <dimen name="magnifier_corner_radius">28dp</dimen>
+    <dimen name="magnifier_edit_corner_radius">16dp</dimen>
+    <dimen name="magnifier_edit_outer_corner_radius">18dp</dimen>
+    <dimen name="magnifier_border_width">8dp</dimen>
+    <dimen name="magnifier_stroke_width">2dp</dimen>
+    <dimen name="magnifier_edit_dash_gap">20dp</dimen>
+    <dimen name="magnification_window_drag_corner_size">26dp</dimen>
+    <dimen name="magnification_window_drag_corner_stroke">3dp</dimen>
     <!-- The extra padding to show the whole outer border -->
     <dimen name="magnifier_drag_handle_padding">3dp</dimen>
     <dimen name="magnification_max_frame_size">300dp</dimen>
@@ -1126,6 +1166,16 @@
     <dimen name="magnification_setting_button_done_corner_radius">100dp</dimen>
     <dimen name="magnification_setting_button_done_padding_vertical">10dp</dimen>
     <dimen name="magnification_setting_button_done_padding_horizontal">24dp</dimen>
+    <dimen name="magnification_setting_image_button_height">58dp</dimen>
+    <dimen name="magnification_setting_image_button_corner_radius">48dp</dimen>
+    <dimen name="magnification_setting_image_button_background_width">316dp</dimen>
+    <dimen name="magnification_setting_image_button_background_corner_radius">80dp</dimen>
+    <dimen name="magnification_setting_image_button_padding_vertical">12dp</dimen>
+    <dimen name="magnification_setting_image_button_padding_horizontal">24dp</dimen>
+    <dimen name="magnification_setting_image_button_open_in_full_padding_vertical">16dp</dimen>
+    <dimen name="magnification_setting_image_button_open_in_full_padding_horizontal">28dp</dimen>
+    <dimen name="magnification_setting_seekbar_icon_size">24dp</dimen>
+
 
     <!-- How far from the right edge of the screen you need to drag the window before the button
          repositions to the other side. -->
@@ -1136,7 +1186,7 @@
 
     <!-- Home Controls -->
     <dimen name="controls_header_menu_size">48dp</dimen>
-    <dimen name="controls_header_bottom_margin">24dp</dimen>
+    <dimen name="controls_header_bottom_margin">16dp</dimen>
     <dimen name="controls_header_app_icon_size">24dp</dimen>
     <dimen name="controls_top_margin">48dp</dimen>
     <dimen name="controls_padding_horizontal">0dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 575dc94..bf11019 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -240,9 +240,15 @@
     <!-- Content description for the right boundary of the screenshot being cropped, with the current position as a percentage. [CHAR LIMIT=NONE] -->
     <string name="screenshot_right_boundary_pct">Right boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>
     <!-- Notification displayed when a screenshot is saved in a work profile. [CHAR LIMIT=NONE] -->
-    <string name="screenshot_work_profile_notification">Work screenshots are saved in the <xliff:g id="app" example="Work Files">%1$s</xliff:g> app</string>
+    <string name="screenshot_work_profile_notification">Saved in <xliff:g id="app" example="Files">%1$s</xliff:g> in the work profile</string>
     <!-- Default name referring to the app on the device that lets the user browse stored files. [CHAR LIMIT=NONE] -->
     <string name="screenshot_default_files_app_name">Files</string>
+    <!-- A notice shown to the user to indicate that an app has detected the screenshot that the user has just taken. [CHAR LIMIT=75] -->
+    <string name="screenshot_detected_template"><xliff:g id="appName" example="Google Chrome">%1$s</xliff:g> detected this screenshot.</string>
+    <!-- A notice shown to the user to indicate that multiple apps have detected the screenshot that the user has just taken. [CHAR LIMIT=75] -->
+    <string name="screenshot_detected_multiple_template"><xliff:g id="appName" example="Google Chrome">%1$s</xliff:g> and other open apps detected this screenshot.</string>
+    <!-- Add to note button used in App Clips flow to return the saved screenshot image to notes app. [CHAR LIMIT=NONE] -->
+    <string name="app_clips_save_add_to_note">Add to note</string>
 
     <!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
     <string name="screenrecord_name">Screen Recorder</string>
@@ -904,14 +910,6 @@
     <!-- Message shown when non-bypass face authentication succeeds. [CHAR LIMIT=60] -->
     <string name="keyguard_face_successful_unlock_alt1">Face recognized</string>
 
-    <!-- Messages shown when users press outside of udfps region during -->
-    <string-array name="udfps_accessibility_touch_hints">
-        <item>Move left</item>
-        <item>Move down</item>
-        <item>Move right</item>
-        <item>Move up</item>
-    </string-array>
-
     <!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] -->
     <string name="keyguard_retry">Swipe up to try again</string>
 
@@ -2482,6 +2480,10 @@
     <string name="media_transfer_loading">Loading</string>
     <!-- Default name of the device. [CHAR LIMIT=30] -->
     <string name="media_ttt_default_device_type">tablet</string>
+    <!-- Description of media transfer icon of unknown app appears in receiver devices. [CHAR LIMIT=NONE]-->
+    <string name="media_transfer_receiver_content_description_unknown_app">Casting your media</string>
+    <!-- Description of media transfer icon appears in receiver devices. [CHAR LIMIT=NONE]-->
+    <string name="media_transfer_receiver_content_description_with_app_name">Casting <xliff:g id="app_label" example="Spotify">%1$s</xliff:g></string>
 
     <!-- Error message indicating that a control timed out while waiting for an update [CHAR_LIMIT=30] -->
     <string name="controls_error_timeout">Inactive, check app</string>
@@ -2534,8 +2536,7 @@
     <string name="media_output_group_title_speakers_and_displays">Speakers &amp; Displays</string>
     <!-- Title for Suggested Devices group. [CHAR LIMIT=NONE] -->
     <string name="media_output_group_title_suggested_device">Suggested Devices</string>
-    <!-- Sub status indicates device need premium account. [CHAR LIMIT=NONE] -->
-    <string name="media_output_status_require_premium">Requires premium account</string>
+
 
     <!-- Media Output Broadcast Dialog -->
     <!-- Title for Broadcast First Notify Dialog [CHAR LIMIT=60] -->
@@ -2794,6 +2795,8 @@
     <string name="dream_overlay_status_bar_mic_off">Mic is off</string>
     <!-- Content description for the camera and mic off icon in the dream overlay status bar [CHAR LIMIT=NONE] -->
     <string name="dream_overlay_status_bar_camera_mic_off">Camera and mic are off</string>
+    <!-- Content description for the assistant attention indicator [CHAR LIMIT=NONE] -->
+    <string name="dream_overlay_status_bar_assistant_attention_indicator">Assistant is listening</string>
     <!-- Content description for the notifications indicator icon in the dream overlay status bar [CHAR LIMIT=NONE] -->
     <string name="dream_overlay_status_bar_notification_indicator">{count, plural,
     =1 {# notification}
@@ -2840,7 +2843,9 @@
     </string>
 
     <!-- Learn more URL for the log access confirmation dialog. [DO NOT TRANSLATE]-->
-    <string name="log_access_confirmation_learn_more" translatable="false">&lt;a href="https://support.google.com/android?p=system_logs#topic=7313011"&gt;Learn more&lt;/a&gt;</string>
+    <string name="log_access_confirmation_learn_more_url" translatable="false">https://support.google.com/android?p=system_logs#topic=7313011</string>
+    <string name="log_access_confirmation_learn_more">Learn more</string>
+    <string name="log_access_confirmation_learn_more_at">Learn more at <xliff:g id="url" example="g.co/android/devicelogs">%s</xliff:g></string>
 
     <!--
     Template for an action that opens a specific app. [CHAR LIMIT=16]
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index dd87e91..4998d68 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -758,6 +758,18 @@
     </style>
 
     <!-- Screenshots -->
+    <style name="AppClipsTrampolineActivity">
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowIsFloating">true</item>
+        <item name="android:backgroundDimEnabled">true</item>
+    </style>
+
+    <style name="AppClipsActivity" parent="LongScreenshotActivity">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowIsTranslucent">true</item>
+    </style>
+
     <style name="LongScreenshotActivity" parent="@android:style/Theme.DeviceDefault.DayNight">
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowLightStatusBar">true</item>
diff --git a/packages/SystemUI/res/xml/qqs_header.xml b/packages/SystemUI/res/xml/qqs_header.xml
index e56e5d5..00a0444 100644
--- a/packages/SystemUI/res/xml/qqs_header.xml
+++ b/packages/SystemUI/res/xml/qqs_header.xml
@@ -48,8 +48,7 @@
             app:layout_constrainedWidth="true"
             app:layout_constraintStart_toEndOf="@id/clock"
             app:layout_constraintEnd_toStartOf="@id/barrier"
-            app:layout_constraintTop_toTopOf="parent"
-            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintBaseline_toBaselineOf="@id/clock"
             app:layout_constraintHorizontal_bias="0"
         />
     </Constraint>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
index 95675ce..209d5e8 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
@@ -38,13 +38,19 @@
 public class Monitor {
     private final String mTag = getClass().getSimpleName();
     private final Executor mExecutor;
+    private final Set<Condition> mPreconditions;
 
     private final HashMap<Condition, ArraySet<Subscription.Token>> mConditions = new HashMap<>();
     private final HashMap<Subscription.Token, SubscriptionState> mSubscriptions = new HashMap<>();
 
     private static class SubscriptionState {
         private final Subscription mSubscription;
+
+        // A subscription must maintain a reference to any active nested subscription so that it may
+        // be later removed when the current subscription becomes invalid.
+        private Subscription.Token mNestedSubscriptionToken;
         private Boolean mAllConditionsMet;
+        private boolean mActive;
 
         SubscriptionState(Subscription subscription) {
             mSubscription = subscription;
@@ -54,7 +60,27 @@
             return mSubscription.mConditions;
         }
 
-        public void update() {
+        /**
+         * Signals that the {@link Subscription} is now being monitored and will receive updates
+         * based on its conditions.
+         */
+        private void setActive(boolean active) {
+            if (mActive == active) {
+                return;
+            }
+
+            mActive = active;
+
+            final Callback callback = mSubscription.getCallback();
+
+            if (callback == null) {
+                return;
+            }
+
+            callback.onActiveChanged(active);
+        }
+
+        public void update(Monitor monitor) {
             final Boolean result = Evaluator.INSTANCE.evaluate(mSubscription.mConditions,
                     Evaluator.OP_AND);
             // Consider unknown (null) as true
@@ -65,7 +91,50 @@
             }
 
             mAllConditionsMet = newAllConditionsMet;
-            mSubscription.mCallback.onConditionsChanged(mAllConditionsMet);
+
+            final Subscription nestedSubscription = mSubscription.getNestedSubscription();
+
+            if (nestedSubscription != null) {
+                if (mAllConditionsMet && mNestedSubscriptionToken == null) {
+                    // When all conditions are met for a subscription with a nested subscription
+                    // that is not currently being monitored, add the nested subscription for
+                    // monitor.
+                    mNestedSubscriptionToken =
+                            monitor.addSubscription(nestedSubscription, null);
+                } else if (!mAllConditionsMet && mNestedSubscriptionToken != null) {
+                    // When conditions are not met and there is an active nested condition, remove
+                    // the nested condition from monitoring.
+                    removeNestedSubscription(monitor);
+                }
+                return;
+            }
+
+            mSubscription.getCallback().onConditionsChanged(mAllConditionsMet);
+        }
+
+        /**
+         * Invoked when the {@link Subscription} has been added to the {@link Monitor}.
+         */
+        public void onAdded() {
+            setActive(true);
+        }
+
+        /**
+         * Invoked when the {@link Subscription} has been removed from the {@link Monitor},
+         * allowing cleanup code to run.
+         */
+        public void onRemoved(Monitor monitor) {
+            setActive(false);
+            removeNestedSubscription(monitor);
+        }
+
+        private void removeNestedSubscription(Monitor monitor) {
+            if (mNestedSubscriptionToken == null) {
+                return;
+            }
+
+            monitor.removeSubscription(mNestedSubscriptionToken);
+            mNestedSubscriptionToken = null;
         }
     }
 
@@ -77,9 +146,20 @@
         }
     };
 
+    /**
+     * Constructor for injected use-cases. By default, no preconditions are present.
+     */
     @Inject
     public Monitor(@Main Executor executor) {
+        this(executor, Collections.emptySet());
+    }
+
+    /**
+     * Main constructor, allowing specifying preconditions.
+     */
+    public Monitor(Executor executor, Set<Condition> preconditions) {
         mExecutor = executor;
+        mPreconditions = preconditions;
     }
 
     private void updateConditionMetState(Condition condition) {
@@ -91,7 +171,7 @@
             return;
         }
 
-        subscriptions.stream().forEach(token -> mSubscriptions.get(token).update());
+        subscriptions.stream().forEach(token -> mSubscriptions.get(token).update(this));
     }
 
     /**
@@ -101,15 +181,25 @@
      * @return A {@link Subscription.Token} that can be used to remove the subscription.
      */
     public Subscription.Token addSubscription(@NonNull Subscription subscription) {
+        return addSubscription(subscription, mPreconditions);
+    }
+
+    private Subscription.Token addSubscription(@NonNull Subscription subscription,
+            Set<Condition> preconditions) {
+        // If preconditions are set on the monitor, set up as a nested condition.
+        final Subscription normalizedCondition = preconditions != null
+                ? new Subscription.Builder(subscription).addConditions(preconditions).build()
+                : subscription;
+
         final Subscription.Token token = new Subscription.Token();
-        final SubscriptionState state = new SubscriptionState(subscription);
+        final SubscriptionState state = new SubscriptionState(normalizedCondition);
 
         mExecutor.execute(() -> {
             if (shouldLog()) Log.d(mTag, "adding subscription");
             mSubscriptions.put(token, state);
 
             // Add and associate conditions.
-            subscription.getConditions().stream().forEach(condition -> {
+            normalizedCondition.getConditions().stream().forEach(condition -> {
                 if (!mConditions.containsKey(condition)) {
                     mConditions.put(condition, new ArraySet<>());
                     condition.addCallback(mConditionCallback);
@@ -118,8 +208,10 @@
                 mConditions.get(condition).add(token);
             });
 
+            state.onAdded();
+
             // Update subscription state.
-            state.update();
+            state.update(this);
 
         });
         return token;
@@ -139,7 +231,9 @@
                 return;
             }
 
-            mSubscriptions.remove(token).getConditions().forEach(condition -> {
+            final SubscriptionState removedSubscription = mSubscriptions.remove(token);
+
+            removedSubscription.getConditions().forEach(condition -> {
                 if (!mConditions.containsKey(condition)) {
                     Log.e(mTag, "condition not present:" + condition);
                     return;
@@ -153,6 +247,8 @@
                     mConditions.remove(condition);
                 }
             });
+
+            removedSubscription.onRemoved(this);
         });
     }
 
@@ -168,12 +264,19 @@
         private final Set<Condition> mConditions;
         private final Callback mCallback;
 
-        /**
-         *
-         */
-        public Subscription(Set<Condition> conditions, Callback callback) {
+        // A nested {@link Subscription} is a special callback where the specified condition's
+        // active state is dependent on the conditions of the parent {@link Subscription} being met.
+        // Once active, the nested subscription's conditions are registered as normal with the
+        // monitor and its callback (which could also be a nested condition) is triggered based on
+        // those conditions. The nested condition will be removed from monitor if the outer
+        // subscription's conditions ever become invalid.
+        private final Subscription mNestedSubscription;
+
+        private Subscription(Set<Condition> conditions, Callback callback,
+                Subscription nestedSubscription) {
             this.mConditions = Collections.unmodifiableSet(conditions);
             this.mCallback = callback;
+            this.mNestedSubscription = nestedSubscription;
         }
 
         public Set<Condition> getConditions() {
@@ -184,6 +287,10 @@
             return mCallback;
         }
 
+        public Subscription getNestedSubscription() {
+            return mNestedSubscription;
+        }
+
         /**
          * A {@link Token} is an identifier that is associated with a {@link Subscription} which is
          * registered with a {@link Monitor}.
@@ -196,14 +303,26 @@
          */
         public static class Builder {
             private final Callback mCallback;
+            private final Subscription mNestedSubscription;
             private final ArraySet<Condition> mConditions;
+            private final ArraySet<Condition> mPreconditions;
 
             /**
              * Default constructor specifying the {@link Callback} for the {@link Subscription}.
              */
             public Builder(Callback callback) {
+                this(null, callback);
+            }
+
+            public Builder(Subscription nestedSubscription) {
+                this(nestedSubscription, null);
+            }
+
+            private Builder(Subscription nestedSubscription, Callback callback) {
+                mNestedSubscription = nestedSubscription;
                 mCallback = callback;
-                mConditions = new ArraySet<>();
+                mConditions = new ArraySet();
+                mPreconditions = new ArraySet();
             }
 
             /**
@@ -217,11 +336,38 @@
             }
 
             /**
+             * Adds a set of {@link Condition} to be a precondition for {@link Subscription}.
+             *
+             * @return The updated {@link Builder}.
+             */
+            public Builder addPreconditions(Set<Condition> condition) {
+                if (condition == null) {
+                    return this;
+                }
+                mPreconditions.addAll(condition);
+                return this;
+            }
+
+            /**
+             * Adds a {@link Condition} to be a precondition for {@link Subscription}.
+             *
+             * @return The updated {@link Builder}.
+             */
+            public Builder addPrecondition(Condition condition) {
+                mPreconditions.add(condition);
+                return this;
+            }
+
+            /**
              * Adds a set of {@link Condition} to be associated with the {@link Subscription}.
              *
              * @return The updated {@link Builder}.
              */
             public Builder addConditions(Set<Condition> condition) {
+                if (condition == null) {
+                    return this;
+                }
+
                 mConditions.addAll(condition);
                 return this;
             }
@@ -232,7 +378,11 @@
              * @return The resulting {@link Subscription}.
              */
             public Subscription build() {
-                return new Subscription(mConditions, mCallback);
+                final Subscription subscription =
+                        new Subscription(mConditions, mCallback, mNestedSubscription);
+                return !mPreconditions.isEmpty()
+                        ? new Subscription(mPreconditions, null, subscription)
+                        : subscription;
             }
         }
     }
@@ -255,5 +405,13 @@
          *                         only partial conditions have been fulfilled.
          */
         void onConditionsChanged(boolean allConditionsMet);
+
+        /**
+         * Called when the active state of the {@link Subscription} changes.
+         * @param active {@code true} when changes to the conditions will affect the
+         *               {@link Subscription}, {@code false} otherwise.
+         */
+        default void onActiveChanged(boolean active) {
+        }
     }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
index ef2247f..9a581aa 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
@@ -114,7 +114,27 @@
 
     /** Dump region sampler */
     fun dump(pw: PrintWriter) {
-        regionSampler?.dump(pw)
+        pw.println("[RegionSampler]")
+        pw.println("regionSamplingEnabled: $regionSamplingEnabled")
+        pw.println("regionDarkness: $regionDarkness")
+        pw.println("lightForegroundColor: ${Integer.toHexString(lightForegroundColor)}")
+        pw.println("darkForegroundColor: ${Integer.toHexString(darkForegroundColor)}")
+        pw.println("passed-in sampledView: $sampledView")
+        pw.println("calculated samplingBounds: $samplingBounds")
+        pw.println(
+            "sampledView width: ${sampledView?.width}, sampledView height: ${sampledView?.height}"
+        )
+        pw.println("screen width: ${displaySize.x}, screen height: ${displaySize.y}")
+        pw.println(
+            "sampledRegionWithOffset: ${convertBounds(calculateSampledRegion(sampledView!!))}"
+        )
+        // TODO(b/265969235): mock initialSampling based on if component is on HS or LS wallpaper
+        // HS Smartspace - wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
+        // LS Smartspace, clock - wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK)
+        pw.println(
+            "initialSampling for lockscreen: " +
+                "${wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK)}"
+        )
     }
 
     fun calculateSampledRegion(sampledView: View): RectF {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextView.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextView.kt
index 9b73cc3..bd20777 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextView.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextView.kt
@@ -25,7 +25,7 @@
 import com.android.systemui.shared.shadow.DoubleShadowTextHelper.applyShadows
 
 /** Extension of [TextView] which draws two shadows on the text (ambient and key shadows} */
-class DoubleShadowTextView
+open class DoubleShadowTextView
 @JvmOverloads
 constructor(
     context: Context,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index b7e2494..44c0e16 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -88,6 +88,7 @@
                 final ArrayList<WindowContainerToken> pausingTasks = new ArrayList<>();
                 WindowContainerToken pipTask = null;
                 WindowContainerToken recentsTask = null;
+                int recentsTaskId = -1;
                 for (int i = apps.length - 1; i >= 0; --i) {
                     final ActivityManager.RunningTaskInfo taskInfo = apps[i].taskInfo;
                     if (apps[i].mode == MODE_CLOSING) {
@@ -106,8 +107,10 @@
                         // This task is for recents, keep it on top.
                         t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i);
                         recentsTask = taskInfo.token;
+                        recentsTaskId = taskInfo.taskId;
                     } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                         recentsTask = taskInfo.token;
+                        recentsTaskId = taskInfo.taskId;
                     }
                 }
                 // Also make all the wallpapers opaque since we want the visible from the start
@@ -116,7 +119,7 @@
                 }
                 t.apply();
                 mRecentsSession.setup(controller, info, finishedCallback, pausingTasks, pipTask,
-                        recentsTask, leashMap, mToken,
+                        recentsTask, recentsTaskId, leashMap, mToken,
                         (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0);
                 recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
                         new Rect());
@@ -154,6 +157,7 @@
         private ArrayList<WindowContainerToken> mPausingTasks = null;
         private WindowContainerToken mPipTask = null;
         private WindowContainerToken mRecentsTask = null;
+        private int mRecentsTaskId = 0;
         private TransitionInfo mInfo = null;
         private ArrayList<SurfaceControl> mOpeningLeashes = null;
         private boolean mOpeningHome = false;
@@ -167,8 +171,8 @@
         void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
                 IRemoteTransitionFinishedCallback finishCB,
                 ArrayList<WindowContainerToken> pausingTasks, WindowContainerToken pipTask,
-                WindowContainerToken recentsTask, ArrayMap<SurfaceControl, SurfaceControl> leashMap,
-                IBinder transition, boolean keyguardLocked) {
+                WindowContainerToken recentsTask, int recentsTaskId, ArrayMap<SurfaceControl,
+                SurfaceControl> leashMap, IBinder transition, boolean keyguardLocked) {
             if (mInfo != null) {
                 throw new IllegalStateException("Trying to run a new recents animation while"
                         + " recents is already active.");
@@ -179,6 +183,7 @@
             mPausingTasks = pausingTasks;
             mPipTask = pipTask;
             mRecentsTask = recentsTask;
+            mRecentsTaskId = recentsTaskId;
             mLeashMap = leashMap;
             mTransition = transition;
             mKeyguardLocked = keyguardLocked;
@@ -296,6 +301,15 @@
         }
 
         @Override public void setInputConsumerEnabled(boolean enabled) {
+            if (enabled) {
+                // transient launches don't receive focus automatically. Since we are taking over
+                // the gesture now, take focus explicitly.
+                try {
+                    ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to set focused task", e);
+                }
+            }
             if (mWrapped != null) mWrapped.setInputConsumerEnabled(enabled);
         }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt b/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
index 38fa354..54ae84f9 100644
--- a/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
@@ -16,18 +16,20 @@
 
 package com.android.keyguard
 
-import android.annotation.IntDef
 import android.content.ContentResolver
 import android.database.ContentObserver
 import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT
 import android.net.Uri
 import android.os.Handler
+import android.os.PowerManager
+import android.os.PowerManager.WAKE_REASON_UNFOLD_DEVICE
 import android.os.UserHandle
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ERRORS
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED
+import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_WAKE
 import android.util.Log
 import com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser
@@ -52,23 +54,26 @@
 
     companion object {
         const val TAG = "ActiveUnlockConfig"
-
-        const val BIOMETRIC_TYPE_NONE = 0
-        const val BIOMETRIC_TYPE_ANY_FACE = 1
-        const val BIOMETRIC_TYPE_ANY_FINGERPRINT = 2
-        const val BIOMETRIC_TYPE_UNDER_DISPLAY_FINGERPRINT = 3
     }
 
-    @Retention(AnnotationRetention.SOURCE)
-    @IntDef(BIOMETRIC_TYPE_NONE, BIOMETRIC_TYPE_ANY_FACE, BIOMETRIC_TYPE_ANY_FINGERPRINT,
-            BIOMETRIC_TYPE_UNDER_DISPLAY_FINGERPRINT)
-    annotation class BiometricType
-
     /**
      * Indicates the origin for an active unlock request.
      */
-    enum class ACTIVE_UNLOCK_REQUEST_ORIGIN {
-        WAKE, UNLOCK_INTENT, BIOMETRIC_FAIL, ASSISTANT
+    enum class ActiveUnlockRequestOrigin {
+        WAKE,
+        UNLOCK_INTENT,
+        BIOMETRIC_FAIL,
+        ASSISTANT,
+    }
+
+    /**
+     * Biometric type options.
+     */
+    enum class BiometricType(val intValue: Int) {
+        NONE(0),
+        ANY_FACE(1),
+        ANY_FINGERPRINT(2),
+        UNDER_DISPLAY_FINGERPRINT(3),
     }
 
     var keyguardUpdateMonitor: KeyguardUpdateMonitor? = null
@@ -76,9 +81,10 @@
     private var requestActiveUnlockOnUnlockIntent = false
     private var requestActiveUnlockOnBioFail = false
 
-    private var faceErrorsToTriggerBiometricFailOn = mutableSetOf(FACE_ERROR_TIMEOUT)
+    private var faceErrorsToTriggerBiometricFailOn = mutableSetOf<Int>()
     private var faceAcquireInfoToTriggerBiometricFailOn = mutableSetOf<Int>()
-    private var onUnlockIntentWhenBiometricEnrolled = mutableSetOf<Int>(BIOMETRIC_TYPE_NONE)
+    private var onUnlockIntentWhenBiometricEnrolled = mutableSetOf<Int>()
+    private var wakeupsConsideredUnlockIntents = mutableSetOf<Int>()
 
     private val settingsObserver = object : ContentObserver(handler) {
         private val wakeUri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_WAKE)
@@ -89,16 +95,19 @@
                 secureSettings.getUriFor(ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO)
         private val unlockIntentWhenBiometricEnrolledUri =
                 secureSettings.getUriFor(ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED)
+        private val wakeupsConsideredUnlockIntentsUri =
+            secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS)
 
         fun register() {
             registerUri(
                     listOf(
-                            wakeUri,
-                            unlockIntentUri,
-                            bioFailUri,
-                            faceErrorsUri,
-                            faceAcquireInfoUri,
-                            unlockIntentWhenBiometricEnrolledUri
+                        wakeUri,
+                        unlockIntentUri,
+                        bioFailUri,
+                        faceErrorsUri,
+                        faceAcquireInfoUri,
+                        unlockIntentWhenBiometricEnrolledUri,
+                        wakeupsConsideredUnlockIntentsUri,
                     )
             )
 
@@ -153,7 +162,7 @@
                         secureSettings.getStringForUser(ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO,
                                 getCurrentUser()),
                         faceAcquireInfoToTriggerBiometricFailOn,
-                        setOf<Int>())
+                        emptySet())
             }
 
             if (selfChange || uris.contains(unlockIntentWhenBiometricEnrolledUri)) {
@@ -162,7 +171,16 @@
                                 ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED,
                                 getCurrentUser()),
                         onUnlockIntentWhenBiometricEnrolled,
-                        setOf(BIOMETRIC_TYPE_NONE))
+                        setOf(BiometricType.NONE.intValue))
+            }
+
+            if (selfChange || uris.contains(wakeupsConsideredUnlockIntentsUri)) {
+                processStringArray(
+                    secureSettings.getStringForUser(
+                        ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS,
+                        getCurrentUser()),
+                    wakeupsConsideredUnlockIntents,
+                    setOf(WAKE_REASON_UNFOLD_DEVICE))
             }
         }
 
@@ -181,10 +199,12 @@
             out.clear()
             stringSetting?.let {
                 for (code: String in stringSetting.split("|")) {
-                    try {
-                        out.add(code.toInt())
-                    } catch (e: NumberFormatException) {
-                        Log.e(TAG, "Passed an invalid setting=$code")
+                    if (code.isNotEmpty()) {
+                        try {
+                            out.add(code.toInt())
+                        } catch (e: NumberFormatException) {
+                            Log.e(TAG, "Passed an invalid setting=$code")
+                        }
                     }
                 }
             } ?: out.addAll(default)
@@ -221,22 +241,30 @@
     }
 
     /**
+     * Whether the PowerManager wake reason is considered an unlock intent and should use origin
+     * [ActiveUnlockRequestOrigin.UNLOCK_INTENT] instead of [ActiveUnlockRequestOrigin.WAKE].
+     */
+    fun isWakeupConsideredUnlockIntent(pmWakeReason: Int): Boolean {
+        return wakeupsConsideredUnlockIntents.contains(pmWakeReason)
+    }
+
+    /**
      * Whether to trigger active unlock based on where the request is coming from and
      * the current settings.
      */
-    fun shouldAllowActiveUnlockFromOrigin(requestOrigin: ACTIVE_UNLOCK_REQUEST_ORIGIN): Boolean {
+    fun shouldAllowActiveUnlockFromOrigin(requestOrigin: ActiveUnlockRequestOrigin): Boolean {
         return when (requestOrigin) {
-            ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE -> requestActiveUnlockOnWakeup
+            ActiveUnlockRequestOrigin.WAKE -> requestActiveUnlockOnWakeup
 
-            ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT ->
+            ActiveUnlockRequestOrigin.UNLOCK_INTENT ->
                 requestActiveUnlockOnUnlockIntent || requestActiveUnlockOnWakeup ||
                         (shouldRequestActiveUnlockOnUnlockIntentFromBiometricEnrollment())
 
-            ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL ->
+            ActiveUnlockRequestOrigin.BIOMETRIC_FAIL ->
                 requestActiveUnlockOnBioFail || requestActiveUnlockOnUnlockIntent ||
                         requestActiveUnlockOnWakeup
 
-            ACTIVE_UNLOCK_REQUEST_ORIGIN.ASSISTANT -> isActiveUnlockEnabled()
+            ActiveUnlockRequestOrigin.ASSISTANT -> isActiveUnlockEnabled()
         }
     }
 
@@ -252,18 +280,18 @@
             val udfpsEnrolled = it.isUdfpsEnrolled
 
             if (!anyFaceEnrolled && !anyFingerprintEnrolled) {
-                return onUnlockIntentWhenBiometricEnrolled.contains(BIOMETRIC_TYPE_NONE)
+                return onUnlockIntentWhenBiometricEnrolled.contains(BiometricType.NONE.intValue)
             }
 
             if (!anyFaceEnrolled && anyFingerprintEnrolled) {
                 return onUnlockIntentWhenBiometricEnrolled.contains(
-                        BIOMETRIC_TYPE_ANY_FINGERPRINT) ||
+                        BiometricType.ANY_FINGERPRINT.intValue) ||
                         (udfpsEnrolled && onUnlockIntentWhenBiometricEnrolled.contains(
-                                BIOMETRIC_TYPE_UNDER_DISPLAY_FINGERPRINT))
+                                BiometricType.UNDER_DISPLAY_FINGERPRINT.intValue))
             }
 
             if (!anyFingerprintEnrolled && anyFaceEnrolled) {
-                return onUnlockIntentWhenBiometricEnrolled.contains(BIOMETRIC_TYPE_ANY_FACE)
+                return onUnlockIntentWhenBiometricEnrolled.contains(BiometricType.ANY_FACE.intValue)
             }
         }
 
@@ -275,11 +303,15 @@
         pw.println("   requestActiveUnlockOnWakeup=$requestActiveUnlockOnWakeup")
         pw.println("   requestActiveUnlockOnUnlockIntent=$requestActiveUnlockOnUnlockIntent")
         pw.println("   requestActiveUnlockOnBioFail=$requestActiveUnlockOnBioFail")
-        pw.println("   requestActiveUnlockOnUnlockIntentWhenBiometricEnrolled=" +
-                "$onUnlockIntentWhenBiometricEnrolled")
+        pw.println("   requestActiveUnlockOnUnlockIntentWhenBiometricEnrolled=${
+            onUnlockIntentWhenBiometricEnrolled.map { BiometricType.values()[it] }
+        }")
         pw.println("   requestActiveUnlockOnFaceError=$faceErrorsToTriggerBiometricFailOn")
         pw.println("   requestActiveUnlockOnFaceAcquireInfo=" +
                 "$faceAcquireInfoToTriggerBiometricFailOn")
+        pw.println("   activeUnlockWakeupsConsideredUnlockIntents=${
+            wakeupsConsideredUnlockIntents.map { PowerManager.wakeReasonToString(it) }
+        }")
 
         pw.println("Current state:")
         keyguardUpdateMonitor?.let {
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 3a940e9..1254e1e 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -24,6 +24,7 @@
 import android.text.format.DateFormat
 import android.util.TypedValue
 import android.view.View
+import android.view.ViewTreeObserver
 import android.widget.FrameLayout
 import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.Lifecycle
@@ -39,31 +40,37 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.log.dagger.KeyguardSmallClockLog
 import com.android.systemui.log.dagger.KeyguardLargeClockLog
+import com.android.systemui.log.dagger.KeyguardSmallClockLog
 import com.android.systemui.plugins.ClockController
+import com.android.systemui.plugins.ClockFaceController
+import com.android.systemui.plugins.ClockTickRate
 import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.plugins.log.LogLevel.DEBUG
 import com.android.systemui.shared.regionsampling.RegionSampler
+import com.android.systemui.plugins.Weather
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
 import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.concurrency.DelayableExecutor
+import java.util.Locale
+import java.util.TimeZone
+import java.util.concurrent.Executor
+import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.launch
-import java.util.Locale
-import java.util.TimeZone
-import java.util.concurrent.Executor
-import javax.inject.Inject
 
 /**
  * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
  * [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController].
  */
-open class ClockEventController @Inject constructor(
+open class ClockEventController
+@Inject
+constructor(
     private val keyguardInteractor: KeyguardInteractor,
     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
     private val broadcastDispatcher: BroadcastDispatcher,
@@ -72,7 +79,7 @@
     private val configurationController: ConfigurationController,
     @Main private val resources: Resources,
     private val context: Context,
-    @Main private val mainExecutor: Executor,
+    @Main private val mainExecutor: DelayableExecutor,
     @Background private val bgExecutor: Executor,
     @KeyguardSmallClockLog private val smallLogBuffer: LogBuffer?,
     @KeyguardLargeClockLog private val largeLogBuffer: LogBuffer?,
@@ -92,8 +99,11 @@
                 if (regionSamplingEnabled) {
                     clock?.smallClock?.view?.addOnLayoutChangeListener(mLayoutChangedListener)
                     clock?.largeClock?.view?.addOnLayoutChangeListener(mLayoutChangedListener)
+                } else {
+                    updateColors()
                 }
                 updateFontSizes()
+                updateTimeListeners()
             }
         }
 
@@ -107,52 +117,59 @@
     private var disposableHandle: DisposableHandle? = null
     private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING)
 
-    private val mLayoutChangedListener = object : View.OnLayoutChangeListener {
-        private var currentSmallClockView: View? = null
-        private var currentLargeClockView: View? = null
-        private var currentSmallClockLocation = IntArray(2)
-        private var currentLargeClockLocation = IntArray(2)
+    private val mLayoutChangedListener =
+        object : View.OnLayoutChangeListener {
+            private var currentSmallClockView: View? = null
+            private var currentLargeClockView: View? = null
+            private var currentSmallClockLocation = IntArray(2)
+            private var currentLargeClockLocation = IntArray(2)
 
-        override fun onLayoutChange(
-            view: View?,
-            left: Int,
-            top: Int,
-            right: Int,
-            bottom: Int,
-            oldLeft: Int,
-            oldTop: Int,
-            oldRight: Int,
-            oldBottom: Int
-        ) {
-        val parent = (view?.parent) as FrameLayout
+            override fun onLayoutChange(
+                view: View?,
+                left: Int,
+                top: Int,
+                right: Int,
+                bottom: Int,
+                oldLeft: Int,
+                oldTop: Int,
+                oldRight: Int,
+                oldBottom: Int
+            ) {
+                val parent = (view?.parent) as FrameLayout
 
-        // don't pass in negative bounds when clocks are in transition state
-        if (view.locationOnScreen[0] < 0 || view.locationOnScreen[1] < 0) {
-            return
-        }
+                // don't pass in negative bounds when clocks are in transition state
+                if (view.locationOnScreen[0] < 0 || view.locationOnScreen[1] < 0) {
+                    return
+                }
 
-        // SMALL CLOCK
-        if (parent.id == R.id.lockscreen_clock_view) {
-            // view bounds have changed due to clock size changing (i.e. different character widths)
-            // AND/OR the view has been translated when transitioning between small and large clock
-            if (view != currentSmallClockView ||
-                !view.locationOnScreen.contentEquals(currentSmallClockLocation)) {
-                currentSmallClockView = view
-                currentSmallClockLocation = view.locationOnScreen
-                updateRegionSampler(view)
+                // SMALL CLOCK
+                if (parent.id == R.id.lockscreen_clock_view) {
+                    // view bounds have changed due to clock size changing (i.e. different character
+                    // widths)
+                    // AND/OR the view has been translated when transitioning between small and
+                    // large clock
+                    if (
+                        view != currentSmallClockView ||
+                            !view.locationOnScreen.contentEquals(currentSmallClockLocation)
+                    ) {
+                        currentSmallClockView = view
+                        currentSmallClockLocation = view.locationOnScreen
+                        updateRegionSampler(view)
+                    }
+                }
+                // LARGE CLOCK
+                else if (parent.id == R.id.lockscreen_clock_view_large) {
+                    if (
+                        view != currentLargeClockView ||
+                            !view.locationOnScreen.contentEquals(currentLargeClockLocation)
+                    ) {
+                        currentLargeClockView = view
+                        currentLargeClockLocation = view.locationOnScreen
+                        updateRegionSampler(view)
+                    }
+                }
             }
         }
-        // LARGE CLOCK
-        else if (parent.id == R.id.lockscreen_clock_view_large) {
-            if (view != currentLargeClockView ||
-                !view.locationOnScreen.contentEquals(currentLargeClockLocation)) {
-                currentLargeClockView = view
-                currentLargeClockLocation = view.locationOnScreen
-                updateRegionSampler(view)
-            }
-        }
-        }
-    }
 
     private fun updateColors() {
         val wallpaperManager = WallpaperManager.getInstance(context)
@@ -181,86 +198,106 @@
 
     private fun updateRegionSampler(sampledRegion: View) {
         regionSampler?.stopRegionSampler()
-        regionSampler = createRegionSampler(
-            sampledRegion,
-            mainExecutor,
-            bgExecutor,
-            regionSamplingEnabled,
-            ::updateColors
-        )?.apply { startRegionSampler() }
+        regionSampler =
+            createRegionSampler(
+                    sampledRegion,
+                    mainExecutor,
+                    bgExecutor,
+                    regionSamplingEnabled,
+                    ::updateColors
+                )
+                ?.apply { startRegionSampler() }
 
         updateColors()
     }
 
     protected open fun createRegionSampler(
-            sampledView: View?,
-            mainExecutor: Executor?,
-            bgExecutor: Executor?,
-            regionSamplingEnabled: Boolean,
-            updateColors: () -> Unit
+        sampledView: View?,
+        mainExecutor: Executor?,
+        bgExecutor: Executor?,
+        regionSamplingEnabled: Boolean,
+        updateColors: () -> Unit
     ): RegionSampler? {
         return RegionSampler(
             sampledView,
             mainExecutor,
             bgExecutor,
             regionSamplingEnabled,
-            updateColors)
+            updateColors
+        )
     }
 
     var regionSampler: RegionSampler? = null
+    var smallTimeListener: TimeListener? = null
+    var largeTimeListener: TimeListener? = null
+    val shouldTimeListenerRun: Boolean
+        get() = isKeyguardVisible && dozeAmount < DOZE_TICKRATE_THRESHOLD
 
     private var smallClockIsDark = true
     private var largeClockIsDark = true
 
-    private val configListener = object : ConfigurationController.ConfigurationListener {
-        override fun onThemeChanged() {
-            clock?.events?.onColorPaletteChanged(resources)
-            updateColors()
-        }
-
-        override fun onDensityOrFontScaleChanged() {
-            updateFontSizes()
-        }
-    }
-
-    private val batteryCallback = object : BatteryStateChangeCallback {
-        override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
-            if (isKeyguardVisible && !isCharging && charging) {
-                clock?.animations?.charge()
+    private val configListener =
+        object : ConfigurationController.ConfigurationListener {
+            override fun onThemeChanged() {
+                clock?.events?.onColorPaletteChanged(resources)
+                updateColors()
             }
-            isCharging = charging
-        }
-    }
 
-    private val localeBroadcastReceiver = object : BroadcastReceiver() {
-        override fun onReceive(context: Context, intent: Intent) {
-            clock?.events?.onLocaleChanged(Locale.getDefault())
+            override fun onDensityOrFontScaleChanged() {
+                updateFontSizes()
+            }
         }
-    }
 
-    private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() {
-        override fun onKeyguardVisibilityChanged(visible: Boolean) {
-            isKeyguardVisible = visible
-            if (!featureFlags.isEnabled(DOZING_MIGRATION_1)) {
-                if (!isKeyguardVisible) {
-                    clock?.animations?.doze(if (isDozing) 1f else 0f)
+    private val batteryCallback =
+        object : BatteryStateChangeCallback {
+            override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
+                if (isKeyguardVisible && !isCharging && charging) {
+                    clock?.animations?.charge()
+                }
+                isCharging = charging
+            }
+        }
+
+    private val localeBroadcastReceiver =
+        object : BroadcastReceiver() {
+            override fun onReceive(context: Context, intent: Intent) {
+                clock?.events?.onLocaleChanged(Locale.getDefault())
+            }
+        }
+
+    private val keyguardUpdateMonitorCallback =
+        object : KeyguardUpdateMonitorCallback() {
+            override fun onKeyguardVisibilityChanged(visible: Boolean) {
+                isKeyguardVisible = visible
+                if (!featureFlags.isEnabled(DOZING_MIGRATION_1)) {
+                    if (!isKeyguardVisible) {
+                        clock?.animations?.doze(if (isDozing) 1f else 0f)
+                    }
+                }
+
+                smallTimeListener?.update(shouldTimeListenerRun)
+                largeTimeListener?.update(shouldTimeListenerRun)
+            }
+
+            override fun onTimeFormatChanged(timeFormat: String) {
+                clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+            }
+
+            override fun onTimeZoneChanged(timeZone: TimeZone) {
+                clock?.events?.onTimeZoneChanged(timeZone)
+            }
+
+            override fun onUserSwitchComplete(userId: Int) {
+                clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
+            }
+
+            override fun onWeatherDataChanged(data: Weather?) {
+                if (data != null) {
+                    clock?.events?.onWeatherDataChanged(data)
                 }
             }
         }
 
-        override fun onTimeFormatChanged(timeFormat: String) {
-            clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
-        }
-
-        override fun onTimeZoneChanged(timeZone: TimeZone) {
-            clock?.events?.onTimeZoneChanged(timeZone)
-        }
-
-        override fun onUserSwitchComplete(userId: Int) {
-            clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
-        }
-    }
-
     fun registerListeners(parent: View) {
         if (isRegistered) {
             return
@@ -274,17 +311,20 @@
         configurationController.addCallback(configListener)
         batteryController.addCallback(batteryCallback)
         keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
-        disposableHandle = parent.repeatWhenAttached {
-            repeatOnLifecycle(Lifecycle.State.STARTED) {
-                listenForDozing(this)
-                if (featureFlags.isEnabled(DOZING_MIGRATION_1)) {
-                    listenForDozeAmountTransition(this)
-                    listenForAnyStateToAodTransition(this)
-                } else {
-                    listenForDozeAmount(this)
+        disposableHandle =
+            parent.repeatWhenAttached {
+                repeatOnLifecycle(Lifecycle.State.STARTED) {
+                    listenForDozing(this)
+                    if (featureFlags.isEnabled(DOZING_MIGRATION_1)) {
+                        listenForDozeAmountTransition(this)
+                        listenForAnyStateToAodTransition(this)
+                    } else {
+                        listenForDozeAmount(this)
+                    }
                 }
             }
-        }
+        smallTimeListener?.update(shouldTimeListenerRun)
+        largeTimeListener?.update(shouldTimeListenerRun)
     }
 
     fun unregisterListeners() {
@@ -299,67 +339,140 @@
         batteryController.removeCallback(batteryCallback)
         keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
         regionSampler?.stopRegionSampler()
+        smallTimeListener?.stop()
+        largeTimeListener?.stop()
+    }
+
+    private fun updateTimeListeners() {
+        smallTimeListener?.stop()
+        largeTimeListener?.stop()
+
+        smallTimeListener = null
+        largeTimeListener = null
+
+        clock?.smallClock?.let {
+            smallTimeListener = TimeListener(it, mainExecutor)
+            smallTimeListener?.update(shouldTimeListenerRun)
+        }
+        clock?.largeClock?.let {
+            largeTimeListener = TimeListener(it, mainExecutor)
+            largeTimeListener?.update(shouldTimeListenerRun)
+        }
     }
 
     private fun updateFontSizes() {
-        clock?.smallClock?.events?.onFontSettingChanged(
-            resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat())
-        clock?.largeClock?.events?.onFontSettingChanged(
-            resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat())
+        clock
+            ?.smallClock
+            ?.events
+            ?.onFontSettingChanged(
+                resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat()
+            )
+        clock
+            ?.largeClock
+            ?.events
+            ?.onFontSettingChanged(
+                resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
+            )
+    }
+
+    private fun handleDoze(doze: Float) {
+        dozeAmount = doze
+        clock?.animations?.doze(dozeAmount)
+        smallTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD)
+        largeTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD)
     }
 
     @VisibleForTesting
     internal fun listenForDozeAmount(scope: CoroutineScope): Job {
-        return scope.launch {
-            keyguardInteractor.dozeAmount.collect {
-                dozeAmount = it
-                clock?.animations?.doze(dozeAmount)
-            }
-        }
+        return scope.launch { keyguardInteractor.dozeAmount.collect { handleDoze(it) } }
     }
 
     @VisibleForTesting
     internal fun listenForDozeAmountTransition(scope: CoroutineScope): Job {
         return scope.launch {
-            keyguardTransitionInteractor.dozeAmountTransition.collect {
-                dozeAmount = it.value
-                clock?.animations?.doze(dozeAmount)
-            }
+            keyguardTransitionInteractor.dozeAmountTransition.collect { handleDoze(it.value) }
         }
     }
 
     /**
-     * When keyguard is displayed again after being gone, the clock must be reset to full
-     * dozing.
+     * When keyguard is displayed again after being gone, the clock must be reset to full dozing.
      */
     @VisibleForTesting
     internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job {
         return scope.launch {
-            keyguardTransitionInteractor.anyStateToAodTransition.filter {
-                it.transitionState == TransitionState.FINISHED
-            }.collect {
-                dozeAmount = 1f
-                clock?.animations?.doze(dozeAmount)
-            }
+            keyguardTransitionInteractor.anyStateToAodTransition
+                .filter { it.transitionState == TransitionState.FINISHED }
+                .collect { handleDoze(1f) }
         }
     }
 
     @VisibleForTesting
     internal fun listenForDozing(scope: CoroutineScope): Job {
         return scope.launch {
-            combine (
-                keyguardInteractor.dozeAmount,
-                keyguardInteractor.isDozing,
-            ) { localDozeAmount, localIsDozing ->
-                localDozeAmount > dozeAmount || localIsDozing
+            combine(
+                    keyguardInteractor.dozeAmount,
+                    keyguardInteractor.isDozing,
+                ) { localDozeAmount, localIsDozing ->
+                    localDozeAmount > dozeAmount || localIsDozing
+                }
+                .collect { localIsDozing -> isDozing = localIsDozing }
+        }
+    }
+
+    class TimeListener(val clockFace: ClockFaceController, val executor: DelayableExecutor) {
+        val predrawListener =
+            ViewTreeObserver.OnPreDrawListener {
+                clockFace.events.onTimeTick()
+                true
             }
-            .collect { localIsDozing ->
-                isDozing = localIsDozing
+
+        val secondsRunnable =
+            object : Runnable {
+                override fun run() {
+                    if (!isRunning) {
+                        return
+                    }
+
+                    executor.executeDelayed(this, 990)
+                    clockFace.events.onTimeTick()
+                }
+            }
+
+        var isRunning: Boolean = false
+            private set
+
+        fun start() {
+            if (isRunning) {
+                return
+            }
+
+            isRunning = true
+            when (clockFace.events.tickRate) {
+                ClockTickRate.PER_MINUTE -> {
+                    /* Handled by KeyguardClockSwitchController */
+                }
+                ClockTickRate.PER_SECOND -> executor.execute(secondsRunnable)
+                ClockTickRate.PER_FRAME -> {
+                    clockFace.view.viewTreeObserver.addOnPreDrawListener(predrawListener)
+                    clockFace.view.invalidate()
+                }
             }
         }
+
+        fun stop() {
+            if (!isRunning) {
+                return
+            }
+
+            isRunning = false
+            clockFace.view.viewTreeObserver.removeOnPreDrawListener(predrawListener)
+        }
+
+        fun update(shouldRun: Boolean) = if (shouldRun) start() else stop()
     }
 
     companion object {
         private val TAG = ClockEventController::class.simpleName!!
+        private val DOZE_TICKRATE_THRESHOLD = 0.99f
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 0685794..e55ac1b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -91,6 +91,7 @@
     private ViewGroup mStatusArea;
 
     // If the SMARTSPACE flag is set, keyguard_slice_view is replaced by the following views.
+    private ViewGroup mDateWeatherView;
     private View mWeatherView;
     private View mSmartspaceView;
 
@@ -105,6 +106,12 @@
             updateDoubleLineClock();
         }
     };
+    private final ContentObserver mShowWeatherObserver = new ContentObserver(null) {
+        @Override
+        public void onChange(boolean change) {
+            setWeatherVisibility();
+        }
+    };
 
     private final KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener
             mKeyguardUnlockAnimationListener =
@@ -201,7 +208,7 @@
             // TODO(b/261757708): add content observer for the Settings toggle and add/remove
             //  weather according to the Settings.
             if (mSmartspaceController.isDateWeatherDecoupled()) {
-                addWeatherView(viewIndex);
+                addDateWeatherView(viewIndex);
                 viewIndex += 1;
             }
 
@@ -215,7 +222,15 @@
                 UserHandle.USER_ALL
         );
 
+        mSecureSettings.registerContentObserverForUser(
+                Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED,
+                false, /* notifyForDescendants */
+                mShowWeatherObserver,
+                UserHandle.USER_ALL
+        );
+
         updateDoubleLineClock();
+        setWeatherVisibility();
 
         mKeyguardUnlockAnimationController.addKeyguardUnlockAnimationListener(
                 mKeyguardUnlockAnimationListener);
@@ -239,6 +254,14 @@
 
     void onLocaleListChanged() {
         if (mSmartspaceController.isEnabled()) {
+            if (mSmartspaceController.isDateWeatherDecoupled()) {
+                mDateWeatherView.removeView(mWeatherView);
+                int index = mStatusArea.indexOfChild(mDateWeatherView);
+                if (index >= 0) {
+                    mStatusArea.removeView(mDateWeatherView);
+                    addDateWeatherView(index);
+                }
+            }
             int index = mStatusArea.indexOfChild(mSmartspaceView);
             if (index >= 0) {
                 mStatusArea.removeView(mSmartspaceView);
@@ -247,16 +270,28 @@
         }
     }
 
-    private void addWeatherView(int index) {
-        mWeatherView = mSmartspaceController.buildAndConnectWeatherView(mView);
+    private void addDateWeatherView(int index) {
+        mDateWeatherView = (ViewGroup) mSmartspaceController.buildAndConnectDateView(mView);
         LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                 MATCH_PARENT, WRAP_CONTENT);
-        mStatusArea.addView(mWeatherView, index, lp);
+        mStatusArea.addView(mDateWeatherView, index, lp);
         int startPadding = getContext().getResources().getDimensionPixelSize(
                 R.dimen.below_clock_padding_start);
         int endPadding = getContext().getResources().getDimensionPixelSize(
                 R.dimen.below_clock_padding_end);
-        mWeatherView.setPaddingRelative(startPadding, 0, endPadding, 0);
+        mDateWeatherView.setPaddingRelative(startPadding, 0, endPadding, 0);
+
+        addWeatherView();
+    }
+
+    private void addWeatherView() {
+        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+                WRAP_CONTENT, WRAP_CONTENT);
+        mWeatherView = mSmartspaceController.buildAndConnectWeatherView(mView);
+        // Place weather right after the date, before the extras
+        final int index = mDateWeatherView.getChildCount() == 0 ? 0 : 1;
+        mDateWeatherView.addView(mWeatherView, index, lp);
+        mWeatherView.setPaddingRelative(0, 0, 4, 0);
     }
 
     private void addSmartspaceView(int index) {
@@ -323,7 +358,8 @@
         }
         ClockController clock = getClock();
         if (clock != null) {
-            clock.getEvents().onTimeTick();
+            clock.getSmallClock().getEvents().onTimeTick();
+            clock.getLargeClock().getEvents().onTimeTick();
         }
     }
 
@@ -427,6 +463,14 @@
         }
     }
 
+    private void setWeatherVisibility() {
+        if (mWeatherView != null) {
+            mUiExecutor.execute(
+                    () -> mWeatherView.setVisibility(
+                        mSmartspaceController.isWeatherEnabled() ? View.VISIBLE : View.GONE));
+        }
+    }
+
     /**
      * Sets the clipChildren property on relevant views, to allow the smartspace to draw out of
      * bounds during the unlock transition.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index 08e9cf6..2a389b6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.graphics.Canvas;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.widget.FrameLayout;
 
 /**
@@ -33,7 +34,7 @@
 public class KeyguardHostView extends FrameLayout {
 
     protected ViewMediatorCallback mViewMediatorCallback;
-
+    private boolean mIsInteractable;
 
     public KeyguardHostView(Context context) {
         this(context, null);
@@ -54,4 +55,24 @@
     public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
         mViewMediatorCallback = viewMediatorCallback;
     }
+
+    /** Set true if the view can be interacted with */
+    public void setInteractable(boolean isInteractable) {
+        mIsInteractable = isInteractable;
+    }
+
+    /**
+     * Make sure to disallow touches while transitioning the bouncer, otherwise
+     * it can remain interactable even when barely visible.
+     */
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        return !mIsInteractable;
+    }
+
+    /** True to consume any events that are sent to it */
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        return true;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index ea84438..6139403 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -527,4 +527,9 @@
             mKeyguardSecurityContainerController.updateKeyguardPosition(x);
         }
     }
+
+    /** Set true if the view can be interacted with */
+    public void setInteractable(boolean isInteractable) {
+        mView.setInteractable(isInteractable);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index b143c5b..48844db 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -30,6 +30,7 @@
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -184,6 +185,7 @@
         private final FalsingCollector mFalsingCollector;
         private final DevicePostureController mDevicePostureController;
         private final KeyguardViewController mKeyguardViewController;
+        private final FeatureFlags mFeatureFlags;
 
         @Inject
         public Factory(KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -195,7 +197,8 @@
                 TelephonyManager telephonyManager, FalsingCollector falsingCollector,
                 EmergencyButtonController.Factory emergencyButtonControllerFactory,
                 DevicePostureController devicePostureController,
-                KeyguardViewController keyguardViewController) {
+                KeyguardViewController keyguardViewController,
+                FeatureFlags featureFlags) {
             mKeyguardUpdateMonitor = keyguardUpdateMonitor;
             mLockPatternUtils = lockPatternUtils;
             mLatencyTracker = latencyTracker;
@@ -209,6 +212,7 @@
             mFalsingCollector = falsingCollector;
             mDevicePostureController = devicePostureController;
             mKeyguardViewController = keyguardViewController;
+            mFeatureFlags = featureFlags;
         }
 
         /** Create a new {@link KeyguardInputViewController}. */
@@ -236,7 +240,7 @@
                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                         keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
                         mLiftToActivateListener, emergencyButtonController, mFalsingCollector,
-                        mDevicePostureController);
+                        mDevicePostureController, mFeatureFlags);
             } else if (keyguardInputView instanceof KeyguardSimPinView) {
                 return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
                         mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
index 8011efd..92e3641 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -131,6 +131,7 @@
 
     @Override
     void resetState() {
+        mMessageAreaController.setMessage(getInitialMessageResId());
         mView.setPasswordEntryEnabled(true);
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index 35b2db2..fd47e39 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -16,6 +16,8 @@
 
 package com.android.keyguard;
 
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.DEFAULT_PIN_LENGTH;
+
 import android.view.View;
 
 import com.android.internal.util.LatencyTracker;
@@ -23,6 +25,8 @@
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 
 public class KeyguardPinViewController
@@ -31,6 +35,14 @@
     private final DevicePostureController mPostureController;
     private final DevicePostureController.Callback mPostureCallback = posture ->
             mView.onDevicePostureChanged(posture);
+    private LockPatternUtils mLockPatternUtils;
+    private final FeatureFlags mFeatureFlags;
+    private static final int DEFAULT_PIN_LENGTH = 6;
+    private NumPadButton mBackspaceKey;
+    private View mOkButton = mView.findViewById(R.id.key_enter);
+
+    private int mUserId;
+    private long mPinLength;
 
     protected KeyguardPinViewController(KeyguardPINView view,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -40,12 +52,16 @@
             LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
             EmergencyButtonController emergencyButtonController,
             FalsingCollector falsingCollector,
-            DevicePostureController postureController) {
+            DevicePostureController postureController,
+            FeatureFlags featureFlags) {
         super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
                 messageAreaControllerFactory, latencyTracker, liftToActivateListener,
                 emergencyButtonController, falsingCollector);
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mPostureController = postureController;
+        mLockPatternUtils = lockPatternUtils;
+        mFeatureFlags = featureFlags;
+        mBackspaceKey = view.findViewById(R.id.delete_button);
     }
 
     @Override
@@ -59,10 +75,20 @@
                 getKeyguardSecurityCallback().onCancelClicked();
             });
         }
-
+        mPasswordEntry.setUserActivityListener(this::onUserInput);
         mPostureController.addCallback(mPostureCallback);
     }
 
+    protected void onUserInput() {
+        super.onUserInput();
+        if (isAutoConfirmation()) {
+            updateBackSpaceVisibility();
+            if (mPasswordEntry.getText().length() == mPinLength) {
+                verifyPasswordAndUnlock();
+            }
+        }
+    }
+
     @Override
     protected void onViewDetached() {
         super.onViewDetached();
@@ -70,8 +96,55 @@
     }
 
     @Override
+    public void startAppearAnimation() {
+        if (mFeatureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)) {
+            mUserId = KeyguardUpdateMonitor.getCurrentUser();
+            mPinLength = mLockPatternUtils.getPinLength(mUserId);
+            mBackspaceKey.setTransparentMode(/* isTransparentMode= */ isAutoConfirmation());
+            mOkButton.setVisibility(isAutoConfirmation() ? View.INVISIBLE : View.VISIBLE);
+            updateBackSpaceVisibility();
+            mPasswordEntry.setUsePinShapes(true);
+            mPasswordEntry.setIsPinHinting(isAutoConfirmation() && isPinHinting());
+        }
+        super.startAppearAnimation();
+    }
+
+    @Override
     public boolean startDisappearAnimation(Runnable finishRunnable) {
         return mView.startDisappearAnimation(
                 mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable);
     }
+
+    //
+
+    /**
+     *  Updates the visibility and the enabled state of the backspace.
+     * Visibility changes are only for auto confirmation configuration.
+     */
+    private void updateBackSpaceVisibility() {
+        if (!isAutoConfirmation()) {
+            return;
+        }
+
+        if (mPasswordEntry.getText().length() > 0) {
+            mBackspaceKey.setVisibility(View.VISIBLE);
+        } else {
+            mBackspaceKey.setVisibility(View.INVISIBLE);
+        }
+    }
+
+    /**
+     *   Responsible for identifying if PIN hinting is to be enabled or not
+     */
+    private boolean isPinHinting() {
+        return mLockPatternUtils.getPinLength(mUserId) == DEFAULT_PIN_LENGTH;
+    }
+
+    /**
+     *   Responsible for identifying if auto confirm is enabled or not in Settings
+     */
+    private boolean isAutoConfirmation() {
+        //Checks if user has enabled the auto confirm in Settings
+        return mLockPatternUtils.isAutoPinConfirmEnabled(mUserId);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 57bfe54..20baa81 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -237,7 +237,7 @@
             }
             if (mUpdateMonitor.isFaceEnrolled()) {
                 mUpdateMonitor.requestActiveUnlock(
-                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
+                        ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT,
                         "swipeUpOnBouncer");
             }
         }
@@ -247,6 +247,7 @@
                 @Override
                 public void onThemeChanged() {
                     reloadColors();
+                    reset();
                 }
 
                 @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index afa9ef6..f491232 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -109,7 +109,6 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -149,6 +148,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.dump.DumpsysTableLogger;
 import com.android.systemui.log.SessionTracker;
+import com.android.systemui.plugins.Weather;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -1312,7 +1312,8 @@
     }
 
     public boolean getUserHasTrust(int userId) {
-        return !isTrustDisabled() && mUserHasTrust.get(userId);
+        return !isTrustDisabled() && mUserHasTrust.get(userId)
+                && isUnlockingWithTrustAgentAllowed();
     }
 
     /**
@@ -1320,12 +1321,19 @@
      */
     public boolean getUserUnlockedWithBiometric(int userId) {
         BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
-        BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
         boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated
                 && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric);
-        boolean faceAllowed = face != null && face.mAuthenticated
+        return fingerprintAllowed || getUserUnlockedWithFace(userId);
+    }
+
+
+    /**
+     * Returns whether the user is unlocked with face.
+     */
+    public boolean getUserUnlockedWithFace(int userId) {
+        BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
+        return face != null && face.mAuthenticated
                 && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric);
-        return fingerprintAllowed || faceAllowed;
     }
 
     /**
@@ -1400,6 +1408,10 @@
         return mUserTrustIsUsuallyManaged.get(userId);
     }
 
+    private boolean isUnlockingWithTrustAgentAllowed() {
+        return isUnlockingWithBiometricAllowed(true);
+    }
+
     public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
         // StrongAuthTracker#isUnlockingWithBiometricAllowed includes
         // STRONG_AUTH_REQUIRED_AFTER_LOCKOUT which is the same as mFingerprintLockedOutPermanent;
@@ -1535,7 +1547,7 @@
                 FACE_AUTH_UPDATED_ASSISTANT_VISIBILITY_CHANGED);
         if (mAssistantVisible) {
             requestActiveUnlock(
-                    ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.ASSISTANT,
+                    ActiveUnlockConfig.ActiveUnlockRequestOrigin.ASSISTANT,
                     "assistant",
                     false);
         }
@@ -1665,7 +1677,7 @@
                 @Override
                 public void onAuthenticationFailed() {
                     requestActiveUnlockDismissKeyguard(
-                            ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
+                            ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL,
                             "fingerprintFailure");
                     handleFingerprintAuthFailed();
                 }
@@ -1734,7 +1746,7 @@
                                                 : mPrimaryBouncerFullyShown ? "bouncer"
                                                         : "udfpsFpDown";
                         requestActiveUnlock(
-                                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
+                                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL,
                                 "faceFailure-" + reason);
 
                     handleFaceAuthFailed();
@@ -1761,7 +1773,7 @@
 
                     if (mActiveUnlockConfig.shouldRequestActiveUnlockOnFaceError(errMsgId)) {
                         requestActiveUnlock(
-                                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
+                                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL,
                                 "faceError-" + errMsgId);
                     }
                 }
@@ -1773,7 +1785,7 @@
                     if (mActiveUnlockConfig.shouldRequestActiveUnlockOnFaceAcquireInfo(
                             acquireInfo)) {
                         requestActiveUnlock(
-                                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL,
+                                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL,
                                 "faceAcquireInfo-" + acquireInfo);
                     }
                 }
@@ -1913,8 +1925,11 @@
             FACE_AUTH_UPDATED_STARTED_WAKING_UP.setExtraInfo(pmWakeReason);
             updateFaceListeningState(BIOMETRIC_ACTION_UPDATE,
                     FACE_AUTH_UPDATED_STARTED_WAKING_UP);
-            requestActiveUnlock(ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE, "wakingUp - "
-                    + PowerManager.wakeReasonToString(pmWakeReason));
+            requestActiveUnlock(
+                    mActiveUnlockConfig.isWakeupConsideredUnlockIntent(pmWakeReason)
+                            ? ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT
+                            : ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE,
+                    "wakingUp - " + PowerManager.wakeReasonToString(pmWakeReason));
         } else {
             mLogger.logSkipUpdateFaceListeningOnWakeup(pmWakeReason);
         }
@@ -2478,7 +2493,7 @@
         mAuthInterruptActive = active;
         updateFaceListeningState(BIOMETRIC_ACTION_UPDATE,
                 FACE_AUTH_TRIGGERED_ON_REACH_GESTURE_ON_AOD);
-        requestActiveUnlock(ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE, "onReach");
+        requestActiveUnlock(ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE, "onReach");
     }
 
     /**
@@ -2548,7 +2563,7 @@
      * Attempts to trigger active unlock from trust agent.
      */
     private void requestActiveUnlock(
-            @NonNull ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN requestOrigin,
+            @NonNull ActiveUnlockConfig.ActiveUnlockRequestOrigin requestOrigin,
             String reason,
             boolean dismissKeyguard
     ) {
@@ -2559,7 +2574,7 @@
 
         final boolean allowRequest =
                 mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin(requestOrigin);
-        if (requestOrigin == ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE
+        if (requestOrigin == ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE
                 && !allowRequest && mActiveUnlockConfig.isActiveUnlockEnabled()) {
             // instead of requesting the active unlock, initiate the unlock
             initiateActiveUnlock(reason);
@@ -2578,7 +2593,7 @@
      * Only dismisses the keyguard under certain conditions.
      */
     public void requestActiveUnlock(
-            @NonNull ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN requestOrigin,
+            @NonNull ActiveUnlockConfig.ActiveUnlockRequestOrigin requestOrigin,
             String extraReason
     ) {
         final boolean canFaceBypass = isFaceEnrolled() && mKeyguardBypassController != null
@@ -2595,7 +2610,7 @@
      * Attempts to trigger active unlock from trust agent with a request to dismiss the keyguard.
      */
     public void requestActiveUnlockDismissKeyguard(
-            @NonNull ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN requestOrigin,
+            @NonNull ActiveUnlockConfig.ActiveUnlockRequestOrigin requestOrigin,
             String extraReason
     ) {
         requestActiveUnlock(
@@ -2612,7 +2627,7 @@
             updateFaceListeningState(BIOMETRIC_ACTION_START,
                     FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN);
             requestActiveUnlock(
-                    ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
+                    ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT,
                     "udfpsBouncer");
         }
     }
@@ -3219,6 +3234,24 @@
     }
 
     /**
+     * @param data the weather data (temp, conditions, unit) for weather clock to use
+     */
+    public void sendWeatherData(Weather data) {
+        mHandler.post(()-> {
+            handleWeatherDataUpdate(data); });
+    }
+
+    private void handleWeatherDataUpdate(Weather data) {
+        Assert.isMainThread();
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onWeatherDataChanged(data);
+            }
+        }
+    }
+
+    /**
      * Handle {@link #MSG_BATTERY_UPDATE}
      */
     private void handleBatteryUpdate(BatteryStatus status) {
@@ -3400,7 +3433,7 @@
         if (wasPrimaryBouncerFullyShown != mPrimaryBouncerFullyShown) {
             if (mPrimaryBouncerFullyShown) {
                 requestActiveUnlock(
-                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
+                        ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT,
                         "bouncerFullyShown");
             }
             for (int i = 0; i < mCallbacks.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index e6b9ac8..0da799e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -23,6 +23,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.settingslib.fuelgauge.BatteryStatus;
+import com.android.systemui.plugins.Weather;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 
 import java.util.TimeZone;
@@ -58,6 +59,11 @@
     public void onTimeFormatChanged(String timeFormat) { }
 
     /**
+     * Called when receive new weather data.
+     */
+    public void onWeatherDataChanged(Weather data) { }
+
+    /**
      * Called when the carrier PLMN or SPN changes.
      */
     public void onRefreshCarrierInfo() { }
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index 41111e3..5135eed 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -95,7 +95,6 @@
         mHeight = height;
         mStartRadius = height / 2f;
         mEndRadius = height / 4f;
-        mBackground.setCornerRadius(mStartRadius);
         mExpandAnimator.setFloatValues(mStartRadius, mEndRadius);
         mContractAnimator.setFloatValues(mEndRadius, mStartRadius);
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
index 37060987c..11c329e 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
@@ -27,6 +27,8 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.systemui.R;
+
 /**
  * Similar to the {@link NumPadKey}, but displays an image.
  */
@@ -35,18 +37,13 @@
     @Nullable
     private NumPadAnimator mAnimator;
     private int mOrientation;
+    private int mStyleAttr;
+    private boolean mIsTransparentMode;
 
     public NumPadButton(Context context, AttributeSet attrs) {
         super(context, attrs);
-
-        Drawable background = getBackground();
-        if (background instanceof GradientDrawable) {
-            mAnimator = new NumPadAnimator(context, background.mutate(),
-                    attrs.getStyleAttribute(), getDrawable());
-        } else {
-            mAnimator = null;
-        }
-
+        mStyleAttr = attrs.getStyleAttribute();
+        setupAnimator();
     }
 
     @Override
@@ -98,7 +95,9 @@
     public void reloadColors() {
         if (mAnimator != null) mAnimator.reloadColors(getContext());
 
-        int[] customAttrs = {android.R.attr.textColorPrimaryInverse};
+        int textColorResId = mIsTransparentMode ? android.R.attr.textColorPrimary
+                : android.R.attr.textColorPrimaryInverse;
+        int[] customAttrs = {textColorResId};
         TypedArray a = getContext().obtainStyledAttributes(customAttrs);
         int imageColor = a.getColor(0, 0);
         a.recycle();
@@ -111,4 +110,34 @@
             mAnimator.setProgress(progress);
         }
     }
+
+    /**
+     * Set whether button is transparent mode.
+     *
+     * @param isTransparentMode
+     */
+    public void setTransparentMode(boolean isTransparentMode) {
+        mIsTransparentMode = isTransparentMode;
+        if (isTransparentMode) {
+            setBackgroundColor(android.R.color.transparent);
+        } else {
+            setBackground(getContext().getDrawable(R.drawable.num_pad_key_background));
+        }
+        setupAnimator();
+        reloadColors();
+        requestLayout();
+    }
+
+    /**
+     * Set up the animator for the NumPadButton.
+     */
+    private void setupAnimator() {
+        Drawable background = getBackground();
+        if (background instanceof GradientDrawable) {
+            mAnimator = new NumPadAnimator(getContext(), background.mutate(),
+                    mStyleAttr, getDrawable());
+        } else {
+            mAnimator = null;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index 35cae09..8554e11 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -35,13 +35,14 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.Gravity;
-import android.view.View;
+import android.view.LayoutInflater;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.EditText;
+import android.widget.FrameLayout;
 
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
@@ -52,12 +53,12 @@
  * A View similar to a textView which contains password text and can animate when the text is
  * changed
  */
-public class PasswordTextView extends View {
+public class PasswordTextView extends FrameLayout {
 
     private static final float DOT_OVERSHOOT_FACTOR = 1.5f;
     private static final long DOT_APPEAR_DURATION_OVERSHOOT = 320;
-    private static final long APPEAR_DURATION = 160;
-    private static final long DISAPPEAR_DURATION = 160;
+    public static final long APPEAR_DURATION = 160;
+    public static final long DISAPPEAR_DURATION = 160;
     private static final long RESET_DELAY_PER_ELEMENT = 40;
     private static final long RESET_MAX_DELAY = 200;
 
@@ -95,11 +96,14 @@
     private PowerManager mPM;
     private int mCharPadding;
     private final Paint mDrawPaint = new Paint();
+    private int mDrawColor;
     private Interpolator mAppearInterpolator;
     private Interpolator mDisappearInterpolator;
     private Interpolator mFastOutSlowInInterpolator;
     private boolean mShowPassword;
     private UserActivityListener mUserActivityListener;
+    private PinShapeInput mPinShapeInput;
+    private boolean mUsePinShapes = false;
 
     public interface UserActivityListener {
         void onUserActivity();
@@ -141,8 +145,10 @@
             mCharPadding = a.getDimensionPixelSize(R.styleable.PasswordTextView_charPadding,
                     getContext().getResources().getDimensionPixelSize(
                             R.dimen.password_char_padding));
-            mDrawPaint.setColor(a.getColor(R.styleable.PasswordTextView_android_textColor,
-                    Color.WHITE));
+            mDrawColor = a.getColor(R.styleable.PasswordTextView_android_textColor,
+                    Color.WHITE);
+            mDrawPaint.setColor(mDrawColor);
+
         } finally {
             a.recycle();
         }
@@ -161,6 +167,7 @@
         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(mContext,
                 android.R.interpolator.fast_out_slow_in);
         mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        setWillNotDraw(false);
     }
 
     @Override
@@ -171,6 +178,12 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
+        // Do not use legacy draw animations for pin shapes.
+        if (mUsePinShapes) {
+            super.onDraw(canvas);
+            return;
+        }
+
         float totalDrawingWidth = getDrawingWidth();
         float currentDrawPosition;
         if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT) {
@@ -205,9 +218,12 @@
      * Reload colors from resources.
      **/
     public void reloadColors() {
-        int textColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)
-                .getDefaultColor();
-        mDrawPaint.setColor(textColor);
+        mDrawColor = Utils.getColorAttr(getContext(),
+                android.R.attr.textColorPrimary).getDefaultColor();
+        mDrawPaint.setColor(mDrawColor);
+        if (mPinShapeInput != null) {
+            mPinShapeInput.setDrawColor(mDrawColor);
+        }
     }
 
     @Override
@@ -252,6 +268,9 @@
             charState = mTextChars.get(newLength - 1);
             charState.whichChar = c;
         }
+        if (mPinShapeInput != null) {
+            mPinShapeInput.append();
+        }
         charState.startAppearAnimation();
 
         // ensure that the previous element is being swapped
@@ -265,8 +284,8 @@
         sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length(), 0, 1);
     }
 
-    public void setUserActivityListener(UserActivityListener userActivitiListener) {
-        mUserActivityListener = userActivitiListener;
+    public void setUserActivityListener(UserActivityListener userActivityListener) {
+        mUserActivityListener = userActivityListener;
     }
 
     private void userActivity() {
@@ -284,6 +303,9 @@
             CharState charState = mTextChars.get(length - 1);
             charState.startRemoveAnimation(0, 0);
             sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0);
+            if (mPinShapeInput != null) {
+                mPinShapeInput.delete();
+            }
         }
         userActivity();
     }
@@ -339,6 +361,11 @@
         }
         if (!animated) {
             mTextChars.clear();
+        } else {
+            userActivity();
+        }
+        if (mPinShapeInput != null) {
+            mPinShapeInput.reset();
         }
         if (announce) {
             sendAccessibilityEventTypeViewTextChanged(textbefore, 0, textbefore.length(), 0);
@@ -385,6 +412,35 @@
         info.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
     }
 
+    /**
+     * Sets whether to use pin shapes.
+     */
+    public void setUsePinShapes(boolean usePinShapes) {
+        mUsePinShapes = usePinShapes;
+    }
+
+    /**
+     * Determines whether AutoConfirmation feature is on.
+     *
+     * @param usePinShapes
+     * @param isPinHinting
+     */
+    public void setIsPinHinting(boolean isPinHinting) {
+        if (mPinShapeInput != null) {
+            removeView(mPinShapeInput.getView());
+            mPinShapeInput = null;
+        }
+
+        if (isPinHinting) {
+            mPinShapeInput = (PinShapeInput) LayoutInflater.from(mContext).inflate(
+                    R.layout.keyguard_pin_shape_hinting_view, null);
+        } else {
+            mPinShapeInput = (PinShapeInput) LayoutInflater.from(mContext).inflate(
+                    R.layout.keyguard_pin_shape_non_hinting_view, null);
+        }
+        addView(mPinShapeInput.getView());
+    }
+
     private class CharState {
         char whichChar;
         ValueAnimator textAnimator;
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeAdapter.kt b/packages/SystemUI/src/com/android/keyguard/PinShapeAdapter.kt
new file mode 100644
index 0000000..4496dc31
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeAdapter.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.keyguard
+
+import android.content.Context
+import com.android.systemui.R
+import kotlin.random.Random
+
+class PinShapeAdapter {
+    var shapes: MutableList<Int> = ArrayList()
+    val random = Random(System.currentTimeMillis())
+
+    constructor(context: Context) {
+        val availableShapes = context.resources.obtainTypedArray(R.array.bouncer_pin_shapes)
+
+        for (i in 0 until availableShapes.length()) {
+            val shape = availableShapes.getResourceId(i, 0)
+            shapes.add(shape)
+        }
+
+        shapes.shuffle()
+        availableShapes.recycle()
+    }
+
+    fun getShape(pos: Int): Int {
+        return shapes[pos.mod(shapes.size)]
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
new file mode 100644
index 0000000..cf9d053
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
@@ -0,0 +1,115 @@
+/*
+ * 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.keyguard;
+
+import android.content.Context;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import androidx.core.graphics.drawable.DrawableCompat;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+
+/**
+ * This class contains implementation for methods that will be used when user has set a
+ * six digit pin on their device
+ */
+public class PinShapeHintingView extends LinearLayout implements PinShapeInput {
+
+    private int mPinLength;
+    private int mDotDiameter;
+    private int mDotSpacing;
+    private int mColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)
+            .getDefaultColor();
+    private int mPosition = 0;
+    private static final int DEFAULT_PIN_LENGTH = 6;
+    private PinShapeAdapter mPinShapeAdapter;
+
+    public PinShapeHintingView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mPinShapeAdapter = new PinShapeAdapter(context);
+        mPinLength = DEFAULT_PIN_LENGTH;
+        mDotDiameter = context.getResources().getDimensionPixelSize(R.dimen.default_dot_diameter);
+        mDotSpacing = context.getResources().getDimensionPixelSize(R.dimen.default_dot_spacing);
+
+        for (int i = 0; i < mPinLength; i++) {
+            ImageView pinDot = new ImageView(context, attrs);
+            LayoutParams layoutParams = new LayoutParams(mDotDiameter, mDotDiameter);
+            pinDot.setLayoutParams(layoutParams);
+            pinDot.setImageResource(R.drawable.pin_dot_avd);
+            if (pinDot.getDrawable() != null) {
+                Drawable drawable = DrawableCompat.wrap(pinDot.getDrawable());
+                DrawableCompat.setTint(drawable, mColor);
+            }
+            addView(pinDot);
+        }
+    }
+
+    @Override
+    public void append() {
+        if (mPosition == DEFAULT_PIN_LENGTH) {
+            return;
+        }
+        setAnimatedDrawable(mPosition, mPinShapeAdapter.getShape(mPosition));
+        mPosition++;
+    }
+
+    @Override
+    public void delete() {
+        if (mPosition == 0) {
+            return;
+        }
+        mPosition--;
+        setAnimatedDrawable(mPosition, R.drawable.pin_dot_delete_avd);
+    }
+
+    @Override
+    public void setDrawColor(int color) {
+        this.mColor = color;
+    }
+
+    @Override
+    public void reset() {
+        int size = mPosition;
+        for (int i = 0; i < size; i++) {
+            delete();
+        }
+        mPosition = 0;
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    private void setAnimatedDrawable(int position, int drawableResId) {
+        ImageView pinDot = (ImageView) getChildAt(position);
+        pinDot.setImageResource(drawableResId);
+        if (pinDot.getDrawable() != null) {
+            Drawable drawable = DrawableCompat.wrap(pinDot.getDrawable());
+            DrawableCompat.setTint(drawable, mColor);
+        }
+        if (pinDot.getDrawable() instanceof AnimatedVectorDrawable) {
+            ((AnimatedVectorDrawable) pinDot.getDrawable()).start();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeInput.java b/packages/SystemUI/src/com/android/keyguard/PinShapeInput.java
new file mode 100644
index 0000000..52ae6ba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeInput.java
@@ -0,0 +1,50 @@
+/*
+ * 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.keyguard;
+
+import android.view.View;
+
+/**
+ * A common interface for classes that provide functionality for the PIN type view
+ */
+public interface PinShapeInput {
+
+    /**
+     * This is the method that is triggered when user types in a character
+     */
+    void append();
+
+    /**
+     * This is the method that is triggered when user deletes a character
+     */
+    void delete();
+
+    /**
+     * This is the method that is triggered for setting the color of the view
+     */
+    void setDrawColor(int color);
+
+    /**
+     * This is the method that is triggered for resetting the view
+     */
+    void reset();
+
+    /**
+     * This is the method that is triggered for getting the view
+     */
+    View getView();
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
new file mode 100644
index 0000000..6a6e81e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
@@ -0,0 +1,183 @@
+/*
+ * 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.keyguard;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
+import android.transition.Transition;
+import android.transition.TransitionManager;
+import android.transition.TransitionValues;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import androidx.core.graphics.drawable.DrawableCompat;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
+
+/**
+ * This class contains implementation for methods that will be used when user has set a
+ * non six digit pin on their device
+ */
+public class PinShapeNonHintingView extends LinearLayout implements PinShapeInput {
+
+    private int mColor = Utils.getColorAttr(getContext(),
+            android.R.attr.textColorPrimary).getDefaultColor();
+    private int mPosition = 0;
+    private final PinShapeAdapter mPinShapeAdapter;
+    private Animation mCurrentPlayingAnimation;
+    public PinShapeNonHintingView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mPinShapeAdapter = new PinShapeAdapter(context);
+    }
+
+    @Override
+    public void append() {
+        int size = getResources().getDimensionPixelSize(R.dimen.password_shape_size);
+        ImageView pinDot = new ImageView(getContext());
+        pinDot.setLayoutParams(new LayoutParams(size, size));
+        pinDot.setImageResource(mPinShapeAdapter.getShape(mPosition));
+        if (pinDot.getDrawable() != null) {
+            Drawable wrappedDrawable = DrawableCompat.wrap(pinDot.getDrawable());
+            DrawableCompat.setTint(wrappedDrawable, mColor);
+        }
+        if (pinDot.getDrawable() instanceof AnimatedVectorDrawable) {
+            ((AnimatedVectorDrawable) pinDot.getDrawable()).start();
+        }
+        TransitionManager.beginDelayedTransition(this, new PinShapeViewTransition());
+        addView(pinDot);
+        mPosition++;
+    }
+
+    @Override
+    public void delete() {
+        if (mPosition == 0) {
+            Log.e(getClass().getName(), "Trying to delete a non-existent char");
+            return;
+        }
+        mPosition--;
+        ImageView pinDot = (ImageView) getChildAt(mPosition);
+        ValueAnimator animator = ValueAnimator.ofFloat(1f, 0f);
+        animator.addUpdateListener(valueAnimator -> {
+            float value = (float) valueAnimator.getAnimatedValue();
+            pinDot.setScaleX(value);
+            pinDot.setScaleY(value);
+        });
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                TransitionManager.beginDelayedTransition(
+                        PinShapeNonHintingView.this,
+                        new PinShapeViewTransition());
+                removeView(pinDot);
+                mCurrentPlayingAnimation = null;
+            }
+        });
+        animator.setDuration(PasswordTextView.DISAPPEAR_DURATION);
+        animator.start();
+    }
+
+    @Override
+    public void setDrawColor(int color) {
+        this.mColor = color;
+    }
+
+    @Override
+    public void reset() {
+        final int position = mPosition;
+        for (int i = 0; i < position; i++) {
+            delete();
+        }
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    class PinShapeViewTransition extends Transition {
+        private static final String PROP_BOUNDS = "PinShapeViewTransition:bounds";
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            if (transitionValues != null) {
+                captureValues(transitionValues);
+            }
+        }
+
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            if (transitionValues != null) {
+                captureValues(transitionValues);
+            }
+        }
+
+        private void captureValues(TransitionValues values) {
+            Rect boundsRect = new Rect();
+            boundsRect.left = values.view.getLeft();
+            boundsRect.top = values.view.getTop();
+            boundsRect.right = values.view.getRight();
+            boundsRect.bottom = values.view.getBottom();
+            values.values.put(PROP_BOUNDS, boundsRect);
+        }
+
+        @Override
+        public String[] getTransitionProperties() {
+            return new String[] { PROP_BOUNDS };
+        }
+
+        @Override
+        public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+                TransitionValues endValues) {
+            if (sceneRoot == null || startValues == null || endValues == null) {
+                return null;
+            }
+
+            Rect startRect = (Rect) startValues.values.get(PROP_BOUNDS);
+            Rect endRect = (Rect) endValues.values.get(PROP_BOUNDS);
+            View v = startValues.view;
+            ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
+            animator.setDuration(PasswordTextView.APPEAR_DURATION);
+            animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+            animator.addUpdateListener(valueAnimator -> {
+                float value = (float) valueAnimator.getAnimatedValue();
+                int diff = startRect.left - endRect.left;
+                int currentTranslation = (int) ((diff) * value);
+                v.setLeftTopRightBottom(
+                        startRect.left - currentTranslation,
+                        startRect.top,
+                        startRect.right - currentTranslation,
+                        startRect.bottom
+                );
+            });
+            animator.start();
+            return animator;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
index 2c7eceb..379c78a 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
@@ -16,9 +16,11 @@
 
 package com.android.keyguard.logging
 
+import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController
 import com.android.systemui.log.dagger.KeyguardLog
 import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.statusbar.KeyguardIndicationController
 import com.google.errorprone.annotations.CompileTimeConstant
 import javax.inject.Inject
 
@@ -76,4 +78,46 @@
             { "$str1 msgId: $str2 msg: $str3" }
         )
     }
+
+    fun logUpdateDeviceEntryIndication(
+        animate: Boolean,
+        visible: Boolean,
+        dozing: Boolean,
+    ) {
+        buffer.log(
+            KeyguardIndicationController.TAG,
+            LogLevel.DEBUG,
+            {
+                bool1 = animate
+                bool2 = visible
+                bool3 = dozing
+            },
+            { "updateDeviceEntryIndication animate:$bool1 visible:$bool2 dozing $bool3" }
+        )
+    }
+
+    fun logKeyguardSwitchIndication(
+        type: Int,
+        message: String?,
+    ) {
+        buffer.log(
+            KeyguardIndicationController.TAG,
+            LogLevel.DEBUG,
+            {
+                int1 = type
+                str1 = message
+            },
+            { "keyguardSwitchIndication ${getKeyguardSwitchIndicationNonSensitiveLog(int1, str1)}" }
+        )
+    }
+
+    fun getKeyguardSwitchIndicationNonSensitiveLog(type: Int, message: String?): String {
+        // only show the battery string. other strings may contain sensitive info
+        return if (type == KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY) {
+            "type=${KeyguardIndicationRotateTextViewController.indicationTypeToString(type)}" +
+                " message=$message"
+        } else {
+            "type=${KeyguardIndicationRotateTextViewController.indicationTypeToString(type)}"
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index 201a1d9..c414c08 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -372,7 +372,7 @@
     }
 
     fun logUserRequestedUnlock(
-        requestOrigin: ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN,
+        requestOrigin: ActiveUnlockConfig.ActiveUnlockRequestOrigin,
         reason: String?,
         dismissKeyguard: Boolean
     ) {
diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
index 3e0fa45..54939fd 100644
--- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
@@ -35,6 +35,7 @@
 import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.settingslib.Utils
 import com.android.systemui.animation.Interpolators
+import com.android.systemui.log.ScreenDecorationsLogger
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import java.util.concurrent.Executor
 
@@ -47,7 +48,8 @@
     pos: Int,
     val statusBarStateController: StatusBarStateController,
     val keyguardUpdateMonitor: KeyguardUpdateMonitor,
-    val mainExecutor: Executor
+    val mainExecutor: Executor,
+    val logger: ScreenDecorationsLogger,
 ) : ScreenDecorations.DisplayCutoutView(context, pos) {
     private var showScanningAnim = false
     private val rimPaint = Paint()
@@ -55,6 +57,7 @@
     private var rimAnimator: AnimatorSet? = null
     private val rimRect = RectF()
     private var cameraProtectionColor = Color.BLACK
+
     var faceScanningAnimColor = Utils.getColorAttrDefaultColor(context,
             R.attr.wallpaperTextColorAccent)
     private var cameraProtectionAnimator: ValueAnimator? = null
@@ -175,15 +178,22 @@
         }
         if (showScanningAnim) {
             // Make sure that our measured height encompasses the extra space for the animation
-            mTotalBounds.union(mBoundingRect)
+            mTotalBounds.set(mBoundingRect)
             mTotalBounds.union(
                 rimRect.left.toInt(),
                 rimRect.top.toInt(),
                 rimRect.right.toInt(),
                 rimRect.bottom.toInt())
-            setMeasuredDimension(
-                resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0),
-                resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0))
+            val measuredWidth = resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0)
+            val measuredHeight = resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0)
+            logger.boundingRect(rimRect, "onMeasure: Face scanning animation")
+            logger.boundingRect(mBoundingRect, "onMeasure: Display cutout view bounding rect")
+            logger.boundingRect(mTotalBounds, "onMeasure: TotalBounds")
+            logger.onMeasureDimensions(widthMeasureSpec,
+                    heightMeasureSpec,
+                    measuredWidth,
+                    measuredHeight)
+            setMeasuredDimension(measuredWidth, measuredHeight)
         } else {
             setMeasuredDimension(
                 resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0),
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 71f98fa..fb65588 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -64,6 +64,7 @@
 
 import com.android.internal.util.Preconditions;
 import com.android.settingslib.Utils;
+import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.decor.CutoutDecorProviderFactory;
@@ -75,6 +76,7 @@
 import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
 import com.android.systemui.decor.RoundedCornerDecorProviderFactory;
 import com.android.systemui.decor.RoundedCornerResDelegate;
+import com.android.systemui.log.ScreenDecorationsLogger;
 import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.settings.UserTracker;
@@ -120,6 +122,9 @@
             R.id.display_cutout_right,
             R.id.display_cutout_bottom
     };
+    private final ScreenDecorationsLogger mLogger;
+
+    private final AuthController mAuthController;
 
     private DisplayTracker mDisplayTracker;
     @VisibleForTesting
@@ -153,6 +158,7 @@
     private WindowManager mWindowManager;
     private int mRotation;
     private SettingObserver mColorInversionSetting;
+    @Nullable
     private DelayableExecutor mExecutor;
     private Handler mHandler;
     boolean mPendingConfigChange;
@@ -172,6 +178,7 @@
             DisplayCutoutView overlay = (DisplayCutoutView) getOverlayView(
                     mFaceScanningViewId);
             if (overlay != null) {
+                mLogger.cameraProtectionBoundsForScanningOverlay(bounds);
                 overlay.setProtection(protectionPath, bounds);
                 overlay.enableShowProtection(true);
                 updateOverlayWindowVisibilityIfViewExists(
@@ -184,6 +191,7 @@
         }
 
         if (mScreenDecorHwcLayer != null) {
+            mLogger.hwcLayerCameraProtectionBounds(bounds);
             mScreenDecorHwcLayer.setProtection(protectionPath, bounds);
             mScreenDecorHwcLayer.enableShowProtection(true);
             return;
@@ -197,11 +205,12 @@
             }
             ++setProtectionCnt;
             final DisplayCutoutView dcv = (DisplayCutoutView) view;
+            mLogger.dcvCameraBounds(id, bounds);
             dcv.setProtection(protectionPath, bounds);
             dcv.enableShowProtection(true);
         }
         if (setProtectionCnt == 0) {
-            Log.e(TAG, "CutoutView not initialized showCameraProtection");
+            mLogger.cutoutViewNotInitialized();
         }
     }
 
@@ -307,7 +316,9 @@
             PrivacyDotViewController dotViewController,
             ThreadFactory threadFactory,
             PrivacyDotDecorProviderFactory dotFactory,
-            FaceScanningProviderFactory faceScanningFactory) {
+            FaceScanningProviderFactory faceScanningFactory,
+            ScreenDecorationsLogger logger,
+            AuthController authController) {
         mContext = context;
         mMainExecutor = mainExecutor;
         mSecureSettings = secureSettings;
@@ -319,8 +330,23 @@
         mDotFactory = dotFactory;
         mFaceScanningFactory = faceScanningFactory;
         mFaceScanningViewId = com.android.systemui.R.id.face_scanning_anim;
+        mLogger = logger;
+        mAuthController = authController;
     }
 
+
+    private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
+        @Override
+        public void onFaceSensorLocationChanged() {
+            mLogger.onSensorLocationChanged();
+            if (mExecutor != null) {
+                mExecutor.execute(
+                        () -> updateOverlayProviderViews(
+                                new Integer[]{mFaceScanningViewId}));
+            }
+        }
+    };
+
     @Override
     public void start() {
         if (DEBUG_DISABLE_SCREEN_DECORATIONS) {
@@ -331,6 +357,7 @@
         mExecutor = mThreadFactory.buildDelayableExecutorOnHandler(mHandler);
         mExecutor.execute(this::startOnScreenDecorationsThread);
         mDotViewController.setUiExecutor(mExecutor);
+        mAuthController.addCallback(mAuthControllerCallback);
     }
 
     private boolean isPrivacyDotEnabled() {
@@ -1306,7 +1333,7 @@
 
             if (showProtection) {
                 // Make sure that our measured height encompasses the protection
-                mTotalBounds.union(mBoundingRect);
+                mTotalBounds.set(mBoundingRect);
                 mTotalBounds.union((int) protectionRect.left, (int) protectionRect.top,
                         (int) protectionRect.right, (int) protectionRect.bottom);
                 setMeasuredDimension(
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index ffdd861..8578845 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -38,6 +38,7 @@
 import android.util.TimingsTraceLog;
 import android.view.SurfaceControl;
 import android.view.ThreadedRenderer;
+import android.view.View;
 
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.systemui.dagger.GlobalRootComponent;
@@ -112,6 +113,11 @@
         // the theme set there.
         setTheme(R.style.Theme_SystemUI);
 
+        View.setTraceLayoutSteps(
+                SystemProperties.getBoolean("persist.debug.trace_layouts", false));
+        View.setTracedRequestLayoutClassClass(
+                SystemProperties.get("persist.debug.trace_request_layout_class", null));
+
         if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
             IntentFilter bootCompletedFilter = new
                     IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
index 3b4114b..d061c8e 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
@@ -50,9 +50,9 @@
     @interface MagnificationState {}
 
     // The window magnification is disabled.
-    private static final int STATE_DISABLED = 0;
+    @VisibleForTesting static final int STATE_DISABLED = 0;
     // The window magnification is enabled.
-    private static final int STATE_ENABLED = 1;
+    @VisibleForTesting static final int STATE_ENABLED = 1;
     // The window magnification is going to be disabled when the animation is end.
     private static final int STATE_DISABLING = 2;
     // The animation is running for enabling the window magnification.
@@ -151,7 +151,7 @@
             }
             mController.enableWindowMagnificationInternal(scale, centerX, centerY,
                     mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
-            setState(STATE_ENABLED);
+            updateState();
             return;
         }
         mAnimationCallback = animationCallback;
@@ -165,7 +165,7 @@
                 mValueAnimator.cancel();
             }
             sendAnimationCallback(true);
-            setState(STATE_ENABLED);
+            updateState();
         } else {
             if (mState == STATE_DISABLING) {
                 mValueAnimator.reverse();
@@ -254,7 +254,7 @@
                 mValueAnimator.cancel();
             }
             mController.deleteWindowMagnification();
-            setState(STATE_DISABLED);
+            updateState();
             return;
         }
 
@@ -272,6 +272,14 @@
         setState(STATE_DISABLING);
     }
 
+    private void updateState() {
+        if (Float.isNaN(mController.getScale())) {
+            setState(STATE_DISABLED);
+        } else {
+            setState(STATE_ENABLED);
+        }
+    }
+
     private void setState(@MagnificationState int state) {
         if (DEBUG) {
             Log.d(TAG, "setState from " + mState + " to " + state);
@@ -279,6 +287,11 @@
         mState = state;
     }
 
+    @VisibleForTesting
+    @MagnificationState int getState() {
+        return mState;
+    }
+
     @Override
     public void onAnimationStart(Animator animation) {
         mEndAnimationCanceled = false;
@@ -289,11 +302,10 @@
         if (mEndAnimationCanceled || mController == null) {
             return;
         }
-        if (Float.isNaN(mController.getScale())) {
-            setState(STATE_DISABLED);
-        } else {
-            setState(STATE_ENABLED);
+        if (mState == STATE_DISABLING) {
+            mController.deleteWindowMagnification();
         }
+        updateState();
         sendAnimationCallback(true);
         // We reset the duration to config_longAnimTime
         mValueAnimator.setDuration(mContext.getResources()
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 74f5f13..b111e1f 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -49,6 +49,7 @@
 import android.util.Log;
 import android.util.Range;
 import android.util.Size;
+import android.util.TypedValue;
 import android.view.Choreographer;
 import android.view.Display;
 import android.view.Gravity;
@@ -97,7 +98,7 @@
     // Delay to avoid updating state description too frequently.
     private static final int UPDATE_STATE_DESCRIPTION_DELAY_MS = 100;
     // It should be consistent with the value defined in WindowMagnificationGestureHandler.
-    private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(2.0f, 8.0f);
+    private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(1.0f, 8.0f);
     private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f;
     private static final float ANIMATION_BOUNCE_EFFECT_SCALE = 1.05f;
     private static final float[] MAGNIFICATION_SCALE_OPTIONS = {1.0f, 1.4f, 1.8f, 2.5f};
@@ -213,7 +214,9 @@
     private static final int MAX_HORIZONTAL_MOVE_ANGLE = 50;
     private static final int HORIZONTAL = 1;
     private static final int VERTICAL = 0;
-    private static final double HORIZONTAL_LOCK_BASE =
+
+    @VisibleForTesting
+    static final double HORIZONTAL_LOCK_BASE =
             Math.tan(Math.toRadians(MAX_HORIZONTAL_MOVE_ANGLE));
 
     private boolean mAllowDiagonalScrolling = false;
@@ -704,6 +707,11 @@
         }
     }
 
+    @VisibleForTesting
+    WindowMagnificationSettings getMagnificationSettings() {
+        return mWindowMagnificationSettings;
+    }
+
     /**
      * Sets the window size with given width and height in pixels without changing the
      * window center. The width or the height will be clamped in the range
@@ -1075,7 +1083,7 @@
 
     /**
      * Enables window magnification with specified parameters. If the given scale is <strong>less
-     * than or equal to 1.0f<strong>, then
+     * than 1.0f<strong>, then
      * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to
      * be consistent with the behavior of display magnification.
      *
@@ -1093,7 +1101,7 @@
      */
     void enableWindowMagnificationInternal(float scale, float centerX, float centerY,
                 float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY) {
-        if (Float.compare(scale, 1.0f)  <= 0) {
+        if (Float.compare(scale, 1.0f) < 0) {
             deleteWindowMagnification();
             return;
         }
@@ -1266,9 +1274,19 @@
     }
 
     private void applyResourcesValues() {
-        mMirrorBorderView.setBackgroundColor(mResources.getColor(mEditSizeEnable
-                ? R.color.magnification_border_color_change : R.color.magnification_border_color));
+        // Sets the border appearance for the magnifier window
+        mMirrorBorderView.setBackground(mResources.getDrawable(mEditSizeEnable
+                ? R.drawable.accessibility_window_magnification_background_change
+                : R.drawable.accessibility_window_magnification_background));
 
+        // Changes the corner radius of the mMirrorSurfaceView
+        mMirrorSurfaceView.setCornerRadius(
+                        TypedValue.applyDimension(
+                                TypedValue.COMPLEX_UNIT_DIP,
+                                mEditSizeEnable ? 16f : 28f,
+                                mContext.getResources().getDisplayMetrics()));
+
+        // Sets visibility of components for the magnifier window
         if (mEditSizeEnable) {
             mDragView.setVisibility(View.GONE);
             mCloseView.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 527c124..15264e64 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -50,9 +50,11 @@
 import android.widget.SeekBar;
 import android.widget.Switch;
 
+import com.android.internal.accessibility.common.MagnificationConstants;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.systemui.R;
+import com.android.systemui.common.ui.view.SeekBarWithIconButtonsView;
 import com.android.systemui.util.settings.SecureSettings;
 
 import java.lang.annotation.Retention;
@@ -79,7 +81,7 @@
     private final MagnificationGestureDetector mGestureDetector;
     private boolean mSingleTapDetected = false;
 
-    private SeekBar mZoomSeekbar;
+    private SeekBarWithIconButtonsView mZoomSeekbar;
     private Switch mAllowDiagonalScrollingSwitch;
     private LinearLayout mPanelView;
     private LinearLayout mSettingView;
@@ -90,9 +92,10 @@
     private Button mDoneButton;
     private Button mEditButton;
     private ImageButton mChangeModeButton;
+    private int mLastSelectedButtonIndex = MagnificationSize.NONE;
     private boolean mAllowDiagonalScrolling = false;
     private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f;
-    private static final float A11Y_SCALE_MIN_VALUE = 2.0f;
+    private static final float A11Y_SCALE_MIN_VALUE = 1.0f;
     private WindowMagnificationSettingsCallback mCallback;
 
     @Retention(RetentionPolicy.SOURCE)
@@ -124,10 +127,11 @@
                 Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, 0,
                 UserHandle.USER_CURRENT) == 1;
 
-        inflateView();
-
         mParams = createLayoutParams(context);
         mWindowInsetChangeRunnable = this::onWindowInsetChanged;
+
+        inflateView();
+
         mGestureDetector = new MagnificationGestureDetector(context,
                 context.getMainThreadHandler(), this);
     }
@@ -136,9 +140,14 @@
         @Override
         public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
             float scale = progress * A11Y_CHANGE_SCALE_DIFFERENCE + A11Y_SCALE_MIN_VALUE;
-            mSecureSettings.putFloatForUser(
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale,
-                    UserHandle.USER_CURRENT);
+            // Update persisted scale only when scale >= PERSISTED_SCALE_MIN_VALUE const.
+            // We assume if the scale is lower than the PERSISTED_SCALE_MIN_VALUE, there will be
+            // no obvious magnification effect.
+            if (scale >= MagnificationConstants.PERSISTED_SCALE_MIN_VALUE) {
+                Settings.Secure.putFloatForUser(mContext.getContentResolver(),
+                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale,
+                        UserHandle.USER_CURRENT);
+            }
             mCallback.onMagnifierScale(scale);
         }
 
@@ -388,13 +397,13 @@
         mEditButton = mSettingView.findViewById(R.id.magnifier_edit_button);
         mChangeModeButton = mSettingView.findViewById(R.id.magnifier_full_button);
 
-        mZoomSeekbar = mSettingView.findViewById(R.id.magnifier_zoom_seekbar);
-        mZoomSeekbar.setOnSeekBarChangeListener(new ZoomSeekbarChangeListener());
-
+        mZoomSeekbar = mSettingView.findViewById(R.id.magnifier_zoom_slider);
         float scale = mSecureSettings.getFloatForUser(
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 0,
                 UserHandle.USER_CURRENT);
         setSeekbarProgress(scale);
+        mZoomSeekbar.setOnSeekBarChangeListener(new ZoomSeekbarChangeListener());
+
         mAllowDiagonalScrollingSwitch =
                 (Switch) mSettingView.findViewById(R.id.magnifier_horizontal_lock_switch);
         mAllowDiagonalScrollingSwitch.setChecked(mAllowDiagonalScrolling);
@@ -423,11 +432,14 @@
         mSettingView.setOnApplyWindowInsetsListener((v, insets) -> {
             // Adds a pending post check to avoiding redundant calculation because this callback
             // is sent frequently when the switch icon window dragged by the users.
-            if (!mSettingView.getHandler().hasCallbacks(mWindowInsetChangeRunnable)) {
+            if (mSettingView.isAttachedToWindow()
+                    && !mSettingView.getHandler().hasCallbacks(mWindowInsetChangeRunnable)) {
                 mSettingView.getHandler().post(mWindowInsetChangeRunnable);
             }
             return v.onApplyWindowInsets(insets);
         });
+
+        updateSelectedButton(mLastSelectedButtonIndex);
     }
 
     void onConfigurationChanged(int configDiff) {
@@ -505,23 +517,29 @@
 
     public void editMagnifierSizeMode(boolean enable) {
         setEditMagnifierSizeMode(enable);
+        updateSelectedButton(MagnificationSize.NONE);
         hideSettingPanel();
     }
 
     private void setMagnifierSize(@MagnificationSize int index) {
         mCallback.onSetMagnifierSize(index);
+        updateSelectedButton(index);
     }
 
     private void toggleDiagonalScrolling() {
         boolean enabled = mSecureSettings.getIntForUser(
                 Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, 0,
                 UserHandle.USER_CURRENT) == 1;
+        setDiagonalScrolling(!enabled);
+    }
 
-        mSecureSettings.putIntForUser(
-                Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, enabled ? 0 : 1,
+    @VisibleForTesting
+    void setDiagonalScrolling(boolean enabled) {
+        Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, enabled ? 1 : 0,
                 UserHandle.USER_CURRENT);
 
-        mCallback.onSetDiagonalScrolling(!enabled);
+        mCallback.onSetDiagonalScrolling(enabled);
     }
 
     private void setEditMagnifierSizeMode(boolean enable) {
@@ -567,4 +585,26 @@
                             new Rect(0, 0, mSettingView.getWidth(), mSettingView.getHeight())));
         });
     }
+
+    private void updateSelectedButton(@MagnificationSize int index) {
+        // Clear the state of last selected button
+        if (mLastSelectedButtonIndex == MagnificationSize.SMALL) {
+            mSmallButton.setSelected(false);
+        } else if (mLastSelectedButtonIndex == MagnificationSize.MEDIUM) {
+            mMediumButton.setSelected(false);
+        } else if (mLastSelectedButtonIndex == MagnificationSize.LARGE) {
+            mLargeButton.setSelected(false);
+        }
+
+        // Set the state for selected button
+        if (index == MagnificationSize.SMALL) {
+            mSmallButton.setSelected(true);
+        } else if (index == MagnificationSize.MEDIUM) {
+            mMediumButton.setSelected(true);
+        } else if (index == MagnificationSize.LARGE) {
+            mLargeButton.setSelected(true);
+        }
+
+        mLastSelectedButtonIndex = index;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java
deleted file mode 100644
index 81d7766..0000000
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static android.provider.Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED;
-import static android.provider.Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE;
-import static android.provider.Settings.Secure.ACCESSIBILITY_FLOATING_MENU_MIGRATION_TOOLTIP_PROMPT;
-import static android.provider.Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY;
-import static android.provider.Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE;
-import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
-
-import static com.android.internal.accessibility.dialog.AccessibilityTargetHelper.getTargets;
-import static com.android.systemui.Prefs.Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP;
-import static com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuView.ShapeType;
-import static com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuView.SizeType;
-
-import android.annotation.FloatRange;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-
-import com.android.internal.accessibility.dialog.AccessibilityTarget;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Prefs;
-import com.android.systemui.shared.system.SysUiStatsLog;
-import com.android.systemui.util.settings.SecureSettings;
-
-import java.util.List;
-
-/**
- * Contains logic for an accessibility floating menu view.
- */
-public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu {
-    private static final int DEFAULT_FADE_EFFECT_IS_ENABLED = 1;
-    private static final int DEFAULT_MIGRATION_TOOLTIP_PROMPT_IS_DISABLED = 0;
-    @FloatRange(from = 0.0, to = 1.0)
-    private static final float DEFAULT_OPACITY_VALUE = 0.55f;
-    @FloatRange(from = 0.0, to = 1.0)
-    private static final float DEFAULT_POSITION_X_PERCENT = 1.0f;
-    @FloatRange(from = 0.0, to = 1.0)
-    private static final float DEFAULT_POSITION_Y_PERCENT = 0.77f;
-
-    private final Context mContext;
-    private final SecureSettings mSecureSettings;
-    private final AccessibilityFloatingMenuView mMenuView;
-    private final MigrationTooltipView mMigrationTooltipView;
-    private final DockTooltipView mDockTooltipView;
-    private final Handler mHandler = new Handler(Looper.getMainLooper());
-
-    private final ContentObserver mContentObserver =
-            new ContentObserver(mHandler) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    mMenuView.onTargetsChanged(getTargets(mContext, ACCESSIBILITY_BUTTON));
-                }
-            };
-
-    private final ContentObserver mSizeContentObserver =
-            new ContentObserver(mHandler) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    mMenuView.setSizeType(getSizeType());
-                }
-            };
-
-    private final ContentObserver mFadeOutContentObserver =
-            new ContentObserver(mHandler) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    mMenuView.updateOpacityWith(isFadeEffectEnabled(),
-                            getOpacityValue());
-                }
-            };
-
-    private final ContentObserver mEnabledA11yServicesContentObserver =
-            new ContentObserver(mHandler) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    mMenuView.onEnabledFeaturesChanged();
-                }
-            };
-
-    public AccessibilityFloatingMenu(Context context, SecureSettings secureSettings) {
-        mContext = context;
-        mSecureSettings = secureSettings;
-        mMenuView = new AccessibilityFloatingMenuView(context, getPosition(context));
-        mMigrationTooltipView = new MigrationTooltipView(mContext, mMenuView);
-        mDockTooltipView = new DockTooltipView(mContext, mMenuView);
-    }
-
-    @VisibleForTesting
-    AccessibilityFloatingMenu(Context context, SecureSettings secureSettings,
-            AccessibilityFloatingMenuView menuView) {
-        mContext = context;
-        mSecureSettings = secureSettings;
-        mMenuView = menuView;
-        mMigrationTooltipView = new MigrationTooltipView(mContext, mMenuView);
-        mDockTooltipView = new DockTooltipView(mContext, mMenuView);
-    }
-
-    @Override
-    public boolean isShowing() {
-        return mMenuView.isShowing();
-    }
-
-    @Override
-    public void show() {
-        if (isShowing()) {
-            return;
-        }
-        final List<AccessibilityTarget> targetList = getTargets(mContext, ACCESSIBILITY_BUTTON);
-        if (targetList.isEmpty()) {
-            return;
-        }
-
-        mMenuView.show();
-        mMenuView.onTargetsChanged(targetList);
-        mMenuView.updateOpacityWith(isFadeEffectEnabled(),
-                getOpacityValue());
-        mMenuView.setSizeType(getSizeType());
-        mMenuView.setShapeType(getShapeType());
-        mMenuView.setOnDragEndListener(this::onDragEnd);
-
-        showMigrationTooltipIfNecessary();
-
-        registerContentObservers();
-    }
-
-    @Override
-    public void hide() {
-        if (!isShowing()) {
-            return;
-        }
-
-        mMenuView.hide();
-        mMenuView.setOnDragEndListener(null);
-        mMigrationTooltipView.hide();
-        mDockTooltipView.hide();
-
-        unregisterContentObservers();
-    }
-
-    @NonNull
-    private Position getPosition(Context context) {
-        final String absolutePositionString = Prefs.getString(context,
-                Prefs.Key.ACCESSIBILITY_FLOATING_MENU_POSITION, /* defaultValue= */ null);
-
-        if (TextUtils.isEmpty(absolutePositionString)) {
-            return new Position(DEFAULT_POSITION_X_PERCENT, DEFAULT_POSITION_Y_PERCENT);
-        } else {
-            return Position.fromString(absolutePositionString);
-        }
-    }
-
-    // Migration tooltip was the android S feature. It's just used on the Android version from R
-    // to S. In addition, it only shows once.
-    private void showMigrationTooltipIfNecessary() {
-        if (isMigrationTooltipPromptEnabled()) {
-            mMigrationTooltipView.show();
-
-            mSecureSettings.putInt(
-                    ACCESSIBILITY_FLOATING_MENU_MIGRATION_TOOLTIP_PROMPT, /* disabled */ 0);
-        }
-    }
-
-    private boolean isMigrationTooltipPromptEnabled() {
-        return mSecureSettings.getInt(
-                ACCESSIBILITY_FLOATING_MENU_MIGRATION_TOOLTIP_PROMPT,
-                DEFAULT_MIGRATION_TOOLTIP_PROMPT_IS_DISABLED) == /* enabled */ 1;
-    }
-
-    private void onDragEnd(Position position) {
-        SysUiStatsLog.write(SysUiStatsLog.ACCESSIBILITY_FLOATING_MENU_UI_CHANGED,
-                position.getPercentageX(), position.getPercentageY(),
-                mContext.getResources().getConfiguration().orientation);
-        savePosition(mContext, position);
-        showDockTooltipIfNecessary(mContext);
-    }
-
-    private void savePosition(Context context, Position position) {
-        Prefs.putString(context, Prefs.Key.ACCESSIBILITY_FLOATING_MENU_POSITION,
-                position.toString());
-    }
-
-    /**
-     * Shows tooltip when user drags accessibility floating menu for the first time.
-     */
-    private void showDockTooltipIfNecessary(Context context) {
-        if (!Prefs.get(context).getBoolean(
-                HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, false)) {
-            // if the menu is an oval, the user has already dragged it out, so show the tooltip.
-            if (mMenuView.isOvalShape()) {
-                mDockTooltipView.show();
-            }
-
-            Prefs.putBoolean(context, HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, true);
-        }
-    }
-
-    private boolean isFadeEffectEnabled() {
-        return mSecureSettings.getInt(
-                ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
-                DEFAULT_FADE_EFFECT_IS_ENABLED) == /* enabled */ 1;
-    }
-
-    private float getOpacityValue() {
-        return mSecureSettings.getFloat(
-                ACCESSIBILITY_FLOATING_MENU_OPACITY,
-                DEFAULT_OPACITY_VALUE);
-    }
-
-    private int getSizeType() {
-        return mSecureSettings.getInt(
-                ACCESSIBILITY_FLOATING_MENU_SIZE, SizeType.SMALL);
-    }
-
-    private int getShapeType() {
-        return mSecureSettings.getInt(
-                ACCESSIBILITY_FLOATING_MENU_ICON_TYPE,
-                ShapeType.OVAL);
-    }
-
-    private void registerContentObservers() {
-        mSecureSettings.registerContentObserverForUser(
-                Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
-                /* notifyForDescendants */ false, mContentObserver,
-                UserHandle.USER_CURRENT);
-        mSecureSettings.registerContentObserverForUser(
-                Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
-                /* notifyForDescendants */ false, mContentObserver,
-                UserHandle.USER_CURRENT);
-        mSecureSettings.registerContentObserverForUser(
-                Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
-                /* notifyForDescendants */ false, mSizeContentObserver,
-                UserHandle.USER_CURRENT);
-        mSecureSettings.registerContentObserverForUser(
-                Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
-                /* notifyForDescendants */ false, mFadeOutContentObserver,
-                UserHandle.USER_CURRENT);
-        mSecureSettings.registerContentObserverForUser(
-                Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY,
-                /* notifyForDescendants */ false, mFadeOutContentObserver,
-                UserHandle.USER_CURRENT);
-        mSecureSettings.registerContentObserverForUser(
-                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                /* notifyForDescendants */ false,
-                mEnabledA11yServicesContentObserver, UserHandle.USER_CURRENT);
-    }
-
-    private void unregisterContentObservers() {
-        mSecureSettings.unregisterContentObserver(mContentObserver);
-        mSecureSettings.unregisterContentObserver(mSizeContentObserver);
-        mSecureSettings.unregisterContentObserver(mFadeOutContentObserver);
-        mSecureSettings.unregisterContentObserver(
-                mEnabledA11yServicesContentObserver);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
index 2c413a2..5924149 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
@@ -19,8 +19,6 @@
 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 
-import static com.android.systemui.flags.Flags.A11Y_FLOATING_MENU_FLING_SPRING_ANIMATIONS;
-
 import android.content.Context;
 import android.hardware.display.DisplayManager;
 import android.os.UserHandle;
@@ -38,7 +36,6 @@
 import com.android.systemui.accessibility.AccessibilityButtonModeObserver.AccessibilityButtonMode;
 import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.util.settings.SecureSettings;
 
@@ -59,7 +56,7 @@
     private final WindowManager mWindowManager;
     private final DisplayManager mDisplayManager;
     private final AccessibilityManager mAccessibilityManager;
-    private final FeatureFlags mFeatureFlags;
+
     private final SecureSettings mSecureSettings;
     private final DisplayTracker mDisplayTracker;
     @VisibleForTesting
@@ -105,7 +102,6 @@
             AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver,
             AccessibilityButtonModeObserver accessibilityButtonModeObserver,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
-            FeatureFlags featureFlags,
             SecureSettings secureSettings,
             DisplayTracker displayTracker) {
         mContext = context;
@@ -115,7 +111,6 @@
         mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver;
         mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        mFeatureFlags = featureFlags;
         mSecureSettings = secureSettings;
         mDisplayTracker = displayTracker;
 
@@ -162,7 +157,7 @@
      * Handles the accessibility floating menu visibility with the given values.
      *
      * @param keyguardVisible the keyguard visibility status. Not show the
-     *                        {@link AccessibilityFloatingMenu} when keyguard appears.
+     *                        {@link MenuView} when keyguard appears.
      * @param mode accessibility button mode {@link AccessibilityButtonMode}
      * @param targets accessibility button list; it should comes from
      *                {@link android.provider.Settings.Secure#ACCESSIBILITY_BUTTON_TARGETS}.
@@ -187,16 +182,12 @@
 
     private void showFloatingMenu() {
         if (mFloatingMenu == null) {
-            if (mFeatureFlags.isEnabled(A11Y_FLOATING_MENU_FLING_SPRING_ANIMATIONS)) {
-                final Display defaultDisplay = mDisplayManager.getDisplay(
-                        mDisplayTracker.getDefaultDisplayId());
-                final Context windowContext = mContext.createWindowContext(defaultDisplay,
-                        TYPE_NAVIGATION_BAR_PANEL, /* options= */ null);
-                mFloatingMenu = new MenuViewLayerController(windowContext, mWindowManager,
-                        mAccessibilityManager, mSecureSettings);
-            } else {
-                mFloatingMenu = new AccessibilityFloatingMenu(mContext, mSecureSettings);
-            }
+            final Display defaultDisplay = mDisplayManager.getDisplay(
+                    mDisplayTracker.getDefaultDisplayId());
+            final Context windowContext = mContext.createWindowContext(defaultDisplay,
+                    TYPE_NAVIGATION_BAR_PANEL, /* options= */ null);
+            mFloatingMenu = new MenuViewLayerController(windowContext, mWindowManager,
+                    mAccessibilityManager, mSecureSettings);
         }
 
         mFloatingMenu.show();
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java
deleted file mode 100644
index aff0b1f..0000000
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java
+++ /dev/null
@@ -1,921 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.util.MathUtils.constrain;
-import static android.util.MathUtils.sq;
-import static android.view.WindowInsets.Type.displayCutout;
-import static android.view.WindowInsets.Type.ime;
-import static android.view.WindowInsets.Type.systemBars;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
-
-import static java.util.Objects.requireNonNull;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.annotation.FloatRange;
-import android.annotation.IntDef;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Insets;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.graphics.drawable.LayerDrawable;
-import android.os.Handler;
-import android.os.Looper;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-import android.view.animation.Animation;
-import android.view.animation.OvershootInterpolator;
-import android.view.animation.TranslateAnimation;
-import android.widget.FrameLayout;
-
-import androidx.annotation.DimenRes;
-import androidx.annotation.NonNull;
-import androidx.core.view.AccessibilityDelegateCompat;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate;
-
-import com.android.internal.accessibility.dialog.AccessibilityTarget;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.R;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Accessibility floating menu is used for the actions of accessibility features, it's also the
- * action set.
- *
- * <p>The number of items would depend on strings key
- * {@link android.provider.Settings.Secure#ACCESSIBILITY_BUTTON_TARGETS}.
- */
-public class AccessibilityFloatingMenuView extends FrameLayout
-        implements RecyclerView.OnItemTouchListener {
-    private static final int INDEX_MENU_ITEM = 0;
-    private static final int FADE_OUT_DURATION_MS = 1000;
-    private static final int FADE_EFFECT_DURATION_MS = 3000;
-    private static final int SNAP_TO_LOCATION_DURATION_MS = 150;
-    private static final int MIN_WINDOW_Y = 0;
-
-    private static final int ANIMATION_START_OFFSET = 600;
-    private static final int ANIMATION_DURATION_MS = 600;
-    private static final float ANIMATION_TO_X_VALUE = 0.5f;
-
-    private boolean mIsFadeEffectEnabled;
-    private boolean mIsShowing;
-    private boolean mIsDownInEnlargedTouchArea;
-    private boolean mIsDragging = false;
-    @Alignment
-    private int mAlignment;
-    @SizeType
-    private int mSizeType = SizeType.SMALL;
-    @VisibleForTesting
-    @ShapeType
-    int mShapeType = ShapeType.OVAL;
-    private int mTemporaryShapeType;
-    @RadiusType
-    private int mRadiusType;
-    private int mMargin;
-    private int mPadding;
-    // The display width excludes the window insets of the system bar and display cutout.
-    private int mDisplayHeight;
-    // The display Height excludes the window insets of the system bar and display cutout.
-    private int mDisplayWidth;
-    private int mIconWidth;
-    private int mIconHeight;
-    private int mInset;
-    private int mDownX;
-    private int mDownY;
-    private int mRelativeToPointerDownX;
-    private int mRelativeToPointerDownY;
-    private float mRadius;
-    private final Rect mDisplayInsetsRect = new Rect();
-    private final Rect mImeInsetsRect = new Rect();
-    private final Position mPosition;
-    private float mSquareScaledTouchSlop;
-    private final Configuration mLastConfiguration;
-    private Optional<OnDragEndListener> mOnDragEndListener = Optional.empty();
-    private final RecyclerView mListView;
-    private final AccessibilityTargetAdapter mAdapter;
-    private float mFadeOutValue;
-    private final ValueAnimator mFadeOutAnimator;
-    @VisibleForTesting
-    final ValueAnimator mDragAnimator;
-    private final Handler mUiHandler;
-    @VisibleForTesting
-    final WindowManager.LayoutParams mCurrentLayoutParams;
-    private final WindowManager mWindowManager;
-    private final List<AccessibilityTarget> mTargets = new ArrayList<>();
-
-    @IntDef({
-            SizeType.SMALL,
-            SizeType.LARGE
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    @interface SizeType {
-        int SMALL = 0;
-        int LARGE = 1;
-    }
-
-    @IntDef({
-            ShapeType.OVAL,
-            ShapeType.HALF_OVAL
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    @interface ShapeType {
-        int OVAL = 0;
-        int HALF_OVAL = 1;
-    }
-
-    @IntDef({
-            RadiusType.LEFT_HALF_OVAL,
-            RadiusType.OVAL,
-            RadiusType.RIGHT_HALF_OVAL
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    @interface RadiusType {
-        int LEFT_HALF_OVAL = 0;
-        int OVAL = 1;
-        int RIGHT_HALF_OVAL = 2;
-    }
-
-    @IntDef({
-            Alignment.LEFT,
-            Alignment.RIGHT
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    @interface Alignment {
-        int LEFT = 0;
-        int RIGHT = 1;
-    }
-
-    /**
-     * Interface for a callback to be invoked when the floating menu was dragging.
-     */
-    interface OnDragEndListener {
-
-        /**
-         * Called when a drag is completed.
-         *
-         * @param position Stores information about the position
-         */
-        void onDragEnd(Position position);
-    }
-
-    public AccessibilityFloatingMenuView(Context context, @NonNull Position position) {
-        this(context, position, new RecyclerView(context));
-    }
-
-    @VisibleForTesting
-    AccessibilityFloatingMenuView(Context context, @NonNull Position position,
-            RecyclerView listView) {
-        super(context);
-
-        mListView = listView;
-        mWindowManager = context.getSystemService(WindowManager.class);
-        mLastConfiguration = new Configuration(getResources().getConfiguration());
-        mAdapter = new AccessibilityTargetAdapter(mTargets);
-        mUiHandler = createUiHandler();
-        mPosition = position;
-        mAlignment = transformToAlignment(mPosition.getPercentageX());
-        mRadiusType = (mAlignment == Alignment.RIGHT)
-                ? RadiusType.LEFT_HALF_OVAL
-                : RadiusType.RIGHT_HALF_OVAL;
-
-        updateDimensions();
-
-        mCurrentLayoutParams = createDefaultLayoutParams();
-
-        mFadeOutAnimator = ValueAnimator.ofFloat(1.0f, mFadeOutValue);
-        mFadeOutAnimator.setDuration(FADE_OUT_DURATION_MS);
-        mFadeOutAnimator.addUpdateListener(
-                (animation) -> setAlpha((float) animation.getAnimatedValue()));
-
-        mDragAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
-        mDragAnimator.setDuration(SNAP_TO_LOCATION_DURATION_MS);
-        mDragAnimator.setInterpolator(new OvershootInterpolator());
-        mDragAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mPosition.update(transformCurrentPercentageXToEdge(),
-                        calculateCurrentPercentageY());
-                mAlignment = transformToAlignment(mPosition.getPercentageX());
-
-                updateLocationWith(mPosition);
-
-                updateInsetWith(getResources().getConfiguration().uiMode, mAlignment);
-
-                mRadiusType = (mAlignment == Alignment.RIGHT)
-                        ? RadiusType.LEFT_HALF_OVAL
-                        : RadiusType.RIGHT_HALF_OVAL;
-                updateRadiusWith(mSizeType, mRadiusType, mTargets.size());
-
-                fadeOut();
-
-                mOnDragEndListener.ifPresent(
-                        onDragEndListener -> onDragEndListener.onDragEnd(mPosition));
-            }
-        });
-
-
-        initListView();
-        updateStrokeWith(getResources().getConfiguration().uiMode, mAlignment);
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView,
-            @NonNull MotionEvent event) {
-        final int currentRawX = (int) event.getRawX();
-        final int currentRawY = (int) event.getRawY();
-
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                fadeIn();
-
-                mDownX = currentRawX;
-                mDownY = currentRawY;
-                mRelativeToPointerDownX = mCurrentLayoutParams.x - mDownX;
-                mRelativeToPointerDownY = mCurrentLayoutParams.y - mDownY;
-                mListView.animate().translationX(0);
-                break;
-            case MotionEvent.ACTION_MOVE:
-                if (mIsDragging
-                        || hasExceededTouchSlop(mDownX, mDownY, currentRawX, currentRawY)) {
-                    if (!mIsDragging) {
-                        mIsDragging = true;
-                        setRadius(mRadius, RadiusType.OVAL);
-                        setInset(0, 0);
-                    }
-
-                    mTemporaryShapeType =
-                            isMovingTowardsScreenEdge(mAlignment, currentRawX, mDownX)
-                                    ? ShapeType.HALF_OVAL
-                                    : ShapeType.OVAL;
-                    final int newWindowX = currentRawX + mRelativeToPointerDownX;
-                    final int newWindowY = currentRawY + mRelativeToPointerDownY;
-                    mCurrentLayoutParams.x =
-                            constrain(newWindowX, getMinWindowX(), getMaxWindowX());
-                    mCurrentLayoutParams.y = constrain(newWindowY, MIN_WINDOW_Y, getMaxWindowY());
-                    mWindowManager.updateViewLayout(this, mCurrentLayoutParams);
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                if (mIsDragging) {
-                    mIsDragging = false;
-
-                    final int minX = getMinWindowX();
-                    final int maxX = getMaxWindowX();
-                    final int endX = mCurrentLayoutParams.x > ((minX + maxX) / 2)
-                            ? maxX : minX;
-                    final int endY = mCurrentLayoutParams.y;
-                    snapToLocation(endX, endY);
-
-                    setShapeType(mTemporaryShapeType);
-
-                    // Avoid triggering the listener of the item.
-                    return true;
-                }
-
-                // Must switch the oval shape type before tapping the corresponding item in the
-                // list view, otherwise it can't work on it.
-                if (!isOvalShape()) {
-                    setShapeType(ShapeType.OVAL);
-
-                    return true;
-                }
-
-                fadeOut();
-                break;
-            default: // Do nothing
-        }
-
-        // not consume all the events here because keeping the scroll behavior of list view.
-        return false;
-    }
-
-    @Override
-    public void onTouchEvent(@NonNull RecyclerView recyclerView, @NonNull MotionEvent motionEvent) {
-        // Do Nothing
-    }
-
-    @Override
-    public void onRequestDisallowInterceptTouchEvent(boolean b) {
-        // Do Nothing
-    }
-
-    void show() {
-        if (isShowing()) {
-            return;
-        }
-
-        mIsShowing = true;
-        mWindowManager.addView(this, mCurrentLayoutParams);
-
-        setOnApplyWindowInsetsListener((view, insets) -> onWindowInsetsApplied(insets));
-        setSystemGestureExclusion();
-    }
-
-    void hide() {
-        if (!isShowing()) {
-            return;
-        }
-
-        mIsShowing = false;
-        mDragAnimator.cancel();
-        mWindowManager.removeView(this);
-
-        setOnApplyWindowInsetsListener(null);
-        setSystemGestureExclusion();
-    }
-
-    boolean isShowing() {
-        return mIsShowing;
-    }
-
-    boolean isOvalShape() {
-        return mShapeType == ShapeType.OVAL;
-    }
-
-    void onTargetsChanged(List<AccessibilityTarget> newTargets) {
-        fadeIn();
-
-        mTargets.clear();
-        mTargets.addAll(newTargets);
-        onEnabledFeaturesChanged();
-
-        updateRadiusWith(mSizeType, mRadiusType, mTargets.size());
-        updateScrollModeWith(hasExceededMaxLayoutHeight());
-        setSystemGestureExclusion();
-
-        fadeOut();
-    }
-
-    void setSizeType(@SizeType int newSizeType) {
-        fadeIn();
-
-        mSizeType = newSizeType;
-
-        updateItemViewWith(newSizeType);
-        updateRadiusWith(newSizeType, mRadiusType, mTargets.size());
-
-        // When the icon sized changed, the menu size and location will be impacted.
-        updateLocationWith(mPosition);
-        updateScrollModeWith(hasExceededMaxLayoutHeight());
-        updateOffsetWith(mShapeType, mAlignment);
-        setSystemGestureExclusion();
-
-        fadeOut();
-    }
-
-    void setShapeType(@ShapeType int newShapeType) {
-        fadeIn();
-
-        mShapeType = newShapeType;
-
-        updateOffsetWith(newShapeType, mAlignment);
-
-        setOnTouchListener(
-                newShapeType == ShapeType.OVAL
-                        ? null
-                        : (view, event) -> onTouched(event));
-
-        fadeOut();
-    }
-
-    public void setOnDragEndListener(OnDragEndListener onDragEndListener) {
-        mOnDragEndListener = Optional.ofNullable(onDragEndListener);
-    }
-
-    void startTranslateXAnimation() {
-        fadeIn();
-
-        final float toXValue = (mAlignment == Alignment.RIGHT)
-                ? ANIMATION_TO_X_VALUE
-                : -ANIMATION_TO_X_VALUE;
-        final TranslateAnimation animation =
-                new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0,
-                        Animation.RELATIVE_TO_SELF, toXValue,
-                        Animation.RELATIVE_TO_SELF, 0,
-                        Animation.RELATIVE_TO_SELF, 0);
-        animation.setDuration(ANIMATION_DURATION_MS);
-        animation.setRepeatMode(Animation.REVERSE);
-        animation.setInterpolator(new OvershootInterpolator());
-        animation.setRepeatCount(Animation.INFINITE);
-        animation.setStartOffset(ANIMATION_START_OFFSET);
-        mListView.startAnimation(animation);
-    }
-
-    void stopTranslateXAnimation() {
-        mListView.clearAnimation();
-
-        fadeOut();
-    }
-
-    Rect getWindowLocationOnScreen() {
-        final int left = mCurrentLayoutParams.x;
-        final int top = mCurrentLayoutParams.y;
-        return new Rect(left, top, left + getWindowWidth(), top + getWindowHeight());
-    }
-
-    void updateOpacityWith(boolean isFadeEffectEnabled, float newOpacityValue) {
-        mIsFadeEffectEnabled = isFadeEffectEnabled;
-        mFadeOutValue = newOpacityValue;
-
-        mFadeOutAnimator.cancel();
-        mFadeOutAnimator.setFloatValues(1.0f, mFadeOutValue);
-        setAlpha(mIsFadeEffectEnabled ? mFadeOutValue : /* completely opaque */ 1.0f);
-    }
-
-    void onEnabledFeaturesChanged() {
-        mAdapter.notifyDataSetChanged();
-    }
-
-    @VisibleForTesting
-    void fadeIn() {
-        if (!mIsFadeEffectEnabled) {
-            return;
-        }
-
-        mFadeOutAnimator.cancel();
-        mUiHandler.removeCallbacksAndMessages(null);
-        mUiHandler.post(() -> setAlpha(/* completely opaque */ 1.0f));
-    }
-
-    @VisibleForTesting
-    void fadeOut() {
-        if (!mIsFadeEffectEnabled) {
-            return;
-        }
-
-        mUiHandler.postDelayed(() -> mFadeOutAnimator.start(), FADE_EFFECT_DURATION_MS);
-    }
-
-    private boolean onTouched(MotionEvent event) {
-        final int action = event.getAction();
-        final int currentX = (int) event.getX();
-        final int currentY = (int) event.getY();
-
-        final int marginStartEnd = getMarginStartEndWith(mLastConfiguration);
-        final Rect touchDelegateBounds =
-                new Rect(marginStartEnd, mMargin, marginStartEnd + getLayoutWidth(),
-                        mMargin + getLayoutHeight());
-        if (action == MotionEvent.ACTION_DOWN
-                && touchDelegateBounds.contains(currentX, currentY)) {
-            mIsDownInEnlargedTouchArea = true;
-        }
-
-        if (!mIsDownInEnlargedTouchArea) {
-            return false;
-        }
-
-        if (action == MotionEvent.ACTION_UP
-                || action == MotionEvent.ACTION_CANCEL) {
-            mIsDownInEnlargedTouchArea = false;
-        }
-
-        // In order to correspond to the correct item of list view.
-        event.setLocation(currentX - mMargin, currentY - mMargin);
-        return mListView.dispatchTouchEvent(event);
-    }
-
-    private WindowInsets onWindowInsetsApplied(WindowInsets insets) {
-        final WindowMetrics windowMetrics = mWindowManager.getCurrentWindowMetrics();
-        final Rect displayWindowInsetsRect = getDisplayInsets(windowMetrics).toRect();
-        if (!displayWindowInsetsRect.equals(mDisplayInsetsRect)) {
-            updateDisplaySizeWith(windowMetrics);
-            updateLocationWith(mPosition);
-        }
-
-        final Rect imeInsetsRect = windowMetrics.getWindowInsets().getInsets(ime()).toRect();
-        if (!imeInsetsRect.equals(mImeInsetsRect)) {
-            if (isImeVisible(imeInsetsRect)) {
-                mImeInsetsRect.set(imeInsetsRect);
-            } else {
-                mImeInsetsRect.setEmpty();
-            }
-
-            updateLocationWith(mPosition);
-        }
-
-        return insets;
-    }
-
-    private boolean isMovingTowardsScreenEdge(@Alignment int side, int currentRawX, int downX) {
-        return (side == Alignment.RIGHT && currentRawX > downX)
-                || (side == Alignment.LEFT && downX > currentRawX);
-    }
-
-    private boolean isImeVisible(Rect imeInsetsRect) {
-        return imeInsetsRect.left != 0 || imeInsetsRect.top != 0 || imeInsetsRect.right != 0
-                || imeInsetsRect.bottom != 0;
-    }
-
-    private boolean hasExceededTouchSlop(int startX, int startY, int endX, int endY) {
-        return (sq(endX - startX) + sq(endY - startY)) > mSquareScaledTouchSlop;
-    }
-
-    private void setRadius(float radius, @RadiusType int type) {
-        getMenuGradientDrawable().setCornerRadii(createRadii(radius, type));
-    }
-
-    private float[] createRadii(float radius, @RadiusType int type) {
-        if (type == RadiusType.LEFT_HALF_OVAL) {
-            return new float[]{radius, radius, 0.0f, 0.0f, 0.0f, 0.0f, radius, radius};
-        }
-
-        if (type == RadiusType.RIGHT_HALF_OVAL) {
-            return new float[]{0.0f, 0.0f, radius, radius, radius, radius, 0.0f, 0.0f};
-        }
-
-        return new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
-    }
-
-    private Handler createUiHandler() {
-        return new Handler(requireNonNull(Looper.myLooper(), "looper must not be null"));
-    }
-
-    private void updateDimensions() {
-        final Resources res = getResources();
-
-        updateDisplaySizeWith(mWindowManager.getCurrentWindowMetrics());
-
-        mMargin =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_margin);
-        mInset =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_stroke_inset);
-
-        mSquareScaledTouchSlop =
-                sq(ViewConfiguration.get(getContext()).getScaledTouchSlop());
-
-        updateItemViewDimensionsWith(mSizeType);
-    }
-
-    private void updateDisplaySizeWith(WindowMetrics metrics) {
-        final Rect displayBounds = metrics.getBounds();
-        final Insets displayInsets = getDisplayInsets(metrics);
-        mDisplayInsetsRect.set(displayInsets.toRect());
-        displayBounds.inset(displayInsets);
-        mDisplayWidth = displayBounds.width();
-        mDisplayHeight = displayBounds.height();
-    }
-
-    private void updateItemViewDimensionsWith(@SizeType int sizeType) {
-        final Resources res = getResources();
-        final int paddingResId =
-                sizeType == SizeType.SMALL
-                        ? R.dimen.accessibility_floating_menu_small_padding
-                        : R.dimen.accessibility_floating_menu_large_padding;
-        mPadding = res.getDimensionPixelSize(paddingResId);
-
-        final int iconResId =
-                sizeType == SizeType.SMALL
-                        ? R.dimen.accessibility_floating_menu_small_width_height
-                        : R.dimen.accessibility_floating_menu_large_width_height;
-        mIconWidth = res.getDimensionPixelSize(iconResId);
-        mIconHeight = mIconWidth;
-    }
-
-    private void updateItemViewWith(@SizeType int sizeType) {
-        updateItemViewDimensionsWith(sizeType);
-
-        mAdapter.setItemPadding(mPadding);
-        mAdapter.setIconWidthHeight(mIconWidth);
-        mAdapter.notifyDataSetChanged();
-    }
-
-    private void initListView() {
-        final Drawable background =
-                getContext().getDrawable(R.drawable.accessibility_floating_menu_background);
-        final LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
-        final LayoutParams layoutParams =
-                new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
-                        ViewGroup.LayoutParams.WRAP_CONTENT);
-        mListView.setLayoutParams(layoutParams);
-        final InstantInsetLayerDrawable layerDrawable =
-                new InstantInsetLayerDrawable(new Drawable[]{background});
-        mListView.setBackground(layerDrawable);
-        mListView.setAdapter(mAdapter);
-        mListView.setLayoutManager(layoutManager);
-        mListView.addOnItemTouchListener(this);
-        mListView.animate().setInterpolator(new OvershootInterpolator());
-        mListView.setAccessibilityDelegateCompat(new RecyclerViewAccessibilityDelegate(mListView) {
-            @NonNull
-            @Override
-            public AccessibilityDelegateCompat getItemDelegate() {
-                return new ItemDelegateCompat(this,
-                        AccessibilityFloatingMenuView.this);
-            }
-        });
-
-        updateListViewWith(mLastConfiguration);
-
-        addView(mListView);
-    }
-
-    private void updateListViewWith(Configuration configuration) {
-        updateMarginWith(configuration);
-
-        final int elevation =
-                getResources().getDimensionPixelSize(R.dimen.accessibility_floating_menu_elevation);
-        mListView.setElevation(elevation);
-    }
-
-    private WindowManager.LayoutParams createDefaultLayoutParams() {
-        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
-                WindowManager.LayoutParams.WRAP_CONTENT,
-                WindowManager.LayoutParams.WRAP_CONTENT,
-                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
-                PixelFormat.TRANSLUCENT);
-        params.receiveInsetsIgnoringZOrder = true;
-        params.privateFlags |= PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
-        params.windowAnimations = android.R.style.Animation_Translucent;
-        params.gravity = Gravity.START | Gravity.TOP;
-        params.x = (mAlignment == Alignment.RIGHT) ? getMaxWindowX() : getMinWindowX();
-//        params.y = (int) (mPosition.getPercentageY() * getMaxWindowY());
-        final int currentLayoutY = (int) (mPosition.getPercentageY() * getMaxWindowY());
-        params.y = Math.max(MIN_WINDOW_Y, currentLayoutY - getInterval());
-        updateAccessibilityTitle(params);
-        return params;
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        mLastConfiguration.setTo(newConfig);
-
-        final int diff = newConfig.diff(mLastConfiguration);
-        if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) {
-            updateAccessibilityTitle(mCurrentLayoutParams);
-        }
-
-        updateDimensions();
-        updateListViewWith(newConfig);
-        updateItemViewWith(mSizeType);
-        updateColor();
-        updateStrokeWith(newConfig.uiMode, mAlignment);
-        updateLocationWith(mPosition);
-        updateRadiusWith(mSizeType, mRadiusType, mTargets.size());
-        updateScrollModeWith(hasExceededMaxLayoutHeight());
-        setSystemGestureExclusion();
-    }
-
-    @VisibleForTesting
-    void snapToLocation(int endX, int endY) {
-        mDragAnimator.cancel();
-        mDragAnimator.removeAllUpdateListeners();
-        mDragAnimator.addUpdateListener(anim -> onDragAnimationUpdate(anim, endX, endY));
-        mDragAnimator.start();
-    }
-
-    private void onDragAnimationUpdate(ValueAnimator animator, int endX, int endY) {
-        float value = (float) animator.getAnimatedValue();
-        final int newX = (int) (((1 - value) * mCurrentLayoutParams.x) + (value * endX));
-        final int newY = (int) (((1 - value) * mCurrentLayoutParams.y) + (value * endY));
-
-        mCurrentLayoutParams.x = newX;
-        mCurrentLayoutParams.y = newY;
-        mWindowManager.updateViewLayout(this, mCurrentLayoutParams);
-    }
-
-    private int getMinWindowX() {
-        return -getMarginStartEndWith(mLastConfiguration);
-    }
-
-    private int getMaxWindowX() {
-        return mDisplayWidth - getMarginStartEndWith(mLastConfiguration) - getLayoutWidth();
-    }
-
-    private int getMaxWindowY() {
-        return mDisplayHeight - getWindowHeight();
-    }
-
-    private InstantInsetLayerDrawable getMenuLayerDrawable() {
-        return (InstantInsetLayerDrawable) mListView.getBackground();
-    }
-
-    private GradientDrawable getMenuGradientDrawable() {
-        return (GradientDrawable) getMenuLayerDrawable().getDrawable(INDEX_MENU_ITEM);
-    }
-
-    private Insets getDisplayInsets(WindowMetrics metrics) {
-        return metrics.getWindowInsets().getInsetsIgnoringVisibility(
-                systemBars() | displayCutout());
-    }
-
-    /**
-     * Updates the floating menu to be fixed at the side of the display.
-     */
-    private void updateLocationWith(Position position) {
-        final @Alignment int alignment = transformToAlignment(position.getPercentageX());
-        mCurrentLayoutParams.x = (alignment == Alignment.RIGHT) ? getMaxWindowX() : getMinWindowX();
-        final int currentLayoutY = (int) (position.getPercentageY() * getMaxWindowY());
-        mCurrentLayoutParams.y = Math.max(MIN_WINDOW_Y, currentLayoutY - getInterval());
-        mWindowManager.updateViewLayout(this, mCurrentLayoutParams);
-    }
-
-    /**
-     * Gets the moving interval to not overlap between the keyboard and menu view.
-     *
-     * @return the moving interval if they overlap each other, otherwise 0.
-     */
-    private int getInterval() {
-        final int currentLayoutY = (int) (mPosition.getPercentageY() * getMaxWindowY());
-        final int imeY = mDisplayHeight - mImeInsetsRect.bottom;
-        final int layoutBottomY = currentLayoutY + getWindowHeight();
-
-        return layoutBottomY > imeY ? (layoutBottomY - imeY) : 0;
-    }
-
-    private void updateMarginWith(Configuration configuration) {
-        // Avoid overlapping with system bars under landscape mode, update the margins of the menu
-        // to align the edge of system bars.
-        final int marginStartEnd = getMarginStartEndWith(configuration);
-        final LayoutParams layoutParams = (FrameLayout.LayoutParams) mListView.getLayoutParams();
-        layoutParams.setMargins(marginStartEnd, mMargin, marginStartEnd, mMargin);
-        mListView.setLayoutParams(layoutParams);
-    }
-
-    private void updateOffsetWith(@ShapeType int shapeType, @Alignment int side) {
-        final float halfWidth = getLayoutWidth() / 2.0f;
-        final float offset = (shapeType == ShapeType.OVAL) ? 0 : halfWidth;
-        mListView.animate().translationX(side == Alignment.RIGHT ? offset : -offset);
-    }
-
-    private void updateScrollModeWith(boolean hasExceededMaxLayoutHeight) {
-        mListView.setOverScrollMode(hasExceededMaxLayoutHeight
-                ? OVER_SCROLL_ALWAYS
-                : OVER_SCROLL_NEVER);
-    }
-
-    private void updateColor() {
-        final int menuColorResId = R.color.accessibility_floating_menu_background;
-        getMenuGradientDrawable().setColor(getResources().getColor(menuColorResId));
-    }
-
-    private void updateStrokeWith(int uiMode, @Alignment int side) {
-        updateInsetWith(uiMode, side);
-
-        final boolean isNightMode =
-                (uiMode & Configuration.UI_MODE_NIGHT_MASK)
-                        == Configuration.UI_MODE_NIGHT_YES;
-        final Resources res = getResources();
-        final int width =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_stroke_width);
-        final int strokeWidth = isNightMode ? width : 0;
-        final int strokeColor = res.getColor(R.color.accessibility_floating_menu_stroke_dark);
-        getMenuGradientDrawable().setStroke(strokeWidth, strokeColor);
-    }
-
-    private void updateRadiusWith(@SizeType int sizeType, @RadiusType int radiusType,
-            int itemCount) {
-        mRadius =
-                getResources().getDimensionPixelSize(getRadiusResId(sizeType, itemCount));
-        setRadius(mRadius, radiusType);
-    }
-
-    private void updateInsetWith(int uiMode, @Alignment int side) {
-        final boolean isNightMode =
-                (uiMode & Configuration.UI_MODE_NIGHT_MASK)
-                        == Configuration.UI_MODE_NIGHT_YES;
-
-        final int layerInset = isNightMode ? mInset : 0;
-        final int insetLeft = (side == Alignment.LEFT) ? layerInset : 0;
-        final int insetRight = (side == Alignment.RIGHT) ? layerInset : 0;
-        setInset(insetLeft, insetRight);
-    }
-
-    private void updateAccessibilityTitle(WindowManager.LayoutParams params) {
-        params.accessibilityTitle = getResources().getString(
-                com.android.internal.R.string.accessibility_select_shortcut_menu_title);
-    }
-
-    private void setInset(int left, int right) {
-        final LayerDrawable layerDrawable = getMenuLayerDrawable();
-        if (layerDrawable.getLayerInsetLeft(INDEX_MENU_ITEM) == left
-                && layerDrawable.getLayerInsetRight(INDEX_MENU_ITEM) == right) {
-            return;
-        }
-
-        layerDrawable.setLayerInset(INDEX_MENU_ITEM, left, 0, right, 0);
-    }
-
-    @VisibleForTesting
-    boolean hasExceededMaxLayoutHeight() {
-        return calculateActualLayoutHeight() > getMaxLayoutHeight();
-    }
-
-    @Alignment
-    private int transformToAlignment(@FloatRange(from = 0.0, to = 1.0) float percentageX) {
-        return (percentageX < 0.5f) ? Alignment.LEFT : Alignment.RIGHT;
-    }
-
-    private float transformCurrentPercentageXToEdge() {
-        final float percentageX = calculateCurrentPercentageX();
-        return (percentageX < 0.5) ? 0.0f : 1.0f;
-    }
-
-    private float calculateCurrentPercentageX() {
-        return mCurrentLayoutParams.x / (float) getMaxWindowX();
-    }
-
-    private float calculateCurrentPercentageY() {
-        return mCurrentLayoutParams.y / (float) getMaxWindowY();
-    }
-
-    private int calculateActualLayoutHeight() {
-        return (mPadding + mIconHeight) * mTargets.size() + mPadding;
-    }
-
-    private int getMarginStartEndWith(Configuration configuration) {
-        return configuration != null
-                && configuration.orientation == ORIENTATION_PORTRAIT
-                ? mMargin : 0;
-    }
-
-    private @DimenRes int getRadiusResId(@SizeType int sizeType, int itemCount) {
-        return sizeType == SizeType.SMALL
-                ? getSmallSizeResIdWith(itemCount)
-                : getLargeSizeResIdWith(itemCount);
-    }
-
-    private int getSmallSizeResIdWith(int itemCount) {
-        return itemCount > 1
-                ? R.dimen.accessibility_floating_menu_small_multiple_radius
-                : R.dimen.accessibility_floating_menu_small_single_radius;
-    }
-
-    private int getLargeSizeResIdWith(int itemCount) {
-        return itemCount > 1
-                ? R.dimen.accessibility_floating_menu_large_multiple_radius
-                : R.dimen.accessibility_floating_menu_large_single_radius;
-    }
-
-    @VisibleForTesting
-    Rect getAvailableBounds() {
-        return new Rect(0, 0, mDisplayWidth - getWindowWidth(),
-                mDisplayHeight - getWindowHeight());
-    }
-
-    private int getMaxLayoutHeight() {
-        return mDisplayHeight - mMargin * 2;
-    }
-
-    private int getLayoutWidth() {
-        return mPadding * 2 + mIconWidth;
-    }
-
-    private int getLayoutHeight() {
-        return Math.min(getMaxLayoutHeight(), calculateActualLayoutHeight());
-    }
-
-    private int getWindowWidth() {
-        return getMarginStartEndWith(mLastConfiguration) * 2 + getLayoutWidth();
-    }
-
-    private int getWindowHeight() {
-        return Math.min(mDisplayHeight, mMargin * 2 + getLayoutHeight());
-    }
-
-    private void setSystemGestureExclusion() {
-        final Rect excludeZone =
-                new Rect(0, 0, getWindowWidth(), getWindowHeight());
-        post(() -> setSystemGestureExclusionRects(
-                mIsShowing
-                        ? Collections.singletonList(excludeZone)
-                        : Collections.emptyList()));
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipView.java
deleted file mode 100644
index 61fc7ed..0000000
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipView.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static android.util.TypedValue.COMPLEX_UNIT_PX;
-import static android.view.View.MeasureSpec.AT_MOST;
-import static android.view.View.MeasureSpec.UNSPECIFIED;
-
-import android.annotation.UiContext;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.CornerPathEffect;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.GradientDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.os.Bundle;
-import android.text.method.MovementMethod;
-import android.util.DisplayMetrics;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.settingslib.Utils;
-import com.android.systemui.R;
-import com.android.systemui.recents.TriangleShape;
-
-/**
- * Base tooltip view that shows the information about the operation of the
- * Accessibility floating menu. In addition, the anchor view is only for {@link
- * AccessibilityFloatingMenuView}, it should be more suited for displaying one-off menus to avoid
- * the performance hit for the extra window.
- */
-class BaseTooltipView extends FrameLayout {
-    private int mFontSize;
-    private int mTextViewMargin;
-    private int mTextViewPadding;
-    private int mTextViewCornerRadius;
-    private int mArrowMargin;
-    private int mArrowWidth;
-    private int mArrowHeight;
-    private int mArrowCornerRadius;
-    private int mScreenWidth;
-    private boolean mIsShowing;
-    private TextView mTextView;
-    private final WindowManager.LayoutParams mCurrentLayoutParams;
-    private final WindowManager mWindowManager;
-    private final AccessibilityFloatingMenuView mAnchorView;
-
-    BaseTooltipView(@UiContext Context context, AccessibilityFloatingMenuView anchorView) {
-        super(context);
-        mWindowManager = context.getSystemService(WindowManager.class);
-        mAnchorView = anchorView;
-        mCurrentLayoutParams = createDefaultLayoutParams();
-
-        initViews();
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-
-        mAnchorView.onConfigurationChanged(newConfig);
-        updateTooltipView();
-
-        mWindowManager.updateViewLayout(this, mCurrentLayoutParams);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
-            hide();
-        }
-
-        return super.onTouchEvent(event);
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(info);
-
-        info.addAction(AccessibilityAction.ACTION_DISMISS);
-    }
-
-    @Override
-    public boolean performAccessibilityAction(int action, Bundle arguments) {
-        if (action == AccessibilityAction.ACTION_DISMISS.getId()) {
-            hide();
-            return true;
-        }
-
-        return super.performAccessibilityAction(action, arguments);
-    }
-
-    void show() {
-        if (isShowing()) {
-            return;
-        }
-
-        mIsShowing = true;
-        updateTooltipView();
-
-        mWindowManager.addView(this, mCurrentLayoutParams);
-    }
-
-    void hide() {
-        if (!isShowing()) {
-            return;
-        }
-
-        mIsShowing = false;
-        mWindowManager.removeView(this);
-    }
-
-    void setDescription(CharSequence text) {
-        mTextView.setText(text);
-    }
-
-    void setMovementMethod(MovementMethod movement) {
-        mTextView.setMovementMethod(movement);
-    }
-
-    private boolean isShowing() {
-        return mIsShowing;
-    }
-
-    private void initViews() {
-        final View contentView =
-                LayoutInflater.from(getContext()).inflate(
-                        R.layout.accessibility_floating_menu_tooltip, this, false);
-
-        mTextView = contentView.findViewById(R.id.text);
-
-        addView(contentView);
-    }
-
-    private static WindowManager.LayoutParams createDefaultLayoutParams() {
-        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
-                WindowManager.LayoutParams.WRAP_CONTENT,
-                WindowManager.LayoutParams.WRAP_CONTENT,
-                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
-                PixelFormat.TRANSLUCENT);
-        params.windowAnimations = android.R.style.Animation_Translucent;
-        params.gravity = Gravity.START | Gravity.TOP;
-
-        return params;
-    }
-
-    private void updateDimensions() {
-        final Resources res = getResources();
-        final DisplayMetrics dm = res.getDisplayMetrics();
-        mScreenWidth = dm.widthPixels;
-        mArrowWidth =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_tooltip_arrow_width);
-        mArrowHeight =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_tooltip_arrow_height);
-        mArrowMargin =
-                res.getDimensionPixelSize(
-                        R.dimen.accessibility_floating_tooltip_arrow_margin);
-        mArrowCornerRadius =
-                res.getDimensionPixelSize(
-                        R.dimen.accessibility_floating_tooltip_arrow_corner_radius);
-        mFontSize =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_tooltip_font_size);
-        mTextViewMargin =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_tooltip_margin);
-        mTextViewPadding =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_tooltip_padding);
-        mTextViewCornerRadius =
-                res.getDimensionPixelSize(
-                        R.dimen.accessibility_floating_tooltip_text_corner_radius);
-    }
-
-    private void updateTooltipView() {
-        updateDimensions();
-        updateTextView();
-
-        final Rect anchorViewLocation = mAnchorView.getWindowLocationOnScreen();
-        updateArrowWith(anchorViewLocation);
-        updateWidthWith(anchorViewLocation);
-        updateLocationWith(anchorViewLocation);
-    }
-
-    private void updateTextView() {
-        mTextView.setTextSize(COMPLEX_UNIT_PX, mFontSize);
-        mTextView.setPadding(mTextViewPadding, mTextViewPadding, mTextViewPadding,
-                mTextViewPadding);
-
-        final GradientDrawable gradientDrawable = (GradientDrawable) mTextView.getBackground();
-        gradientDrawable.setCornerRadius(mTextViewCornerRadius);
-        gradientDrawable.setColor(Utils.getColorAttrDefaultColor(getContext(),
-                com.android.internal.R.attr.colorAccentPrimary));
-    }
-
-    private void updateArrowWith(Rect anchorViewLocation) {
-        final boolean isAnchorViewOnLeft = isAnchorViewOnLeft(anchorViewLocation);
-        final View arrowView = findViewById(isAnchorViewOnLeft
-                ? R.id.arrow_left
-                : R.id.arrow_right);
-        arrowView.setVisibility(VISIBLE);
-        drawArrow(arrowView, isAnchorViewOnLeft);
-
-        final LinearLayout.LayoutParams layoutParams =
-                (LinearLayout.LayoutParams) arrowView.getLayoutParams();
-        layoutParams.width = mArrowWidth;
-        layoutParams.height = mArrowHeight;
-
-        final int leftMargin = isAnchorViewOnLeft ? 0 : mArrowMargin;
-        final int rightMargin = isAnchorViewOnLeft ? mArrowMargin : 0;
-        layoutParams.setMargins(leftMargin, 0, rightMargin, 0);
-        arrowView.setLayoutParams(layoutParams);
-    }
-
-    private void updateWidthWith(Rect anchorViewLocation) {
-        final ViewGroup.LayoutParams layoutParams = mTextView.getLayoutParams();
-        layoutParams.width = getTextWidthWith(anchorViewLocation);
-        mTextView.setLayoutParams(layoutParams);
-    }
-
-    private void updateLocationWith(Rect anchorViewLocation) {
-        mCurrentLayoutParams.x = isAnchorViewOnLeft(anchorViewLocation)
-                ? anchorViewLocation.width()
-                : mScreenWidth - getWindowWidthWith(anchorViewLocation)
-                        - anchorViewLocation.width();
-        mCurrentLayoutParams.y =
-                anchorViewLocation.centerY() - (getTextHeightWith(anchorViewLocation) / 2);
-    }
-
-    private void drawArrow(View view, boolean isPointingLeft) {
-        final ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
-        final TriangleShape triangleShape =
-                TriangleShape.createHorizontal(layoutParams.width, layoutParams.height,
-                        isPointingLeft);
-        final ShapeDrawable arrowDrawable = new ShapeDrawable(triangleShape);
-        final Paint arrowPaint = arrowDrawable.getPaint();
-        arrowPaint.setColor(Utils.getColorAttrDefaultColor(getContext(),
-                com.android.internal.R.attr.colorAccentPrimary));
-        final CornerPathEffect effect = new CornerPathEffect(mArrowCornerRadius);
-        arrowPaint.setPathEffect(effect);
-        view.setBackground(arrowDrawable);
-    }
-
-    private boolean isAnchorViewOnLeft(Rect anchorViewLocation) {
-        return anchorViewLocation.left < (mScreenWidth / 2);
-    }
-
-    private int getTextWidthWith(Rect anchorViewLocation) {
-        final int widthSpec =
-                MeasureSpec.makeMeasureSpec(getAvailableTextWidthWith(anchorViewLocation), AT_MOST);
-        final int heightSpec =
-                MeasureSpec.makeMeasureSpec(0, UNSPECIFIED);
-        mTextView.measure(widthSpec, heightSpec);
-        return mTextView.getMeasuredWidth();
-    }
-
-    private int getTextHeightWith(Rect anchorViewLocation) {
-        final int widthSpec =
-                MeasureSpec.makeMeasureSpec(getAvailableTextWidthWith(anchorViewLocation), AT_MOST);
-        final int heightSpec =
-                MeasureSpec.makeMeasureSpec(0, UNSPECIFIED);
-        mTextView.measure(widthSpec, heightSpec);
-        return mTextView.getMeasuredHeight();
-    }
-
-    private int getAvailableTextWidthWith(Rect anchorViewLocation) {
-        return mScreenWidth - anchorViewLocation.width() - mArrowWidth - mArrowMargin
-                - mTextViewMargin;
-    }
-
-    private int getWindowWidthWith(Rect anchorViewLocation) {
-        return getTextWidthWith(anchorViewLocation) + mArrowWidth + mArrowMargin;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/DockTooltipView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/DockTooltipView.java
deleted file mode 100644
index 49056a6..0000000
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/DockTooltipView.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import android.content.Context;
-
-import com.android.systemui.R;
-
-/**
- * Dock tooltip view that shows the info about moving the Accessibility button to the edge to hide.
- */
-class DockTooltipView extends BaseTooltipView {
-    private final AccessibilityFloatingMenuView mAnchorView;
-
-    DockTooltipView(Context context, AccessibilityFloatingMenuView anchorView) {
-        super(context, anchorView);
-        mAnchorView = anchorView;
-
-        setDescription(
-                getContext().getText(R.string.accessibility_floating_button_docking_tooltip));
-    }
-
-    @Override
-    void hide() {
-        super.hide();
-
-        mAnchorView.stopTranslateXAnimation();
-    }
-
-    @Override
-    void show() {
-        super.show();
-
-        mAnchorView.startTranslateXAnimation();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/ItemDelegateCompat.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/ItemDelegateCompat.java
deleted file mode 100644
index 93b0676..0000000
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/ItemDelegateCompat.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import android.content.res.Resources;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
-import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate;
-
-import com.android.systemui.R;
-import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuView.ShapeType;
-
-import java.lang.ref.WeakReference;
-
-/**
- * An accessibility item delegate for the individual items of the list view
- * {@link AccessibilityFloatingMenuView}.
- */
-final class ItemDelegateCompat extends RecyclerViewAccessibilityDelegate.ItemDelegate {
-    private final WeakReference<AccessibilityFloatingMenuView> mMenuViewRef;
-
-    ItemDelegateCompat(@NonNull RecyclerViewAccessibilityDelegate recyclerViewDelegate,
-            AccessibilityFloatingMenuView menuView) {
-        super(recyclerViewDelegate);
-        this.mMenuViewRef = new WeakReference<>(menuView);
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
-        super.onInitializeAccessibilityNodeInfo(host, info);
-
-        if (mMenuViewRef.get() == null) {
-            return;
-        }
-        final AccessibilityFloatingMenuView menuView = mMenuViewRef.get();
-
-        final Resources res = menuView.getResources();
-        final AccessibilityNodeInfoCompat.AccessibilityActionCompat moveTopLeft =
-                new AccessibilityNodeInfoCompat.AccessibilityActionCompat(R.id.action_move_top_left,
-                        res.getString(
-                                R.string.accessibility_floating_button_action_move_top_left));
-        info.addAction(moveTopLeft);
-
-        final AccessibilityNodeInfoCompat.AccessibilityActionCompat moveTopRight =
-                new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
-                        R.id.action_move_top_right,
-                        res.getString(
-                                R.string.accessibility_floating_button_action_move_top_right));
-        info.addAction(moveTopRight);
-
-        final AccessibilityNodeInfoCompat.AccessibilityActionCompat moveBottomLeft =
-                new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
-                        R.id.action_move_bottom_left,
-                        res.getString(
-                                R.string.accessibility_floating_button_action_move_bottom_left));
-        info.addAction(moveBottomLeft);
-
-        final AccessibilityNodeInfoCompat.AccessibilityActionCompat moveBottomRight =
-                new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
-                        R.id.action_move_bottom_right,
-                        res.getString(
-                                R.string.accessibility_floating_button_action_move_bottom_right));
-        info.addAction(moveBottomRight);
-
-        final int moveEdgeId = menuView.isOvalShape()
-                ? R.id.action_move_to_edge_and_hide
-                : R.id.action_move_out_edge_and_show;
-        final int moveEdgeTextResId = menuView.isOvalShape()
-                ? R.string.accessibility_floating_button_action_move_to_edge_and_hide_to_half
-                : R.string.accessibility_floating_button_action_move_out_edge_and_show;
-        final AccessibilityNodeInfoCompat.AccessibilityActionCompat moveToOrOutEdge =
-                new AccessibilityNodeInfoCompat.AccessibilityActionCompat(moveEdgeId,
-                        res.getString(moveEdgeTextResId));
-        info.addAction(moveToOrOutEdge);
-    }
-
-    @Override
-    public boolean performAccessibilityAction(View host, int action, Bundle args) {
-        if (mMenuViewRef.get() == null) {
-            return super.performAccessibilityAction(host, action, args);
-        }
-        final AccessibilityFloatingMenuView menuView = mMenuViewRef.get();
-
-        menuView.fadeIn();
-
-        final Rect bounds = menuView.getAvailableBounds();
-        if (action == R.id.action_move_top_left) {
-            menuView.setShapeType(ShapeType.OVAL);
-            menuView.snapToLocation(bounds.left, bounds.top);
-            return true;
-        }
-
-        if (action == R.id.action_move_top_right) {
-            menuView.setShapeType(ShapeType.OVAL);
-            menuView.snapToLocation(bounds.right, bounds.top);
-            return true;
-        }
-
-        if (action == R.id.action_move_bottom_left) {
-            menuView.setShapeType(ShapeType.OVAL);
-            menuView.snapToLocation(bounds.left, bounds.bottom);
-            return true;
-        }
-
-        if (action == R.id.action_move_bottom_right) {
-            menuView.setShapeType(ShapeType.OVAL);
-            menuView.snapToLocation(bounds.right, bounds.bottom);
-            return true;
-        }
-
-        if (action == R.id.action_move_to_edge_and_hide) {
-            menuView.setShapeType(ShapeType.HALF_OVAL);
-            return true;
-        }
-
-        if (action == R.id.action_move_out_edge_and_show) {
-            menuView.setShapeType(ShapeType.OVAL);
-            return true;
-        }
-
-        return super.performAccessibilityAction(host, action, args);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
index d0c426d..3f41a76 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
@@ -17,6 +17,7 @@
 package com.android.systemui.accessibility.floatingmenu;
 
 import static android.view.WindowInsets.Type.ime;
+import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
 
 import static androidx.core.view.WindowInsetsCompat.Type;
 
@@ -32,6 +33,7 @@
 import android.annotation.StringDef;
 import android.annotation.SuppressLint;
 import android.content.ComponentCallbacks;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -132,16 +134,30 @@
                     Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, /* value= */ "",
                     UserHandle.USER_CURRENT);
 
+            final List<ComponentName> hardwareKeyShortcutComponents =
+                    mAccessibilityManager.getAccessibilityShortcutTargets(
+                                    ACCESSIBILITY_SHORTCUT_KEY)
+                            .stream()
+                            .map(ComponentName::unflattenFromString)
+                            .toList();
+
             // Should disable the corresponding service when the fragment type is
             // INVISIBLE_TOGGLE, which will enable service when the shortcut is on.
             final List<AccessibilityServiceInfo> serviceInfoList =
                     mAccessibilityManager.getEnabledAccessibilityServiceList(
                             AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
             serviceInfoList.forEach(info -> {
-                if (getAccessibilityServiceFragmentType(info) == INVISIBLE_TOGGLE) {
-                    setAccessibilityServiceState(getContext(),
-                            info.getComponentName(), /* enabled= */ false);
+                if (getAccessibilityServiceFragmentType(info) != INVISIBLE_TOGGLE) {
+                    return;
                 }
+
+                final ComponentName serviceComponentName = info.getComponentName();
+                if (hardwareKeyShortcutComponents.contains(serviceComponentName)) {
+                    return;
+                }
+
+                setAccessibilityServiceState(getContext(), serviceComponentName, /* enabled= */
+                        false);
             });
 
             mFloatingMenu.hide();
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipView.java
deleted file mode 100644
index e4f3e31..0000000
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipView.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_BUTTON_COMPONENT_NAME;
-
-import android.content.Context;
-import android.content.Intent;
-import android.provider.Settings;
-import android.text.method.LinkMovementMethod;
-
-import com.android.systemui.R;
-
-/**
- * Migration tooltip view that shows the information about the Accessibility button was replaced
- * with the floating menu.
- */
-class MigrationTooltipView extends BaseTooltipView {
-    MigrationTooltipView(Context context, AccessibilityFloatingMenuView anchorView) {
-        super(context, anchorView);
-
-        final Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_DETAILS_SETTINGS);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(Intent.EXTRA_COMPONENT_NAME,
-                ACCESSIBILITY_BUTTON_COMPONENT_NAME.flattenToShortString());
-
-        final AnnotationLinkSpan.LinkInfo linkInfo = new AnnotationLinkSpan.LinkInfo(
-                AnnotationLinkSpan.LinkInfo.DEFAULT_ANNOTATION,
-                v -> {
-                    getContext().startActivity(intent);
-                    hide();
-                });
-
-        final int textResId = R.string.accessibility_floating_button_migration_tooltip;
-        setDescription(AnnotationLinkSpan.linkify(getContext().getText(textResId), linkInfo));
-        setMovementMethod(LinkMovementMethod.getInstance());
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index 436f9df..1f6f6d9 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -46,6 +46,8 @@
 
     private var isDeviceFolded: Boolean = false
     private val isSideFps: Boolean
+    private val isReverseDefaultRotation =
+            context.resources.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)
     private val screenSizeFoldProvider: ScreenSizeFoldProvider = ScreenSizeFoldProvider(context)
     var iconLayoutParamSize: Pair<Int, Int> = Pair(1, 1)
         set(value) {
@@ -76,7 +78,7 @@
         isSideFps = sideFps
         val displayInfo = DisplayInfo()
         context.display?.getDisplayInfo(displayInfo)
-        if (isSideFps && displayInfo.rotation == Surface.ROTATION_180) {
+        if (isSideFps && getRotationFromDefault(displayInfo.rotation) == Surface.ROTATION_180) {
             iconView.rotation = 180f
         }
         screenSizeFoldProvider.registerCallback(this, context.mainExecutor)
@@ -86,7 +88,7 @@
     private fun updateIconSideFps(@BiometricState lastState: Int, @BiometricState newState: Int) {
         val displayInfo = DisplayInfo()
         context.display?.getDisplayInfo(displayInfo)
-        val rotation = displayInfo.rotation
+        val rotation = getRotationFromDefault(displayInfo.rotation)
         val iconAnimation = getSideFpsAnimationForTransition(rotation)
         val iconViewOverlayAnimation =
                 getSideFpsOverlayAnimationForTransition(lastState, newState, rotation) ?: return
@@ -104,7 +106,7 @@
 
         iconView.frame = 0
         iconViewOverlay.frame = 0
-        if (shouldAnimateIconViewForTransition(lastState, newState)) {
+        if (shouldAnimateSfpsIconViewForTransition(lastState, newState)) {
             iconView.playAnimation()
         }
 
@@ -169,6 +171,18 @@
         STATE_HELP,
         STATE_ERROR -> true
         STATE_AUTHENTICATING_ANIMATING_IN,
+        STATE_AUTHENTICATING -> oldState == STATE_ERROR || oldState == STATE_HELP
+        STATE_AUTHENTICATED -> true
+        else -> false
+    }
+
+    private fun shouldAnimateSfpsIconViewForTransition(
+            @BiometricState oldState: Int,
+            @BiometricState newState: Int
+    ) = when (newState) {
+        STATE_HELP,
+        STATE_ERROR -> true
+        STATE_AUTHENTICATING_ANIMATING_IN,
         STATE_AUTHENTICATING ->
             oldState == STATE_ERROR || oldState == STATE_HELP || oldState == STATE_IDLE
         STATE_AUTHENTICATED -> true
@@ -217,6 +231,9 @@
         return if (id != null) return id else null
     }
 
+    private fun getRotationFromDefault(rotation: Int): Int =
+            if (isReverseDefaultRotation) (rotation + 1) % 4 else rotation
+
     @RawRes
     private fun getSideFpsAnimationForTransition(rotation: Int): Int = when (rotation) {
         Surface.ROTATION_90 -> if (isDeviceFolded) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index dad6ebe..c8cf5d7 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -55,7 +55,6 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserManager;
-import android.util.DisplayUtils;
 import android.util.Log;
 import android.util.RotationUtils;
 import android.util.SparseBooleanArray;
@@ -69,6 +68,8 @@
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.settingslib.udfps.UdfpsOverlayParams;
+import com.android.settingslib.udfps.UdfpsUtils;
 import com.android.systemui.CoreStartable;
 import com.android.systemui.biometrics.domain.interactor.BiometricPromptCredentialInteractor;
 import com.android.systemui.biometrics.domain.interactor.LogContextInteractor;
@@ -169,6 +170,7 @@
     @NonNull private final UserManager mUserManager;
     @NonNull private final LockPatternUtils mLockPatternUtils;
     @NonNull private final InteractionJankMonitor mInteractionJankMonitor;
+    @NonNull private final UdfpsUtils mUdfpsUtils;
     private final @Background DelayableExecutor mBackgroundExecutor;
     private final DisplayInfo mCachedDisplayInfo = new DisplayInfo();
 
@@ -578,17 +580,7 @@
      */
     private void updateSensorLocations() {
         mDisplay.getDisplayInfo(mCachedDisplayInfo);
-        final Display.Mode maxDisplayMode =
-                DisplayUtils.getMaximumResolutionDisplayMode(mCachedDisplayInfo.supportedModes);
-        final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
-                maxDisplayMode.getPhysicalWidth(), maxDisplayMode.getPhysicalHeight(),
-                mCachedDisplayInfo.getNaturalWidth(), mCachedDisplayInfo.getNaturalHeight());
-        if (scaleFactor == Float.POSITIVE_INFINITY) {
-            mScaleFactor = 1f;
-        } else {
-            mScaleFactor = scaleFactor;
-        }
-
+        mScaleFactor = mUdfpsUtils.getScaleFactor(mCachedDisplayInfo);
         updateUdfpsLocation();
         updateFingerprintLocation();
         updateFaceLocation();
@@ -732,7 +724,8 @@
             @NonNull InteractionJankMonitor jankMonitor,
             @Main Handler handler,
             @Background DelayableExecutor bgExecutor,
-            @NonNull VibratorHelper vibrator) {
+            @NonNull VibratorHelper vibrator,
+            @NonNull UdfpsUtils udfpsUtils) {
         mContext = context;
         mExecution = execution;
         mUserManager = userManager;
@@ -753,6 +746,7 @@
         mSfpsEnrolledForUser = new SparseBooleanArray();
         mFaceEnrolledForUser = new SparseBooleanArray();
         mVibratorHelper = vibrator;
+        mUdfpsUtils = udfpsUtils;
 
         mLogContextInteractor = logContextInteractor;
         mBiometricPromptInteractor = biometricPromptInteractor;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 53ab6d6..58b230f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -88,6 +88,7 @@
         rippleShader.color = 0xffffffff.toInt() // default color
         rippleShader.rawProgress = 0f
         rippleShader.sparkleStrength = RIPPLE_SPARKLE_STRENGTH
+        setupRippleFadeParams()
         ripplePaint.shader = rippleShader
 
         dwellShader.color = 0xffffffff.toInt() // default color
@@ -294,7 +295,6 @@
             )
             addListener(object : AnimatorListenerAdapter() {
                 override fun onAnimationStart(animation: Animator?) {
-                    rippleShader.rippleFill = false
                     drawRipple = true
                     visibility = VISIBLE
                 }
@@ -339,6 +339,18 @@
         )
     }
 
+    private fun setupRippleFadeParams() {
+        with(rippleShader) {
+            baseRingFadeParams.fadeOutStart = RippleShader.DEFAULT_BASE_RING_FADE_OUT_START
+            baseRingFadeParams.fadeOutEnd = RippleShader.DEFAULT_FADE_OUT_END
+
+            centerFillFadeParams.fadeInStart = RippleShader.DEFAULT_FADE_IN_START
+            centerFillFadeParams.fadeInEnd = RippleShader.DEFAULT_CENTER_FILL_FADE_IN_END
+            centerFillFadeParams.fadeOutStart = RippleShader.DEFAULT_CENTER_FILL_FADE_OUT_START
+            centerFillFadeParams.fadeOutEnd = RippleShader.DEFAULT_CENTER_FILL_FADE_OUT_END
+        }
+    }
+
     override fun onDraw(canvas: Canvas?) {
         // To reduce overdraw, we mask the effect to a circle whose radius is big enough to cover
         // the active effect area. Values here should be kept in sync with the
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/EllipseOverlapDetectorParams.kt b/packages/SystemUI/src/com/android/systemui/biometrics/EllipseOverlapDetectorParams.kt
new file mode 100644
index 0000000..ab9b690
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/EllipseOverlapDetectorParams.kt
@@ -0,0 +1,13 @@
+package com.android.systemui.biometrics
+
+/**
+ * Collection of parameters used by EllipseOverlapDetector
+ *
+ * [minOverlap] minimum percentage (float from 0-1) needed to be considered a valid overlap
+ *
+ * [targetSize] percentage (defined as a float of 0-1) of sensor that is considered the target,
+ * expands outward from center
+ *
+ * [stepSize] size of each step when iterating over sensor pixel grid
+ */
+class EllipseOverlapDetectorParams(val minOverlap: Float, val targetSize: Float, val stepSize: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 7217f99..074928a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -50,10 +50,8 @@
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.util.Log;
-import android.util.RotationUtils;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
-import android.view.Surface;
 import android.view.VelocityTracker;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
@@ -66,6 +64,8 @@
 import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.FaceAuthApiRequestReason;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.settingslib.udfps.UdfpsOverlayParams;
+import com.android.settingslib.udfps.UdfpsUtils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.biometrics.dagger.BiometricsBackground;
@@ -168,6 +168,7 @@
     @NonNull private final SessionTracker mSessionTracker;
     @NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor;
     @NonNull private final SecureSettings mSecureSettings;
+    @NonNull private final UdfpsUtils mUdfpsUtils;
 
     // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
     // sensors, this, in addition to a lot of the code here, will be updated.
@@ -266,7 +267,7 @@
                             mUdfpsDisplayMode, mSecureSettings, requestId, reason, callback,
                             (view, event, fromUdfpsView) -> onTouch(requestId, event,
                                     fromUdfpsView), mActivityLaunchAnimator, mFeatureFlags,
-                            mPrimaryBouncerInteractor, mAlternateBouncerInteractor)));
+                            mPrimaryBouncerInteractor, mAlternateBouncerInteractor, mUdfpsUtils)));
         }
 
         @Override
@@ -475,27 +476,6 @@
                 && mOverlayParams.getSensorBounds().contains((int) x, (int) y);
     }
 
-    private Point getTouchInNativeCoordinates(@NonNull MotionEvent event, int idx) {
-        Point portraitTouch = new Point(
-                (int) event.getRawX(idx),
-                (int) event.getRawY(idx)
-        );
-        final int rot = mOverlayParams.getRotation();
-        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
-            RotationUtils.rotatePoint(portraitTouch,
-                    RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
-                    mOverlayParams.getLogicalDisplayWidth(),
-                    mOverlayParams.getLogicalDisplayHeight()
-            );
-        }
-
-        // Scale the coordinates to native resolution.
-        final float scale = mOverlayParams.getScaleFactor();
-        portraitTouch.x = (int) (portraitTouch.x / scale);
-        portraitTouch.y = (int) (portraitTouch.y / scale);
-        return portraitTouch;
-    }
-
     private void tryDismissingKeyguard() {
         if (!mOnFingerDown) {
             playStartHaptic();
@@ -557,7 +537,8 @@
         final InstanceId sessionIdProvider = mSessionTracker.getSessionId(
                 getBiometricSessionType());
         final int sessionId = (sessionIdProvider != null) ? sessionIdProvider.getId() : -1;
-        final int touchConfigId = BOUNDING_BOX_TOUCH_CONFIG_ID;
+        final int touchConfigId = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_selected_udfps_touch_detection);
 
         SysUiStatsLog.write(SysUiStatsLog.BIOMETRIC_TOUCH_REPORTED, biometricTouchReportedTouchType,
                 touchConfigId, sessionId, data.getX(), data.getY(), data.getMinor(),
@@ -712,7 +693,8 @@
                         break;
                     }
                     // Map the touch to portrait mode if the device is in landscape mode.
-                    final Point scaledTouch = getTouchInNativeCoordinates(event, idx);
+                    final Point scaledTouch = mUdfpsUtils.getTouchInNativeCoordinates(
+                            idx, event, mOverlayParams);
                     if (actionMoveWithinSensorArea) {
                         if (mVelocityTracker == null) {
                             // touches could be injected, so the velocity tracker may not have
@@ -756,16 +738,7 @@
                                         + "but serverRequest is null");
                                 return;
                             }
-                            // Scale the coordinates to native resolution.
-                            final float scale = mOverlayParams.getScaleFactor();
-                            final float scaledSensorX =
-                                    mOverlayParams.getSensorBounds().centerX() / scale;
-                            final float scaledSensorY =
-                                    mOverlayParams.getSensorBounds().centerY() / scale;
-
-                            mOverlay.onTouchOutsideOfSensorArea(
-                                    scaledTouch.x, scaledTouch.y, scaledSensorX, scaledSensorY,
-                                    mOverlayParams.getRotation());
+                            mOverlay.onTouchOutsideOfSensorArea(scaledTouch);
                         });
                     }
                 }
@@ -837,7 +810,8 @@
             @NonNull SinglePointerTouchProcessor singlePointerTouchProcessor,
             @NonNull SessionTracker sessionTracker,
             @NonNull AlternateBouncerInteractor alternateBouncerInteractor,
-            @NonNull SecureSettings secureSettings) {
+            @NonNull SecureSettings secureSettings,
+            @NonNull UdfpsUtils udfpsUtils) {
         mContext = context;
         mExecution = execution;
         mVibrator = vibrator;
@@ -879,6 +853,7 @@
         mPrimaryBouncerInteractor = primaryBouncerInteractor;
         mAlternateBouncerInteractor = alternateBouncerInteractor;
         mSecureSettings = secureSettings;
+        mUdfpsUtils = udfpsUtils;
 
         mTouchProcessor = mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
                 ? singlePointerTouchProcessor : null;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 6680787..55bacef 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -20,6 +20,7 @@
 import android.annotation.UiThread
 import android.content.Context
 import android.graphics.PixelFormat
+import android.graphics.Point
 import android.graphics.Rect
 import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP
 import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
@@ -46,6 +47,8 @@
 import androidx.annotation.LayoutRes
 import androidx.annotation.VisibleForTesting
 import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.settingslib.udfps.UdfpsUtils
+import com.android.settingslib.udfps.UdfpsOverlayParams
 import com.android.systemui.R
 import com.android.systemui.animation.ActivityLaunchAnimator
 import com.android.systemui.dump.DumpManager
@@ -101,6 +104,7 @@
         private val primaryBouncerInteractor: PrimaryBouncerInteractor,
         private val alternateBouncerInteractor: AlternateBouncerInteractor,
         private val isDebuggable: Boolean = Build.IS_DEBUGGABLE,
+        private val udfpsUtils: UdfpsUtils
 ) {
     /** The view, when [isShowing], or null. */
     var overlayView: UdfpsView? = null
@@ -239,7 +243,9 @@
                                 FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
                     // Enroll udfps UI is handled by settings, so use empty view here
                     UdfpsFpmEmptyViewController(
-                            view.addUdfpsView(R.layout.udfps_fpm_empty_view),
+                            view.addUdfpsView(R.layout.udfps_fpm_empty_view){
+                                updateAccessibilityViewLocation(sensorBounds)
+                            },
                             statusBarStateController,
                             shadeExpansionStateManager,
                             dialogManager,
@@ -348,81 +354,18 @@
      * the angle to a list of help messages which are announced if accessibility is enabled.
      *
      */
-    fun onTouchOutsideOfSensorArea(
-        touchX: Float,
-        touchY: Float,
-        sensorX: Float,
-        sensorY: Float,
-        rotation: Int
-    ) {
-
-        if (!touchExplorationEnabled) {
-            return
+    fun onTouchOutsideOfSensorArea(scaledTouch: Point) {
+        val theStr =
+            udfpsUtils.onTouchOutsideOfSensorArea(
+                touchExplorationEnabled,
+                context,
+                scaledTouch.x,
+                scaledTouch.y,
+                overlayParams
+            )
+        if (theStr != null) {
+            animationViewController?.doAnnounceForAccessibility(theStr)
         }
-        val touchHints =
-            context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
-        if (touchHints.size != 4) {
-            Log.e(TAG, "expected exactly 4 touch hints, got $touchHints.size?")
-            return
-        }
-        val theStr = onTouchOutsideOfSensorAreaImpl(touchX, touchY, sensorX, sensorY, rotation)
-        Log.v(TAG, "Announcing touch outside : " + theStr)
-        animationViewController?.doAnnounceForAccessibility(theStr)
-    }
-
-    /**
-     * This function computes the angle of touch relative to the sensor and maps
-     * the angle to a list of help messages which are announced if accessibility is enabled.
-     *
-     * There are 4 quadrants of the circle (90 degree arcs)
-     *
-     * [315, 360] && [0, 45) -> touchHints[0] = "Move Fingerprint to the left"
-     * [45,  135)            -> touchHints[1] = "Move Fingerprint down"
-     * And so on.
-     */
-    fun onTouchOutsideOfSensorAreaImpl(
-        touchX: Float,
-        touchY: Float,
-        sensorX: Float,
-        sensorY: Float,
-        rotation: Int
-    ): String {
-        val touchHints =
-            context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
-
-        val xRelativeToSensor = touchX - sensorX
-        // Touch coordinates are with respect to the upper left corner, so reverse
-        // this calculation
-        val yRelativeToSensor = sensorY - touchY
-
-        var angleInRad =
-            Math.atan2(yRelativeToSensor.toDouble(), xRelativeToSensor.toDouble())
-        // If the radians are negative, that means we are counting clockwise.
-        // So we need to add 360 degrees
-        if (angleInRad < 0.0) {
-            angleInRad += 2.0 * Math.PI
-        }
-        // rad to deg conversion
-        val degrees = Math.toDegrees(angleInRad)
-
-        val degreesPerBucket = 360.0 / touchHints.size
-        val halfBucketDegrees = degreesPerBucket / 2.0
-        // The mapping should be as follows
-        // [315, 360] && [0, 45] -> 0
-        // [45, 135]             -> 1
-        var index = (((degrees + halfBucketDegrees) % 360) / degreesPerBucket).toInt()
-        index %= touchHints.size
-
-        // A rotation of 90 degrees corresponds to increasing the index by 1.
-        if (rotation == Surface.ROTATION_90) {
-            index = (index + 1) % touchHints.size
-        }
-
-        if (rotation == Surface.ROTATION_270) {
-            index = (index + 3) % touchHints.size
-        }
-
-        return touchHints[index]
     }
 
     /** Cancel this request. */
@@ -442,7 +385,8 @@
     ): WindowManager.LayoutParams {
         val paddingX = animation?.paddingX ?: 0
         val paddingY = animation?.paddingY ?: 0
-        if (animation != null && animation.listenForTouchesOutsideView()) {
+        if (!featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION) && animation != null &&
+                animation.listenForTouchesOutsideView()) {
             flags = flags or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyView.kt
index e8f041e..8352d0a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyView.kt
@@ -16,7 +16,11 @@
 package com.android.systemui.biometrics
 
 import android.content.Context
+import android.graphics.Rect
 import android.util.AttributeSet
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.R
 
 /**
  * View corresponding with udfps_fpm_empty_view.xml
@@ -32,4 +36,13 @@
     private val fingerprintDrawable: UdfpsFpDrawable = UdfpsFpDrawable(context)
 
     override fun getDrawable(): UdfpsDrawable = fingerprintDrawable
+
+    fun updateAccessibilityViewLocation(sensorBounds: Rect) {
+        val fingerprintAccessibilityView: View = findViewById(R.id.udfps_enroll_accessibility_view)
+        val params: ViewGroup.LayoutParams = fingerprintAccessibilityView.layoutParams
+        params.width = sensorBounds.width()
+        params.height = sensorBounds.height()
+        fingerprintAccessibilityView.layoutParams = params
+        fingerprintAccessibilityView.requestLayout()
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlay.kt
index 802b9b6..079c0b3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlay.kt
@@ -32,6 +32,7 @@
 import android.view.WindowManager
 import android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY
 import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.settingslib.udfps.UdfpsOverlayParams
 import com.android.systemui.CoreStartable
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayView.kt
index 4e6a06b..28ca41d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayView.kt
@@ -25,6 +25,7 @@
 import android.util.AttributeSet
 import android.view.MotionEvent
 import android.widget.FrameLayout
+import com.android.settingslib.udfps.UdfpsOverlayParams
 
 private const val TAG = "UdfpsOverlayView"
 private const val POINT_SIZE = 10f
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
index e61c614..06dee7a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
@@ -26,6 +26,7 @@
 import android.util.Log
 import android.view.MotionEvent
 import android.widget.FrameLayout
+import com.android.settingslib.udfps.UdfpsOverlayParams
 import com.android.systemui.R
 import com.android.systemui.doze.DozeReceiver
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
index 6f8efba..67d2f30 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.biometrics.dagger
 
+import com.android.settingslib.udfps.UdfpsUtils
 import com.android.systemui.biometrics.data.repository.PromptRepository
 import com.android.systemui.biometrics.data.repository.PromptRepositoryImpl
 import com.android.systemui.biometrics.domain.interactor.CredentialInteractor
@@ -54,6 +55,9 @@
         @BiometricsBackground
         fun providesPluginExecutor(threadFactory: ThreadFactory): Executor =
             threadFactory.buildExecutorOnNewThread("biometrics")
+
+        @Provides
+        fun providesUdfpsUtils(): UdfpsUtils = UdfpsUtils()
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/UdfpsModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/UdfpsModule.kt
index 001fed7..20c3e40 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/UdfpsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/UdfpsModule.kt
@@ -16,6 +16,9 @@
 
 package com.android.systemui.biometrics.dagger
 
+import android.content.res.Resources
+import com.android.internal.R
+import com.android.systemui.biometrics.EllipseOverlapDetectorParams
 import com.android.systemui.biometrics.udfps.BoundingBoxOverlapDetector
 import com.android.systemui.biometrics.udfps.EllipseOverlapDetector
 import com.android.systemui.biometrics.udfps.OverlapDetector
@@ -33,10 +36,30 @@
         @Provides
         @SysUISingleton
         fun providesOverlapDetector(featureFlags: FeatureFlags): OverlapDetector {
-            return if (featureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
-                EllipseOverlapDetector()
+            if (featureFlags.isEnabled(Flags.UDFPS_ELLIPSE_DETECTION)) {
+                val selectedOption =
+                    Resources.getSystem()
+                        .getInteger(R.integer.config_selected_udfps_touch_detection)
+                val values =
+                    Resources.getSystem()
+                        .getStringArray(R.array.config_udfps_touch_detection_options)[
+                            selectedOption]
+                        .split(",")
+                        .map { it.toFloat() }
+
+                return if (values[0] == 1f) {
+                    EllipseOverlapDetector(
+                        EllipseOverlapDetectorParams(
+                            minOverlap = values[3],
+                            targetSize = values[2],
+                            stepSize = values[4].toInt()
+                        )
+                    )
+                } else {
+                    BoundingBoxOverlapDetector()
+                }
             } else {
-                BoundingBoxOverlapDetector()
+                return BoundingBoxOverlapDetector()
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
index 682d38a..2e2970f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
@@ -18,22 +18,84 @@
 
 import android.graphics.Point
 import android.graphics.Rect
-import androidx.annotation.VisibleForTesting
+import android.util.Log
+import com.android.systemui.biometrics.EllipseOverlapDetectorParams
 import com.android.systemui.dagger.SysUISingleton
 import kotlin.math.cos
-import kotlin.math.pow
 import kotlin.math.sin
 
+private enum class SensorPixelPosition {
+    OUTSIDE, // Pixel that falls outside of sensor circle
+    SENSOR, // Pixel within sensor circle
+    TARGET // Pixel within sensor center target
+}
+
+private val isDebug = true
+private val TAG = "EllipseOverlapDetector"
+
 /**
  * Approximates the touch as an ellipse and determines whether the ellipse has a sufficient overlap
  * with the sensor.
  */
 @SysUISingleton
-class EllipseOverlapDetector(private val neededPoints: Int = 2) : OverlapDetector {
-
+class EllipseOverlapDetector(private val params: EllipseOverlapDetectorParams) : OverlapDetector {
     override fun isGoodOverlap(touchData: NormalizedTouchData, nativeSensorBounds: Rect): Boolean {
-        val points = calculateSensorPoints(nativeSensorBounds)
-        return points.count { checkPoint(it, touchData) } >= neededPoints
+        var isTargetTouched = false
+        var sensorPixels = 0
+        var coveredPixels = 0
+        for (y in nativeSensorBounds.top..nativeSensorBounds.bottom step params.stepSize) {
+            for (x in nativeSensorBounds.left..nativeSensorBounds.right step params.stepSize) {
+                // Check where pixel is within the sensor TODO: (b/265836919) This could be improved
+                // by precomputing these points
+                val pixelPosition =
+                    isPartOfSensorArea(
+                        x,
+                        y,
+                        nativeSensorBounds.centerX(),
+                        nativeSensorBounds.centerY(),
+                        nativeSensorBounds.width() / 2
+                    )
+                if (pixelPosition != SensorPixelPosition.OUTSIDE) {
+                    sensorPixels++
+
+                    // Check if this pixel falls within ellipse touch
+                    if (checkPoint(Point(x, y), touchData)) {
+                        coveredPixels++
+
+                        // Check that at least one covered pixel is within sensor target
+                        isTargetTouched =
+                            isTargetTouched or (pixelPosition == SensorPixelPosition.TARGET)
+                    }
+                }
+            }
+        }
+
+        val percentage: Float = coveredPixels.toFloat() / sensorPixels
+        if (isDebug) {
+            Log.v(
+                TAG,
+                "covered: $coveredPixels, sensor: $sensorPixels, " +
+                    "percentage: $percentage, isCenterTouched: $isTargetTouched"
+            )
+        }
+
+        return percentage >= params.minOverlap && isTargetTouched
+    }
+
+    /** Checks if point is in the sensor center target circle, outer circle, or outside of sensor */
+    private fun isPartOfSensorArea(x: Int, y: Int, cX: Int, cY: Int, r: Int): SensorPixelPosition {
+        val dx = cX - x
+        val dy = cY - y
+
+        val disSquared = dx * dx + dy * dy
+
+        return if (disSquared <= (r * params.targetSize) * (r * params.targetSize)) {
+            SensorPixelPosition.TARGET
+        } else if (disSquared <= r * r) {
+            SensorPixelPosition.SENSOR
+        } else {
+            SensorPixelPosition.OUTSIDE
+        }
     }
 
     private fun checkPoint(point: Point, touchData: NormalizedTouchData): Boolean {
@@ -45,29 +107,9 @@
         val c: Float = sin(touchData.orientation) * (point.x - touchData.x)
         val d: Float = cos(touchData.orientation) * (point.y - touchData.y)
         val result =
-            (a + b).pow(2) / (touchData.minor / 2).pow(2) +
-                (c - d).pow(2) / (touchData.major / 2).pow(2)
+            (a + b) * (a + b) / ((touchData.minor / 2) * (touchData.minor / 2)) +
+                (c - d) * (c - d) / ((touchData.major / 2) * (touchData.major / 2))
 
         return result <= 1
     }
-
-    @VisibleForTesting
-    fun calculateSensorPoints(sensorBounds: Rect): List<Point> {
-        val sensorX = sensorBounds.centerX()
-        val sensorY = sensorBounds.centerY()
-        val cornerOffset: Int = sensorBounds.width() / 4
-        val sideOffset: Int = sensorBounds.width() / 3
-
-        return listOf(
-            Point(sensorX - cornerOffset, sensorY - cornerOffset),
-            Point(sensorX, sensorY - sideOffset),
-            Point(sensorX + cornerOffset, sensorY - cornerOffset),
-            Point(sensorX - sideOffset, sensorY),
-            Point(sensorX, sensorY),
-            Point(sensorX + sideOffset, sensorY),
-            Point(sensorX - cornerOffset, sensorY + cornerOffset),
-            Point(sensorX, sensorY + sideOffset),
-            Point(sensorX + cornerOffset, sensorY + cornerOffset)
-        )
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt
index 39ea936..234b383 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessor.kt
@@ -21,7 +21,7 @@
 import android.view.MotionEvent
 import android.view.MotionEvent.INVALID_POINTER_ID
 import android.view.Surface
-import com.android.systemui.biometrics.UdfpsOverlayParams
+import com.android.settingslib.udfps.UdfpsOverlayParams
 import com.android.systemui.biometrics.udfps.TouchProcessorResult.Failure
 import com.android.systemui.biometrics.udfps.TouchProcessorResult.ProcessedTouch
 import com.android.systemui.dagger.SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/TouchProcessor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/TouchProcessor.kt
index ffcebf9..4bf0ef6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/TouchProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/TouchProcessor.kt
@@ -17,7 +17,7 @@
 package com.android.systemui.biometrics.udfps
 
 import android.view.MotionEvent
-import com.android.systemui.biometrics.UdfpsOverlayParams
+import com.android.settingslib.udfps.UdfpsOverlayParams
 
 /**
  * Determines whether a finger entered or left the area of the under-display fingerprint sensor
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt b/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
index fb0c0a6..5ca36ab 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
@@ -72,7 +72,7 @@
         height = WindowManager.LayoutParams.MATCH_PARENT
         layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
         format = PixelFormat.TRANSLUCENT
-        type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY
+        type = WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
         fitInsetsTypes = 0 // Ignore insets from all system bars
         title = "Wired Charging Animation"
         flags = (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
index 1c26841..82bb723 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
@@ -21,6 +21,7 @@
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN;
+import static com.android.systemui.flags.Flags.CLIPBOARD_MINIMIZED_LAYOUT;
 
 import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE;
 
@@ -35,6 +36,7 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.CoreStartable;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.flags.FeatureFlags;
 
 import javax.inject.Inject;
 import javax.inject.Provider;
@@ -57,6 +59,7 @@
     private final Provider<ClipboardOverlayController> mOverlayProvider;
     private final ClipboardToast mClipboardToast;
     private final ClipboardManager mClipboardManager;
+    private final FeatureFlags mFeatureFlags;
     private final UiEventLogger mUiEventLogger;
     private ClipboardOverlay mClipboardOverlay;
 
@@ -65,11 +68,13 @@
             Provider<ClipboardOverlayController> clipboardOverlayControllerProvider,
             ClipboardToast clipboardToast,
             ClipboardManager clipboardManager,
+            FeatureFlags featureFlags,
             UiEventLogger uiEventLogger) {
         mContext = context;
         mOverlayProvider = clipboardOverlayControllerProvider;
         mClipboardToast = clipboardToast;
         mClipboardManager = clipboardManager;
+        mFeatureFlags = featureFlags;
         mUiEventLogger = uiEventLogger;
     }
 
@@ -107,7 +112,11 @@
         } else {
             mUiEventLogger.log(CLIPBOARD_OVERLAY_UPDATED, 0, clipSource);
         }
-        mClipboardOverlay.setClipData(clipData, clipSource);
+        if (mFeatureFlags.isEnabled(CLIPBOARD_MINIMIZED_LAYOUT)) {
+            mClipboardOverlay.setClipData(clipData, clipSource);
+        } else {
+            mClipboardOverlay.setClipDataLegacy(clipData, clipSource);
+        }
         mClipboardOverlay.setOnSessionCompleteListener(() -> {
             // Session is complete, free memory until it's needed again.
             mClipboardOverlay = null;
@@ -150,6 +159,8 @@
     }
 
     interface ClipboardOverlay {
+        void setClipDataLegacy(ClipData clipData, String clipSource);
+
         void setClipData(ClipData clipData, String clipSource);
 
         void setOnSessionCompleteListener(Runnable runnable);
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardModel.kt b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardModel.kt
new file mode 100644
index 0000000..c7aaf09
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardModel.kt
@@ -0,0 +1,101 @@
+/*
+ * 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.clipboardoverlay
+
+import android.content.ClipData
+import android.content.ClipDescription.EXTRA_IS_SENSITIVE
+import android.content.Context
+import android.graphics.Bitmap
+import android.text.TextUtils
+import android.util.Log
+import android.util.Size
+import com.android.systemui.R
+import java.io.IOException
+
+data class ClipboardModel(
+    val clipData: ClipData?,
+    val source: String,
+    val type: Type = Type.OTHER,
+    val item: ClipData.Item? = null,
+    val isSensitive: Boolean = false,
+    val isRemote: Boolean = false,
+) {
+    private var _bitmap: Bitmap? = null
+
+    fun dataMatches(other: ClipboardModel?): Boolean {
+        if (other == null) {
+            return false
+        }
+        return source == other.source &&
+            type == other.type &&
+            item?.text == other.item?.text &&
+            item?.uri == other.item?.uri &&
+            isSensitive == other.isSensitive
+    }
+
+    fun loadThumbnail(context: Context): Bitmap? {
+        if (_bitmap == null && type == Type.IMAGE && item?.uri != null) {
+            try {
+                val size = context.resources.getDimensionPixelSize(R.dimen.overlay_x_scale)
+                _bitmap =
+                    context.contentResolver.loadThumbnail(item.uri, Size(size, size * 4), null)
+            } catch (e: IOException) {
+                Log.e(TAG, "Thumbnail loading failed!", e)
+            }
+        }
+        return _bitmap
+    }
+
+    internal companion object {
+        private val TAG: String = "ClipboardModel"
+
+        @JvmStatic
+        fun fromClipData(
+            context: Context,
+            utils: ClipboardOverlayUtils,
+            clipData: ClipData?,
+            source: String
+        ): ClipboardModel {
+            if (clipData == null || clipData.itemCount == 0) {
+                return ClipboardModel(clipData, source)
+            }
+            val sensitive = clipData.description?.extras?.getBoolean(EXTRA_IS_SENSITIVE) ?: false
+            val item = clipData.getItemAt(0)!!
+            val type = getType(context, item)
+            val remote = utils.isRemoteCopy(context, clipData, source)
+            return ClipboardModel(clipData, source, type, item, sensitive, remote)
+        }
+
+        private fun getType(context: Context, item: ClipData.Item): Type {
+            return if (!TextUtils.isEmpty(item.text)) {
+                Type.TEXT
+            } else if (
+                item.uri != null &&
+                    context.contentResolver.getType(item.uri)?.startsWith("image") == true
+            ) {
+                Type.IMAGE
+            } else {
+                Type.OTHER
+            }
+        }
+    }
+
+    enum class Type {
+        TEXT,
+        IMAGE,
+        OTHER
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index 8c8ee8a..b41f308 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -17,7 +17,6 @@
 package com.android.systemui.clipboardoverlay;
 
 import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
-import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_ACTIONS;
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON;
@@ -31,10 +30,9 @@
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TAP_OUTSIDE;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TIMED_OUT;
+import static com.android.systemui.flags.Flags.CLIPBOARD_MINIMIZED_LAYOUT;
 import static com.android.systemui.flags.Flags.CLIPBOARD_REMOTE_BEHAVIOR;
 
-import static java.util.Objects.requireNonNull;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.app.RemoteAction;
@@ -47,7 +45,6 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
-import android.hardware.display.DisplayManager;
 import android.hardware.input.InputManager;
 import android.net.Uri;
 import android.os.Looper;
@@ -55,14 +52,15 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Size;
-import android.view.Display;
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
 import android.view.InputMonitor;
 import android.view.MotionEvent;
+import android.view.WindowInsets;
 
 import androidx.annotation.NonNull;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -71,7 +69,6 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.screenshot.TimeoutHandler;
-import com.android.systemui.settings.DisplayTracker;
 
 import java.io.IOException;
 import java.util.Optional;
@@ -95,8 +92,6 @@
     private final Context mContext;
     private final ClipboardLogger mClipboardLogger;
     private final BroadcastDispatcher mBroadcastDispatcher;
-    private final DisplayManager mDisplayManager;
-    private final DisplayTracker mDisplayTracker;
     private final ClipboardOverlayWindow mWindow;
     private final TimeoutHandler mTimeoutHandler;
     private final ClipboardOverlayUtils mClipboardUtils;
@@ -122,6 +117,9 @@
 
     private Runnable mOnUiUpdate;
 
+    private boolean mIsMinimized;
+    private ClipboardModel mClipboardModel;
+
     private final ClipboardOverlayView.ClipboardOverlayCallbacks mClipboardCallbacks =
             new ClipboardOverlayView.ClipboardOverlayCallbacks() {
                 @Override
@@ -175,6 +173,13 @@
                     mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISS_TAPPED);
                     animateOut();
                 }
+
+                @Override
+                public void onMinimizedViewTapped() {
+                    if (mFeatureFlags.isEnabled(CLIPBOARD_MINIMIZED_LAYOUT)) {
+                        animateFromMinimized();
+                    }
+                }
             };
 
     @Inject
@@ -187,33 +192,28 @@
             FeatureFlags featureFlags,
             ClipboardOverlayUtils clipboardUtils,
             @Background Executor bgExecutor,
-            UiEventLogger uiEventLogger,
-            DisplayTracker displayTracker) {
+            UiEventLogger uiEventLogger) {
+        mContext = context;
         mBroadcastDispatcher = broadcastDispatcher;
-        mDisplayManager = requireNonNull(context.getSystemService(DisplayManager.class));
-        mDisplayTracker = displayTracker;
-        final Context displayContext = context.createDisplayContext(getDefaultDisplay());
-        mContext = displayContext.createWindowContext(TYPE_SCREENSHOT, null);
 
         mClipboardLogger = new ClipboardLogger(uiEventLogger);
 
         mView = clipboardOverlayView;
         mWindow = clipboardOverlayWindow;
-        mWindow.init(mView::setInsets, () -> {
+        mWindow.init(this::onInsetsChanged, () -> {
             mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
             hideImmediate();
         });
 
+        mFeatureFlags = featureFlags;
         mTimeoutHandler = timeoutHandler;
         mTimeoutHandler.setDefaultTimeoutMillis(CLIPBOARD_DEFAULT_TIMEOUT_MILLIS);
 
-        mFeatureFlags = featureFlags;
         mClipboardUtils = clipboardUtils;
         mBgExecutor = bgExecutor;
 
         mView.setCallbacks(mClipboardCallbacks);
 
-
         mWindow.withWindowAttached(() -> {
             mWindow.setContentView(mView);
             mView.setInsets(mWindow.getWindowInsets(),
@@ -258,8 +258,135 @@
         broadcastSender.sendBroadcast(copyIntent, SELF_PERMISSION);
     }
 
+    @VisibleForTesting
+    void onInsetsChanged(WindowInsets insets, int orientation) {
+        mView.setInsets(insets, orientation);
+        if (mFeatureFlags.isEnabled(CLIPBOARD_MINIMIZED_LAYOUT)) {
+            if (shouldShowMinimized(insets) && !mIsMinimized) {
+                mIsMinimized = true;
+                mView.setMinimized(true);
+            }
+        }
+    }
+
     @Override // ClipboardListener.ClipboardOverlay
-    public void setClipData(ClipData clipData, String clipSource) {
+    public void setClipData(ClipData data, String source) {
+        ClipboardModel model = ClipboardModel.fromClipData(mContext, mClipboardUtils, data, source);
+        if (mExitAnimator != null && mExitAnimator.isRunning()) {
+            mExitAnimator.cancel();
+        }
+        boolean shouldAnimate = !model.dataMatches(mClipboardModel);
+        mClipboardModel = model;
+        mClipboardLogger.setClipSource(mClipboardModel.getSource());
+        if (shouldAnimate) {
+            reset();
+            mClipboardLogger.setClipSource(mClipboardModel.getSource());
+            if (shouldShowMinimized(mWindow.getWindowInsets())) {
+                mIsMinimized = true;
+                mView.setMinimized(true);
+            } else {
+                setExpandedView();
+            }
+            animateIn();
+            mView.announceForAccessibility(getAccessibilityAnnouncement(mClipboardModel.getType()));
+        } else if (!mIsMinimized) {
+            setExpandedView();
+        }
+        if (mFeatureFlags.isEnabled(CLIPBOARD_REMOTE_BEHAVIOR) && mClipboardModel.isRemote()) {
+            mTimeoutHandler.cancelTimeout();
+            mOnUiUpdate = null;
+        } else {
+            mOnUiUpdate = mTimeoutHandler::resetTimeout;
+            mOnUiUpdate.run();
+        }
+    }
+
+    private void setExpandedView() {
+        final ClipboardModel model = mClipboardModel;
+        mView.setMinimized(false);
+        switch (model.getType()) {
+            case TEXT:
+                if ((mFeatureFlags.isEnabled(CLIPBOARD_REMOTE_BEHAVIOR) && model.isRemote())
+                        || DeviceConfig.getBoolean(
+                        DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_SHOW_ACTIONS, false)) {
+                    if (model.getItem().getTextLinks() != null) {
+                        classifyText(model);
+                    }
+                }
+                if (model.isSensitive()) {
+                    mView.showTextPreview(mContext.getString(R.string.clipboard_asterisks), true);
+                } else {
+                    mView.showTextPreview(model.getItem().getText(), false);
+                }
+                mView.setEditAccessibilityAction(true);
+                mOnPreviewTapped = this::editText;
+                break;
+            case IMAGE:
+                if (model.isSensitive() || model.loadThumbnail(mContext) != null) {
+                    mView.showImagePreview(
+                            model.isSensitive() ? null : model.loadThumbnail(mContext));
+                    mView.setEditAccessibilityAction(true);
+                    mOnPreviewTapped = () -> editImage(model.getItem().getUri());
+                } else {
+                    // image loading failed
+                    mView.showDefaultTextPreview();
+                }
+                break;
+            case OTHER:
+                mView.showDefaultTextPreview();
+                break;
+        }
+        if (mFeatureFlags.isEnabled(CLIPBOARD_REMOTE_BEHAVIOR)) {
+            if (!model.isRemote()) {
+                maybeShowRemoteCopy(model.getClipData());
+            }
+        } else {
+            maybeShowRemoteCopy(model.getClipData());
+        }
+        if (model.getType() != ClipboardModel.Type.OTHER) {
+            mOnShareTapped = () -> shareContent(model.getClipData());
+            mView.showShareChip();
+        }
+    }
+
+    private boolean shouldShowMinimized(WindowInsets insets) {
+        return insets.getInsets(WindowInsets.Type.ime()).bottom > 0;
+    }
+
+    private void animateFromMinimized() {
+        mIsMinimized = false;
+        setExpandedView();
+        animateIn();
+    }
+
+    private String getAccessibilityAnnouncement(ClipboardModel.Type type) {
+        if (type == ClipboardModel.Type.TEXT) {
+            return mContext.getString(R.string.clipboard_text_copied);
+        } else if (type == ClipboardModel.Type.IMAGE) {
+            return mContext.getString(R.string.clipboard_image_copied);
+        } else {
+            return mContext.getString(R.string.clipboard_content_copied);
+        }
+    }
+
+    private void classifyText(ClipboardModel model) {
+        mBgExecutor.execute(() -> {
+            Optional<RemoteAction> remoteAction =
+                    mClipboardUtils.getAction(model.getItem(), model.getSource());
+            if (model.equals(mClipboardModel)) {
+                remoteAction.ifPresent(action -> {
+                    mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_ACTION_SHOWN);
+                    mView.setActionChip(action, () -> {
+                        mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED);
+                        animateOut();
+                    });
+                });
+            }
+        });
+    }
+
+    @Override // ClipboardListener.ClipboardOverlay
+    public void setClipDataLegacy(ClipData clipData, String clipSource) {
         if (mExitAnimator != null && mExitAnimator.isRunning()) {
             mExitAnimator.cancel();
         }
@@ -516,10 +643,6 @@
         mClipboardLogger.reset();
     }
 
-    private Display getDefaultDisplay() {
-        return mDisplayManager.getDisplay(mDisplayTracker.getDefaultDisplayId());
-    }
-
     static class ClipboardLogger {
         private final UiEventLogger mUiEventLogger;
         private String mClipSource;
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
index 2d33157..c9e01ce 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
@@ -18,8 +18,6 @@
 
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 
-import static java.util.Objects.requireNonNull;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -77,6 +75,8 @@
         void onShareButtonTapped();
 
         void onPreviewTapped();
+
+        void onMinimizedViewTapped();
     }
 
     private static final String TAG = "ClipboardView";
@@ -92,6 +92,7 @@
     private ImageView mImagePreview;
     private TextView mTextPreview;
     private TextView mHiddenPreview;
+    private LinearLayout mMinimizedPreview;
     private View mPreviewBorder;
     private OverlayActionChip mEditChip;
     private OverlayActionChip mShareChip;
@@ -117,18 +118,18 @@
 
     @Override
     protected void onFinishInflate() {
-        mActionContainerBackground =
-                requireNonNull(findViewById(R.id.actions_container_background));
-        mActionContainer = requireNonNull(findViewById(R.id.actions));
-        mClipboardPreview = requireNonNull(findViewById(R.id.clipboard_preview));
-        mImagePreview = requireNonNull(findViewById(R.id.image_preview));
-        mTextPreview = requireNonNull(findViewById(R.id.text_preview));
-        mHiddenPreview = requireNonNull(findViewById(R.id.hidden_preview));
-        mPreviewBorder = requireNonNull(findViewById(R.id.preview_border));
-        mEditChip = requireNonNull(findViewById(R.id.edit_chip));
-        mShareChip = requireNonNull(findViewById(R.id.share_chip));
-        mRemoteCopyChip = requireNonNull(findViewById(R.id.remote_copy_chip));
-        mDismissButton = requireNonNull(findViewById(R.id.dismiss_button));
+        mActionContainerBackground = requireViewById(R.id.actions_container_background);
+        mActionContainer = requireViewById(R.id.actions);
+        mClipboardPreview = requireViewById(R.id.clipboard_preview);
+        mPreviewBorder = requireViewById(R.id.preview_border);
+        mImagePreview = requireViewById(R.id.image_preview);
+        mTextPreview = requireViewById(R.id.text_preview);
+        mHiddenPreview = requireViewById(R.id.hidden_preview);
+        mMinimizedPreview = requireViewById(R.id.minimized_preview);
+        mEditChip = requireViewById(R.id.edit_chip);
+        mShareChip = requireViewById(R.id.share_chip);
+        mRemoteCopyChip = requireViewById(R.id.remote_copy_chip);
+        mDismissButton = requireViewById(R.id.dismiss_button);
 
         mEditChip.setAlpha(1);
         mShareChip.setAlpha(1);
@@ -163,6 +164,7 @@
         mDismissButton.setOnClickListener(v -> clipboardCallbacks.onDismissButtonTapped());
         mRemoteCopyChip.setOnClickListener(v -> clipboardCallbacks.onRemoteCopyButtonTapped());
         mClipboardPreview.setOnClickListener(v -> clipboardCallbacks.onPreviewTapped());
+        mMinimizedPreview.setOnClickListener(v -> clipboardCallbacks.onMinimizedViewTapped());
     }
 
     void setEditAccessibilityAction(boolean editable) {
@@ -177,12 +179,28 @@
         }
     }
 
+    void setMinimized(boolean minimized) {
+        if (minimized) {
+            mMinimizedPreview.setVisibility(View.VISIBLE);
+            mClipboardPreview.setVisibility(View.GONE);
+            mPreviewBorder.setVisibility(View.GONE);
+            mActionContainer.setVisibility(View.GONE);
+            mActionContainerBackground.setVisibility(View.GONE);
+        } else {
+            mMinimizedPreview.setVisibility(View.GONE);
+            mClipboardPreview.setVisibility(View.VISIBLE);
+            mPreviewBorder.setVisibility(View.VISIBLE);
+            mActionContainer.setVisibility(View.VISIBLE);
+        }
+    }
+
     void setInsets(WindowInsets insets, int orientation) {
         FrameLayout.LayoutParams p = (FrameLayout.LayoutParams) getLayoutParams();
         if (p == null) {
             return;
         }
         Rect margins = computeMargins(insets, orientation);
+
         p.setMargins(margins.left, margins.top, margins.right, margins.bottom);
         setLayoutParams(p);
         requestLayout();
@@ -204,6 +222,12 @@
                 (int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP));
         touchRegion.op(tmpRect, Region.Op.UNION);
 
+        mMinimizedPreview.getBoundsOnScreen(tmpRect);
+        tmpRect.inset(
+                (int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP),
+                (int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP));
+        touchRegion.op(tmpRect, Region.Op.UNION);
+
         mDismissButton.getBoundsOnScreen(tmpRect);
         touchRegion.op(tmpRect, Region.Op.UNION);
 
@@ -298,6 +322,8 @@
         scaleAnim.setDuration(333);
         scaleAnim.addUpdateListener(animation -> {
             float previewScale = MathUtils.lerp(.9f, 1f, animation.getAnimatedFraction());
+            mMinimizedPreview.setScaleX(previewScale);
+            mMinimizedPreview.setScaleY(previewScale);
             mClipboardPreview.setScaleX(previewScale);
             mClipboardPreview.setScaleY(previewScale);
             mPreviewBorder.setScaleX(previewScale);
@@ -319,12 +345,14 @@
         alphaAnim.setDuration(283);
         alphaAnim.addUpdateListener(animation -> {
             float alpha = animation.getAnimatedFraction();
+            mMinimizedPreview.setAlpha(alpha);
             mClipboardPreview.setAlpha(alpha);
             mPreviewBorder.setAlpha(alpha);
             mDismissButton.setAlpha(alpha);
             mActionContainer.setAlpha(alpha);
         });
 
+        mMinimizedPreview.setAlpha(0);
         mActionContainer.setAlpha(0);
         mPreviewBorder.setAlpha(0);
         mClipboardPreview.setAlpha(0);
@@ -356,6 +384,8 @@
         scaleAnim.setDuration(250);
         scaleAnim.addUpdateListener(animation -> {
             float previewScale = MathUtils.lerp(1f, .9f, animation.getAnimatedFraction());
+            mMinimizedPreview.setScaleX(previewScale);
+            mMinimizedPreview.setScaleY(previewScale);
             mClipboardPreview.setScaleX(previewScale);
             mClipboardPreview.setScaleY(previewScale);
             mPreviewBorder.setScaleX(previewScale);
@@ -377,6 +407,7 @@
         alphaAnim.setDuration(166);
         alphaAnim.addUpdateListener(animation -> {
             float alpha = 1 - animation.getAnimatedFraction();
+            mMinimizedPreview.setAlpha(alpha);
             mClipboardPreview.setAlpha(alpha);
             mPreviewBorder.setAlpha(alpha);
             mDismissButton.setAlpha(alpha);
@@ -399,6 +430,7 @@
         mTextPreview.setVisibility(View.GONE);
         mImagePreview.setVisibility(View.GONE);
         mHiddenPreview.setVisibility(View.GONE);
+        mMinimizedPreview.setVisibility(View.GONE);
         v.setVisibility(View.VISIBLE);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/CoroutineResult.kt b/packages/SystemUI/src/com/android/systemui/common/coroutine/CoroutineResult.kt
new file mode 100644
index 0000000..b973667
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/coroutine/CoroutineResult.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.common.coroutine
+
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.TimeoutCancellationException
+import kotlinx.coroutines.currentCoroutineContext
+import kotlinx.coroutines.ensureActive
+import kotlinx.coroutines.withTimeout
+
+/**
+ * Calls the specified function [block] and returns its encapsulated result if invocation was
+ * successful, catching any [Throwable] exception that was thrown from the block function execution
+ * and encapsulating it as a failure.
+ *
+ * Unlike [runCatching], [suspendRunCatching] does not break structured concurrency by rethrowing
+ * any [CancellationException].
+ *
+ * **Heads-up:** [TimeoutCancellationException] extends [CancellationException] but catching it does
+ * not breaks structured concurrency and therefore, will not be rethrown. Therefore, you can use
+ * [suspendRunCatching] with [withTimeout], and handle any timeout gracefully.
+ *
+ * @see <a href="https://github.com/Kotlin/kotlinx.coroutines/issues/1814">link</a>
+ */
+suspend inline fun <T> suspendRunCatching(crossinline block: suspend () -> T): Result<T> =
+    try {
+        Result.success(block())
+    } catch (e: Throwable) {
+        // Ensures the try-catch block will not break structured concurrency.
+        currentCoroutineContext().ensureActive()
+        Result.failure(e)
+    }
+
+/**
+ * Calls the specified function [block] and returns its encapsulated result if invocation was
+ * successful, catching any [Throwable] exception that was thrown from the block function execution
+ * and encapsulating it as a failure.
+ *
+ * Unlike [runCatching], [suspendRunCatching] does not break structured concurrency by rethrowing
+ * any [CancellationException].
+ *
+ * **Heads-up:** [TimeoutCancellationException] extends [CancellationException] but catching it does
+ * not breaks structured concurrency and therefore, will not be rethrown. Therefore, you can use
+ * [suspendRunCatching] with [withTimeout], and handle any timeout gracefully.
+ *
+ * @see <a href="https://github.com/Kotlin/kotlinx.coroutines/issues/1814">link</a>
+ */
+suspend inline fun <T, R> T.suspendRunCatching(crossinline block: suspend T.() -> R): Result<R> =
+    // Overload with a `this` receiver, matches with `kotlin.runCatching` functions.
+    // Qualified name needs to be used to avoid a recursive call.
+    com.android.systemui.common.coroutine.suspendRunCatching { block(this) }
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
new file mode 100644
index 0000000..ae6a08f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
@@ -0,0 +1,185 @@
+/*
+ * 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.common.ui.view;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+
+import com.android.systemui.R;
+
+/**
+ * The layout contains a seekbar whose progress could be modified
+ * through the icons on two ends of the seekbar.
+ */
+public class SeekBarWithIconButtonsView extends LinearLayout {
+
+    private static final int DEFAULT_SEEKBAR_MAX = 6;
+    private static final int DEFAULT_SEEKBAR_PROGRESS = 0;
+
+    private ImageView mIconStart;
+    private ImageView mIconEnd;
+    private SeekBar mSeekbar;
+
+    private SeekBarChangeListener mSeekBarListener = new SeekBarChangeListener();
+
+    public SeekBarWithIconButtonsView(Context context) {
+        this(context, null);
+    }
+
+    public SeekBarWithIconButtonsView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SeekBarWithIconButtonsView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public SeekBarWithIconButtonsView(Context context,
+            AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        LayoutInflater.from(context).inflate(
+                R.layout.seekbar_with_icon_buttons, this, /* attachToRoot= */ true);
+
+        mIconStart = findViewById(R.id.icon_start);
+        mIconEnd = findViewById(R.id.icon_end);
+        mSeekbar = findViewById(R.id.seekbar);
+
+        if (attrs != null) {
+            TypedArray typedArray = context.obtainStyledAttributes(
+                    attrs,
+                    R.styleable.SeekBarWithIconButtonsView_Layout,
+                    defStyleAttr, defStyleRes
+            );
+            int max = typedArray.getInt(
+                    R.styleable.SeekBarWithIconButtonsView_Layout_max, DEFAULT_SEEKBAR_MAX);
+            int progress = typedArray.getInt(
+                    R.styleable.SeekBarWithIconButtonsView_Layout_progress,
+                    DEFAULT_SEEKBAR_PROGRESS);
+            mSeekbar.setMax(max);
+            setProgress(progress);
+
+            int iconStartContentDescriptionId = typedArray.getResourceId(
+                    R.styleable.SeekBarWithIconButtonsView_Layout_iconStartContentDescription,
+                    /* defValue= */ 0);
+            int iconEndContentDescriptionId = typedArray.getResourceId(
+                    R.styleable.SeekBarWithIconButtonsView_Layout_iconEndContentDescription,
+                    /* defValue= */ 0);
+            if (iconStartContentDescriptionId != 0) {
+                final String contentDescription =
+                        context.getString(iconStartContentDescriptionId);
+                mIconStart.setContentDescription(contentDescription);
+            }
+            if (iconEndContentDescriptionId != 0) {
+                final String contentDescription =
+                        context.getString(iconEndContentDescriptionId);
+                mIconEnd.setContentDescription(contentDescription);
+            }
+
+            typedArray.recycle();
+        } else {
+            mSeekbar.setMax(DEFAULT_SEEKBAR_MAX);
+            setProgress(DEFAULT_SEEKBAR_PROGRESS);
+        }
+
+        mSeekbar.setOnSeekBarChangeListener(mSeekBarListener);
+
+        mIconStart.setOnClickListener((view) -> {
+            final int progress = mSeekbar.getProgress();
+            if (progress > 0) {
+                mSeekbar.setProgress(progress - 1);
+                setIconViewEnabled(mIconStart, mSeekbar.getProgress() > 0);
+            }
+        });
+
+        mIconEnd.setOnClickListener((view) -> {
+            final int progress = mSeekbar.getProgress();
+            if (progress < mSeekbar.getMax()) {
+                mSeekbar.setProgress(progress + 1);
+                setIconViewEnabled(mIconEnd, mSeekbar.getProgress() < mSeekbar.getMax());
+            }
+        });
+    }
+
+    private static void setIconViewEnabled(View iconView, boolean enabled) {
+        iconView.setEnabled(enabled);
+    }
+
+    /**
+     * Sets a onSeekbarChangeListener to the seekbar in the layout.
+     * We update the Start Icon and End Icon if needed when the seekbar progress is changed.
+     */
+    public void setOnSeekBarChangeListener(
+            @Nullable SeekBar.OnSeekBarChangeListener onSeekBarChangeListener) {
+        mSeekBarListener.setOnSeekBarChangeListener(onSeekBarChangeListener);
+    }
+
+    /**
+     * Start and End icons might need to be updated when there is a change in seekbar progress.
+     * Icon Start will need to be enabled when the seekbar progress is larger than 0.
+     * Icon End will need to be enabled when the seekbar progress is less than Max.
+     */
+    private void updateIconViewIfNeeded(int progress) {
+        setIconViewEnabled(mIconStart, progress > 0);
+        setIconViewEnabled(mIconEnd, progress < mSeekbar.getMax());
+    }
+
+    /**
+     * Sets progress to the seekbar in the layout.
+     */
+    public void setProgress(int progress) {
+        mSeekbar.setProgress(progress);
+        updateIconViewIfNeeded(progress);
+    }
+
+    private class SeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
+        private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener = null;
+
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            if (mOnSeekBarChangeListener != null) {
+                mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
+            }
+            updateIconViewIfNeeded(progress);
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+            if (mOnSeekBarChangeListener != null) {
+                mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
+            }
+        }
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            if (mOnSeekBarChangeListener != null) {
+                mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
+            }
+        }
+
+        void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener listener) {
+            mOnSeekBarChangeListener = listener;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
index dbe301d..860149d 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
@@ -28,12 +28,13 @@
 import android.content.pm.ServiceInfo
 import android.os.UserHandle
 import android.service.controls.ControlsProviderService
+import androidx.annotation.VisibleForTesting
 import androidx.annotation.WorkerThread
 import com.android.settingslib.applications.DefaultAppInfo
 import com.android.systemui.R
 import java.util.Objects
 
-class ControlsServiceInfo(
+open class ControlsServiceInfo(
     private val context: Context,
     val serviceInfo: ServiceInfo
 ) : DefaultAppInfo(
@@ -64,7 +65,7 @@
      * [R.array.config_controlsPreferredPackages] can declare activities for use as a panel.
      */
     var panelActivity: ComponentName? = null
-        private set
+        protected set
 
     private var resolved: Boolean = false
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index ce82af7..700f4f6 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -123,16 +123,13 @@
         userChanging = false
     }
 
-    private val userTrackerCallback = object : UserTracker.Callback {
-        override fun onUserChanged(newUser: Int, userContext: Context) {
-            userChanging = true
-            val newUserHandle = UserHandle.of(newUser)
-            if (currentUser == newUserHandle) {
-                userChanging = false
-                return
-            }
-            setValuesForUser(newUserHandle)
+    override fun changeUser(newUser: UserHandle) {
+        userChanging = true
+        if (currentUser == newUser) {
+            userChanging = false
+            return
         }
+        setValuesForUser(newUser)
     }
 
     @VisibleForTesting
@@ -233,7 +230,6 @@
         dumpManager.registerDumpable(javaClass.name, this)
         resetFavorites()
         userChanging = false
-        userTracker.addCallback(userTrackerCallback, executor)
         context.registerReceiver(
             restoreFinishedReceiver,
             IntentFilter(BackupHelper.ACTION_RESTORE_FINISHED),
@@ -245,7 +241,6 @@
     }
 
     fun destroy() {
-        userTracker.removeCallback(userTrackerCallback)
         context.unregisterReceiver(restoreFinishedReceiver)
         listingController.removeCallback(listingCallback)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/StartControlsStartableModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/StartControlsStartableModule.kt
new file mode 100644
index 0000000..3f20c26
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/StartControlsStartableModule.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.controls.dagger
+
+import com.android.systemui.CoreStartable
+import com.android.systemui.controls.start.ControlsStartable
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+
+@Module
+abstract class StartControlsStartableModule {
+    @Binds
+    @IntoMap
+    @ClassKey(ControlsStartable::class)
+    abstract fun bindFeature(impl: ControlsStartable): CoreStartable
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt b/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
new file mode 100644
index 0000000..9d99253
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
@@ -0,0 +1,119 @@
+/*
+ * 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.controls.start
+
+import android.content.Context
+import android.content.res.Resources
+import android.os.UserHandle
+import com.android.systemui.CoreStartable
+import com.android.systemui.R
+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.SelectedItem
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.settings.UserTracker
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+/**
+ * Started with SystemUI to perform early operations for device controls subsystem (only if enabled)
+ *
+ * In particular, it will perform the following:
+ * * If there is no preferred selection for provider and at least one of the preferred packages 
+ * provides a panel, it will select the first one that does.
+ * * If the preferred selection provides a panel, it will bind to that service (to reduce latency on
+ * displaying the panel).
+ *
+ * It will also perform those operations on user change.
+ */
+@SysUISingleton
+class ControlsStartable
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    @Background private val executor: Executor,
+    private val controlsComponent: ControlsComponent,
+    private val userTracker: UserTracker
+) : CoreStartable {
+
+    // These two controllers can only be accessed after `start` method once we've checked if the
+    // feature is enabled
+    private val controlsController: ControlsController
+        get() = controlsComponent.getControlsController().get()
+
+    private val controlsListingController: ControlsListingController
+        get() = controlsComponent.getControlsListingController().get()
+
+    private val userTrackerCallback =
+        object : UserTracker.Callback {
+            override fun onUserChanged(newUser: Int, userContext: Context) {
+                controlsController.changeUser(UserHandle.of(newUser))
+                startForUser()
+            }
+        }
+
+    override fun start() {
+        if (!controlsComponent.isEnabled()) {
+            // Controls is disabled, we don't need this anymore
+            return
+        }
+        startForUser()
+        userTracker.addCallback(userTrackerCallback, executor)
+    }
+
+    private fun startForUser() {
+        selectDefaultPanelIfNecessary()
+        bindToPanel()
+    }
+
+    private fun selectDefaultPanelIfNecessary() {
+        val currentSelection = controlsController.getPreferredSelection()
+        if (currentSelection == SelectedItem.EMPTY_SELECTION) {
+            val availableServices = controlsListingController.getCurrentServices()
+            val panels = availableServices.filter { it.panelActivity != null }
+            resources
+                .getStringArray(R.array.config_controlsPreferredPackages)
+                // Looking for the first element in the string array such that there is one package
+                // that has a panel. It will return null if there are no packages in the array,
+                // or if no packages in the array have a panel associated with it.
+                .firstNotNullOfOrNull { name ->
+                    panels.firstOrNull { it.componentName.packageName == name }
+                }
+                ?.let { info ->
+                    controlsController.setPreferredSelection(
+                        SelectedItem.PanelItem(info.loadLabel(), info.componentName)
+                    )
+                }
+        }
+    }
+
+    private fun bindToPanel() {
+        val currentSelection = controlsController.getPreferredSelection()
+        val panels =
+            controlsListingController.getCurrentServices().filter { it.panelActivity != null }
+        if (
+            currentSelection is SelectedItem.PanelItem &&
+                panels.firstOrNull { it.componentName == currentSelection.componentName } != null
+        ) {
+            controlsController.bindComponentForPanel(currentSelection.componentName)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 9e71bef..58f4835 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -28,6 +28,7 @@
 import android.content.pm.PackageManager
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.LayerDrawable
+import android.os.Trace
 import android.service.controls.Control
 import android.service.controls.ControlsProviderService
 import android.util.Log
@@ -224,6 +225,7 @@
         activityContext: Context
     ) {
         Log.d(ControlsUiController.TAG, "show()")
+        Trace.instant(Trace.TRACE_TAG_APP, "ControlsUiControllerImpl#show")
         this.parent = parent
         this.onDismiss = onDismiss
         this.activityContext = activityContext
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
index f5764c2..3b6ab20 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
@@ -27,6 +27,7 @@
 import android.graphics.Color
 import android.graphics.drawable.ShapeDrawable
 import android.graphics.drawable.shapes.RoundRectShape
+import android.os.Trace
 import com.android.systemui.R
 import com.android.systemui.util.boundsOnScreen
 import com.android.wm.shell.TaskView
@@ -84,6 +85,7 @@
                         options,
                         taskView.boundsOnScreen
                     )
+                    Trace.instant(Trace.TRACE_TAG_APP, "PanelTaskViewController - startActivity")
                 }
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
index 4eb444e..a5beb4e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
@@ -23,6 +23,8 @@
 import com.android.systemui.keyguard.WorkLockActivity;
 import com.android.systemui.people.PeopleSpaceActivity;
 import com.android.systemui.people.widget.LaunchConversationActivity;
+import com.android.systemui.screenshot.AppClipsActivity;
+import com.android.systemui.screenshot.AppClipsTrampolineActivity;
 import com.android.systemui.screenshot.LongScreenshotActivity;
 import com.android.systemui.sensorprivacy.SensorUseStartedActivity;
 import com.android.systemui.sensorprivacy.television.TvSensorPrivacyChangedActivity;
@@ -119,6 +121,18 @@
     @ClassKey(LongScreenshotActivity.class)
     public abstract Activity bindLongScreenshotActivity(LongScreenshotActivity activity);
 
+    /** Inject into AppClipsTrampolineActivity. */
+    @Binds
+    @IntoMap
+    @ClassKey(AppClipsTrampolineActivity.class)
+    public abstract Activity bindAppClipsTrampolineActivity(AppClipsTrampolineActivity activity);
+
+    /** Inject into AppClipsActivity. */
+    @Binds
+    @IntoMap
+    @ClassKey(AppClipsActivity.class)
+    public abstract Activity bindAppClipsActivity(AppClipsActivity activity);
+
     /** Inject into LaunchConversationActivity. */
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 96bfa43..b054c7e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -32,6 +32,7 @@
 import android.app.UiModeManager;
 import android.app.WallpaperManager;
 import android.app.admin.DevicePolicyManager;
+import android.app.ambientcontext.AmbientContextManager;
 import android.app.job.JobScheduler;
 import android.app.role.RoleManager;
 import android.app.smartspace.SmartspaceManager;
@@ -80,6 +81,7 @@
 import android.safetycenter.SafetyCenterManager;
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
+import android.service.vr.IVrManager;
 import android.telecom.TelecomManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
@@ -147,6 +149,13 @@
         return Optional.ofNullable(context.getSystemService(SystemUpdateManager.class));
     }
 
+    @Provides
+    @Nullable
+    @Singleton
+    static AmbientContextManager provideAmbientContextManager(Context context) {
+        return context.getSystemService(AmbientContextManager.class);
+    }
+
     /** */
     @Provides
     public AmbientDisplayConfiguration provideAmbientDisplayConfiguration(Context context) {
@@ -268,6 +277,13 @@
     @Provides
     @Singleton
     @Nullable
+    static IVrManager provideIVrManager() {
+        return IVrManager.Stub.asInterface(ServiceManager.getService(Context.VR_SERVICE));
+    }
+
+    @Provides
+    @Singleton
+    @Nullable
     static FaceManager provideFaceManager(Context context) {
         if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
             return context.getSystemService(FaceManager.class);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index c9e5449..b5a1f45 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -27,11 +27,14 @@
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.biometrics.UdfpsOverlay
 import com.android.systemui.clipboardoverlay.ClipboardListener
+import com.android.systemui.controls.dagger.StartControlsStartableModule
 import com.android.systemui.dagger.qualifiers.PerUser
+import com.android.systemui.dreams.AssistantAttentionMonitor
 import com.android.systemui.dreams.DreamMonitor
 import com.android.systemui.globalactions.GlobalActionsComponent
 import com.android.systemui.keyboard.KeyboardUI
 import com.android.systemui.keyguard.KeyguardViewMediator
+import com.android.systemui.keyguard.data.quickaffordance.MuteQuickAffordanceCoreStartable
 import com.android.systemui.log.SessionTracker
 import com.android.systemui.media.dialog.MediaOutputSwitcherDialogUI
 import com.android.systemui.media.RingtonePlayer
@@ -65,7 +68,10 @@
 /**
  * Collection of {@link CoreStartable}s that should be run on AOSP.
  */
-@Module(includes = [MultiUserUtilsModule::class])
+@Module(includes = [
+    MultiUserUtilsModule::class,
+    StartControlsStartableModule::class
+])
 abstract class SystemUICoreStartableModule {
     /** Inject into AuthController.  */
     @Binds
@@ -295,9 +301,23 @@
     @ClassKey(StylusUsiPowerStartable::class)
     abstract fun bindStylusUsiPowerStartable(sysui: StylusUsiPowerStartable): CoreStartable
 
+    /** Inject into MuteQuickAffordanceCoreStartable*/
+    @Binds
+    @IntoMap
+    @ClassKey(MuteQuickAffordanceCoreStartable::class)
+    abstract fun bindMuteQuickAffordanceCoreStartable(
+            sysui: MuteQuickAffordanceCoreStartable
+    ): CoreStartable
+
     /**Inject into DreamMonitor */
     @Binds
     @IntoMap
     @ClassKey(DreamMonitor::class)
     abstract fun bindDreamMonitor(sysui: DreamMonitor): CoreStartable
+
+    /**Inject into AssistantAttentionMonitor */
+    @Binds
+    @IntoMap
+    @ClassKey(AssistantAttentionMonitor::class)
+    abstract fun bindAssistantAttentionMonitor(sysui: AssistantAttentionMonitor): CoreStartable
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index c3f24f0..45872f4 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -218,6 +218,10 @@
     abstract BcSmartspaceConfigPlugin optionalBcSmartspaceConfigPlugin();
 
     @BindsOptionalOf
+    @Named(SmartspaceModule.DATE_SMARTSPACE_DATA_PLUGIN)
+    abstract BcSmartspaceDataPlugin optionalDateSmartspaceConfigPlugin();
+
+    @BindsOptionalOf
     @Named(SmartspaceModule.WEATHER_SMARTSPACE_DATA_PLUGIN)
     abstract BcSmartspaceDataPlugin optionalWeatherSmartspaceConfigPlugin();
 
diff --git a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
index 976afd4..88c0c50 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.log.ScreenDecorationsLogger
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import java.util.concurrent.Executor
 import javax.inject.Inject
@@ -45,6 +46,7 @@
     private val statusBarStateController: StatusBarStateController,
     private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
     @Main private val mainExecutor: Executor,
+    private val logger: ScreenDecorationsLogger,
 ) : DecorProviderFactory() {
     private val display = context.display
     private val displayInfo = DisplayInfo()
@@ -82,7 +84,8 @@
                                         authController,
                                         statusBarStateController,
                                         keyguardUpdateMonitor,
-                                        mainExecutor
+                                        mainExecutor,
+                                        logger,
                                 )
                         )
                     }
@@ -104,7 +107,8 @@
     private val authController: AuthController,
     private val statusBarStateController: StatusBarStateController,
     private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
-    private val mainExecutor: Executor
+    private val mainExecutor: Executor,
+    private val logger: ScreenDecorationsLogger,
 ) : BoundDecorProvider() {
     override val viewId: Int = com.android.systemui.R.id.face_scanning_anim
 
@@ -136,7 +140,8 @@
                 alignedBound,
                 statusBarStateController,
                 keyguardUpdateMonitor,
-                mainExecutor
+                mainExecutor,
+                logger,
         )
         view.id = viewId
         view.setColor(tintColor)
@@ -155,8 +160,9 @@
         layoutParams.let { lp ->
             lp.width = ViewGroup.LayoutParams.MATCH_PARENT
             lp.height = ViewGroup.LayoutParams.MATCH_PARENT
+            logger.faceSensorLocation(authController.faceSensorLocation)
             authController.faceSensorLocation?.y?.let { faceAuthSensorHeight ->
-                val faceScanningHeight = (faceAuthSensorHeight * 2).toInt()
+                val faceScanningHeight = (faceAuthSensorHeight * 2)
                 when (rotation) {
                     Surface.ROTATION_0, Surface.ROTATION_180 ->
                         lp.height = faceScanningHeight
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/AssistantAttentionMonitor.java b/packages/SystemUI/src/com/android/systemui/dreams/AssistantAttentionMonitor.java
new file mode 100644
index 0000000..49d7f78
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/AssistantAttentionMonitor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.dreams;
+
+import android.util.Log;
+
+import com.android.systemui.CoreStartable;
+import com.android.systemui.dreams.callbacks.AssistantAttentionCallback;
+import com.android.systemui.dreams.conditions.AssistantAttentionCondition;
+import com.android.systemui.shared.condition.Monitor;
+
+import javax.inject.Inject;
+
+/**
+ * A {@link CoreStartable} to retain a monitor for tracking assistant attention.
+ */
+public class AssistantAttentionMonitor implements CoreStartable {
+    private static final String TAG = "AssistAttentionMonitor";
+
+    // We retain a reference to the monitor so it is not garbage-collected.
+    private final Monitor mConditionMonitor;
+    private final AssistantAttentionCondition mAssistantAttentionCondition;
+    private final AssistantAttentionCallback mCallback;
+
+    @Inject
+    public AssistantAttentionMonitor(
+            Monitor monitor,
+            AssistantAttentionCondition assistantAttentionCondition,
+            AssistantAttentionCallback callback) {
+        mConditionMonitor = monitor;
+        mAssistantAttentionCondition = assistantAttentionCondition;
+        mCallback = callback;
+
+    }
+    @Override
+    public void start() {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "started");
+        }
+
+        mConditionMonitor.addSubscription(new Monitor.Subscription.Builder(mCallback)
+                .addCondition(mAssistantAttentionCondition)
+                .build());
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
index 2c7ecb1..b7f6a70 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
@@ -56,6 +56,8 @@
     public static final int STATE_LOW_LIGHT_ACTIVE = 1 << 1;
     public static final int STATE_DREAM_ENTRY_ANIMATIONS_FINISHED = 1 << 2;
     public static final int STATE_DREAM_EXIT_ANIMATIONS_RUNNING = 1 << 3;
+    public static final int STATE_HAS_ASSISTANT_ATTENTION = 1 << 4;
+    public static final int STATE_DREAM_OVERLAY_STATUS_BAR_VISIBLE = 1 << 5;
 
     private static final int OP_CLEAR_STATE = 1;
     private static final int OP_SET_STATE = 2;
@@ -251,6 +253,22 @@
         return containsState(STATE_DREAM_EXIT_ANIMATIONS_RUNNING);
     }
 
+    /**
+     * Returns whether assistant currently has the user's attention.
+     * @return {@code true} if assistant has the user's attention, {@code false} otherwise.
+     */
+    public boolean hasAssistantAttention() {
+        return containsState(STATE_HAS_ASSISTANT_ATTENTION);
+    }
+
+    /**
+     * Returns whether the dream overlay status bar is currently visible.
+     * @return {@code true} if the status bar is visible, {@code false} otherwise.
+     */
+    public boolean isDreamOverlayStatusBarVisible() {
+        return containsState(STATE_DREAM_OVERLAY_STATUS_BAR_VISIBLE);
+    }
+
     private boolean containsState(int state) {
         return (mState & state) != 0;
     }
@@ -310,6 +328,23 @@
     }
 
     /**
+     * Sets whether assistant currently has the user's attention.
+     * @param hasAttention {@code true} if has the user's attention, {@code false} otherwise.
+     */
+    public void setHasAssistantAttention(boolean hasAttention) {
+        modifyState(hasAttention ? OP_SET_STATE : OP_CLEAR_STATE, STATE_HAS_ASSISTANT_ATTENTION);
+    }
+
+    /**
+     * Sets whether the dream overlay status bar is visible.
+     * @param visible {@code true} if the status bar is visible, {@code false} otherwise.
+     */
+    public void setDreamOverlayStatusBarVisible(boolean visible) {
+        modifyState(
+                visible ? OP_SET_STATE : OP_CLEAR_STATE, STATE_DREAM_OVERLAY_STATUS_BAR_VISIBLE);
+    }
+
+    /**
      * Returns the available complication types.
      */
     @Complication.ComplicationType
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
index 96bce4c..7c1bfed 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java
@@ -52,7 +52,8 @@
             STATUS_ICON_CAMERA_DISABLED,
             STATUS_ICON_MIC_DISABLED,
             STATUS_ICON_MIC_CAMERA_DISABLED,
-            STATUS_ICON_PRIORITY_MODE_ON
+            STATUS_ICON_PRIORITY_MODE_ON,
+            STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE,
     })
     public @interface StatusIconType {}
     public static final int STATUS_ICON_NOTIFICATIONS = 0;
@@ -62,6 +63,7 @@
     public static final int STATUS_ICON_MIC_DISABLED = 4;
     public static final int STATUS_ICON_MIC_CAMERA_DISABLED = 5;
     public static final int STATUS_ICON_PRIORITY_MODE_ON = 6;
+    public static final int STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE = 7;
 
     private final Map<Integer, View> mStatusIcons = new HashMap<>();
     private Context mContext;
@@ -132,6 +134,8 @@
                 fetchStatusIconForResId(R.id.dream_overlay_notification_indicator));
         mStatusIcons.put(STATUS_ICON_PRIORITY_MODE_ON,
                 addDoubleShadow(fetchStatusIconForResId(R.id.dream_overlay_priority_mode)));
+        mStatusIcons.put(STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE,
+                fetchStatusIconForResId(R.id.dream_overlay_assistant_attention_indicator));
 
         mSystemStatusViewGroup = findViewById(R.id.dream_overlay_system_status);
         mExtraSystemStatusViewGroup = findViewById(R.id.dream_overlay_extra_items);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index 90c440c..2221a04 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -113,6 +113,7 @@
                     mEntryAnimationsFinished =
                             mDreamOverlayStateController.areEntryAnimationsFinished();
                     updateVisibility();
+                    updateAssistantAttentionIcon();
                 }
             };
 
@@ -214,6 +215,7 @@
                 provider -> provider.removeCallback(mNotificationCountCallback));
         mStatusBarItemsProvider.removeCallback(mStatusBarItemsProviderCallback);
         mView.removeAllExtraStatusBarItemViews();
+        mDreamOverlayStateController.setDreamOverlayStatusBarVisible(false);
         mDreamOverlayStateController.removeCallback(mDreamOverlayStateCallback);
         mTouchInsetSession.clear();
 
@@ -270,12 +272,20 @@
                 hasAlarm ? buildAlarmContentDescription(alarm) : null);
     }
 
+    private void updateAssistantAttentionIcon() {
+        showIcon(DreamOverlayStatusBarView.STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE,
+                mDreamOverlayStateController.hasAssistantAttention());
+    }
+
     private void updateVisibility() {
-        if (shouldShowStatusBar()) {
-            mView.setVisibility(View.VISIBLE);
-        } else {
-            mView.setVisibility(View.INVISIBLE);
+        final int currentVisibility = mView.getVisibility();
+        final int newVisibility = shouldShowStatusBar() ? View.VISIBLE : View.INVISIBLE;
+        if (currentVisibility == newVisibility) {
+            return;
         }
+
+        mView.setVisibility(newVisibility);
+        mDreamOverlayStateController.setDreamOverlayStatusBarVisible(newVisibility == View.VISIBLE);
     }
 
     private String buildAlarmContentDescription(AlarmManager.AlarmClockInfo alarm) {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/callbacks/AssistantAttentionCallback.java b/packages/SystemUI/src/com/android/systemui/dreams/callbacks/AssistantAttentionCallback.java
new file mode 100644
index 0000000..5d8a9b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/callbacks/AssistantAttentionCallback.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.callbacks;
+
+import android.util.Log;
+
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.shared.condition.Monitor;
+
+import javax.inject.Inject;
+
+/**
+ * A callback that informs {@link DreamOverlayStateController} when assistant has the user's
+ * attention.
+ */
+public class AssistantAttentionCallback implements Monitor.Callback {
+    private static final String TAG = "AssistAttentionCallback";
+
+    private final DreamOverlayStateController mStateController;
+
+    @Inject
+    public AssistantAttentionCallback(DreamOverlayStateController stateController) {
+        mStateController = stateController;
+    }
+
+    @Override
+    public void onConditionsChanged(boolean allConditionsMet) {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "onConditionChanged:" + allConditionsMet);
+        }
+
+        mStateController.setHasAssistantAttention(allConditionsMet);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
new file mode 100644
index 0000000..250cfec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
@@ -0,0 +1,95 @@
+/*
+ * 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.dreams.conditions;
+
+import com.android.internal.app.AssistUtils;
+import com.android.internal.app.IVisualQueryDetectionAttentionListener;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.shared.condition.Condition;
+
+import javax.inject.Inject;
+
+/**
+ * {@link AssistantAttentionCondition} provides a signal when assistant has the user's attention.
+ */
+public class AssistantAttentionCondition extends Condition {
+    private final DreamOverlayStateController mDreamOverlayStateController;
+    private final AssistUtils mAssistUtils;
+    private boolean mEnabled;
+
+    private final IVisualQueryDetectionAttentionListener mVisualQueryDetectionAttentionListener =
+            new IVisualQueryDetectionAttentionListener.Stub() {
+        @Override
+        public void onAttentionGained() {
+            updateCondition(true);
+        }
+
+        @Override
+        public void onAttentionLost() {
+            updateCondition(false);
+        }
+    };
+
+    private final DreamOverlayStateController.Callback mCallback =
+            new DreamOverlayStateController.Callback() {
+        @Override
+        public void onStateChanged() {
+            if (mDreamOverlayStateController.isDreamOverlayStatusBarVisible()) {
+                enableVisualQueryDetection();
+            } else {
+                disableVisualQueryDetection();
+            }
+        }
+    };
+
+    @Inject
+    public AssistantAttentionCondition(
+            DreamOverlayStateController dreamOverlayStateController,
+            AssistUtils assistUtils) {
+        mDreamOverlayStateController = dreamOverlayStateController;
+        mAssistUtils = assistUtils;
+    }
+
+    @Override
+    protected void start() {
+        mDreamOverlayStateController.addCallback(mCallback);
+    }
+
+    @Override
+    protected void stop() {
+        disableVisualQueryDetection();
+        mDreamOverlayStateController.removeCallback(mCallback);
+    }
+
+    private void enableVisualQueryDetection() {
+        if (mEnabled) {
+            return;
+        }
+        mEnabled = true;
+        mAssistUtils.enableVisualQueryDetection(mVisualQueryDetectionAttentionListener);
+    }
+
+    private void disableVisualQueryDetection() {
+        if (!mEnabled) {
+            return;
+        }
+        mEnabled = false;
+        mAssistUtils.disableVisualQueryDetection();
+        // Make sure the condition is set to false as well.
+        updateCondition(false);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index fa0ce24..d594fce 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -68,7 +68,7 @@
     @JvmField val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
 
     // TODO(b/254512538): Tracking Bug
-    val INSTANT_VOICE_REPLY = unreleasedFlag(111, "instant_voice_reply", teamfood = true)
+    val INSTANT_VOICE_REPLY = releasedFlag(111, "instant_voice_reply")
 
     // TODO(b/254512425): Tracking Bug
     val NOTIFICATION_MEMORY_MONITOR_ENABLED =
@@ -85,7 +85,7 @@
     // TODO(b/259217907)
     @JvmField
     val NOTIFICATION_GROUP_DISMISSAL_ANIMATION =
-        unreleasedFlag(259217907, "notification_group_dismissal_animation", teamfood = true)
+        releasedFlag(259217907, "notification_group_dismissal_animation")
 
     // TODO(b/257506350): Tracking Bug
     @JvmField val FSI_CHROME = unreleasedFlag(117, "fsi_chrome")
@@ -95,7 +95,7 @@
         unreleasedFlag(259395680, "simplified_appear_fraction", teamfood = true)
 
     // TODO(b/257315550): Tracking Bug
-    val NO_HUN_FOR_OLD_WHEN = unreleasedFlag(118, "no_hun_for_old_when", teamfood = true)
+    val NO_HUN_FOR_OLD_WHEN = releasedFlag(118, "no_hun_for_old_when")
 
     // TODO(b/260335638): Tracking Bug
     @JvmField
@@ -108,7 +108,7 @@
     // TODO(b/263414400): Tracking Bug
     @JvmField
     val NOTIFICATION_ANIMATE_BIG_PICTURE =
-        unreleasedFlag(120, "notification_animate_big_picture", teamfood = true)
+        releasedFlag(120, "notification_animate_big_picture", teamfood = true)
 
     // 200 - keyguard/lockscreen
     // ** Flag retired **
@@ -125,8 +125,7 @@
         resourceBooleanFlag(204, R.bool.config_enableBouncerUserSwitcher, "bouncer_user_switcher")
 
     // TODO(b/254512676): Tracking Bug
-    @JvmField
-    val LOCKSCREEN_CUSTOM_CLOCKS = unreleasedFlag(207, "lockscreen_custom_clocks", teamfood = true)
+    @JvmField val LOCKSCREEN_CUSTOM_CLOCKS = releasedFlag(207, "lockscreen_custom_clocks")
 
     /**
      * Whether the clock on a wide lock screen should use the new "stepping" animation for moving
@@ -209,9 +208,7 @@
         unreleasedFlag(226, "enable_wallet_contextual_loyalty_cards", teamfood = false)
 
     // TODO(b/242908637): Tracking Bug
-    @JvmField
-    val WALLPAPER_FULLSCREEN_PREVIEW =
-        unreleasedFlag(227, "wallpaper_fullscreen_preview", teamfood = true)
+    @JvmField val WALLPAPER_FULLSCREEN_PREVIEW = releasedFlag(227, "wallpaper_fullscreen_preview")
 
     /** Whether the long-press gesture to open wallpaper picker is enabled. */
     // TODO(b/266242192): Tracking Bug
@@ -235,7 +232,7 @@
     // TODO(b/258517050): Clean up after the feature is launched.
     @JvmField
     val SMARTSPACE_DATE_WEATHER_DECOUPLED =
-        sysPropBooleanFlag(403, "persist.sysui.ss.dw_decoupled", default = false)
+        sysPropBooleanFlag(403, "persist.sysui.ss.dw_decoupled", default = true)
 
     // 500 - quick settings
 
@@ -266,11 +263,10 @@
     // 600- status bar
 
     // TODO(b/256614753): Tracking Bug
-    val NEW_STATUS_BAR_MOBILE_ICONS =
-        unreleasedFlag(606, "new_status_bar_mobile_icons", teamfood = true)
+    val NEW_STATUS_BAR_MOBILE_ICONS = releasedFlag(606, "new_status_bar_mobile_icons")
 
     // TODO(b/256614210): Tracking Bug
-    val NEW_STATUS_BAR_WIFI_ICON = unreleasedFlag(607, "new_status_bar_wifi_icon", teamfood = true)
+    val NEW_STATUS_BAR_WIFI_ICON = releasedFlag(607, "new_status_bar_wifi_icon")
 
     // TODO(b/256614751): Tracking Bug
     val NEW_STATUS_BAR_MOBILE_ICONS_BACKEND =
@@ -311,9 +307,7 @@
     val SCREEN_CONTENTS_TRANSLATION = unreleasedFlag(803, "screen_contents_translation")
 
     // 804 - monochromatic themes
-    @JvmField
-    val MONOCHROMATIC_THEMES =
-        sysPropBooleanFlag(804, "persist.sysui.monochromatic", default = false)
+    @JvmField val MONOCHROMATIC_THEME = releasedFlag(804, "monochromatic")
 
     // 900 - media
     // TODO(b/254512697): Tracking Bug
@@ -335,31 +329,34 @@
     @JvmField val DREAM_MEDIA_TAP_TO_OPEN = unreleasedFlag(906, "dream_media_tap_to_open")
 
     // TODO(b/254513168): Tracking Bug
-    @JvmField val UMO_SURFACE_RIPPLE = unreleasedFlag(907, "umo_surface_ripple")
+    @JvmField val UMO_SURFACE_RIPPLE = releasedFlag(907, "umo_surface_ripple")
 
-    @JvmField
-    val MEDIA_FALSING_PENALTY = unreleasedFlag(908, "media_falsing_media", teamfood = true)
+    @JvmField val MEDIA_FALSING_PENALTY = releasedFlag(908, "media_falsing_media")
 
     // TODO(b/261734857): Tracking Bug
-    @JvmField val UMO_TURBULENCE_NOISE = unreleasedFlag(909, "umo_turbulence_noise")
+    @JvmField val UMO_TURBULENCE_NOISE = releasedFlag(909, "umo_turbulence_noise")
 
     // TODO(b/263272731): Tracking Bug
-    val MEDIA_TTT_RECEIVER_SUCCESS_RIPPLE =
-        unreleasedFlag(910, "media_ttt_receiver_success_ripple", teamfood = true)
+    val MEDIA_TTT_RECEIVER_SUCCESS_RIPPLE = releasedFlag(910, "media_ttt_receiver_success_ripple")
 
     // TODO(b/263512203): Tracking Bug
-    val MEDIA_EXPLICIT_INDICATOR = unreleasedFlag(911, "media_explicit_indicator", teamfood = true)
+    val MEDIA_EXPLICIT_INDICATOR = releasedFlag(911, "media_explicit_indicator")
 
     // TODO(b/265813373): Tracking Bug
-    val MEDIA_TAP_TO_TRANSFER_DISMISS_GESTURE =
-        unreleasedFlag(912, "media_ttt_dismiss_gesture", teamfood = true)
+    val MEDIA_TAP_TO_TRANSFER_DISMISS_GESTURE = releasedFlag(912, "media_ttt_dismiss_gesture")
 
     // TODO(b/266157412): Tracking Bug
-    val MEDIA_RETAIN_SESSIONS = unreleasedFlag(913, "media_retain_sessions")
+    val MEDIA_RETAIN_SESSIONS = releasedFlag(913, "media_retain_sessions")
 
     // TODO(b/266739309): Tracking Bug
     @JvmField
-    val MEDIA_RECOMMENDATION_CARD_UPDATE = unreleasedFlag(914, "media_recommendation_card_update")
+    val MEDIA_RECOMMENDATION_CARD_UPDATE = releasedFlag(914, "media_recommendation_card_update")
+
+    // TODO(b/267007629): Tracking Bug
+    val MEDIA_RESUME_PROGRESS = releasedFlag(915, "media_resume_progress")
+
+    // TODO(b/267166152) : Tracking Bug
+    val MEDIA_RETAIN_RECOMMENDATIONS = releasedFlag(916, "media_retain_recommendations")
 
     // 1000 - dock
     val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
@@ -463,7 +460,7 @@
     @Keep
     @JvmField
     val WM_ENABLE_PREDICTIVE_BACK_ANIM =
-        sysPropBooleanFlag(1201, "persist.wm.debug.predictive_back_anim", default = false)
+        sysPropBooleanFlag(1201, "persist.wm.debug.predictive_back_anim", default = true)
 
     @Keep
     @JvmField
@@ -471,8 +468,7 @@
         sysPropBooleanFlag(1202, "persist.wm.debug.predictive_back_always_enforce", default = false)
 
     // TODO(b/254512728): Tracking Bug
-    @JvmField
-    val NEW_BACK_AFFORDANCE = unreleasedFlag(1203, "new_back_affordance", teamfood = false)
+    @JvmField val NEW_BACK_AFFORDANCE = releasedFlag(1203, "new_back_affordance")
 
     // TODO(b/255854141): Tracking Bug
     @JvmField
@@ -491,12 +487,12 @@
     // TODO(b/238475428): Tracking Bug
     @JvmField
     val WM_SHADE_ALLOW_BACK_GESTURE =
-        unreleasedFlag(1207, "persist.wm.debug.shade_allow_back_gesture", teamfood = false)
+        sysPropBooleanFlag(1207, "persist.wm.debug.shade_allow_back_gesture", default = false)
 
     // TODO(b/238475428): Tracking Bug
     @JvmField
     val WM_SHADE_ANIMATE_BACK_GESTURE =
-        unreleasedFlag(1208, "persist.wm.debug.shade_animate_back_gesture", teamfood = true)
+        unreleasedFlag(1208, "persist.wm.debug.shade_animate_back_gesture", teamfood = false)
 
     // TODO(b/265639042): Tracking Bug
     @JvmField
@@ -506,11 +502,16 @@
     // 1300 - screenshots
     // TODO(b/254513155): Tracking Bug
     @JvmField
-    val SCREENSHOT_WORK_PROFILE_POLICY =
-        unreleasedFlag(1301, "screenshot_work_profile_policy", teamfood = true)
+    val SCREENSHOT_WORK_PROFILE_POLICY = releasedFlag(1301, "screenshot_work_profile_policy")
 
     // TODO(b/264916608): Tracking Bug
-    @JvmField val SCREENSHOT_METADATA = unreleasedFlag(1302, "screenshot_metadata")
+    @JvmField val SCREENSHOT_METADATA = unreleasedFlag(1302, "screenshot_metadata", teamfood = true)
+
+    // TODO(b/266955521): Tracking bug
+    @JvmField val SCREENSHOT_DETECTION = releasedFlag(1303, "screenshot_detection")
+
+    // TODO(b/251205791): Tracking Bug
+    @JvmField val SCREENSHOT_APP_CLIPS = releasedFlag(1304, "screenshot_app_clips")
 
     // 1400 - columbus
     // TODO(b/254512756): Tracking Bug
@@ -520,18 +521,27 @@
     val QUICK_TAP_FLOW_FRAMEWORK =
         unreleasedFlag(1401, "quick_tap_flow_framework", teamfood = false)
 
-    // 1500 - chooser
+    // 1500 - chooser aka sharesheet
     // TODO(b/254512507): Tracking Bug
-    val CHOOSER_UNBUNDLED = unreleasedFlag(1500, "chooser_unbundled", teamfood = true)
+    val CHOOSER_UNBUNDLED = releasedFlag(1500, "chooser_unbundled")
 
-    // 1600 - accessibility
-    // TODO(b/262224538): Tracking Bug
-    @JvmField
-    val A11Y_FLOATING_MENU_FLING_SPRING_ANIMATIONS =
-        releasedFlag(1600, "a11y_floating_menu_fling_spring_animations")
+    // TODO(b/266983432) Tracking Bug
+    val SHARESHEET_CUSTOM_ACTIONS = releasedFlag(1501, "sharesheet_custom_actions")
+
+    // TODO(b/266982749) Tracking Bug
+    val SHARESHEET_RESELECTION_ACTION = releasedFlag(1502, "sharesheet_reselection_action")
+
+    // TODO(b/266983474) Tracking Bug
+    val SHARESHEET_IMAGE_AND_TEXT_PREVIEW = releasedFlag(1503, "sharesheet_image_text_preview")
+
+    // TODO(b/267355521) Tracking Bug
+    val SHARESHEET_SCROLLABLE_IMAGE_PREVIEW =
+        releasedFlag(1504, "sharesheet_scrollable_image_preview")
 
     // 1700 - clipboard
     @JvmField val CLIPBOARD_REMOTE_BEHAVIOR = releasedFlag(1701, "clipboard_remote_behavior")
+    // TODO(b/267162944): Tracking bug
+    @JvmField val CLIPBOARD_MINIMIZED_LAYOUT = unreleasedFlag(1702, "clipboard_data_model")
 
     // 1800 - shade container
     @JvmField
@@ -540,7 +550,7 @@
     @JvmField val DUAL_SHADE = releasedFlag(1801, "dual_shade")
 
     // 1900
-    @JvmField val NOTE_TASKS = unreleasedFlag(1900, "keycode_flag")
+    @JvmField val NOTE_TASKS = releasedFlag(1900, "keycode_flag")
 
     // 2000 - device controls
     @Keep @JvmField val USE_APP_PANELS = releasedFlag(2000, "use_app_panels", teamfood = true)
@@ -551,22 +561,25 @@
 
     @JvmField
     val CONTROLS_MANAGEMENT_NEW_FLOWS =
-        unreleasedFlag(2002, "controls_management_new_flows", teamfood = true)
+        releasedFlag(2002, "controls_management_new_flows", teamfood = true)
 
     // 2100 - Falsing Manager
     @JvmField val FALSING_FOR_LONG_TAPS = releasedFlag(2100, "falsing_for_long_taps")
 
     // 2200 - udfps
     // TODO(b/259264861): Tracking Bug
-    @JvmField val UDFPS_NEW_TOUCH_DETECTION = unreleasedFlag(2200, "udfps_new_touch_detection")
-    @JvmField val UDFPS_ELLIPSE_DEBUG_UI = unreleasedFlag(2201, "udfps_ellipse_debug")
-    @JvmField val UDFPS_ELLIPSE_DETECTION = unreleasedFlag(2202, "udfps_ellipse_detection")
+    @JvmField val UDFPS_NEW_TOUCH_DETECTION = releasedFlag(2200, "udfps_new_touch_detection")
+    @JvmField val UDFPS_ELLIPSE_DETECTION = releasedFlag(2201, "udfps_ellipse_detection")
 
     // 2300 - stylus
-    @JvmField val TRACK_STYLUS_EVER_USED = unreleasedFlag(2300, "track_stylus_ever_used")
-    @JvmField val ENABLE_STYLUS_CHARGING_UI = unreleasedFlag(2301, "enable_stylus_charging_ui")
     @JvmField
-    val ENABLE_USI_BATTERY_NOTIFICATIONS = unreleasedFlag(2302, "enable_usi_battery_notifications")
+    val TRACK_STYLUS_EVER_USED = unreleasedFlag(2300, "track_stylus_ever_used", teamfood = true)
+    @JvmField
+    val ENABLE_STYLUS_CHARGING_UI =
+        unreleasedFlag(2301, "enable_stylus_charging_ui", teamfood = true)
+    @JvmField
+    val ENABLE_USI_BATTERY_NOTIFICATIONS =
+        unreleasedFlag(2302, "enable_usi_battery_notifications", teamfood = true)
     @JvmField val ENABLE_STYLUS_EDUCATION = unreleasedFlag(2303, "enable_stylus_education")
 
     // 2400 - performance tools and debugging info
@@ -578,12 +591,11 @@
     // 2500 - output switcher
     // TODO(b/261538825): Tracking Bug
     @JvmField
-    val OUTPUT_SWITCHER_ADVANCED_LAYOUT = unreleasedFlag(2500, "output_switcher_advanced_layout")
+    val OUTPUT_SWITCHER_ADVANCED_LAYOUT = releasedFlag(2500, "output_switcher_advanced_layout")
     @JvmField
-    val OUTPUT_SWITCHER_ROUTES_PROCESSING =
-        unreleasedFlag(2501, "output_switcher_routes_processing")
+    val OUTPUT_SWITCHER_ROUTES_PROCESSING = releasedFlag(2501, "output_switcher_routes_processing")
     @JvmField
-    val OUTPUT_SWITCHER_DEVICE_STATUS = unreleasedFlag(2502, "output_switcher_device_status")
+    val OUTPUT_SWITCHER_DEVICE_STATUS = releasedFlag(2502, "output_switcher_device_status")
 
     // TODO(b/20911786): Tracking Bug
     @JvmField
@@ -600,7 +612,11 @@
     // TODO(b259590361): Tracking bug
     val EXPERIMENTAL_FLAG = unreleasedFlag(2, "exp_flag_release")
 
-    // 2600 - keyboard shortcut
+    // 2600 - keyboard
     // TODO(b/259352579): Tracking Bug
     @JvmField val SHORTCUT_LIST_SEARCH_LAYOUT = unreleasedFlag(2600, "shortcut_list_search_layout")
+
+    // TODO(b/259428678): Tracking Bug
+    @JvmField
+    val KEYBOARD_BACKLIGHT_INDICATOR = unreleasedFlag(2601, "keyboard_backlight_indicator")
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
index 9b2e6b8..d3fe2c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
@@ -24,6 +24,7 @@
 
 import androidx.annotation.IntDef;
 
+import com.android.keyguard.logging.KeyguardLogger;
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -64,6 +65,7 @@
             2000L + KeyguardIndicationTextView.Y_IN_DURATION;
 
     private final StatusBarStateController mStatusBarStateController;
+    private final KeyguardLogger mLogger;
     private final float mMaxAlpha;
     private final ColorStateList mInitialTextColorState;
 
@@ -85,7 +87,8 @@
     public KeyguardIndicationRotateTextViewController(
             KeyguardIndicationTextView view,
             @Main DelayableExecutor executor,
-            StatusBarStateController statusBarStateController
+            StatusBarStateController statusBarStateController,
+            KeyguardLogger logger
     ) {
         super(view);
         mMaxAlpha = view.getAlpha();
@@ -93,6 +96,7 @@
         mInitialTextColorState = mView != null
                 ? mView.getTextColors() : ColorStateList.valueOf(Color.WHITE);
         mStatusBarStateController = statusBarStateController;
+        mLogger = logger;
         init();
     }
 
@@ -259,6 +263,8 @@
         mLastIndicationSwitch = SystemClock.uptimeMillis();
         if (!TextUtils.equals(previousMessage, mCurrMessage)
                 || previousIndicationType != mCurrIndicationType) {
+            mLogger.logKeyguardSwitchIndication(type,
+                    mCurrMessage != null ? mCurrMessage.toString() : null);
             mView.switchIndication(mIndicationMessages.get(type));
         }
 
@@ -352,9 +358,10 @@
     @Override
     public void dump(PrintWriter pw, String[] args) {
         pw.println("KeyguardIndicationRotatingTextViewController:");
-        pw.println("    currentMessage=" + mView.getText());
+        pw.println("    currentTextViewMessage=" + mView.getText());
+        pw.println("    currentStoredMessage=" + mView.getMessage());
         pw.println("    dozing:" + mIsDozing);
-        pw.println("    queue:" + mIndicationQueue.toString());
+        pw.println("    queue:" + mIndicationQueue);
         pw.println("    showNextIndicationRunnable:" + mShowNextIndicationRunnable);
 
         if (hasIndications()) {
@@ -398,4 +405,40 @@
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface IndicationType{}
+
+    /**
+     * Get human-readable string representation of the indication type.
+     */
+    public static String indicationTypeToString(@IndicationType int type) {
+        switch (type) {
+            case INDICATION_TYPE_NONE:
+                return "none";
+            case INDICATION_TYPE_DISCLOSURE:
+                return "disclosure";
+            case INDICATION_TYPE_OWNER_INFO:
+                return "owner_info";
+            case INDICATION_TYPE_LOGOUT:
+                return "logout";
+            case INDICATION_TYPE_BATTERY:
+                return "battery";
+            case INDICATION_TYPE_ALIGNMENT:
+                return "alignment";
+            case INDICATION_TYPE_TRANSIENT:
+                return "transient";
+            case INDICATION_TYPE_TRUST:
+                return "trust";
+            case INDICATION_TYPE_PERSISTENT_UNLOCK_MESSAGE:
+                return "persistent_unlock_message";
+            case INDICATION_TYPE_USER_LOCKED:
+                return "user_locked";
+            case INDICATION_TYPE_REVERSE_CHARGING:
+                return "reverse_charging";
+            case INDICATION_TYPE_BIOMETRIC_MESSAGE:
+                return "biometric_message";
+            case INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP:
+                return "biometric_message_followup";
+            default:
+                return "unknown[" + type + "]";
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt
index 76c2430..80675d3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt
@@ -29,6 +29,7 @@
     const val DO_NOT_DISTURB = "do_not_disturb"
     const val FLASHLIGHT = "flashlight"
     const val HOME_CONTROLS = "home"
+    const val MUTE = "mute"
     const val QR_CODE_SCANNER = "qr_code_scanner"
     const val QUICK_ACCESS_WALLET = "wallet"
     const val VIDEO_CAMERA = "video_camera"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt
index a1cce5c..4556195 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt
@@ -33,12 +33,13 @@
         @Provides
         @ElementsIntoSet
         fun quickAffordanceConfigs(
+            camera: CameraQuickAffordanceConfig,
             doNotDisturb: DoNotDisturbQuickAffordanceConfig,
             flashlight: FlashlightQuickAffordanceConfig,
             home: HomeControlsKeyguardQuickAffordanceConfig,
+            mute: MuteQuickAffordanceConfig,
             quickAccessWallet: QuickAccessWalletKeyguardQuickAffordanceConfig,
             qrCodeScanner: QrCodeScannerKeyguardQuickAffordanceConfig,
-            camera: CameraQuickAffordanceConfig,
             videoCamera: VideoCameraQuickAffordanceConfig,
         ): Set<KeyguardQuickAffordanceConfig> {
             return setOf(
@@ -46,6 +47,7 @@
                 doNotDisturb,
                 flashlight,
                 home,
+                mute,
                 quickAccessWallet,
                 qrCodeScanner,
                 videoCamera,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
new file mode 100644
index 0000000..da91572
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.content.Context
+import android.media.AudioManager
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.Observer
+import com.android.systemui.R
+import com.android.systemui.animation.Expandable
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.RingerModeTracker
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+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.onEach
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import javax.inject.Inject
+
+@SysUISingleton
+class MuteQuickAffordanceConfig @Inject constructor(
+        context: Context,
+        private val userTracker: UserTracker,
+        private val userFileManager: UserFileManager,
+        private val ringerModeTracker: RingerModeTracker,
+        private val audioManager: AudioManager,
+        @Application private val coroutineScope: CoroutineScope,
+        @Main private val mainDispatcher: CoroutineDispatcher,
+        @Background private val backgroundDispatcher: CoroutineDispatcher,
+) : KeyguardQuickAffordanceConfig {
+
+    private var previousNonSilentMode: Int = DEFAULT_LAST_NON_SILENT_VALUE
+
+    override val key: String = BuiltInKeyguardQuickAffordanceKeys.MUTE
+
+    override val pickerName: String = context.getString(R.string.volume_ringer_status_silent)
+
+    override val pickerIconResourceId: Int = R.drawable.ic_notifications_silence
+
+    override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> =
+        ringerModeTracker.ringerModeInternal.asFlow()
+            .onStart { getLastNonSilentRingerMode() }
+            .distinctUntilChanged()
+            .onEach { mode ->
+                // only remember last non-SILENT ringer mode
+                if (mode != null && mode != AudioManager.RINGER_MODE_SILENT) {
+                    previousNonSilentMode = mode
+                }
+            }
+            .map { mode ->
+                val (activationState, contentDescriptionRes) = when {
+                    audioManager.isVolumeFixed ->
+                        ActivationState.NotSupported to
+                            R.string.volume_ringer_hint_mute
+                    mode == AudioManager.RINGER_MODE_SILENT ->
+                        ActivationState.Active to
+                            R.string.volume_ringer_hint_mute
+                    else ->
+                        ActivationState.Inactive to
+                            R.string.volume_ringer_hint_unmute
+                }
+
+                KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+                    Icon.Resource(
+                        R.drawable.ic_notifications_silence,
+                        ContentDescription.Resource(contentDescriptionRes),
+                    ),
+                    activationState,
+                )
+            }
+            .flowOn(backgroundDispatcher)
+
+    override fun onTriggered(
+        expandable: Expandable?
+    ): KeyguardQuickAffordanceConfig.OnTriggeredResult {
+        coroutineScope.launch(backgroundDispatcher) {
+            val newRingerMode: Int
+            val currentRingerMode = audioManager.ringerModeInternal
+            if (currentRingerMode == AudioManager.RINGER_MODE_SILENT) {
+                newRingerMode = previousNonSilentMode
+            } else {
+                previousNonSilentMode = currentRingerMode
+                newRingerMode = AudioManager.RINGER_MODE_SILENT
+            }
+
+            if (currentRingerMode != newRingerMode) {
+                audioManager.ringerModeInternal = newRingerMode
+            }
+        }
+        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+    }
+
+    override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState =
+        withContext(backgroundDispatcher) {
+            if (audioManager.isVolumeFixed) {
+                KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
+            } else {
+                KeyguardQuickAffordanceConfig.PickerScreenState.Default()
+            }
+        }
+
+    /**
+     * Gets the last non-silent ringer mode from shared-preferences if it exists. This is
+     *  cached by [MuteQuickAffordanceCoreStartable] while this affordance is selected
+     */
+    private suspend fun getLastNonSilentRingerMode(): Int =
+        withContext(backgroundDispatcher) {
+            userFileManager.getSharedPreferences(
+                    MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME,
+                    Context.MODE_PRIVATE,
+                    userTracker.userId
+            ).getInt(
+                    LAST_NON_SILENT_RINGER_MODE_KEY,
+                    ringerModeTracker.ringerModeInternal.value ?: DEFAULT_LAST_NON_SILENT_VALUE
+            )
+        }
+
+    private fun <T> LiveData<T>.asFlow(): Flow<T?> =
+        conflatedCallbackFlow {
+            val observer = Observer { value: T -> trySend(value) }
+            observeForever(observer)
+            send(value)
+            awaitClose { removeObserver(observer) }
+        }.flowOn(mainDispatcher)
+
+    companion object {
+        const val LAST_NON_SILENT_RINGER_MODE_KEY = "key_last_non_silent_ringer_mode"
+        const val MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME = "quick_affordance_mute_ringer_mode_cache"
+        private const val DEFAULT_LAST_NON_SILENT_VALUE = AudioManager.RINGER_MODE_NORMAL
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt
new file mode 100644
index 0000000..cd0805e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.content.Context
+import android.media.AudioManager
+import androidx.lifecycle.Observer
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.RingerModeTracker
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+/**
+ * Store previous non-silent Ringer Mode into shared prefs to be used for Mute Lockscreen Shortcut
+ */
+@SysUISingleton
+class MuteQuickAffordanceCoreStartable @Inject constructor(
+    private val featureFlags: FeatureFlags,
+    private val userTracker: UserTracker,
+    private val ringerModeTracker: RingerModeTracker,
+    private val userFileManager: UserFileManager,
+    private val keyguardQuickAffordanceRepository: KeyguardQuickAffordanceRepository,
+    @Application private val coroutineScope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+) : CoreStartable {
+
+    private val observer = Observer(this::updateLastNonSilentRingerMode)
+
+    override fun start() {
+        if (!featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES)) return
+
+        // only listen to ringerModeInternal changes when Mute is one of the selected affordances
+        keyguardQuickAffordanceRepository
+            .selections
+            .map { selections ->
+                // determines if Mute is selected in any lockscreen shortcut position
+                val muteSelected: Boolean = selections.values.any { configList ->
+                    configList.any { config ->
+                        config.key == BuiltInKeyguardQuickAffordanceKeys.MUTE
+                    }
+                }
+                if (muteSelected) {
+                    ringerModeTracker.ringerModeInternal.observeForever(observer)
+                } else {
+                    ringerModeTracker.ringerModeInternal.removeObserver(observer)
+                }
+            }
+            .launchIn(coroutineScope)
+    }
+
+    private fun updateLastNonSilentRingerMode(lastRingerMode: Int) {
+        coroutineScope.launch(backgroundDispatcher) {
+            if (AudioManager.RINGER_MODE_SILENT != lastRingerMode) {
+                userFileManager.getSharedPreferences(
+                        MuteQuickAffordanceConfig.MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME,
+                        Context.MODE_PRIVATE,
+                        userTracker.userId
+                )
+                .edit()
+                .putInt(MuteQuickAffordanceConfig.LAST_NON_SILENT_RINGER_MODE_KEY, lastRingerMode)
+                .apply()
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricRepository.kt
deleted file mode 100644
index de15890..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricRepository.kt
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.keyguard.data.repository
-
-import android.app.admin.DevicePolicyManager
-import android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
-import android.content.Context
-import android.content.IntentFilter
-import android.os.Looper
-import android.os.UserHandle
-import com.android.internal.widget.LockPatternUtils
-import com.android.systemui.biometrics.AuthController
-import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
-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.dagger.qualifiers.Main
-import com.android.systemui.user.data.repository.UserRepository
-import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.flow.transformLatest
-
-/**
- * Acts as source of truth for biometric features.
- *
- * Abstracts-away data sources and their schemas so the rest of the app doesn't need to worry about
- * upstream changes.
- */
-interface BiometricRepository {
-    /** Whether any fingerprints are enrolled for the current user. */
-    val isFingerprintEnrolled: StateFlow<Boolean>
-
-    /**
-     * Whether the current user is allowed to use a strong biometric for device entry based on
-     * Android Security policies. If false, the user may be able to use primary authentication for
-     * device entry.
-     */
-    val isStrongBiometricAllowed: StateFlow<Boolean>
-
-    /** Whether fingerprint feature is enabled for the current user by the DevicePolicy */
-    val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean>
-}
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SysUISingleton
-class BiometricRepositoryImpl
-@Inject
-constructor(
-    context: Context,
-    lockPatternUtils: LockPatternUtils,
-    broadcastDispatcher: BroadcastDispatcher,
-    authController: AuthController,
-    userRepository: UserRepository,
-    devicePolicyManager: DevicePolicyManager,
-    @Application scope: CoroutineScope,
-    @Background backgroundDispatcher: CoroutineDispatcher,
-    @Main looper: Looper,
-) : BiometricRepository {
-
-    /** UserId of the current selected user. */
-    private val selectedUserId: Flow<Int> =
-        userRepository.selectedUserInfo.map { it.id }.distinctUntilChanged()
-
-    override val isFingerprintEnrolled: StateFlow<Boolean> =
-        selectedUserId
-            .flatMapLatest { userId ->
-                conflatedCallbackFlow {
-                    val callback =
-                        object : AuthController.Callback {
-                            override fun onEnrollmentsChanged(
-                                sensorBiometricType: BiometricType,
-                                userId: Int,
-                                hasEnrollments: Boolean
-                            ) {
-                                if (sensorBiometricType.isFingerprint) {
-                                    trySendWithFailureLogging(
-                                        hasEnrollments,
-                                        TAG,
-                                        "update fpEnrollment"
-                                    )
-                                }
-                            }
-                        }
-                    authController.addCallback(callback)
-                    awaitClose { authController.removeCallback(callback) }
-                }
-            }
-            .stateIn(
-                scope,
-                started = SharingStarted.Eagerly,
-                initialValue =
-                    authController.isFingerprintEnrolled(userRepository.getSelectedUserInfo().id)
-            )
-
-    override val isStrongBiometricAllowed: StateFlow<Boolean> =
-        selectedUserId
-            .flatMapLatest { currUserId ->
-                conflatedCallbackFlow {
-                    val callback =
-                        object : LockPatternUtils.StrongAuthTracker(context, looper) {
-                            override fun onStrongAuthRequiredChanged(userId: Int) {
-                                if (currUserId != userId) {
-                                    return
-                                }
-
-                                trySendWithFailureLogging(
-                                    isBiometricAllowedForUser(true, currUserId),
-                                    TAG
-                                )
-                            }
-
-                            override fun onIsNonStrongBiometricAllowedChanged(userId: Int) {
-                                // no-op
-                            }
-                        }
-                    lockPatternUtils.registerStrongAuthTracker(callback)
-                    awaitClose { lockPatternUtils.unregisterStrongAuthTracker(callback) }
-                }
-            }
-            .stateIn(
-                scope,
-                started = SharingStarted.Eagerly,
-                initialValue =
-                    lockPatternUtils.isBiometricAllowedForUser(
-                        userRepository.getSelectedUserInfo().id
-                    )
-            )
-
-    override val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean> =
-        selectedUserId
-            .flatMapLatest { userId ->
-                broadcastDispatcher
-                    .broadcastFlow(
-                        filter = IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
-                        user = UserHandle.ALL
-                    )
-                    .transformLatest {
-                        emit(
-                            (devicePolicyManager.getKeyguardDisabledFeatures(null, userId) and
-                                DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) == 0
-                        )
-                    }
-                    .flowOn(backgroundDispatcher)
-                    .distinctUntilChanged()
-            }
-            .stateIn(
-                scope,
-                started = SharingStarted.Eagerly,
-                initialValue =
-                    devicePolicyManager.getKeyguardDisabledFeatures(
-                        null,
-                        userRepository.getSelectedUserInfo().id
-                    ) and DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT == 0
-            )
-
-    companion object {
-        private const val TAG = "BiometricsRepositoryImpl"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
new file mode 100644
index 0000000..baadc66
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.keyguard.data.repository
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
+import android.content.Context
+import android.content.IntentFilter
+import android.hardware.biometrics.BiometricManager
+import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
+import android.os.Looper
+import android.os.UserHandle
+import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.Dumpable
+import com.android.systemui.biometrics.AuthController
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+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.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.user.data.repository.UserRepository
+import java.io.PrintWriter
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.transformLatest
+
+/**
+ * Acts as source of truth for biometric authentication related settings like enrollments, device
+ * policy, etc.
+ *
+ * Abstracts-away data sources and their schemas so the rest of the app doesn't need to worry about
+ * upstream changes.
+ */
+interface BiometricSettingsRepository {
+    /** Whether any fingerprints are enrolled for the current user. */
+    val isFingerprintEnrolled: StateFlow<Boolean>
+
+    /** Whether face authentication is enrolled for the current user. */
+    val isFaceEnrolled: Flow<Boolean>
+
+    /**
+     * Whether face authentication is enabled/disabled based on system settings like device policy,
+     * biometrics setting.
+     */
+    val isFaceAuthenticationEnabled: Flow<Boolean>
+
+    /**
+     * Whether the current user is allowed to use a strong biometric for device entry based on
+     * Android Security policies. If false, the user may be able to use primary authentication for
+     * device entry.
+     */
+    val isStrongBiometricAllowed: StateFlow<Boolean>
+
+    /** Whether fingerprint feature is enabled for the current user by the DevicePolicy */
+    val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean>
+}
+
+@SysUISingleton
+class BiometricSettingsRepositoryImpl
+@Inject
+constructor(
+    context: Context,
+    lockPatternUtils: LockPatternUtils,
+    broadcastDispatcher: BroadcastDispatcher,
+    authController: AuthController,
+    userRepository: UserRepository,
+    devicePolicyManager: DevicePolicyManager,
+    @Application scope: CoroutineScope,
+    @Background backgroundDispatcher: CoroutineDispatcher,
+    biometricManager: BiometricManager?,
+    @Main looper: Looper,
+    dumpManager: DumpManager,
+) : BiometricSettingsRepository, Dumpable {
+
+    init {
+        dumpManager.registerDumpable(this)
+    }
+
+    override fun dump(pw: PrintWriter, args: Array<String?>) {
+        pw.println("isFingerprintEnrolled=${isFingerprintEnrolled.value}")
+        pw.println("isStrongBiometricAllowed=${isStrongBiometricAllowed.value}")
+        pw.println("isFingerprintEnabledByDevicePolicy=${isFingerprintEnabledByDevicePolicy.value}")
+    }
+
+    /** UserId of the current selected user. */
+    private val selectedUserId: Flow<Int> =
+        userRepository.selectedUserInfo.map { it.id }.distinctUntilChanged()
+
+    private val devicePolicyChangedForAllUsers =
+        broadcastDispatcher.broadcastFlow(
+            filter = IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+            user = UserHandle.ALL
+        )
+
+    override val isFingerprintEnrolled: StateFlow<Boolean> =
+        selectedUserId
+            .flatMapLatest { currentUserId ->
+                conflatedCallbackFlow {
+                    val callback =
+                        object : AuthController.Callback {
+                            override fun onEnrollmentsChanged(
+                                sensorBiometricType: BiometricType,
+                                userId: Int,
+                                hasEnrollments: Boolean
+                            ) {
+                                if (sensorBiometricType.isFingerprint && userId == currentUserId) {
+                                    trySendWithFailureLogging(
+                                        hasEnrollments,
+                                        TAG,
+                                        "update fpEnrollment"
+                                    )
+                                }
+                            }
+                        }
+                    authController.addCallback(callback)
+                    awaitClose { authController.removeCallback(callback) }
+                }
+            }
+            .stateIn(
+                scope,
+                started = SharingStarted.Eagerly,
+                initialValue =
+                    authController.isFingerprintEnrolled(userRepository.getSelectedUserInfo().id)
+            )
+
+    override val isFaceEnrolled: Flow<Boolean> =
+        selectedUserId.flatMapLatest { selectedUserId: Int ->
+            conflatedCallbackFlow {
+                val callback =
+                    object : AuthController.Callback {
+                        override fun onEnrollmentsChanged(
+                            sensorBiometricType: BiometricType,
+                            userId: Int,
+                            hasEnrollments: Boolean
+                        ) {
+                            // TODO(b/242022358), use authController.isFaceAuthEnrolled after
+                            //  ag/20176811 is available.
+                            if (
+                                sensorBiometricType == BiometricType.FACE &&
+                                    userId == selectedUserId
+                            ) {
+                                trySendWithFailureLogging(
+                                    hasEnrollments,
+                                    TAG,
+                                    "Face enrollment changed"
+                                )
+                            }
+                        }
+                    }
+                authController.addCallback(callback)
+                trySendWithFailureLogging(
+                    authController.isFaceAuthEnrolled(selectedUserId),
+                    TAG,
+                    "Initial value of face auth enrollment"
+                )
+                awaitClose { authController.removeCallback(callback) }
+            }
+        }
+
+    override val isFaceAuthenticationEnabled: Flow<Boolean>
+        get() =
+            combine(isFaceEnabledByBiometricsManager, isFaceEnabledByDevicePolicy) {
+                biometricsManagerSetting,
+                devicePolicySetting ->
+                biometricsManagerSetting && devicePolicySetting
+            }
+
+    private val isFaceEnabledByDevicePolicy: Flow<Boolean> =
+        combine(selectedUserId, devicePolicyChangedForAllUsers) { userId, _ ->
+                devicePolicyManager.isFaceDisabled(userId)
+            }
+            .onStart {
+                emit(devicePolicyManager.isFaceDisabled(userRepository.getSelectedUserInfo().id))
+            }
+            .flowOn(backgroundDispatcher)
+            .distinctUntilChanged()
+
+    private val isFaceEnabledByBiometricsManager =
+        conflatedCallbackFlow {
+                val callback =
+                    object : IBiometricEnabledOnKeyguardCallback.Stub() {
+                        override fun onChanged(enabled: Boolean, userId: Int) {
+                            trySendWithFailureLogging(
+                                enabled,
+                                TAG,
+                                "biometricsEnabled state changed"
+                            )
+                        }
+                    }
+                biometricManager?.registerEnabledOnKeyguardCallback(callback)
+                awaitClose {}
+            }
+            // This is because the callback is binder-based and we want to avoid multiple callbacks
+            // being registered.
+            .stateIn(scope, SharingStarted.Eagerly, false)
+
+    override val isStrongBiometricAllowed: StateFlow<Boolean> =
+        selectedUserId
+            .flatMapLatest { currUserId ->
+                conflatedCallbackFlow {
+                    val callback =
+                        object : LockPatternUtils.StrongAuthTracker(context, looper) {
+                            override fun onStrongAuthRequiredChanged(userId: Int) {
+                                if (currUserId != userId) {
+                                    return
+                                }
+
+                                trySendWithFailureLogging(
+                                    isBiometricAllowedForUser(true, currUserId),
+                                    TAG
+                                )
+                            }
+
+                            override fun onIsNonStrongBiometricAllowedChanged(userId: Int) {
+                                // no-op
+                            }
+                        }
+                    lockPatternUtils.registerStrongAuthTracker(callback)
+                    awaitClose { lockPatternUtils.unregisterStrongAuthTracker(callback) }
+                }
+            }
+            .stateIn(
+                scope,
+                started = SharingStarted.Eagerly,
+                initialValue =
+                    lockPatternUtils.isBiometricAllowedForUser(
+                        userRepository.getSelectedUserInfo().id
+                    )
+            )
+
+    override val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean> =
+        selectedUserId
+            .flatMapLatest { userId ->
+                devicePolicyChangedForAllUsers
+                    .transformLatest { emit(devicePolicyManager.isFingerprintDisabled(userId)) }
+                    .flowOn(backgroundDispatcher)
+                    .distinctUntilChanged()
+            }
+            .stateIn(
+                scope,
+                started = SharingStarted.Eagerly,
+                initialValue =
+                    devicePolicyManager.isFingerprintDisabled(
+                        userRepository.getSelectedUserInfo().id
+                    )
+            )
+
+    companion object {
+        private const val TAG = "BiometricsRepositoryImpl"
+    }
+}
+
+private fun DevicePolicyManager.isFaceDisabled(userId: Int): Boolean =
+    isNotActive(userId, DevicePolicyManager.KEYGUARD_DISABLE_FACE)
+
+private fun DevicePolicyManager.isFingerprintDisabled(userId: Int): Boolean =
+    isNotActive(userId, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT)
+
+private fun DevicePolicyManager.isNotActive(userId: Int, policy: Int): Boolean =
+    (getKeyguardDisabledFeatures(null, userId) and policy) == 0
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
index b3a9cf5..7c46684 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
@@ -19,10 +19,13 @@
 import android.hardware.biometrics.BiometricSourceType
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.Dumpable
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 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.dump.DumpManager
+import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
@@ -49,7 +52,16 @@
 constructor(
     val keyguardUpdateMonitor: KeyguardUpdateMonitor,
     @Application scope: CoroutineScope,
-) : DeviceEntryFingerprintAuthRepository {
+    dumpManager: DumpManager,
+) : DeviceEntryFingerprintAuthRepository, Dumpable {
+
+    init {
+        dumpManager.registerDumpable(this)
+    }
+
+    override fun dump(pw: PrintWriter, args: Array<String?>) {
+        pw.println("isLockedOut=${isLockedOut.value}")
+    }
 
     override val isLockedOut: StateFlow<Boolean> =
         conflatedCallbackFlow {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index 35ae9b4..091acad 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -41,31 +41,96 @@
  *
  * Make sure to add newly added flows to the logger.
  */
+interface KeyguardBouncerRepository {
+    /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
+    val primaryBouncerVisible: StateFlow<Boolean>
+    val primaryBouncerShow: StateFlow<KeyguardBouncerModel?>
+    val primaryBouncerShowingSoon: StateFlow<Boolean>
+    val primaryBouncerHide: StateFlow<Boolean>
+    val primaryBouncerStartingToHide: StateFlow<Boolean>
+    val primaryBouncerStartingDisappearAnimation: StateFlow<Runnable?>
+    /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
+    val primaryBouncerScrimmed: StateFlow<Boolean>
+    /**
+     * Set how much of the notification panel is showing on the screen.
+     * ```
+     *      0f = panel fully hidden = bouncer fully showing
+     *      1f = panel fully showing = bouncer fully hidden
+     * ```
+     */
+    val panelExpansionAmount: StateFlow<Float>
+    val keyguardPosition: StateFlow<Float>
+    val onScreenTurnedOff: StateFlow<Boolean>
+    val isBackButtonEnabled: StateFlow<Boolean?>
+    /** Determines if user is already unlocked */
+    val keyguardAuthenticated: StateFlow<Boolean?>
+    val showMessage: StateFlow<BouncerShowMessageModel?>
+    val resourceUpdateRequests: StateFlow<Boolean>
+    val bouncerPromptReason: Int
+    val bouncerErrorMessage: CharSequence?
+    val isAlternateBouncerVisible: StateFlow<Boolean>
+    val isAlternateBouncerUIAvailable: StateFlow<Boolean>
+    var lastAlternateBouncerVisibleTime: Long
+
+    fun setPrimaryScrimmed(isScrimmed: Boolean)
+
+    fun setPrimaryVisible(isVisible: Boolean)
+
+    fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?)
+
+    fun setPrimaryShowingSoon(showingSoon: Boolean)
+
+    fun setPrimaryHide(hide: Boolean)
+
+    fun setPrimaryStartingToHide(startingToHide: Boolean)
+
+    fun setPrimaryStartDisappearAnimation(runnable: Runnable?)
+
+    fun setPanelExpansion(panelExpansion: Float)
+
+    fun setKeyguardPosition(keyguardPosition: Float)
+
+    fun setResourceUpdateRequests(willUpdateResources: Boolean)
+
+    fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?)
+
+    fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?)
+
+    fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean)
+
+    fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean)
+
+    fun setAlternateVisible(isVisible: Boolean)
+
+    fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
+}
+
 @SysUISingleton
-class KeyguardBouncerRepository
+class KeyguardBouncerRepositoryImpl
 @Inject
 constructor(
     private val viewMediatorCallback: ViewMediatorCallback,
     private val clock: SystemClock,
     @Application private val applicationScope: CoroutineScope,
     @BouncerLog private val buffer: TableLogBuffer,
-) {
+) : KeyguardBouncerRepository {
     /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
     private val _primaryBouncerVisible = MutableStateFlow(false)
-    val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
+    override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
     private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
-    val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
+    override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
     private val _primaryBouncerShowingSoon = MutableStateFlow(false)
-    val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
+    override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
     private val _primaryBouncerHide = MutableStateFlow(false)
-    val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
+    override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
     private val _primaryBouncerStartingToHide = MutableStateFlow(false)
-    val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
+    override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
     private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
-    val primaryBouncerStartingDisappearAnimation = _primaryBouncerDisappearAnimation.asStateFlow()
+    override val primaryBouncerStartingDisappearAnimation =
+        _primaryBouncerDisappearAnimation.asStateFlow()
     /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
     private val _primaryBouncerScrimmed = MutableStateFlow(false)
-    val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
+    override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
     /**
      * Set how much of the notification panel is showing on the screen.
      * ```
@@ -74,46 +139,46 @@
      * ```
      */
     private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
-    val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
+    override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
     private val _keyguardPosition = MutableStateFlow(0f)
-    val keyguardPosition = _keyguardPosition.asStateFlow()
+    override val keyguardPosition = _keyguardPosition.asStateFlow()
     private val _onScreenTurnedOff = MutableStateFlow(false)
-    val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
+    override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
     private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
-    val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
+    override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
     private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
     /** Determines if user is already unlocked */
-    val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
+    override val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
     private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
-    val showMessage = _showMessage.asStateFlow()
+    override val showMessage = _showMessage.asStateFlow()
     private val _resourceUpdateRequests = MutableStateFlow(false)
-    val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
-    val bouncerPromptReason: Int
+    override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
+    override val bouncerPromptReason: Int
         get() = viewMediatorCallback.bouncerPromptReason
-    val bouncerErrorMessage: CharSequence?
+    override val bouncerErrorMessage: CharSequence?
         get() = viewMediatorCallback.consumeCustomMessage()
 
     /** Values associated with the AlternateBouncer */
     private val _isAlternateBouncerVisible = MutableStateFlow(false)
-    val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
-    var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE
-    private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
-    val isAlternateBouncerUIAvailable: StateFlow<Boolean> =
+    override val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
+    override var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE
+    private val _isAlternateBouncerUIAvailable = MutableStateFlow(false)
+    override val isAlternateBouncerUIAvailable: StateFlow<Boolean> =
         _isAlternateBouncerUIAvailable.asStateFlow()
 
     init {
         setUpLogging()
     }
 
-    fun setPrimaryScrimmed(isScrimmed: Boolean) {
+    override fun setPrimaryScrimmed(isScrimmed: Boolean) {
         _primaryBouncerScrimmed.value = isScrimmed
     }
 
-    fun setPrimaryVisible(isVisible: Boolean) {
+    override fun setPrimaryVisible(isVisible: Boolean) {
         _primaryBouncerVisible.value = isVisible
     }
 
-    fun setAlternateVisible(isVisible: Boolean) {
+    override fun setAlternateVisible(isVisible: Boolean) {
         if (isVisible && !_isAlternateBouncerVisible.value) {
             lastAlternateBouncerVisibleTime = clock.uptimeMillis()
         } else if (!isVisible) {
@@ -122,55 +187,55 @@
         _isAlternateBouncerVisible.value = isVisible
     }
 
-    fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
+    override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
         _isAlternateBouncerUIAvailable.value = isAvailable
     }
 
-    fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
+    override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
         _primaryBouncerShow.value = keyguardBouncerModel
     }
 
-    fun setPrimaryShowingSoon(showingSoon: Boolean) {
+    override fun setPrimaryShowingSoon(showingSoon: Boolean) {
         _primaryBouncerShowingSoon.value = showingSoon
     }
 
-    fun setPrimaryHide(hide: Boolean) {
+    override fun setPrimaryHide(hide: Boolean) {
         _primaryBouncerHide.value = hide
     }
 
-    fun setPrimaryStartingToHide(startingToHide: Boolean) {
+    override fun setPrimaryStartingToHide(startingToHide: Boolean) {
         _primaryBouncerStartingToHide.value = startingToHide
     }
 
-    fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
+    override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
         _primaryBouncerDisappearAnimation.value = runnable
     }
 
-    fun setPanelExpansion(panelExpansion: Float) {
+    override fun setPanelExpansion(panelExpansion: Float) {
         _panelExpansionAmount.value = panelExpansion
     }
 
-    fun setKeyguardPosition(keyguardPosition: Float) {
+    override fun setKeyguardPosition(keyguardPosition: Float) {
         _keyguardPosition.value = keyguardPosition
     }
 
-    fun setResourceUpdateRequests(willUpdateResources: Boolean) {
+    override fun setResourceUpdateRequests(willUpdateResources: Boolean) {
         _resourceUpdateRequests.value = willUpdateResources
     }
 
-    fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
+    override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
         _showMessage.value = bouncerShowMessageModel
     }
 
-    fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
+    override fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
         _keyguardAuthenticated.value = keyguardAuthenticated
     }
 
-    fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
+    override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
         _isBackButtonEnabled.value = isBackButtonEnabled
     }
 
-    fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
+    override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
         _onScreenTurnedOff.value = onScreenTurnedOff
     }
 
@@ -225,6 +290,9 @@
         resourceUpdateRequests
             .logDiffsForTable(buffer, "", "ResourceUpdateRequests", false)
             .launchIn(applicationScope)
+        isAlternateBouncerUIAvailable
+            .logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
+            .launchIn(applicationScope)
     }
 
     companion object {
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 2b2b9d0..8ece318 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
@@ -146,7 +146,7 @@
      * Returns a snapshot of the [KeyguardQuickAffordanceConfig] instances of the affordances at the
      * slot with the given ID. The configs are sorted in descending priority order.
      */
-    fun getSelections(slotId: String): List<KeyguardQuickAffordanceConfig> {
+    fun getCurrentSelections(slotId: String): List<KeyguardQuickAffordanceConfig> {
         val selections = selectionManager.value.getSelections().getOrDefault(slotId, emptyList())
         return configs.filter { selections.contains(it.key) }
     }
@@ -155,7 +155,7 @@
      * Returns a snapshot of the IDs of the selected affordances, indexed by slot ID. The configs
      * are sorted in descending priority order.
      */
-    fun getSelections(): Map<String, List<String>> {
+    fun getCurrentSelections(): Map<String, List<String>> {
         return selectionManager.value.getSelections()
     }
 
@@ -217,7 +217,7 @@
     private inner class Dumpster : Dumpable {
         override fun dump(pw: PrintWriter, args: Array<out String>) {
             val slotPickerRepresentations = getSlotPickerRepresentations()
-            val selectionsBySlotId = getSelections()
+            val selectionsBySlotId = getCurrentSelections()
             pw.println("Slots & selections:")
             slotPickerRepresentations.forEach { slotPickerRepresentation ->
                 val slotId = slotPickerRepresentation.id
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
index cc99eb7..4a262f5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
@@ -31,10 +31,16 @@
     @Binds
     fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository
 
-    @Binds fun biometricRepository(impl: BiometricRepositoryImpl): BiometricRepository
+    @Binds
+    fun biometricSettingsRepository(
+        impl: BiometricSettingsRepositoryImpl
+    ): BiometricSettingsRepository
 
     @Binds
     fun deviceEntryFingerprintAuthRepository(
         impl: DeviceEntryFingerprintAuthRepositoryImpl
     ): DeviceEntryFingerprintAuthRepository
+
+    @Binds
+    fun keyguardBouncerRepository(impl: KeyguardBouncerRepositoryImpl): KeyguardBouncerRepository
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
index 6020ef8..6452e0e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
@@ -20,7 +20,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.BiometricRepository
+import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.LegacyAlternateBouncer
@@ -34,7 +34,7 @@
 @Inject
 constructor(
     private val bouncerRepository: KeyguardBouncerRepository,
-    private val biometricRepository: BiometricRepository,
+    private val biometricSettingsRepository: BiometricSettingsRepository,
     private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
     private val systemClock: SystemClock,
     private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
@@ -99,9 +99,9 @@
     fun canShowAlternateBouncerForFingerprint(): Boolean {
         return if (isModernAlternateBouncerEnabled) {
             bouncerRepository.isAlternateBouncerUIAvailable.value &&
-                biometricRepository.isFingerprintEnrolled.value &&
-                biometricRepository.isStrongBiometricAllowed.value &&
-                biometricRepository.isFingerprintEnabledByDevicePolicy.value &&
+                biometricSettingsRepository.isFingerprintEnrolled.value &&
+                biometricSettingsRepository.isStrongBiometricAllowed.value &&
+                biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value &&
                 !deviceEntryFingerprintAuthRepository.isLockedOut.value
         } else {
             legacyAlternateBouncer != null &&
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index ce61f2f..86f65dde 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionInfo
 import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
@@ -44,6 +45,7 @@
 
     override fun start() {
         listenForDozingToLockscreen()
+        listenForDozingToGone()
     }
 
     private fun listenForDozingToLockscreen() {
@@ -68,6 +70,28 @@
         }
     }
 
+    private fun listenForDozingToGone() {
+        scope.launch {
+            keyguardInteractor.biometricUnlockState
+                .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
+                .collect { (biometricUnlockState, lastStartedTransition) ->
+                    if (
+                        lastStartedTransition.to == KeyguardState.DOZING &&
+                            isWakeAndUnlock(biometricUnlockState)
+                    ) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                name,
+                                KeyguardState.DOZING,
+                                KeyguardState.GONE,
+                                getAnimator(),
+                            )
+                        )
+                    }
+                }
+        }
+    }
+
     private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
         return ValueAnimator().apply {
             setInterpolator(Interpolators.LINEAR)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 81a5828..8715d1f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -34,6 +34,7 @@
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.launch
 
@@ -56,9 +57,14 @@
 
     private fun listenForDreamingToLockscreen() {
         scope.launch {
-            // Using isDreamingWithOverlay provides an optimized path to LOCKSCREEN state, which
-            // otherwise would have gone through OCCLUDED first
-            keyguardInteractor.isAbleToDream
+            // Dependending on the dream, either dream state or occluded change will change first,
+            // so listen for both
+            combine(keyguardInteractor.isAbleToDream, keyguardInteractor.isKeyguardOccluded) {
+                    isAbleToDream,
+                    isKeyguardOccluded ->
+                    isAbleToDream && isKeyguardOccluded
+                }
+                .distinctUntilChanged()
                 .sample(
                     combine(
                         keyguardInteractor.dozeTransitionModel,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 3d39da6..7e86a5d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -22,6 +22,8 @@
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
 import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
@@ -31,7 +33,6 @@
 import com.android.systemui.keyguard.shared.model.StatusBarState
 import com.android.systemui.keyguard.shared.model.WakefulnessModel
 import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.statusbar.CommandQueue.Callbacks
 import javax.inject.Inject
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.delay
@@ -41,7 +42,9 @@
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onStart
 
 /**
  * Encapsulates business-logic related to the keyguard but not to a more specific part within it.
@@ -52,6 +55,7 @@
 constructor(
     private val repository: KeyguardRepository,
     private val commandQueue: CommandQueue,
+    featureFlags: FeatureFlags,
 ) {
     /**
      * The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at
@@ -129,6 +133,29 @@
      */
     val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState
 
+    /** Keyguard is present and is not occluded. */
+    val isKeyguardVisible: Flow<Boolean> =
+        combine(isKeyguardShowing, isKeyguardOccluded) { showing, occluded -> showing && !occluded }
+
+    /** Whether camera is launched over keyguard. */
+    var isSecureCameraActive =
+        if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) {
+            combine(
+                    isKeyguardVisible,
+                    repository.isBouncerShowing,
+                    onCameraLaunchDetected,
+                ) { isKeyguardVisible, isBouncerShowing, cameraLaunchEvent ->
+                    when {
+                        isKeyguardVisible -> false
+                        isBouncerShowing -> false
+                        else -> cameraLaunchEvent == CameraLaunchSourceModel.POWER_DOUBLE_TAP
+                    }
+                }
+                .onStart { emit(false) }
+        } else {
+            flowOf(false)
+        }
+
     /** The approximate location on the screen of the fingerprint sensor, if one is available. */
     val fingerprintSensorLocation: Flow<Point?> = repository.fingerprintSensorLocation
 
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 9ddc575..fb0fb1f 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
@@ -154,7 +154,11 @@
         val slots = repository.get().getSlotPickerRepresentations()
         val slot = slots.find { it.id == slotId } ?: return false
         val selections =
-            repository.get().getSelections().getOrDefault(slotId, emptyList()).toMutableList()
+            repository
+                .get()
+                .getCurrentSelections()
+                .getOrDefault(slotId, emptyList())
+                .toMutableList()
         val alreadySelected = selections.remove(affordanceId)
         if (!alreadySelected) {
             while (selections.size > 0 && selections.size >= slot.maxSelectedAffordances) {
@@ -193,7 +197,7 @@
 
         if (affordanceId.isNullOrEmpty()) {
             return if (
-                repository.get().getSelections().getOrDefault(slotId, emptyList()).isEmpty()
+                repository.get().getCurrentSelections().getOrDefault(slotId, emptyList()).isEmpty()
             ) {
                 false
             } else {
@@ -203,7 +207,11 @@
         }
 
         val selections =
-            repository.get().getSelections().getOrDefault(slotId, emptyList()).toMutableList()
+            repository
+                .get()
+                .getCurrentSelections()
+                .getOrDefault(slotId, emptyList())
+                .toMutableList()
         return if (selections.remove(affordanceId)) {
             repository
                 .get()
@@ -220,7 +228,7 @@
     /** Returns affordance IDs indexed by slot ID, for all known slots. */
     suspend fun getSelections(): Map<String, List<KeyguardQuickAffordancePickerRepresentation>> {
         val slots = repository.get().getSlotPickerRepresentations()
-        val selections = repository.get().getSelections()
+        val selections = repository.get().getCurrentSelections()
         val affordanceById =
             getAffordancePickerRepresentations().associateBy { affordance -> affordance.id }
         return slots.associate { slot ->
@@ -367,6 +375,10 @@
                 name = Contract.FlagsTable.FLAG_NAME_WALLPAPER_FULLSCREEN_PREVIEW,
                 value = featureFlags.isEnabled(Flags.WALLPAPER_FULLSCREEN_PREVIEW),
             ),
+            KeyguardPickerFlag(
+                name = Contract.FlagsTable.FLAG_NAME_MONOCHROMATIC_THEME,
+                value = featureFlags.isEnabled(Flags.MONOCHROMATIC_THEME)
+            )
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
index ad6dbea..84bcdf9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
@@ -19,7 +19,6 @@
 
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.AnimationParams
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
 import com.android.systemui.keyguard.shared.model.KeyguardState.BOUNCER
@@ -31,9 +30,6 @@
 import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import javax.inject.Inject
-import kotlin.math.max
-import kotlin.math.min
-import kotlin.time.Duration
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
@@ -46,6 +42,10 @@
 constructor(
     repository: KeyguardTransitionRepository,
 ) {
+    /** (any)->GONE transition information */
+    val anyStateToGoneTransition: Flow<TransitionStep> =
+        repository.transitions.filter { step -> step.to == KeyguardState.GONE }
+
     /** (any)->AOD transition information */
     val anyStateToAodTransition: Flow<TransitionStep> =
         repository.transitions.filter { step -> step.to == KeyguardState.AOD }
@@ -104,38 +104,4 @@
     /* The last completed [KeyguardState] transition */
     val finishedKeyguardState: Flow<KeyguardState> =
         finishedKeyguardTransitionStep.map { step -> step.to }
-
-    /**
-     * Transitions will occur over a [totalDuration] with [TransitionStep]s being emitted in the
-     * range of [0, 1]. View animations should begin and end within a subset of this range. This
-     * function maps the [startTime] and [duration] into [0, 1], when this subset is valid.
-     */
-    fun transitionStepAnimation(
-        flow: Flow<TransitionStep>,
-        params: AnimationParams,
-        totalDuration: Duration,
-    ): Flow<Float> {
-        val start = (params.startTime / totalDuration).toFloat()
-        val chunks = (totalDuration / params.duration).toFloat()
-        var isRunning = false
-        return flow
-            .map { step ->
-                val value = (step.value - start) * chunks
-                if (step.transitionState == STARTED) {
-                    // When starting, make sure to always emit. If a transition is started from the
-                    // middle, it is possible this animation is being skipped but we need to inform
-                    // the ViewModels of the last update
-                    isRunning = true
-                    max(0f, min(1f, value))
-                } else if (isRunning && value >= 1f) {
-                    // Always send a final value of 1. Because of rounding, [value] may never be
-                    // exactly 1.
-                    isRunning = false
-                    1f
-                } else {
-                    value
-                }
-            }
-            .filter { value -> value >= 0f && value <= 1f }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index 6679b22..4579e37 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -111,6 +111,8 @@
                 0f
             }
         }
+    /** Allow for interaction when just about fully visible */
+    val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
 
     // TODO(b/243685699): Move isScrimmed logic to data layer.
     // TODO(b/243695312): Encapsulate all of the show logic for the bouncer.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt
index 8222dd5..3b3ec39 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt
@@ -26,4 +26,10 @@
     const val EXPANSION_HIDDEN = 1f
     const val EXPANSION_VISIBLE = 0f
     const val ALPHA_EXPANSION_THRESHOLD = 0.95f
+
+    /**
+     * This value is used for denoting the PIN length at which we want to layout the view in which
+     * PIN hinting is enabled
+     */
+    const val DEFAULT_PIN_LENGTH = 6
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AnimationParams.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AnimationParams.kt
deleted file mode 100644
index 67733e9..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AnimationParams.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.systemui.keyguard.shared.model
-
-import kotlin.time.Duration
-import kotlin.time.Duration.Companion.milliseconds
-
-/** Animation parameters */
-data class AnimationParams(
-    val startTime: Duration = 0.milliseconds,
-    val duration: Duration,
-)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
new file mode 100644
index 0000000..ca1e27c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.keyguard.ui
+
+import android.view.animation.Interpolator
+import com.android.systemui.animation.Interpolators.LINEAR
+import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
+import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
+import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
+import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import kotlin.math.max
+import kotlin.math.min
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
+
+/**
+ * For the given transition params, construct a flow using [createFlow] for the specified portion of
+ * the overall transition.
+ */
+class KeyguardTransitionAnimationFlow(
+    private val transitionDuration: Duration,
+    private val transitionFlow: Flow<TransitionStep>,
+) {
+    /**
+     * Transitions will occur over a [transitionDuration] with [TransitionStep]s being emitted in
+     * the range of [0, 1]. View animations should begin and end within a subset of this range. This
+     * function maps the [startTime] and [duration] into [0, 1], when this subset is valid.
+     */
+    fun createFlow(
+        duration: Duration,
+        onStep: (Float) -> Float,
+        startTime: Duration = 0.milliseconds,
+        onCancel: (() -> Float)? = null,
+        onFinish: (() -> Float)? = null,
+        interpolator: Interpolator = LINEAR,
+    ): Flow<Float> {
+        if (!duration.isPositive()) {
+            throw IllegalArgumentException("duration must be a positive number: $duration")
+        }
+        if ((startTime + duration).compareTo(transitionDuration) > 0) {
+            throw IllegalArgumentException(
+                "startTime($startTime) + duration($duration) must be" +
+                    " <= transitionDuration($transitionDuration)"
+            )
+        }
+
+        val start = (startTime / transitionDuration).toFloat()
+        val chunks = (transitionDuration / duration).toFloat()
+        var isComplete = true
+
+        fun stepToValue(step: TransitionStep): Float? {
+            val value = (step.value - start) * chunks
+            return when (step.transitionState) {
+                // When starting, make sure to always emit. If a transition is started from the
+                // middle, it is possible this animation is being skipped but we need to inform
+                // the ViewModels of the last update
+                STARTED -> {
+                    isComplete = false
+                    max(0f, min(1f, value))
+                }
+                // Always send a final value of 1. Because of rounding, [value] may never be
+                // exactly 1.
+                RUNNING ->
+                    if (isComplete) {
+                        null
+                    } else if (value >= 1f) {
+                        isComplete = true
+                        1f
+                    } else if (value >= 0f) {
+                        value
+                    } else {
+                        null
+                    }
+                else -> null
+            }?.let { onStep(interpolator.getInterpolation(it)) }
+        }
+
+        return transitionFlow
+            .map { step ->
+                when (step.transitionState) {
+                    STARTED -> stepToValue(step)
+                    RUNNING -> stepToValue(step)
+                    CANCELED -> onCancel?.invoke()
+                    FINISHED -> onFinish?.invoke()
+                }
+            }
+            .filterNotNull()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index 3319f9d..ab009f4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -381,82 +381,87 @@
             return when (event?.actionMasked) {
                 MotionEvent.ACTION_DOWN ->
                     if (viewModel.configKey != null) {
-                        longPressAnimator =
-                            view
-                                .animate()
-                                .scaleX(PRESSED_SCALE)
-                                .scaleY(PRESSED_SCALE)
-                                .setDuration(longPressDurationMs)
-                                .withEndAction {
-                                    view.setOnClickListener {
-                                        vibratorHelper?.vibrate(
-                                            if (viewModel.isActivated) {
-                                                Vibrations.Activated
-                                            } else {
-                                                Vibrations.Deactivated
-                                            }
-                                        )
-                                        viewModel.onClicked(
-                                            KeyguardQuickAffordanceViewModel.OnClickedParameters(
-                                                configKey = viewModel.configKey,
-                                                expandable = Expandable.fromView(view),
-                                            )
-                                        )
+                        if (isUsingAccurateTool(event)) {
+                            // For accurate tool types (stylus, mouse, etc.), we don't require a
+                            // long-press.
+                        } else {
+                            // When not using a stylus, we require a long-press to activate the
+                            // quick affordance, mostly to do "falsing" (e.g. protect from false
+                            // clicks in the pocket/bag).
+                            longPressAnimator =
+                                view
+                                    .animate()
+                                    .scaleX(PRESSED_SCALE)
+                                    .scaleY(PRESSED_SCALE)
+                                    .setDuration(longPressDurationMs)
+                                    .withEndAction {
+                                        dispatchClick(viewModel.configKey)
+                                        cancel()
                                     }
-                                    view.performClick()
-                                    view.setOnClickListener(null)
-                                    cancel()
-                                }
+                        }
                         true
                     } else {
                         false
                     }
                 MotionEvent.ACTION_MOVE -> {
-                    if (event.historySize > 0) {
-                        val distance =
-                            sqrt(
-                                (event.y - event.getHistoricalY(0)).pow(2) +
-                                    (event.x - event.getHistoricalX(0)).pow(2)
-                            )
-                        if (distance > ViewConfiguration.getTouchSlop()) {
+                    if (!isUsingAccurateTool(event)) {
+                        // Moving too far while performing a long-press gesture cancels that
+                        // gesture.
+                        val distanceMoved = distanceMoved(event)
+                        if (distanceMoved > ViewConfiguration.getTouchSlop()) {
                             cancel()
                         }
                     }
                     true
                 }
                 MotionEvent.ACTION_UP -> {
-                    cancel(
-                        onAnimationEnd =
-                            if (event.eventTime - event.downTime < longPressDurationMs) {
-                                Runnable {
-                                    messageDisplayer.invoke(
-                                        R.string.keyguard_affordance_press_too_short
-                                    )
-                                    val amplitude =
-                                        view.context.resources
-                                            .getDimensionPixelSize(
-                                                R.dimen.keyguard_affordance_shake_amplitude
-                                            )
-                                            .toFloat()
-                                    val shakeAnimator =
-                                        ObjectAnimator.ofFloat(
-                                            view,
-                                            "translationX",
-                                            -amplitude / 2,
-                                            amplitude / 2,
+                    if (isUsingAccurateTool(event)) {
+                        // When using an accurate tool type (stylus, mouse, etc.), we don't require
+                        // a long-press gesture to activate the quick affordance. Therefore, lifting
+                        // the pointer performs a click.
+                        if (
+                            viewModel.configKey != null &&
+                                distanceMoved(event) <= ViewConfiguration.getTouchSlop()
+                        ) {
+                            dispatchClick(viewModel.configKey)
+                        }
+                    } else {
+                        // When not using a stylus, lifting the finger/pointer will actually cancel
+                        // the long-press gesture. Calling cancel after the quick affordance was
+                        // already long-press activated is a no-op, so it's safe to call from here.
+                        cancel(
+                            onAnimationEnd =
+                                if (event.eventTime - event.downTime < longPressDurationMs) {
+                                    Runnable {
+                                        messageDisplayer.invoke(
+                                            R.string.keyguard_affordance_press_too_short
                                         )
-                                    shakeAnimator.duration =
-                                        ShakeAnimationDuration.inWholeMilliseconds
-                                    shakeAnimator.interpolator =
-                                        CycleInterpolator(ShakeAnimationCycles)
-                                    shakeAnimator.start()
+                                        val amplitude =
+                                            view.context.resources
+                                                .getDimensionPixelSize(
+                                                    R.dimen.keyguard_affordance_shake_amplitude
+                                                )
+                                                .toFloat()
+                                        val shakeAnimator =
+                                            ObjectAnimator.ofFloat(
+                                                view,
+                                                "translationX",
+                                                -amplitude / 2,
+                                                amplitude / 2,
+                                            )
+                                        shakeAnimator.duration =
+                                            ShakeAnimationDuration.inWholeMilliseconds
+                                        shakeAnimator.interpolator =
+                                            CycleInterpolator(ShakeAnimationCycles)
+                                        shakeAnimator.start()
 
-                                    vibratorHelper?.vibrate(Vibrations.Shake)
+                                        vibratorHelper?.vibrate(Vibrations.Shake)
+                                    }
+                                } else {
+                                    null
                                 }
-                            } else {
-                                null
-                            }
-                    )
+                        )
+                    }
                     true
                 }
                 MotionEvent.ACTION_CANCEL -> {
@@ -467,6 +472,28 @@
             }
         }
 
+        private fun dispatchClick(
+            configKey: String,
+        ) {
+            view.setOnClickListener {
+                vibratorHelper?.vibrate(
+                    if (viewModel.isActivated) {
+                        Vibrations.Activated
+                    } else {
+                        Vibrations.Deactivated
+                    }
+                )
+                viewModel.onClicked(
+                    KeyguardQuickAffordanceViewModel.OnClickedParameters(
+                        configKey = configKey,
+                        expandable = Expandable.fromView(view),
+                    )
+                )
+            }
+            view.performClick()
+            view.setOnClickListener(null)
+        }
+
         private fun cancel(onAnimationEnd: Runnable? = null) {
             longPressAnimator?.cancel()
             longPressAnimator = null
@@ -475,6 +502,40 @@
 
         companion object {
             private const val PRESSED_SCALE = 1.5f
+
+            /**
+             * Returns `true` if the tool type at the given pointer index is an accurate tool (like
+             * stylus or mouse), which means we can trust it to not be a false click; `false`
+             * otherwise.
+             */
+            private fun isUsingAccurateTool(
+                event: MotionEvent,
+                pointerIndex: Int = 0,
+            ): Boolean {
+                return when (event.getToolType(pointerIndex)) {
+                    MotionEvent.TOOL_TYPE_STYLUS -> true
+                    MotionEvent.TOOL_TYPE_MOUSE -> true
+                    else -> false
+                }
+            }
+
+            /**
+             * Returns the amount of distance the pointer moved since the historical record at the
+             * [since] index.
+             */
+            private fun distanceMoved(
+                event: MotionEvent,
+                since: Int = 0,
+            ): Float {
+                return if (event.historySize > 0) {
+                    sqrt(
+                        (event.y - event.getHistoricalY(since)).pow(2) +
+                            (event.x - event.getHistoricalX(since)).pow(2)
+                    )
+                } else {
+                    0f
+                }
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
index c1731e0..9f09d53 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
@@ -154,6 +154,12 @@
                     }
 
                     launch {
+                        viewModel.isInteractable.collect { isInteractable ->
+                            hostViewController.setInteractable(isInteractable)
+                        }
+                    }
+
+                    launch {
                         viewModel.isBouncerVisible
                             .filter { !it }
                             .collect {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 8808574..adde595 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -177,7 +177,8 @@
         val receiver =
             object : BroadcastReceiver() {
                 override fun onReceive(context: Context?, intent: Intent?) {
-                    clockController.clock?.events?.onTimeTick()
+                    clockController.clock?.smallClock?.events?.onTimeTick()
+                    clockController.clock?.largeClock?.events?.onTimeTick()
                 }
             }
         broadcastDispatcher.registerReceiver(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index 6627865..8d6545a4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -21,15 +21,10 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
-import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
-import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
 
 /**
  * Breaks down DREAMING->LOCKSCREEN transition into discrete steps for corresponding views to
@@ -41,39 +36,46 @@
 constructor(
     private val interactor: KeyguardTransitionInteractor,
 ) {
+    private val transitionAnimation =
+        KeyguardTransitionAnimationFlow(
+            transitionDuration = TO_LOCKSCREEN_DURATION,
+            transitionFlow = interactor.dreamingToLockscreenTransition,
+        )
 
     /** Dream overlay y-translation on exit */
     fun dreamOverlayTranslationY(translatePx: Int): Flow<Float> {
-        return flowForAnimation(DREAM_OVERLAY_TRANSLATION_Y).map { value ->
-            EMPHASIZED_ACCELERATE.getInterpolation(value) * translatePx
-        }
+        return transitionAnimation.createFlow(
+            duration = 600.milliseconds,
+            onStep = { it * translatePx },
+            interpolator = EMPHASIZED_ACCELERATE,
+        )
     }
     /** Dream overlay views alpha - fade out */
-    val dreamOverlayAlpha: Flow<Float> = flowForAnimation(DREAM_OVERLAY_ALPHA).map { 1f - it }
+    val dreamOverlayAlpha: Flow<Float> =
+        transitionAnimation.createFlow(
+            duration = 250.milliseconds,
+            onStep = { 1f - it },
+        )
 
     /** Lockscreen views y-translation */
     fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
-        return merge(
-            flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
-                -translatePx + (EMPHASIZED_DECELERATE.getInterpolation(value) * translatePx)
-            },
-            // On end, reset the translation to 0
-            interactor.dreamingToLockscreenTransition
-                .filter { it.transitionState == FINISHED || it.transitionState == CANCELED }
-                .map { 0f }
+        return transitionAnimation.createFlow(
+            duration = TO_LOCKSCREEN_DURATION,
+            onStep = { value -> -translatePx + value * translatePx },
+            // Reset on cancel or finish
+            onFinish = { 0f },
+            onCancel = { 0f },
+            interpolator = EMPHASIZED_DECELERATE,
         )
     }
 
     /** Lockscreen views alpha */
-    val lockscreenAlpha: Flow<Float> = flowForAnimation(LOCKSCREEN_ALPHA)
-
-    private fun flowForAnimation(params: AnimationParams): Flow<Float> {
-        return interactor.transitionStepAnimation(
-            interactor.dreamingToLockscreenTransition,
-            params,
-            totalDuration = TO_LOCKSCREEN_DURATION
+    val lockscreenAlpha: Flow<Float> =
+        transitionAnimation.createFlow(
+            startTime = 233.milliseconds,
+            duration = 250.milliseconds,
+            onStep = { it },
         )
-    }
 
     companion object {
         /* Length of time before ending the dream activity, in order to start unoccluding */
@@ -81,11 +83,5 @@
         @JvmField
         val LOCKSCREEN_ANIMATION_DURATION_MS =
             (TO_LOCKSCREEN_DURATION - DREAM_ANIMATION_DURATION).inWholeMilliseconds
-
-        val DREAM_OVERLAY_TRANSLATION_Y = AnimationParams(duration = 600.milliseconds)
-        val DREAM_OVERLAY_ALPHA = AnimationParams(duration = 250.milliseconds)
-        val LOCKSCREEN_TRANSLATION_Y = AnimationParams(duration = TO_LOCKSCREEN_DURATION)
-        val LOCKSCREEN_ALPHA =
-            AnimationParams(startTime = 233.milliseconds, duration = 250.milliseconds)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
index 5a47960..f16827d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
@@ -20,15 +20,10 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.FromGoneTransitionInteractor.Companion.TO_DREAMING_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
-import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
-import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
 
 /** Breaks down GONE->DREAMING transition into discrete steps for corresponding views to consume. */
 @SysUISingleton
@@ -38,32 +33,28 @@
     private val interactor: KeyguardTransitionInteractor,
 ) {
 
+    private val transitionAnimation =
+        KeyguardTransitionAnimationFlow(
+            transitionDuration = TO_DREAMING_DURATION,
+            transitionFlow = interactor.goneToDreamingTransition,
+        )
+
     /** Lockscreen views y-translation */
     fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
-        return merge(
-            flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
-                (EMPHASIZED_ACCELERATE.getInterpolation(value) * translatePx)
-            },
-            // On end, reset the translation to 0
-            interactor.goneToDreamingTransition
-                .filter { it.transitionState == FINISHED || it.transitionState == CANCELED }
-                .map { 0f }
+        return transitionAnimation.createFlow(
+            duration = 500.milliseconds,
+            onStep = { it * translatePx },
+            // Reset on cancel or finish
+            onFinish = { 0f },
+            onCancel = { 0f },
+            interpolator = EMPHASIZED_ACCELERATE,
         )
     }
 
     /** Lockscreen views alpha */
-    val lockscreenAlpha: Flow<Float> = flowForAnimation(LOCKSCREEN_ALPHA).map { 1f - it }
-
-    private fun flowForAnimation(params: AnimationParams): Flow<Float> {
-        return interactor.transitionStepAnimation(
-            interactor.goneToDreamingTransition,
-            params,
-            totalDuration = TO_DREAMING_DURATION
+    val lockscreenAlpha: Flow<Float> =
+        transitionAnimation.createFlow(
+            duration = 250.milliseconds,
+            onStep = { 1f - it },
         )
-    }
-
-    companion object {
-        val LOCKSCREEN_TRANSLATION_Y = AnimationParams(duration = 500.milliseconds)
-        val LOCKSCREEN_ALPHA = AnimationParams(duration = 250.milliseconds)
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
index 737c35d..b8b3a8e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -39,6 +39,9 @@
     /** Observe on bouncer visibility. */
     val isBouncerVisible: Flow<Boolean> = interactor.isVisible
 
+    /** Can the user interact with the view? */
+    val isInteractable: Flow<Boolean> = interactor.isInteractable
+
     /** Observe whether bouncer is showing. */
     val show: Flow<KeyguardBouncerModel> = interactor.show
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
index e05adbd..bc9dc4f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
@@ -20,15 +20,10 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_DREAMING_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
-import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
-import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
 
 /**
  * Breaks down LOCKSCREEN->DREAMING transition into discrete steps for corresponding views to
@@ -40,35 +35,32 @@
 constructor(
     private val interactor: KeyguardTransitionInteractor,
 ) {
+    private val transitionAnimation =
+        KeyguardTransitionAnimationFlow(
+            transitionDuration = TO_DREAMING_DURATION,
+            transitionFlow = interactor.lockscreenToDreamingTransition,
+        )
 
     /** Lockscreen views y-translation */
     fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
-        return merge(
-            flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
-                (EMPHASIZED_ACCELERATE.getInterpolation(value) * translatePx)
-            },
-            // On end, reset the translation to 0
-            interactor.lockscreenToDreamingTransition
-                .filter { it.transitionState == FINISHED || it.transitionState == CANCELED }
-                .map { 0f }
+        return transitionAnimation.createFlow(
+            duration = 500.milliseconds,
+            onStep = { it * translatePx },
+            // Reset on cancel or finish
+            onFinish = { 0f },
+            onCancel = { 0f },
+            interpolator = EMPHASIZED_ACCELERATE,
         )
     }
 
     /** Lockscreen views alpha */
-    val lockscreenAlpha: Flow<Float> = flowForAnimation(LOCKSCREEN_ALPHA).map { 1f - it }
-
-    private fun flowForAnimation(params: AnimationParams): Flow<Float> {
-        return interactor.transitionStepAnimation(
-            interactor.lockscreenToDreamingTransition,
-            params,
-            totalDuration = TO_DREAMING_DURATION
+    val lockscreenAlpha: Flow<Float> =
+        transitionAnimation.createFlow(
+            duration = 250.milliseconds,
+            onStep = { 1f - it },
         )
-    }
 
     companion object {
         @JvmField val DREAMING_ANIMATION_DURATION_MS = TO_DREAMING_DURATION.inWholeMilliseconds
-
-        val LOCKSCREEN_TRANSLATION_Y = AnimationParams(duration = 500.milliseconds)
-        val LOCKSCREEN_ALPHA = AnimationParams(duration = 250.milliseconds)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
index 22d292e..a60665a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
@@ -20,14 +20,10 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_OCCLUDED_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
-import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
 
 /**
  * Breaks down LOCKSCREEN->OCCLUDED transition into discrete steps for corresponding views to
@@ -39,33 +35,28 @@
 constructor(
     private val interactor: KeyguardTransitionInteractor,
 ) {
+    private val transitionAnimation =
+        KeyguardTransitionAnimationFlow(
+            transitionDuration = TO_OCCLUDED_DURATION,
+            transitionFlow = interactor.lockscreenToOccludedTransition,
+        )
+
+    /** Lockscreen views alpha */
+    val lockscreenAlpha: Flow<Float> =
+        transitionAnimation.createFlow(
+            duration = 250.milliseconds,
+            onStep = { 1f - it },
+        )
 
     /** Lockscreen views y-translation */
     fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
-        return merge(
-            flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
-                (EMPHASIZED_ACCELERATE.getInterpolation(value) * translatePx)
-            },
-            // On end, reset the translation to 0
-            interactor.lockscreenToOccludedTransition
-                .filter { step -> step.transitionState == TransitionState.FINISHED }
-                .map { 0f }
+        return transitionAnimation.createFlow(
+            duration = TO_OCCLUDED_DURATION,
+            onStep = { value -> value * translatePx },
+            // Reset on cancel or finish
+            onFinish = { 0f },
+            onCancel = { 0f },
+            interpolator = EMPHASIZED_ACCELERATE,
         )
     }
-
-    /** Lockscreen views alpha */
-    val lockscreenAlpha: Flow<Float> = flowForAnimation(LOCKSCREEN_ALPHA).map { 1f - it }
-
-    private fun flowForAnimation(params: AnimationParams): Flow<Float> {
-        return interactor.transitionStepAnimation(
-            interactor.lockscreenToOccludedTransition,
-            params,
-            totalDuration = TO_OCCLUDED_DURATION
-        )
-    }
-
-    companion object {
-        val LOCKSCREEN_TRANSLATION_Y = AnimationParams(duration = TO_OCCLUDED_DURATION)
-        val LOCKSCREEN_ALPHA = AnimationParams(duration = 250.milliseconds)
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
index e804562..5770f3e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
@@ -20,11 +20,10 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
 
 /**
  * Breaks down OCCLUDED->LOCKSCREEN transition into discrete steps for corresponding views to
@@ -36,28 +35,26 @@
 constructor(
     private val interactor: KeyguardTransitionInteractor,
 ) {
+    private val transitionAnimation =
+        KeyguardTransitionAnimationFlow(
+            transitionDuration = TO_LOCKSCREEN_DURATION,
+            transitionFlow = interactor.occludedToLockscreenTransition,
+        )
+
     /** Lockscreen views y-translation */
     fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
-        return flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
-            -translatePx + (EMPHASIZED_DECELERATE.getInterpolation(value) * translatePx)
-        }
-    }
-
-    /** Lockscreen views alpha */
-    val lockscreenAlpha: Flow<Float> = flowForAnimation(LOCKSCREEN_ALPHA)
-
-    private fun flowForAnimation(params: AnimationParams): Flow<Float> {
-        return interactor.transitionStepAnimation(
-            interactor.occludedToLockscreenTransition,
-            params,
-            totalDuration = TO_LOCKSCREEN_DURATION
+        return transitionAnimation.createFlow(
+            duration = TO_LOCKSCREEN_DURATION,
+            onStep = { value -> -translatePx + value * translatePx },
+            interpolator = EMPHASIZED_DECELERATE,
         )
     }
 
-    companion object {
-        @JvmField val LOCKSCREEN_ANIMATION_DURATION_MS = TO_LOCKSCREEN_DURATION.inWholeMilliseconds
-        val LOCKSCREEN_TRANSLATION_Y = AnimationParams(duration = TO_LOCKSCREEN_DURATION)
-        val LOCKSCREEN_ALPHA =
-            AnimationParams(startTime = 233.milliseconds, duration = 250.milliseconds)
-    }
+    /** Lockscreen views alpha */
+    val lockscreenAlpha: Flow<Float> =
+        transitionAnimation.createFlow(
+            startTime = 233.milliseconds,
+            duration = 250.milliseconds,
+            onStep = { it },
+        )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
new file mode 100644
index 0000000..5acaa46
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
@@ -0,0 +1,135 @@
+/*
+ * 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.log
+
+import android.graphics.Point
+import android.graphics.Rect
+import android.graphics.RectF
+import androidx.core.graphics.toRectF
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.dagger.ScreenDecorationsLog
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel.DEBUG
+import com.android.systemui.plugins.log.LogLevel.ERROR
+import javax.inject.Inject
+
+private const val TAG = "ScreenDecorationsLog"
+
+/**
+ * Helper class for logging for [com.android.systemui.ScreenDecorations]
+ *
+ * To enable logcat echoing for an entire buffer:
+ *
+ * ```
+ *   adb shell settings put global systemui/buffer/ScreenDecorationsLog <logLevel>
+ *
+ * ```
+ */
+@SysUISingleton
+class ScreenDecorationsLogger
+@Inject
+constructor(
+    @ScreenDecorationsLog private val logBuffer: LogBuffer,
+) {
+    fun cameraProtectionBoundsForScanningOverlay(bounds: Rect) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { str1 = bounds.toShortString() },
+            { "Face scanning overlay present camera protection bounds: $str1" }
+        )
+    }
+
+    fun hwcLayerCameraProtectionBounds(bounds: Rect) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { str1 = bounds.toShortString() },
+            { "Hwc layer present camera protection bounds: $str1" }
+        )
+    }
+
+    fun dcvCameraBounds(id: Int, bounds: Rect) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = bounds.toShortString()
+                int1 = id
+            },
+            { "DisplayCutoutView id=$int1 present, camera protection bounds: $str1" }
+        )
+    }
+
+    fun cutoutViewNotInitialized() {
+        logBuffer.log(TAG, ERROR, "CutoutView not initialized showCameraProtection")
+    }
+
+    fun boundingRect(boundingRectangle: RectF, context: String) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = context
+                str2 = boundingRectangle.toShortString()
+            },
+            { "Bounding rect $str1 : $str2" }
+        )
+    }
+
+    fun boundingRect(boundingRectangle: Rect, context: String) {
+        boundingRect(boundingRectangle.toRectF(), context)
+    }
+
+    fun onMeasureDimensions(
+        widthMeasureSpec: Int,
+        heightMeasureSpec: Int,
+        measuredWidth: Int,
+        measuredHeight: Int
+    ) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                long1 = widthMeasureSpec.toLong()
+                long2 = heightMeasureSpec.toLong()
+                int1 = measuredWidth
+                int2 = measuredHeight
+            },
+            {
+                "Face scanning animation: widthMeasureSpec: $long1 measuredWidth: $int1, " +
+                    "heightMeasureSpec: $long2 measuredHeight: $int2"
+            }
+        )
+    }
+
+    fun faceSensorLocation(faceSensorLocation: Point?) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = faceSensorLocation?.y?.times(2) ?: 0
+                str1 = "$faceSensorLocation"
+            },
+            { "Reinflating view: Face sensor location: $str1, faceScanningHeight: $int1" }
+        )
+    }
+
+    fun onSensorLocationChanged() {
+        logBuffer.log(TAG, DEBUG, "AuthControllerCallback in ScreenDecorations triggered")
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index f61d135..c02fd9c 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -350,6 +350,16 @@
     }
 
     /**
+     * Provides a {@link LogBuffer} for use by {@link com.android.systemui.ScreenDecorations}.
+     */
+    @Provides
+    @SysUISingleton
+    @ScreenDecorationsLog
+    public static LogBuffer provideScreenDecorationsLog(LogBufferFactory factory) {
+        return factory.create("ScreenDecorationsLog", 200);
+    }
+
+    /**
      * Provides a {@link LogBuffer} for bluetooth-related logs.
      */
     @Provides
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/ScreenDecorationsLog.kt
similarity index 63%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to packages/SystemUI/src/com/android/systemui/log/dagger/ScreenDecorationsLog.kt
index 497c272..de2a8b6 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/ScreenDecorationsLog.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package com.android.systemui.log.dagger
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+import javax.inject.Qualifier
+
+/** A [com.android.systemui.log.LogBuffer] for ScreenDecorations added by SysUI. */
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class ScreenDecorationsLog
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
index 348d941..ccd4060 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
@@ -79,10 +79,10 @@
     }
 }
 
-/**
- * Each time the boolean flow is updated with a new value that's different from the previous value,
- * logs the new value to the given [tableLogBuffer].
- */
+// Here and below: Various Flow<SomeType> extension functions that are effectively equivalent to the
+// above [logDiffsForTable] method.
+
+/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
 fun Flow<Boolean>.logDiffsForTable(
     tableLogBuffer: TableLogBuffer,
     columnPrefix: String,
@@ -100,10 +100,8 @@
         newVal
     }
 }
-/**
- * Each time the Int flow is updated with a new value that's different from the previous value, logs
- * the new value to the given [tableLogBuffer].
- */
+
+/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
 fun Flow<Int>.logDiffsForTable(
     tableLogBuffer: TableLogBuffer,
     columnPrefix: String,
@@ -122,10 +120,26 @@
     }
 }
 
-/**
- * Each time the String? flow is updated with a new value that's different from the previous value,
- * logs the new value to the given [tableLogBuffer].
- */
+/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
+fun Flow<Int?>.logDiffsForTable(
+    tableLogBuffer: TableLogBuffer,
+    columnPrefix: String,
+    columnName: String,
+    initialValue: Int?,
+): Flow<Int?> {
+    val initialValueFun = {
+        tableLogBuffer.logChange(columnPrefix, columnName, initialValue)
+        initialValue
+    }
+    return this.pairwiseBy(initialValueFun) { prevVal, newVal: Int? ->
+        if (prevVal != newVal) {
+            tableLogBuffer.logChange(columnPrefix, columnName, newVal)
+        }
+        newVal
+    }
+}
+
+/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
 fun Flow<String?>.logDiffsForTable(
     tableLogBuffer: TableLogBuffer,
     columnPrefix: String,
@@ -143,3 +157,23 @@
         newVal
     }
 }
+
+/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
+fun <T> Flow<List<T>>.logDiffsForTable(
+    tableLogBuffer: TableLogBuffer,
+    columnPrefix: String,
+    columnName: String,
+    initialValue: List<T>,
+): Flow<List<T>> {
+    val initialValueFun = {
+        tableLogBuffer.logChange(columnPrefix, columnName, initialValue.toString())
+        initialValue
+    }
+    return this.pairwiseBy(initialValueFun) { prevVal, newVal: List<T> ->
+        if (prevVal != newVal) {
+            // TODO(b/267761156): Can we log list changes without using toString?
+            tableLogBuffer.logChange(columnPrefix, columnName, newVal.toString())
+        }
+        newVal
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt
index 68c297f..4880f80 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt
@@ -27,7 +27,7 @@
     var columnName: String = "",
     var type: DataType = DataType.EMPTY,
     var bool: Boolean = false,
-    var int: Int = 0,
+    var int: Int? = null,
     var str: String? = null,
 ) {
     /** Resets to default values so that the object can be recycled. */
@@ -54,7 +54,7 @@
     }
 
     /** Sets this to store an int change. */
-    fun set(value: Int) {
+    fun set(value: Int?) {
         type = DataType.INT
         int = value
     }
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index 2c299d6..1712dab 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -138,7 +138,7 @@
     }
 
     /** Logs a Int change. */
-    fun logChange(prefix: String, columnName: String, value: Int) {
+    fun logChange(prefix: String, columnName: String, value: Int?) {
         logChange(systemClock.currentTimeMillis(), prefix, columnName, value)
     }
 
@@ -155,7 +155,7 @@
         change.set(value)
     }
 
-    private fun logChange(timestamp: Long, prefix: String, columnName: String, value: Int) {
+    private fun logChange(timestamp: Long, prefix: String, columnName: String, value: Int?) {
         val change = obtain(timestamp, prefix, columnName)
         change.set(value)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java b/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java
index a88a4ca..4f5bbb7 100644
--- a/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java
@@ -28,11 +28,10 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.text.Html;
-import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
 import android.text.TextUtils;
 import android.text.method.LinkMovementMethod;
-import android.text.style.TypefaceSpan;
 import android.text.style.URLSpan;
 import android.util.Slog;
 import android.view.ContextThemeWrapper;
@@ -64,7 +63,10 @@
 
     private String mAlertTitle;
     private String mAlertBody;
-    private String mAlertLearnMore;
+
+    private boolean mAlertLearnMoreLink;
+    private SpannableString mAlertLearnMore;
+
     private AlertDialog.Builder mAlertDialog;
     private AlertDialog mAlert;
     private View mAlertView;
@@ -90,8 +92,20 @@
             return;
         }
 
-        mAlertBody = getResources().getString(R.string.log_access_confirmation_body);
-        mAlertLearnMore = getResources().getString(R.string.log_access_confirmation_learn_more);
+        mAlertBody = getString(R.string.log_access_confirmation_body);
+        mAlertLearnMoreLink = this.getResources()
+            .getBoolean(R.bool.log_access_confirmation_learn_more_as_link);
+        if (mAlertLearnMoreLink) {
+            mAlertLearnMore = new SpannableString(
+                    getString(R.string.log_access_confirmation_learn_more));
+            mAlertLearnMore.setSpan(new URLSpan(
+                    getString(R.string.log_access_confirmation_learn_more_url)),
+                    0, mAlertLearnMore.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        } else {
+            mAlertLearnMore = new SpannableString(
+                getString(R.string.log_access_confirmation_learn_more_at,
+                getString(R.string.log_access_confirmation_learn_more_url)));
+        }
 
         // create View
         int themeId = R.style.LogAccessDialogTheme;
@@ -180,15 +194,6 @@
         return titleString;
     }
 
-    private Spannable styleFont(String text) {
-        Spannable s = (Spannable) Html.fromHtml(text);
-        for (URLSpan span : s.getSpans(0, s.length(), URLSpan.class)) {
-            TypefaceSpan typefaceSpan = new TypefaceSpan("google-sans");
-            s.setSpan(typefaceSpan, s.getSpanStart(span), s.getSpanEnd(span), 0);
-        }
-        return s;
-    }
-
     /**
      * Returns the dialog view.
      * If we cannot retrieve the package name, it returns null and we decline the full device log
@@ -207,13 +212,12 @@
             .setText(mAlertTitle);
 
         if (!TextUtils.isEmpty(mAlertLearnMore)) {
-            Spannable mSpannableLearnMore = styleFont(mAlertLearnMore);
-
             ((TextView) view.findViewById(R.id.log_access_dialog_body))
-                    .setText(TextUtils.concat(mAlertBody, "\n\n", mSpannableLearnMore));
-
-            ((TextView) view.findViewById(R.id.log_access_dialog_body))
+                .setText(TextUtils.concat(mAlertBody, "\n\n", mAlertLearnMore));
+            if (mAlertLearnMoreLink) {
+                ((TextView) view.findViewById(R.id.log_access_dialog_body))
                     .setMovementMethod(LinkMovementMethod.getInstance());
+            }
         } else {
             ((TextView) view.findViewById(R.id.log_access_dialog_body))
                     .setText(mAlertBody);
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
index a692ad7..52d4171 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
@@ -28,12 +28,15 @@
 import android.os.UserHandle
 import android.view.ViewGroup
 import com.android.internal.annotations.VisibleForTesting
+import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider
 import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider
 import com.android.internal.app.ChooserActivity
 import com.android.internal.app.ResolverListController
 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
@@ -47,6 +50,7 @@
 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)?
@@ -56,7 +60,8 @@
     constructor(
         componentFactory: MediaProjectionAppSelectorComponent.Factory,
         activityLauncher: AsyncActivityLauncher,
-    ) : this(componentFactory, activityLauncher, null)
+        featureFlags: FeatureFlags
+    ) : this(componentFactory, activityLauncher, featureFlags, listControllerFactory = null)
 
     private lateinit var configurationController: ConfigurationController
     private lateinit var controller: MediaProjectionAppSelectorController
@@ -91,6 +96,13 @@
 
     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 {
+            super.createBlockerEmptyStateProvider()
+        }
+
     override fun createListController(userHandle: UserHandle): ResolverListController =
         listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle)
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index d830fc4..c4e76b2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -45,33 +45,46 @@
 import android.util.Log;
 import android.view.Window;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver;
+import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog;
 import com.android.systemui.screenrecord.MediaProjectionPermissionDialog;
 import com.android.systemui.screenrecord.ScreenShareOption;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.util.Utils;
 
+import javax.inject.Inject;
+
+import dagger.Lazy;
+
 public class MediaProjectionPermissionActivity extends Activity
         implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
     private static final String TAG = "MediaProjectionPermissionActivity";
     private static final float MAX_APP_NAME_SIZE_PX = 500f;
     private static final String ELLIPSIS = "\u2026";
 
+    private final FeatureFlags mFeatureFlags;
+    private final Lazy<ScreenCaptureDevicePolicyResolver> mScreenCaptureDevicePolicyResolver;
+
     private String mPackageName;
     private int mUid;
     private IMediaProjectionManager mService;
-    private FeatureFlags mFeatureFlags;
 
     private AlertDialog mDialog;
 
+    @Inject
+    public MediaProjectionPermissionActivity(FeatureFlags featureFlags,
+            Lazy<ScreenCaptureDevicePolicyResolver> screenCaptureDevicePolicyResolver) {
+        mFeatureFlags = featureFlags;
+        mScreenCaptureDevicePolicyResolver = screenCaptureDevicePolicyResolver;
+    }
+
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        mFeatureFlags = Dependency.get(FeatureFlags.class);
         mPackageName = getCallingPackage();
         IBinder b = ServiceManager.getService(MEDIA_PROJECTION_SERVICE);
         mService = IMediaProjectionManager.Stub.asInterface(b);
@@ -104,6 +117,12 @@
             return;
         }
 
+        if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) {
+            if (showScreenCaptureDisabledDialogIfNeeded()) {
+                return;
+            }
+        }
+
         TextPaint paint = new TextPaint();
         paint.setTextSize(42);
 
@@ -171,16 +190,7 @@
             mDialog = dialogBuilder.create();
         }
 
-        SystemUIDialog.registerDismissListener(mDialog);
-        SystemUIDialog.applyFlags(mDialog);
-        SystemUIDialog.setDialogSize(mDialog);
-
-        mDialog.setOnCancelListener(this);
-        mDialog.create();
-        mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true);
-
-        final Window w = mDialog.getWindow();
-        w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+        setUpDialog(mDialog);
 
         mDialog.show();
     }
@@ -200,6 +210,32 @@
         }
     }
 
+    private void setUpDialog(AlertDialog dialog) {
+        SystemUIDialog.registerDismissListener(dialog);
+        SystemUIDialog.applyFlags(dialog);
+        SystemUIDialog.setDialogSize(dialog);
+
+        dialog.setOnCancelListener(this);
+        dialog.create();
+        dialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true);
+
+        final Window w = dialog.getWindow();
+        w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+    }
+
+    private boolean showScreenCaptureDisabledDialogIfNeeded() {
+        final UserHandle hostUserHandle = getHostUserHandle();
+        if (mScreenCaptureDevicePolicyResolver.get()
+                .isScreenCaptureCompletelyDisabled(hostUserHandle)) {
+            AlertDialog dialog = new ScreenCaptureDisabledDialog(this);
+            setUpDialog(dialog);
+            dialog.show();
+            return true;
+        }
+
+        return false;
+    }
+
     private void grantMediaProjectionPermission(int screenShareMode) {
         try {
             if (screenShareMode == ENTIRE_SCREEN) {
@@ -211,7 +247,7 @@
                 intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
                         projection.asBinder());
                 intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
-                        UserHandle.getUserHandleForUid(getLaunchedFromUid()));
+                        getHostUserHandle());
                 intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
 
                 // Start activity from the current foreground user to avoid creating a separate
@@ -230,6 +266,10 @@
         }
     }
 
+    private UserHandle getHostUserHandle() {
+        return UserHandle.getUserHandleForUid(getLaunchedFromUid());
+    }
+
     private IMediaProjection createProjection(int uid, String packageName) throws RemoteException {
         return mService.createProjection(uid, packageName,
                 MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */);
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaData.kt
index be18cbe..b7a2522 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/MediaData.kt
@@ -92,6 +92,9 @@
 
     /** Whether explicit indicator exists */
     val isExplicit: Boolean = false,
+
+    /** Track progress (0 - 1) to display for players where [resumption] is true */
+    val resumeProgress: Double? = null,
 ) {
     companion object {
         /** Media is playing on the local device */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
index bba5f35..a057c9f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
@@ -238,6 +238,24 @@
     }
 
     /**
+     * Set the progress to a fixed percentage value that cannot be changed by the user.
+     *
+     * @param percent value between 0 and 1
+     */
+    fun updateStaticProgress(percent: Double) {
+        val position = (percent * 100).toInt()
+        _data =
+            Progress(
+                enabled = true,
+                seekAvailable = false,
+                playing = false,
+                scrubbing = false,
+                elapsedTime = position,
+                duration = 100,
+            )
+    }
+
+    /**
      * Puts the seek bar into a resumption state.
      *
      * This should be called when the media session behind the controller has been destroyed.
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/RecommendationViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/RecommendationViewHolder.kt
index 8c1ec16..70f2dee 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/RecommendationViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/RecommendationViewHolder.kt
@@ -20,6 +20,7 @@
 import android.view.View
 import android.view.ViewGroup
 import android.widget.ImageView
+import android.widget.SeekBar
 import android.widget.TextView
 import com.android.internal.widget.CachingIconView
 import com.android.systemui.R
@@ -37,6 +38,7 @@
     // Recommendation screen
     lateinit var cardIcon: ImageView
     lateinit var mediaAppIcons: List<CachingIconView>
+    lateinit var mediaProgressBars: List<SeekBar>
     lateinit var cardTitle: TextView
 
     val mediaCoverContainers =
@@ -82,6 +84,13 @@
         if (updatedView) {
             mediaAppIcons = mediaCoverContainers.map { it.requireViewById(R.id.media_rec_app_icon) }
             cardTitle = itemView.requireViewById(R.id.media_rec_title)
+            mediaProgressBars =
+                mediaCoverContainers.map {
+                    it.requireViewById<SeekBar?>(R.id.media_progress_bar).apply {
+                        // Media playback is in the direction of tape, not time, so it stays LTR
+                        layoutDirection = View.LAYOUT_DIRECTION_LTR
+                    }
+                }
         } else {
             cardIcon = itemView.requireViewById<ImageView>(R.id.recommendation_card_icon)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
index 1df42c6..dc7a4f1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
@@ -41,10 +41,12 @@
     val recommendations: List<SmartspaceAction>,
     /** Intent for the user's initiated dismissal. */
     val dismissIntent: Intent?,
-    /** The timestamp in milliseconds that headphone is connected. */
+    /** The timestamp in milliseconds that the card was generated */
     val headphoneConnectionTimeMillis: Long,
     /** Instance ID for [MediaUiEventLogger] */
-    val instanceId: InstanceId
+    val instanceId: InstanceId,
+    /** The timestamp in milliseconds indicating when the card should be removed */
+    val expiryTimeMs: Long,
 ) {
     /**
      * Indicates if all the data is valid.
@@ -86,5 +88,12 @@
     }
 }
 
+/** Key for extras [SmartspaceMediaData.cardAction] indicating why the card was sent */
+const val EXTRA_KEY_TRIGGER_SOURCE = "MEDIA_RECOMMENDATION_TRIGGER_SOURCE"
+/** Value for [EXTRA_KEY_TRIGGER_SOURCE] when the card is sent on headphone connection */
+const val EXTRA_VALUE_TRIGGER_HEADPHONE = "HEADPHONE_CONNECTION"
+/** Value for key [EXTRA_KEY_TRIGGER_SOURCE] when the card is sent as a regular update */
+const val EXTRA_VALUE_TRIGGER_PERIODIC = "PERIODIC_TRIGGER"
+
 const val NUM_REQUIRED_RECOMMENDATIONS = 3
 private val TAG = SmartspaceMediaData::class.simpleName!!
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
index cf71d67..27f7b97 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
+import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.media.controls.util.MediaUiEventLogger
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
@@ -66,7 +67,8 @@
     private val lockscreenUserManager: NotificationLockscreenUserManager,
     @Main private val executor: Executor,
     private val systemClock: SystemClock,
-    private val logger: MediaUiEventLogger
+    private val logger: MediaUiEventLogger,
+    private val mediaFlags: MediaFlags,
 ) : MediaDataManager.Listener {
     private val _listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
     internal val listeners: Set<MediaDataManager.Listener>
@@ -121,7 +123,9 @@
         data: SmartspaceMediaData,
         shouldPrioritize: Boolean
     ) {
-        if (!data.isActive) {
+        // With persistent recommendation card, we could get a background update while inactive
+        // Otherwise, consider it an invalid update
+        if (!data.isActive && !mediaFlags.isPersistentSsCardEnabled()) {
             Log.d(TAG, "Inactive recommendation data. Skip triggering.")
             return
         }
@@ -141,7 +145,7 @@
             }
         }
 
-        val shouldReactivate = !hasActiveMedia() && hasAnyMedia()
+        val shouldReactivate = !hasActiveMedia() && hasAnyMedia() && data.isActive
 
         if (timeSinceActive < smartspaceMaxAgeMillis) {
             // It could happen there are existing active media resume cards, then we don't need to
@@ -169,7 +173,7 @@
                     )
                 }
             }
-        } else {
+        } else if (data.isActive) {
             // Mark to prioritize Smartspace card if no recent media.
             shouldPrioritizeMutable = true
         }
@@ -252,7 +256,7 @@
             if (dismissIntent == null) {
                 Log.w(
                     TAG,
-                    "Cannot create dismiss action click action: " + "extras missing dismiss_intent."
+                    "Cannot create dismiss action click action: extras missing dismiss_intent."
                 )
             } else if (
                 dismissIntent.getComponent() != null &&
@@ -264,15 +268,21 @@
             } else {
                 broadcastSender.sendBroadcast(dismissIntent)
             }
-            smartspaceMediaData =
-                EMPTY_SMARTSPACE_MEDIA_DATA.copy(
-                    targetId = smartspaceMediaData.targetId,
-                    instanceId = smartspaceMediaData.instanceId
+
+            if (mediaFlags.isPersistentSsCardEnabled()) {
+                smartspaceMediaData = smartspaceMediaData.copy(isActive = false)
+                mediaDataManager.setRecommendationInactive(smartspaceMediaData.targetId)
+            } else {
+                smartspaceMediaData =
+                    EMPTY_SMARTSPACE_MEDIA_DATA.copy(
+                        targetId = smartspaceMediaData.targetId,
+                        instanceId = smartspaceMediaData.instanceId,
+                    )
+                mediaDataManager.dismissSmartspaceRecommendation(
+                    smartspaceMediaData.targetId,
+                    delay = 0L,
                 )
-            mediaDataManager.dismissSmartspaceRecommendation(
-                smartspaceMediaData.targetId,
-                delay = 0L
-            )
+            }
         }
     }
 
@@ -283,8 +293,15 @@
                 (smartspaceMediaData.isValid() || reactivatedKey != null))
 
     /** Are there any media entries we should display? */
-    fun hasAnyMediaOrRecommendation() =
-        userEntries.isNotEmpty() || (smartspaceMediaData.isActive && smartspaceMediaData.isValid())
+    fun hasAnyMediaOrRecommendation(): Boolean {
+        val hasSmartspace =
+            if (mediaFlags.isPersistentSsCardEnabled()) {
+                smartspaceMediaData.isValid()
+            } else {
+                smartspaceMediaData.isActive && smartspaceMediaData.isValid()
+            }
+        return userEntries.isNotEmpty() || hasSmartspace
+    }
 
     /** Are there any media notifications active (excluding the recommendation)? */
     fun hasActiveMedia() = userEntries.any { it.value.active }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
index da2164e..5dd532a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
@@ -50,8 +50,8 @@
 import android.text.TextUtils
 import android.util.Log
 import androidx.media.utils.MediaConstants
-import com.android.internal.annotations.VisibleForTesting
 import com.android.internal.logging.InstanceId
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.Dumpable
 import com.android.systemui.R
 import com.android.systemui.broadcast.BroadcastDispatcher
@@ -64,10 +64,14 @@
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.models.player.MediaDeviceData
 import com.android.systemui.media.controls.models.player.MediaViewHolder
+import com.android.systemui.media.controls.models.recommendation.EXTRA_KEY_TRIGGER_SOURCE
+import com.android.systemui.media.controls.models.recommendation.EXTRA_VALUE_TRIGGER_PERIODIC
 import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
 import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaDataProvider
 import com.android.systemui.media.controls.resume.MediaResumeListener
+import com.android.systemui.media.controls.resume.ResumeMediaBrowser
 import com.android.systemui.media.controls.util.MediaControllerFactory
+import com.android.systemui.media.controls.util.MediaDataUtils
 import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.media.controls.util.MediaUiEventLogger
 import com.android.systemui.plugins.ActivityStarter
@@ -119,7 +123,6 @@
         appUid = Process.INVALID_UID
     )
 
-@VisibleForTesting
 internal val EMPTY_SMARTSPACE_MEDIA_DATA =
     SmartspaceMediaData(
         targetId = "INVALID",
@@ -129,7 +132,8 @@
         recommendations = emptyList(),
         dismissIntent = null,
         headphoneConnectionTimeMillis = 0,
-        instanceId = InstanceId.fakeInstanceId(-1)
+        instanceId = InstanceId.fakeInstanceId(-1),
+        expiryTimeMs = 0,
     )
 
 fun isMediaNotification(sbn: StatusBarNotification): Boolean {
@@ -175,6 +179,7 @@
     private val mediaFlags: MediaFlags,
     private val logger: MediaUiEventLogger,
     private val smartspaceManager: SmartspaceManager,
+    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
 ) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener {
 
     companion object {
@@ -239,6 +244,7 @@
         mediaFlags: MediaFlags,
         logger: MediaUiEventLogger,
         smartspaceManager: SmartspaceManager,
+        keyguardUpdateMonitor: KeyguardUpdateMonitor,
     ) : this(
         context,
         backgroundExecutor,
@@ -262,6 +268,7 @@
         mediaFlags,
         logger,
         smartspaceManager,
+        keyguardUpdateMonitor,
     )
 
     private val appChangeReceiver =
@@ -548,6 +555,11 @@
             if (DEBUG) Log.d(TAG, "Updating $key timedOut: $timedOut")
             onMediaDataLoaded(key, key, it)
         }
+
+        if (key == smartspaceMediaData.targetId) {
+            if (DEBUG) Log.d(TAG, "smartspace card expired")
+            dismissSmartspaceRecommendation(key, delay = 0L)
+        }
     }
 
     /** Called when the player's [PlaybackState] has been updated with new actions and/or state */
@@ -605,8 +617,8 @@
     }
 
     /**
-     * Called whenever the recommendation has been expired, or swiped from QQS. This will make the
-     * recommendation view to not be shown anymore during this headphone connection session.
+     * Called whenever the recommendation has been expired or removed by the user. This will remove
+     * the recommendation card entirely from the carousel.
      */
     fun dismissSmartspaceRecommendation(key: String, delay: Long) {
         if (smartspaceMediaData.targetId != key || !smartspaceMediaData.isValid()) {
@@ -628,6 +640,23 @@
         )
     }
 
+    /** Called when the recommendation card should no longer be visible in QQS or lockscreen */
+    fun setRecommendationInactive(key: String) {
+        if (!mediaFlags.isPersistentSsCardEnabled()) {
+            Log.e(TAG, "Only persistent recommendation can be inactive!")
+            return
+        }
+        if (DEBUG) Log.d(TAG, "Setting smartspace recommendation inactive")
+
+        if (smartspaceMediaData.targetId != key || !smartspaceMediaData.isValid()) {
+            // If this doesn't match, or we've already invalidated the data, no action needed
+            return
+        }
+
+        smartspaceMediaData = smartspaceMediaData.copy(isActive = false)
+        notifySmartspaceMediaDataLoaded(smartspaceMediaData.targetId, smartspaceMediaData)
+    }
+
     private fun loadMediaDataInBgForResumption(
         userId: Int,
         desc: MediaDescription,
@@ -668,6 +697,11 @@
                 MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT &&
                 mediaFlags.isExplicitIndicatorEnabled()
 
+        val progress =
+            if (mediaFlags.isResumeProgressEnabled()) {
+                MediaDataUtils.getDescriptionProgress(desc.extras)
+            } else null
+
         val mediaAction = getResumeMediaAction(resumeAction)
         val lastActive = systemClock.elapsedRealtime()
         foregroundExecutor.execute {
@@ -698,6 +732,7 @@
                     instanceId = instanceId,
                     appUid = appUid,
                     isExplicit = isExplicit,
+                    resumeProgress = progress,
                 )
             )
         }
@@ -1261,12 +1296,25 @@
                 if (DEBUG) {
                     Log.d(TAG, "Set Smartspace media to be inactive for the data update")
                 }
-                smartspaceMediaData =
-                    EMPTY_SMARTSPACE_MEDIA_DATA.copy(
-                        targetId = smartspaceMediaData.targetId,
-                        instanceId = smartspaceMediaData.instanceId
+                if (mediaFlags.isPersistentSsCardEnabled()) {
+                    // Smartspace uses this signal to hide the card (e.g. when it expires or user
+                    // disconnects headphones), so treat as setting inactive when flag is on
+                    smartspaceMediaData = smartspaceMediaData.copy(isActive = false)
+                    notifySmartspaceMediaDataLoaded(
+                        smartspaceMediaData.targetId,
+                        smartspaceMediaData,
                     )
-                notifySmartspaceMediaDataRemoved(smartspaceMediaData.targetId, immediately = false)
+                } else {
+                    smartspaceMediaData =
+                        EMPTY_SMARTSPACE_MEDIA_DATA.copy(
+                            targetId = smartspaceMediaData.targetId,
+                            instanceId = smartspaceMediaData.instanceId,
+                        )
+                    notifySmartspaceMediaDataRemoved(
+                        smartspaceMediaData.targetId,
+                        immediately = false,
+                    )
+                }
             }
             1 -> {
                 val newMediaTarget = mediaTargets.get(0)
@@ -1275,7 +1323,7 @@
                     return
                 }
                 if (DEBUG) Log.d(TAG, "Forwarding Smartspace media update.")
-                smartspaceMediaData = toSmartspaceMediaData(newMediaTarget, isActive = true)
+                smartspaceMediaData = toSmartspaceMediaData(newMediaTarget)
                 notifySmartspaceMediaDataLoaded(smartspaceMediaData.targetId, smartspaceMediaData)
             }
             else -> {
@@ -1284,7 +1332,7 @@
                 Log.wtf(TAG, "More than 1 Smartspace Media Update. Resetting the status...")
                 notifySmartspaceMediaDataRemoved(
                     smartspaceMediaData.targetId,
-                    false /* immediately */
+                    immediately = false,
                 )
                 smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA
             }
@@ -1295,7 +1343,9 @@
         Assert.isMainThread()
         val removed = mediaEntries.remove(key) ?: return
 
-        if (useMediaResumption && removed.resumeAction != null && removed.isLocalSession()) {
+        if (keyguardUpdateMonitor.isUserInLockdown(removed.userId)) {
+            logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
+        } else if (useMediaResumption && removed.resumeAction != null && removed.isLocalSession()) {
             convertToResumePlayer(removed)
         } else if (mediaFlags.isRetainingPlayersEnabled()) {
             handlePossibleRemoval(removed, notificationRemoved = true)
@@ -1391,6 +1441,22 @@
             notifyMediaDataLoaded(key = pkg, oldKey = pkg, info = updated)
         }
         logger.logActiveConvertedToResume(updated.appUid, pkg, updated.instanceId)
+
+        // Limit total number of resume controls
+        val resumeEntries = mediaEntries.filter { (key, data) -> data.resumption }
+        val numResume = resumeEntries.size
+        if (numResume > ResumeMediaBrowser.MAX_RESUMPTION_CONTROLS) {
+            resumeEntries
+                .toList()
+                .sortedBy { (key, data) -> data.lastActive }
+                .subList(0, numResume - ResumeMediaBrowser.MAX_RESUMPTION_CONTROLS)
+                .forEach { (key, data) ->
+                    Log.d(TAG, "Removing excess control $key")
+                    mediaEntries.remove(key)
+                    notifyMediaDataRemoved(key)
+                    logger.logMediaRemoved(data.appUid, data.packageName, data.instanceId)
+                }
+        }
     }
 
     fun setMediaResumptionEnabled(isEnabled: Boolean) {
@@ -1490,21 +1556,28 @@
     }
 
     /**
-     * Converts the pass-in SmartspaceTarget to SmartspaceMediaData with the pass-in active status.
+     * Converts the pass-in SmartspaceTarget to SmartspaceMediaData
      *
      * @return An empty SmartspaceMediaData with the valid target Id is returned if the
      * SmartspaceTarget's data is invalid.
      */
-    private fun toSmartspaceMediaData(
-        target: SmartspaceTarget,
-        isActive: Boolean
-    ): SmartspaceMediaData {
+    private fun toSmartspaceMediaData(target: SmartspaceTarget): SmartspaceMediaData {
         var dismissIntent: Intent? = null
         if (target.baseAction != null && target.baseAction.extras != null) {
             dismissIntent =
                 target.baseAction.extras.getParcelable(EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY)
                     as Intent?
         }
+
+        val isActive =
+            when {
+                !mediaFlags.isPersistentSsCardEnabled() -> true
+                target.baseAction == null -> true
+                else ->
+                    target.baseAction.extras.getString(EXTRA_KEY_TRIGGER_SOURCE) !=
+                        EXTRA_VALUE_TRIGGER_PERIODIC
+            }
+
         packageName(target)?.let {
             return SmartspaceMediaData(
                 targetId = target.smartspaceTargetId,
@@ -1514,7 +1587,8 @@
                 recommendations = target.iconGrid,
                 dismissIntent = dismissIntent,
                 headphoneConnectionTimeMillis = target.creationTimeMillis,
-                instanceId = logger.getNewInstanceId()
+                instanceId = logger.getNewInstanceId(),
+                expiryTimeMs = target.expiryTimeMillis,
             )
         }
         return EMPTY_SMARTSPACE_MEDIA_DATA.copy(
@@ -1522,7 +1596,8 @@
             isActive = isActive,
             dismissIntent = dismissIntent,
             headphoneConnectionTimeMillis = target.creationTimeMillis,
-            instanceId = logger.getNewInstanceId()
+            instanceId = logger.getNewInstanceId(),
+            expiryTimeMs = target.expiryTimeMillis,
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
index a898b00..878962d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
@@ -23,7 +23,9 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.media.controls.models.player.MediaData
+import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
 import com.android.systemui.media.controls.util.MediaControllerFactory
+import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
 import com.android.systemui.statusbar.SysuiStatusBarStateController
@@ -38,7 +40,7 @@
 
 @VisibleForTesting
 val RESUME_MEDIA_TIMEOUT =
-    SystemProperties.getLong("debug.sysui.media_timeout_resume", TimeUnit.DAYS.toMillis(3))
+    SystemProperties.getLong("debug.sysui.media_timeout_resume", TimeUnit.DAYS.toMillis(2))
 
 /** Controller responsible for keeping track of playback states and expiring inactive streams. */
 @SysUISingleton
@@ -49,10 +51,12 @@
     @Main private val mainExecutor: DelayableExecutor,
     private val logger: MediaTimeoutLogger,
     statusBarStateController: SysuiStatusBarStateController,
-    private val systemClock: SystemClock
+    private val systemClock: SystemClock,
+    private val mediaFlags: MediaFlags,
 ) : MediaDataManager.Listener {
 
     private val mediaListeners: MutableMap<String, PlaybackStateListener> = mutableMapOf()
+    private val recommendationListeners: MutableMap<String, RecommendationListener> = mutableMapOf()
 
     /**
      * Callback representing that a media object is now expired:
@@ -93,6 +97,16 @@
                                 listener.doTimeout()
                             }
                         }
+
+                        recommendationListeners.forEach { (key, listener) ->
+                            if (
+                                listener.cancellation != null &&
+                                    listener.expiration <= systemClock.currentTimeMillis()
+                            ) {
+                                logger.logTimeoutCancelled(key, "Timed out while dozing")
+                                listener.doTimeout()
+                            }
+                        }
                     }
                 }
             }
@@ -155,6 +169,30 @@
         mediaListeners.remove(key)?.destroy()
     }
 
+    override fun onSmartspaceMediaDataLoaded(
+        key: String,
+        data: SmartspaceMediaData,
+        shouldPrioritize: Boolean
+    ) {
+        if (!mediaFlags.isPersistentSsCardEnabled()) return
+
+        // First check if we already have a listener
+        recommendationListeners.get(key)?.let {
+            if (!it.destroyed) {
+                it.recommendationData = data
+                return
+            }
+        }
+
+        // Otherwise, create a new one
+        recommendationListeners[key] = RecommendationListener(key, data)
+    }
+
+    override fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean) {
+        if (!mediaFlags.isPersistentSsCardEnabled()) return
+        recommendationListeners.remove(key)?.destroy()
+    }
+
     fun isTimedOut(key: String): Boolean {
         return mediaListeners[key]?.timedOut ?: false
     }
@@ -335,4 +373,53 @@
         }
         return true
     }
+
+    /** Listens to changes in recommendation card data and schedules a timeout for its expiration */
+    private inner class RecommendationListener(var key: String, data: SmartspaceMediaData) {
+        private var timedOut = false
+        var destroyed = false
+        var expiration = Long.MAX_VALUE
+            private set
+        var cancellation: Runnable? = null
+            private set
+
+        var recommendationData: SmartspaceMediaData = data
+            set(value) {
+                destroyed = false
+                field = value
+                processUpdate()
+            }
+
+        init {
+            recommendationData = data
+        }
+
+        fun destroy() {
+            cancellation?.run()
+            cancellation = null
+            destroyed = true
+        }
+
+        private fun processUpdate() {
+            if (recommendationData.expiryTimeMs != expiration) {
+                // The expiry time changed - cancel and reschedule
+                val timeout =
+                    recommendationData.expiryTimeMs -
+                        recommendationData.headphoneConnectionTimeMillis
+                logger.logRecommendationTimeoutScheduled(key, timeout)
+                cancellation?.run()
+                cancellation = mainExecutor.executeDelayed({ doTimeout() }, timeout)
+                expiration = recommendationData.expiryTimeMs
+            }
+        }
+
+        fun doTimeout() {
+            cancellation?.run()
+            cancellation = null
+            logger.logTimeout(key)
+            timedOut = true
+            expiration = Long.MAX_VALUE
+            timeoutCallback(key, timedOut)
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutLogger.kt
index 8f3f054..f731dc0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutLogger.kt
@@ -107,6 +107,17 @@
                 str1 = key
                 str2 = reason
             },
-            { "media timeout cancelled for $str1, reason: $str2" }
+            { "timeout cancelled for $str1, reason: $str2" }
+        )
+
+    fun logRecommendationTimeoutScheduled(key: String, timeout: Long) =
+        buffer.log(
+            TAG,
+            LogLevel.VERBOSE,
+            {
+                str1 = key
+                long1 = timeout
+            },
+            { "recommendation timeout scheduled for $str1 in $long1 ms" }
         )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index b2ad155..b72923a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -30,13 +30,20 @@
 import android.view.animation.PathInterpolator
 import android.widget.LinearLayout
 import androidx.annotation.VisibleForTesting
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
 import com.android.internal.logging.InstanceId
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.systemui.Dumpable
 import com.android.systemui.R
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.models.player.MediaViewHolder
 import com.android.systemui.media.controls.models.recommendation.RecommendationViewHolder
@@ -63,6 +70,10 @@
 import java.util.TreeMap
 import javax.inject.Inject
 import javax.inject.Provider
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.launch
 
 private const val TAG = "MediaCarouselController"
 private val settingsIntent = Intent().setAction(ACTION_MEDIA_CONTROLS_SETTINGS)
@@ -91,6 +102,8 @@
     private val logger: MediaUiEventLogger,
     private val debugLogger: MediaCarouselControllerLogger,
     private val mediaFlags: MediaFlags,
+    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
 ) : Dumpable {
     /** The current width of the carousel */
     private var currentCarouselWidth: Int = 0
@@ -213,6 +226,17 @@
             }
         }
 
+    private val keyguardUpdateMonitorCallback =
+        object : KeyguardUpdateMonitorCallback() {
+            override fun onStrongAuthStateChanged(userId: Int) {
+                if (keyguardUpdateMonitor.isUserInLockdown(userId)) {
+                    hideMediaCarousel()
+                } else if (keyguardUpdateMonitor.isUserUnlocked(userId)) {
+                    showMediaCarousel()
+                }
+            }
+        }
+
     /**
      * Update MediaCarouselScrollHandler.visibleToUser to reflect media card container visibility.
      * It will be called when the container is out of view.
@@ -368,7 +392,7 @@
                     data: SmartspaceMediaData,
                     shouldPrioritize: Boolean
                 ) {
-                    debugLogger.logRecommendationLoaded(key)
+                    debugLogger.logRecommendationLoaded(key, data.isActive)
                     // Log the case where the hidden media carousel with the existed inactive resume
                     // media is shown by the Smartspace signal.
                     if (data.isActive) {
@@ -442,7 +466,12 @@
                             logSmartspaceImpression(mediaCarouselScrollHandler.qsExpanded)
                         }
                     } else {
-                        onSmartspaceMediaDataRemoved(data.targetId, immediately = true)
+                        if (!mediaFlags.isPersistentSsCardEnabled()) {
+                            // Handle update to inactive as a removal
+                            onSmartspaceMediaDataRemoved(data.targetId, immediately = true)
+                        } else {
+                            addSmartspaceMediaRecommendations(key, data, shouldPrioritize)
+                        }
                     }
                 }
 
@@ -482,6 +511,13 @@
                 }
             }
         )
+        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+        mediaCarousel.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                // A backup to show media carousel (if available) once the keyguard is gone.
+                listenForAnyStateToGoneKeyguardTransition(this)
+            }
+        }
     }
 
     private fun inflateSettingsButton() {
@@ -511,6 +547,23 @@
         return mediaCarousel
     }
 
+    private fun hideMediaCarousel() {
+        mediaCarousel.visibility = View.GONE
+    }
+
+    private fun showMediaCarousel() {
+        mediaCarousel.visibility = View.VISIBLE
+    }
+
+    @VisibleForTesting
+    internal fun listenForAnyStateToGoneKeyguardTransition(scope: CoroutineScope): Job {
+        return scope.launch {
+            keyguardTransitionInteractor.anyStateToGoneTransition
+                .filter { it.transitionState == TransitionState.FINISHED }
+                .collect { showMediaCarousel() }
+        }
+    }
+
     private fun reorderAllPlayers(
         previousVisiblePlayerKey: MediaPlayerData.MediaSortKey?,
         key: String? = null
@@ -633,7 +686,19 @@
     ) =
         traceSection("MediaCarouselController#addSmartspaceMediaRecommendations") {
             if (DEBUG) Log.d(TAG, "Updating smartspace target in carousel")
-            if (MediaPlayerData.getMediaPlayer(key) != null) {
+            MediaPlayerData.getMediaPlayer(key)?.let {
+                if (mediaFlags.isPersistentSsCardEnabled()) {
+                    // The card exists, but could have changed active state, so update for sorting
+                    MediaPlayerData.addMediaRecommendation(
+                        key,
+                        data,
+                        it,
+                        shouldPrioritize,
+                        systemClock,
+                        debugLogger,
+                        update = true,
+                    )
+                }
                 Log.w(TAG, "Skip adding smartspace target in carousel")
                 return
             }
@@ -672,7 +737,7 @@
                 newRecs,
                 shouldPrioritize,
                 systemClock,
-                debugLogger
+                debugLogger,
             )
             updatePlayerToState(newRecs, noAnimation = true)
             reorderAllPlayers(curVisibleMediaKey)
@@ -1225,17 +1290,18 @@
         player: MediaControlPanel,
         shouldPrioritize: Boolean,
         clock: SystemClock,
-        debugLogger: MediaCarouselControllerLogger? = null
+        debugLogger: MediaCarouselControllerLogger? = null,
+        update: Boolean = false
     ) {
         shouldPrioritizeSs = shouldPrioritize
         val removedPlayer = removeMediaPlayer(key)
-        if (removedPlayer != null && removedPlayer != player) {
+        if (!update && removedPlayer != null && removedPlayer != player) {
             debugLogger?.logPotentialMemoryLeak(key)
         }
         val sortKey =
             MediaSortKey(
                 isSsMediaRec = true,
-                EMPTY.copy(isPlaying = false),
+                EMPTY.copy(active = data.isActive, isPlaying = false),
                 key,
                 clock.currentTimeMillis(),
                 isSsReactivated = true
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselControllerLogger.kt
index eed1bd7..35bda15 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselControllerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselControllerLogger.kt
@@ -48,8 +48,16 @@
     fun logMediaRemoved(key: String) =
         buffer.log(TAG, LogLevel.DEBUG, { str1 = key }, { "removing player $str1" })
 
-    fun logRecommendationLoaded(key: String) =
-        buffer.log(TAG, LogLevel.DEBUG, { str1 = key }, { "add recommendation $str1" })
+    fun logRecommendationLoaded(key: String, isActive: Boolean) =
+        buffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            {
+                str1 = key
+                bool1 = isActive
+            },
+            { "add recommendation $str1, active $bool1" }
+        )
 
     fun logRecommendationRemoved(key: String, immediately: Boolean) =
         buffer.log(
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 2fd4f27..6076e58 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
@@ -57,6 +57,7 @@
 import android.view.animation.Interpolator;
 import android.widget.ImageButton;
 import android.widget.ImageView;
+import android.widget.SeekBar;
 import android.widget.TextView;
 
 import androidx.annotation.NonNull;
@@ -116,8 +117,6 @@
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.time.SystemClock;
 
-import dagger.Lazy;
-
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.List;
@@ -125,6 +124,7 @@
 
 import javax.inject.Inject;
 
+import dagger.Lazy;
 import kotlin.Triple;
 import kotlin.Unit;
 
@@ -524,8 +524,13 @@
         }
 
         // Seek Bar
-        final MediaController controller = getController();
-        mBackgroundExecutor.execute(() -> mSeekBarViewModel.updateController(controller));
+        if (data.getResumption() && data.getResumeProgress() != null) {
+            double progress = data.getResumeProgress();
+            mSeekBarViewModel.updateStaticProgress(progress);
+        } else {
+            final MediaController controller = getController();
+            mBackgroundExecutor.execute(() -> mSeekBarViewModel.updateController(controller));
+        }
 
         // Show the broadcast dialog button only when the le audio is enabled.
         mShowBroadcastDialogButton =
@@ -732,9 +737,14 @@
             contentDescription =
                     mRecommendationViewHolder.getGutsViewHolder().getGutsText().getText();
         } else if (data != null) {
-            contentDescription = mContext.getString(
-                    R.string.controls_media_smartspace_rec_description,
-                    data.getAppName(mContext));
+            if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
+                contentDescription = mContext.getString(
+                        R.string.controls_media_smartspace_rec_header);
+            } else {
+                contentDescription = mContext.getString(
+                        R.string.controls_media_smartspace_rec_description,
+                        data.getAppName(mContext));
+            }
         } else {
             contentDescription = null;
         }
@@ -1129,8 +1139,10 @@
                         /* pixelDensity= */ getContext().getResources().getDisplayMetrics().density,
                         mColorSchemeTransition.getAccentPrimary().getCurrentColor(),
                         /* opacity= */ 100,
-                        /* shouldFillRipple= */ false,
                         /* sparkleStrength= */ 0f,
+                        /* baseRingFadeParams= */ null,
+                        /* sparkleRingFadeParams= */ null,
+                        /* centerFillFadeParams= */ null,
                         /* shouldDistort= */ false
                 )
         );
@@ -1365,6 +1377,24 @@
             hasSubtitle |= !TextUtils.isEmpty(subtitle);
             TextView subtitleView = mRecommendationViewHolder.getMediaSubtitles().get(itemIndex);
             subtitleView.setText(subtitle);
+
+            // Set up progress bar
+            if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
+                SeekBar mediaProgressBar =
+                        mRecommendationViewHolder.getMediaProgressBars().get(itemIndex);
+                TextView mediaSubtitle =
+                        mRecommendationViewHolder.getMediaSubtitles().get(itemIndex);
+                // show progress bar if the recommended album is played.
+                Double progress = MediaDataUtils.getDescriptionProgress(recommendation.getExtras());
+                if (progress == null || progress <= 0.0) {
+                    mediaProgressBar.setVisibility(View.GONE);
+                    mediaSubtitle.setVisibility(View.VISIBLE);
+                } else {
+                    mediaProgressBar.setProgress((int) (progress * 100));
+                    mediaProgressBar.setVisibility(View.VISIBLE);
+                    mediaSubtitle.setVisibility(View.GONE);
+                }
+            }
         }
         mSmartspaceMediaItemsCount = NUM_REQUIRED_RECOMMENDATIONS;
 
@@ -1439,6 +1469,12 @@
                 (title) -> title.setTextColor(textPrimaryColor));
         mRecommendationViewHolder.getMediaSubtitles().forEach(
                 (subtitle) -> subtitle.setTextColor(textSecondaryColor));
+        if (mFeatureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)) {
+            mRecommendationViewHolder.getMediaProgressBars().forEach(
+                    (progressBar) -> progressBar.setProgressTintList(
+                            ColorStateList.valueOf(textPrimaryColor))
+            );
+        }
 
         mRecommendationViewHolder.getGutsViewHolder().setColors(colorScheme);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaDataUtils.java b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaDataUtils.java
index bcfceaa..85282a1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaDataUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaDataUtils.java
@@ -19,8 +19,12 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.os.Bundle;
 import android.text.TextUtils;
 
+import androidx.core.math.MathUtils;
+import androidx.media.utils.MediaConstants;
+
 /**
  * Utility class with common methods for media controls
  */
@@ -50,4 +54,35 @@
                         : unknownName);
         return applicationName;
     }
+
+    /**
+     * Check the bundle for extras indicating the progress percentage
+     *
+     * @param extras
+     * @return the progress value between 0-1 inclusive if prsent, otherwise null
+     */
+    public static Double getDescriptionProgress(Bundle extras) {
+        if (!extras.containsKey(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS)) {
+            return null;
+        }
+
+        int status = extras.getInt(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS);
+        switch (status) {
+            case MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED:
+                return 0.0;
+            case MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED:
+                return 1.0;
+            case MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED: {
+                if (extras
+                        .containsKey(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE)) {
+                    double percent = extras
+                            .getDouble(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE);
+                    return MathUtils.clamp(percent, 0.0, 1.0);
+                } else {
+                    return 0.5;
+                }
+            }
+        }
+        return null;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index 81efa36..c3fa76e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -55,4 +55,10 @@
     /** Check whether we show the updated recommendation card. */
     fun isRecommendationCardUpdateEnabled() =
         featureFlags.isEnabled(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE)
+
+    /** Check whether to get progress information for resume players */
+    fun isResumeProgressEnabled() = featureFlags.isEnabled(Flags.MEDIA_RESUME_PROGRESS)
+
+    /** If true, do not automatically dismiss the recommendation card */
+    fun isPersistentSsCardEnabled() = featureFlags.isEnabled(Flags.MEDIA_RETAIN_RECOMMENDATIONS)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index d6c6a81..99e5740 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -16,14 +16,18 @@
 
 package com.android.systemui.media.dialog;
 
-import static android.media.RouteListingPreference.Item.DISABLE_REASON_SUBSCRIPTION_REQUIRED;
+import static android.media.RouteListingPreference.Item.SELECTION_BEHAVIOR_GO_TO_APP;
+import static android.media.RouteListingPreference.Item.SELECTION_BEHAVIOR_NONE;
+import static android.media.RouteListingPreference.Item.SELECTION_BEHAVIOR_TRANSFER;
+import static android.media.RouteListingPreference.Item.SUBTEXT_AD_ROUTING_DISALLOWED;
+import static android.media.RouteListingPreference.Item.SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED;
+import static android.media.RouteListingPreference.Item.SUBTEXT_SUBSCRIPTION_REQUIRED;
 
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
-import android.media.RouteListingPreference;
 import android.os.Build;
 import android.util.Log;
 import android.view.View;
@@ -50,6 +54,8 @@
 
     private static final String TAG = "MediaOutputAdapter";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final float DEVICE_DISCONNECTED_ALPHA = 0.5f;
+    private static final float DEVICE_CONNECTED_ALPHA = 1f;
 
     public MediaOutputAdapter(MediaOutputController controller) {
         super(controller);
@@ -140,6 +146,11 @@
 
     @Override
     public int getItemViewType(int position) {
+        if (mController.isAdvancedLayoutSupported()
+                && position >= mController.getMediaItemList().size()) {
+            Log.d(TAG, "Incorrect position for item type: " + position);
+            return MediaItem.MediaItemType.TYPE_GROUP_DIVIDER;
+        }
         return mController.isAdvancedLayoutSupported()
                 ? mController.getMediaItemList().get(position).getMediaItemType()
                 : super.getItemViewType(position);
@@ -168,6 +179,7 @@
             if (mCurrentActivePosition == position) {
                 mCurrentActivePosition = -1;
             }
+            mStatusIcon.setVisibility(View.GONE);
 
             if (mController.isAnyDeviceTransferring()) {
                 if (device.getState() == MediaDeviceState.STATE_CONNECTING
@@ -194,16 +206,51 @@
                     updateFullItemClickListener(v -> onItemClick(v, device));
                     setSingleLineLayout(getItemTitle(device));
                 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
-                        && mController.isSubStatusSupported() && device.hasDisabledReason()) {
-                    //update to subtext with device status
-                    setUpDeviceIcon(device);
-                    mSubTitleText.setText(
-                            Api34Impl.composeDisabledReason(device.getDisableReason(), mContext));
-                    updateConnectionFailedStatusIcon();
-                    updateFullItemClickListener(null);
-                    setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */,
-                            false /* showProgressBar */, true /* showSubtitle */,
-                            true /* showStatus */);
+                        && mController.isSubStatusSupported()
+                        && mController.isAdvancedLayoutSupported() && device.hasSubtext()) {
+                    boolean isActiveWithOngoingSession =
+                            (device.hasOngoingSession() && currentlyConnected);
+                    boolean isHost = device.isHostForOngoingSession()
+                            && isActiveWithOngoingSession;
+                    if (isHost) {
+                        mCurrentActivePosition = position;
+                        updateTitleIcon(R.drawable.media_output_icon_volume,
+                                mController.getColorItemContent());
+                        mSubTitleText.setText(device.getSubtextString());
+                        updateTwoLineLayoutContentAlpha(DEVICE_CONNECTED_ALPHA);
+                        updateEndClickAreaAsSessionEditing(device);
+                        setTwoLineLayout(device, null /* title */, true /* bFocused */,
+                                true /* showSeekBar */, false /* showProgressBar */,
+                                true /* showSubtitle */, false /* showStatus */,
+                                true /* showEndTouchArea */, false /* isFakeActive */);
+                        initSeekbar(device, isCurrentSeekbarInvisible);
+                    } else {
+                        if (isActiveWithOngoingSession) {
+                            //Selected device which has ongoing session, disable seekbar since we
+                            //only allow volume control on Host
+                            initSeekbar(device, isCurrentSeekbarInvisible);
+                            mCurrentActivePosition = position;
+                        }
+                        setUpDeviceIcon(device);
+                        mSubTitleText.setText(device.getSubtextString());
+                        Drawable deviceStatusIcon =
+                                device.hasOngoingSession() ? mContext.getDrawable(
+                                        R.drawable.media_output_status_session)
+                                        : Api34Impl.getDeviceStatusIconBasedOnSelectionBehavior(
+                                                device,
+                                                mContext);
+                        if (deviceStatusIcon != null) {
+                            updateDeviceStatusIcon(deviceStatusIcon);
+                        }
+                        updateTwoLineLayoutContentAlpha(
+                                updateClickActionBasedOnSelectionBehavior(device)
+                                        ? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
+                        setTwoLineLayout(device, isActiveWithOngoingSession /* bFocused */,
+                                isActiveWithOngoingSession /* showSeekBar */,
+                                false /* showProgressBar */, true /* showSubtitle */,
+                                deviceStatusIcon != null /* showStatus */,
+                                isActiveWithOngoingSession /* isFakeActive */);
+                    }
                 } else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
                     setUpDeviceIcon(device);
                     updateConnectionFailedStatusIcon();
@@ -211,7 +258,7 @@
                     updateFullItemClickListener(v -> onItemClick(v, device));
                     setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */,
                             false /* showProgressBar */, true /* showSubtitle */,
-                            true /* showStatus */);
+                            true /* showStatus */, false /*isFakeActive*/);
                 } else if (device.getState() == MediaDeviceState.STATE_GROUPING) {
                     setUpDeviceIcon(device);
                     updateProgressBarColor();
@@ -220,6 +267,7 @@
                             false /* showEndTouchArea */);
                 } else if (mController.getSelectedMediaDevice().size() > 1
                         && isDeviceIncluded(mController.getSelectedMediaDevice(), device)) {
+                    // selected device in group
                     boolean isDeviceDeselectable = isDeviceIncluded(
                             mController.getDeselectableMediaDevice(), device);
                     if (!mController.isAdvancedLayoutSupported()) {
@@ -235,6 +283,7 @@
                     initSeekbar(device, isCurrentSeekbarInvisible);
                 } else if (!mController.hasAdjustVolumeUserRestriction()
                         && currentlyConnected) {
+                    // single selected device
                     if (isMutingExpectedDeviceExist
                             && !mController.isCurrentConnectedDeviceRemote()) {
                         // mark as disconnected and set special click listener
@@ -266,6 +315,7 @@
                         initSeekbar(device, isCurrentSeekbarInvisible);
                     }
                 } else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
+                    //groupable device
                     setUpDeviceIcon(device);
                     updateGroupableCheckBox(false, true, device);
                     if (mController.isAdvancedLayoutSupported()) {
@@ -280,7 +330,24 @@
                 } else {
                     setUpDeviceIcon(device);
                     setSingleLineLayout(getItemTitle(device));
-                    updateFullItemClickListener(v -> onItemClick(v, device));
+                    if (mController.isAdvancedLayoutSupported()
+                            && mController.isSubStatusSupported()) {
+                        Drawable deviceStatusIcon =
+                                device.hasOngoingSession() ? mContext.getDrawable(
+                                        R.drawable.media_output_status_session)
+                                        : Api34Impl.getDeviceStatusIconBasedOnSelectionBehavior(
+                                                device,
+                                                mContext);
+                        if (deviceStatusIcon != null) {
+                            updateDeviceStatusIcon(deviceStatusIcon);
+                            mStatusIcon.setVisibility(View.VISIBLE);
+                        }
+                        updateTwoLineLayoutContentAlpha(
+                                updateClickActionBasedOnSelectionBehavior(device)
+                                        ? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
+                    } else {
+                        updateFullItemClickListener(v -> onItemClick(v, device));
+                    }
                 }
             }
         }
@@ -292,12 +359,48 @@
                     ColorStateList(states, colors));
         }
 
+        private void updateTwoLineLayoutContentAlpha(float alphaValue) {
+            mSubTitleText.setAlpha(alphaValue);
+            mTitleIcon.setAlpha(alphaValue);
+            mTwoLineTitleText.setAlpha(alphaValue);
+            mStatusIcon.setAlpha(alphaValue);
+        }
+
+        private void updateEndClickAreaAsSessionEditing(MediaDevice device) {
+            mEndClickIcon.setOnClickListener(null);
+            mEndTouchArea.setOnClickListener(null);
+            updateEndClickAreaColor(mController.getColorSeekbarProgress());
+            mEndClickIcon.setColorFilter(mController.getColorItemContent());
+            mEndClickIcon.setOnClickListener(
+                    v -> mController.tryToLaunchInAppRoutingIntent(device.getId(), v));
+            mEndTouchArea.setOnClickListener(v -> mCheckBox.performClick());
+        }
+
+        public void updateEndClickAreaColor(int color) {
+            if (mController.isAdvancedLayoutSupported()) {
+                mEndTouchArea.getBackground().setColorFilter(
+                        new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
+            }
+        }
+
+        private boolean updateClickActionBasedOnSelectionBehavior(MediaDevice device) {
+            View.OnClickListener clickListener = Api34Impl.getClickListenerBasedOnSelectionBehavior(
+                    device, mController, v -> onItemClick(v, device));
+            updateFullItemClickListener(clickListener);
+            return clickListener != null;
+        }
+
         private void updateConnectionFailedStatusIcon() {
             mStatusIcon.setImageDrawable(
                     mContext.getDrawable(R.drawable.media_output_status_failed));
             mStatusIcon.setColorFilter(mController.getColorItemContent());
         }
 
+        private void updateDeviceStatusIcon(Drawable drawable) {
+            mStatusIcon.setImageDrawable(drawable);
+            mStatusIcon.setColorFilter(mController.getColorItemContent());
+        }
+
         private void updateProgressBarColor() {
             mProgressBar.getIndeterminateDrawable().setColorFilter(
                     new PorterDuffColorFilter(
@@ -411,13 +514,30 @@
     @RequiresApi(34)
     private static class Api34Impl {
         @DoNotInline
-        static String composeDisabledReason(@RouteListingPreference.Item.DisableReason int reason,
-                Context context) {
-            switch(reason) {
-                case DISABLE_REASON_SUBSCRIPTION_REQUIRED:
-                    return context.getString(R.string.media_output_status_require_premium);
+        static View.OnClickListener getClickListenerBasedOnSelectionBehavior(MediaDevice device,
+                MediaOutputController controller, View.OnClickListener defaultTransferListener) {
+            switch (device.getSelectionBehavior()) {
+                case SELECTION_BEHAVIOR_NONE:
+                    return null;
+                case SELECTION_BEHAVIOR_TRANSFER:
+                    return defaultTransferListener;
+                case SELECTION_BEHAVIOR_GO_TO_APP:
+                    return v -> controller.tryToLaunchInAppRoutingIntent(device.getId(), v);
             }
-            return "";
+            return defaultTransferListener;
+        }
+
+        @DoNotInline
+        static Drawable getDeviceStatusIconBasedOnSelectionBehavior(MediaDevice device,
+                Context context) {
+            switch (device.getSubtext()) {
+                case SUBTEXT_AD_ROUTING_DISALLOWED:
+                case SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED:
+                    return context.getDrawable(R.drawable.media_output_status_failed);
+                case SUBTEXT_SUBSCRIPTION_REQUIRED:
+                    return context.getDrawable(R.drawable.media_output_status_help);
+            }
+            return null;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index dc75538..2a2cf63 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -147,6 +147,7 @@
         final ImageView mStatusIcon;
         final CheckBox mCheckBox;
         final ViewGroup mEndTouchArea;
+        final ImageView mEndClickIcon;
         @VisibleForTesting
         MediaOutputSeekbar mSeekBar;
         private String mDeviceId;
@@ -168,11 +169,13 @@
             mCheckBox = view.requireViewById(R.id.check_box);
             mEndTouchArea = view.requireViewById(R.id.end_action_area);
             if (mController.isAdvancedLayoutSupported()) {
+                mEndClickIcon = view.requireViewById(R.id.media_output_item_end_click_icon);
                 mVolumeValueText = view.requireViewById(R.id.volume_value);
                 mIconAreaLayout = view.requireViewById(R.id.icon_area);
             } else {
                 mVolumeValueText = null;
                 mIconAreaLayout = null;
+                mEndClickIcon = null;
             }
             initAnimator();
         }
@@ -218,20 +221,7 @@
                                 .mutate();
                 mItemLayout.setBackground(backgroundDrawable);
                 if (showSeekBar) {
-                    final ClipDrawable clipDrawable =
-                            (ClipDrawable) ((LayerDrawable) mSeekBar.getProgressDrawable())
-                                    .findDrawableByLayerId(android.R.id.progress);
-                    final GradientDrawable progressDrawable =
-                            (GradientDrawable) clipDrawable.getDrawable();
-                    if (mController.isAdvancedLayoutSupported()) {
-                        progressDrawable.setCornerRadii(
-                                new float[]{0, 0, mController.getActiveRadius(),
-                                        mController.getActiveRadius(),
-                                        mController.getActiveRadius(),
-                                        mController.getActiveRadius(), 0, 0});
-                    } else {
-                        progressDrawable.setCornerRadius(mController.getActiveRadius());
-                    }
+                    updateSeekbarProgressBackground();
                 }
             }
             mItemLayout.getBackground().setColorFilter(new PorterDuffColorFilter(
@@ -265,25 +255,52 @@
         }
 
         void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
-                boolean showProgressBar, boolean showSubtitle, boolean showStatus) {
+                boolean showProgressBar, boolean showSubtitle, boolean showStatus,
+                boolean isFakeActive) {
             setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle,
-                    showStatus);
+                    showStatus, false, isFakeActive);
         }
 
-        private void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
+        void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
                 boolean showSeekBar, boolean showProgressBar, boolean showSubtitle,
-                boolean showStatus) {
+                boolean showStatus , boolean showEndTouchArea, boolean isFakeActive) {
             mTitleText.setVisibility(View.GONE);
             mTwoLineLayout.setVisibility(View.VISIBLE);
             mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
             mSeekBar.setAlpha(1);
             mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
-            final Drawable backgroundDrawable = mContext.getDrawable(
-                            R.drawable.media_output_item_background)
-                    .mutate();
-            backgroundDrawable.setColorFilter(new PorterDuffColorFilter(
-                    mController.getColorItemBackground(),
-                    PorterDuff.Mode.SRC_IN));
+            final Drawable backgroundDrawable;
+            if (mController.isAdvancedLayoutSupported() && mController.isSubStatusSupported()) {
+                backgroundDrawable = mContext.getDrawable(
+                        showSeekBar ? R.drawable.media_output_item_background_active
+                                : R.drawable.media_output_item_background).mutate();
+                backgroundDrawable.setColorFilter(new PorterDuffColorFilter(
+                        showSeekBar ? mController.getColorConnectedItemBackground()
+                                : mController.getColorItemBackground(), PorterDuff.Mode.SRC_IN));
+                mIconAreaLayout.getBackground().setColorFilter(new PorterDuffColorFilter(
+                        showProgressBar || isFakeActive
+                                ? mController.getColorConnectedItemBackground()
+                                : showSeekBar ? mController.getColorSeekbarProgress()
+                                        : mController.getColorItemBackground(),
+                        PorterDuff.Mode.SRC_IN));
+                if (showSeekBar) {
+                    updateSeekbarProgressBackground();
+                }
+                //update end click area by isActive
+                mEndTouchArea.setVisibility(showEndTouchArea ? View.VISIBLE : View.GONE);
+                mEndClickIcon.setVisibility(showEndTouchArea ? View.VISIBLE : View.GONE);
+                ViewGroup.MarginLayoutParams params =
+                        (ViewGroup.MarginLayoutParams) mItemLayout.getLayoutParams();
+                params.rightMargin = showEndTouchArea ? mController.getItemMarginEndSelectable()
+                        : mController.getItemMarginEndDefault();
+            } else {
+                backgroundDrawable = mContext.getDrawable(
+                                R.drawable.media_output_item_background)
+                        .mutate();
+                backgroundDrawable.setColorFilter(new PorterDuffColorFilter(
+                        mController.getColorItemBackground(),
+                        PorterDuff.Mode.SRC_IN));
+            }
             mItemLayout.setBackground(backgroundDrawable);
             mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
             mSubTitleText.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
@@ -295,11 +312,28 @@
                     Typeface.NORMAL));
         }
 
+        void updateSeekbarProgressBackground() {
+            final ClipDrawable clipDrawable =
+                    (ClipDrawable) ((LayerDrawable) mSeekBar.getProgressDrawable())
+                            .findDrawableByLayerId(android.R.id.progress);
+            final GradientDrawable progressDrawable =
+                    (GradientDrawable) clipDrawable.getDrawable();
+            if (mController.isAdvancedLayoutSupported()) {
+                progressDrawable.setCornerRadii(
+                        new float[]{0, 0, mController.getActiveRadius(),
+                                mController.getActiveRadius(),
+                                mController.getActiveRadius(),
+                                mController.getActiveRadius(), 0, 0});
+            } else {
+                progressDrawable.setCornerRadius(mController.getActiveRadius());
+            }
+        }
+
         void initSeekbar(MediaDevice device, boolean isCurrentSeekbarInvisible) {
             if (!mController.isVolumeControlEnabled(device)) {
                 disableSeekBar();
             } else {
-                enableSeekBar();
+                enableSeekBar(device);
             }
             mSeekBar.setMaxVolume(device.getMaxVolume());
             final int currentVolume = device.getCurrentVolume();
@@ -335,13 +369,6 @@
             if (mIsInitVolumeFirstTime) {
                 mIsInitVolumeFirstTime = false;
             }
-            if (mController.isAdvancedLayoutSupported()) {
-                updateIconAreaClickListener((v) -> {
-                    mSeekBar.resetVolume();
-                    mController.adjustVolume(device, 0);
-                    updateMutedVolumeIcon();
-                });
-            }
             mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                 @Override
                 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
@@ -522,11 +549,21 @@
         protected void disableSeekBar() {
             mSeekBar.setEnabled(false);
             mSeekBar.setOnTouchListener((v, event) -> true);
+            if (mController.isAdvancedLayoutSupported()) {
+                updateIconAreaClickListener(null);
+            }
         }
 
-        private void enableSeekBar() {
+        private void enableSeekBar(MediaDevice device) {
             mSeekBar.setEnabled(true);
             mSeekBar.setOnTouchListener((v, event) -> false);
+            if (mController.isAdvancedLayoutSupported()) {
+                updateIconAreaClickListener((v) -> {
+                    mSeekBar.resetVolume();
+                    mController.adjustVolume(device, 0);
+                    updateMutedVolumeIcon();
+                });
+            }
         }
 
         protected void setUpDeviceIcon(MediaDevice device) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 4803371..35819e3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -263,10 +263,10 @@
             mMediaOutputController.releaseSession();
             dismiss();
         });
-        mAppButton.setOnClickListener(v -> mMediaOutputController.tryToLaunchMediaApplication());
+        mAppButton.setOnClickListener(mMediaOutputController::tryToLaunchMediaApplication);
         if (mMediaOutputController.isAdvancedLayoutSupported()) {
             mMediaMetadataSectionLayout.setOnClickListener(
-                    v -> mMediaOutputController.tryToLaunchMediaApplication());
+                    mMediaOutputController::tryToLaunchMediaApplication);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 5f5c686..2aedd36 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.media.dialog;
 
+import static android.media.RouteListingPreference.ACTION_TRANSFER_MEDIA;
+import static android.media.RouteListingPreference.EXTRA_ROUTE_ID;
 import static android.provider.Settings.ACTION_BLUETOOTH_SETTINGS;
 
 import android.annotation.CallbackExecutor;
@@ -24,6 +26,7 @@
 import android.app.Notification;
 import android.app.WallpaperColors;
 import android.bluetooth.BluetoothLeBroadcast;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -382,12 +385,29 @@
         return mContext.getPackageManager().getLaunchIntentForPackage(mPackageName);
     }
 
-    void tryToLaunchMediaApplication() {
+    void tryToLaunchInAppRoutingIntent(String routeId, View view) {
+        ComponentName componentName = mLocalMediaManager.getLinkedItemComponentName();
+        if (componentName != null) {
+            ActivityLaunchAnimator.Controller controller =
+                    mDialogLaunchAnimator.createActivityLaunchController(view);
+            Intent launchIntent = new Intent(ACTION_TRANSFER_MEDIA);
+            launchIntent.setComponent(componentName);
+            launchIntent.putExtra(EXTRA_ROUTE_ID, routeId);
+            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mCallback.dismissDialog();
+            mContext.startActivity(launchIntent);
+            mActivityStarter.startActivity(launchIntent, true, controller);
+        }
+    }
+
+    void tryToLaunchMediaApplication(View view) {
+        ActivityLaunchAnimator.Controller controller =
+                mDialogLaunchAnimator.createActivityLaunchController(view);
         Intent launchIntent = getAppLaunchIntent();
         if (launchIntent != null) {
             launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             mCallback.dismissDialog();
-            mContext.startActivity(launchIntent);
+            mActivityStarter.startActivity(launchIntent, true, controller);
         }
     }
 
@@ -684,19 +704,21 @@
                 devices.removeAll(targetMediaDevices);
                 targetMediaDevices.addAll(devices);
             }
-            mMediaItemList.clear();
-            mMediaItemList.addAll(
-                    targetMediaDevices.stream().map(MediaItem::new).collect(Collectors.toList()));
+            List<MediaItem> finalMediaItems = targetMediaDevices.stream().map(
+                    MediaItem::new).collect(Collectors.toList());
             dividerItems.forEach((key, item) -> {
-                mMediaItemList.add(key, item);
+                finalMediaItems.add(key, item);
             });
-            mMediaItemList.add(new MediaItem());
+            finalMediaItems.add(new MediaItem());
+            mMediaItemList.clear();
+            mMediaItemList.addAll(finalMediaItems);
         }
     }
 
     private void categorizeMediaItems(MediaDevice connectedMediaDevice, List<MediaDevice> devices,
             boolean needToHandleMutingExpectedDevice) {
         synchronized (mMediaDevicesLock) {
+            List<MediaItem> finalMediaItems = new ArrayList<>();
             Set<String> selectedDevicesIds = getSelectedMediaDevice().stream().map(
                     MediaDevice::getId).collect(Collectors.toSet());
             if (connectedMediaDevice != null) {
@@ -706,32 +728,32 @@
             boolean displayGroupAdded = false;
             for (MediaDevice device : devices) {
                 if (needToHandleMutingExpectedDevice && device.isMutingExpectedDevice()) {
-                    mMediaItemList.add(0, new MediaItem(device));
+                    finalMediaItems.add(0, new MediaItem(device));
                 } else if (!needToHandleMutingExpectedDevice && selectedDevicesIds.contains(
                         device.getId())) {
-                    mMediaItemList.add(0, new MediaItem(device));
+                    finalMediaItems.add(0, new MediaItem(device));
                 } else {
                     if (device.isSuggestedDevice() && !suggestedDeviceAdded) {
-                        attachGroupDivider(mContext.getString(
+                        attachGroupDivider(finalMediaItems, mContext.getString(
                                 R.string.media_output_group_title_suggested_device));
                         suggestedDeviceAdded = true;
                     } else if (!device.isSuggestedDevice() && !displayGroupAdded) {
-                        attachGroupDivider(mContext.getString(
+                        attachGroupDivider(finalMediaItems, mContext.getString(
                                 R.string.media_output_group_title_speakers_and_displays));
                         displayGroupAdded = true;
                     }
-                    mMediaItemList.add(new MediaItem(device));
+                    finalMediaItems.add(new MediaItem(device));
                 }
             }
-            mMediaItemList.add(new MediaItem());
+            finalMediaItems.add(new MediaItem());
+            mMediaItemList.clear();
+            mMediaItemList.addAll(finalMediaItems);
         }
     }
 
-    private void attachGroupDivider(String title) {
-        synchronized (mMediaDevicesLock) {
-            mMediaItemList.add(
-                    new MediaItem(title, MediaItem.MediaItemType.TYPE_GROUP_DIVIDER));
-        }
+    private void attachGroupDivider(List<MediaItem> mediaItems, String title) {
+        mediaItems.add(
+                new MediaItem(title, MediaItem.MediaItemType.TYPE_GROUP_DIVIDER));
     }
 
     private void attachRangeInfo(List<MediaDevice> devices) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
index fbd0079..a174b45 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.Bundle;
+import android.util.FeatureFlagUtils;
 import android.view.View;
 import android.view.WindowManager;
 
@@ -99,10 +100,18 @@
     @Override
     public boolean isBroadcastSupported() {
         boolean isBluetoothLeDevice = false;
-        if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) {
-            isBluetoothLeDevice = mMediaOutputController.isBluetoothLeDevice(
+        if (FeatureFlagUtils.isEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST)) {
+            if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) {
+                isBluetoothLeDevice = mMediaOutputController.isBluetoothLeDevice(
                     mMediaOutputController.getCurrentConnectedMediaDevice());
+            }
+        } else {
+            // To decouple LE Audio Broadcast and Unicast, it always displays the button when there
+            // is no LE Audio device connected to the phone
+            isBluetoothLeDevice = true;
         }
+
         return mMediaOutputController.isBroadcastSupported() && isBluetoothLeDevice;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
index a3ae943..720c44a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
@@ -44,25 +44,37 @@
          * @param appPackageName the package name of the app playing the media.
          * @param onPackageNotFoundException a function run if a
          * [PackageManager.NameNotFoundException] occurs.
+         * @param isReceiver indicates whether the icon is displayed in a receiver view.
          */
         fun getIconInfoFromPackageName(
             context: Context,
             appPackageName: String?,
+            isReceiver: Boolean,
             onPackageNotFoundException: () -> Unit,
         ): IconInfo {
             if (appPackageName != null) {
                 val packageManager = context.packageManager
                 try {
+                    val appName =
+                        packageManager
+                            .getApplicationInfo(
+                                appPackageName,
+                                PackageManager.ApplicationInfoFlags.of(0),
+                            )
+                            .loadLabel(packageManager)
+                            .toString()
                     val contentDescription =
-                        ContentDescription.Loaded(
-                            packageManager
-                                .getApplicationInfo(
-                                    appPackageName,
-                                    PackageManager.ApplicationInfoFlags.of(0)
+                        if (isReceiver) {
+                            ContentDescription.Loaded(
+                                context.getString(
+                                    R.string
+                                        .media_transfer_receiver_content_description_with_app_name,
+                                    appName
                                 )
-                                .loadLabel(packageManager)
-                                .toString()
-                        )
+                            )
+                        } else {
+                            ContentDescription.Loaded(appName)
+                        }
                     return IconInfo(
                         contentDescription,
                         MediaTttIcon.Loaded(packageManager.getApplicationIcon(appPackageName)),
@@ -74,7 +86,15 @@
                 }
             }
             return IconInfo(
-                ContentDescription.Resource(R.string.media_output_dialog_unknown_launch_app_name),
+                if (isReceiver) {
+                    ContentDescription.Resource(
+                        R.string.media_transfer_receiver_content_description_unknown_app
+                    )
+                } else {
+                    ContentDescription.Resource(
+                        R.string.media_output_dialog_unknown_launch_app_name
+                    )
+                },
                 MediaTttIcon.Resource(R.drawable.ic_cast),
                 tintAttr = android.R.attr.textColorPrimary,
                 isAppIcon = false
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
index 34bf74fa..fab8c06 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
@@ -16,7 +16,9 @@
 
 package com.android.systemui.media.taptotransfer.receiver
 
+import android.animation.TimeInterpolator
 import android.annotation.SuppressLint
+import android.animation.ValueAnimator
 import android.app.StatusBarManager
 import android.content.Context
 import android.graphics.Rect
@@ -31,8 +33,10 @@
 import android.view.WindowManager
 import android.view.accessibility.AccessibilityManager
 import android.view.View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE
+import android.view.View.ACCESSIBILITY_LIVE_REGION_NONE
 import com.android.internal.widget.CachingIconView
 import com.android.systemui.R
+import com.android.systemui.animation.Interpolators
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.ui.binder.TintedIconViewBinder
 import com.android.systemui.dagger.SysUISingleton
@@ -101,6 +105,13 @@
         fitInsetsTypes = 0 // Ignore insets from all system bars
     }
 
+    // Value animator that controls the bouncing animation of views.
+    private val bounceAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
+        repeatCount = ValueAnimator.INFINITE
+        repeatMode = ValueAnimator.REVERSE
+        duration = ICON_BOUNCE_ANIM_DURATION
+    }
+
     private val commandQueueCallbacks = object : CommandQueue.Callbacks {
         override fun updateMediaTapToTransferReceiverDisplay(
             @StatusBarManager.MediaTransferReceiverState displayState: Int,
@@ -173,7 +184,11 @@
 
     override fun updateView(newInfo: ChipReceiverInfo, currentView: ViewGroup) {
         val packageName = newInfo.routeInfo.clientPackageName
-        var iconInfo = MediaTttUtils.getIconInfoFromPackageName(context, packageName) {
+        var iconInfo = MediaTttUtils.getIconInfoFromPackageName(
+            context,
+            packageName,
+            isReceiver = true,
+        ) {
             logger.logPackageNotFound(packageName)
         }
 
@@ -199,44 +214,52 @@
 
         val iconView = currentView.getAppIconView()
         iconView.setPadding(iconPadding, iconPadding, iconPadding, iconPadding)
-        iconView.accessibilityLiveRegion = ACCESSIBILITY_LIVE_REGION_ASSERTIVE
         TintedIconViewBinder.bind(iconInfo.toTintedIcon(), iconView)
+
+        val iconContainerView = currentView.getIconContainerView()
+        iconContainerView.accessibilityLiveRegion = ACCESSIBILITY_LIVE_REGION_ASSERTIVE
     }
 
     override fun animateViewIn(view: ViewGroup) {
-        val appIconView = view.getAppIconView()
+        val iconContainerView = view.getIconContainerView()
         val iconRippleView: ReceiverChipRippleView = view.requireViewById(R.id.icon_glow_ripple)
         val rippleView: ReceiverChipRippleView = view.requireViewById(R.id.ripple)
-        animateViewTranslationAndFade(appIconView, -1 * getTranslationAmount(), 1f)
-        animateViewTranslationAndFade(iconRippleView, -1 * getTranslationAmount(), 1f)
+        val translationYBy = getTranslationAmount()
+        // Make the icon container view starts animation from bottom of the screen.
+        iconContainerView.translationY += rippleController.getReceiverIconSize()
+        animateViewTranslationAndFade(
+            iconContainerView,
+            translationYBy = -1 * translationYBy,
+            alphaEndValue = 1f,
+            Interpolators.EMPHASIZED_DECELERATE,
+        ) {
+            animateBouncingView(iconContainerView, translationYBy * BOUNCE_TRANSLATION_RATIO)
+        }
         rippleController.expandToInProgressState(rippleView, iconRippleView)
     }
 
     override fun animateViewOut(view: ViewGroup, removalReason: String?, onAnimationEnd: Runnable) {
-        val appIconView = view.getAppIconView()
-        val iconRippleView: ReceiverChipRippleView = view.requireViewById(R.id.icon_glow_ripple)
+        val iconContainerView = view.getIconContainerView()
         val rippleView: ReceiverChipRippleView = view.requireViewById(R.id.ripple)
+        val translationYBy = getTranslationAmount()
+
+        // Remove update listeners from bounce animator to prevent any conflict with
+        // translation animation.
+        bounceAnimator.removeAllUpdateListeners()
+        bounceAnimator.cancel()
         if (removalReason == ChipStateReceiver.TRANSFER_TO_RECEIVER_SUCCEEDED.name &&
                 mediaTttFlags.isMediaTttReceiverSuccessRippleEnabled()) {
             rippleController.expandToSuccessState(rippleView, onAnimationEnd)
             animateViewTranslationAndFade(
-                iconRippleView,
-                -1 * getTranslationAmount(),
-                0f,
-                translationDuration = ICON_TRANSLATION_SUCCEEDED_DURATION,
-                alphaDuration = ICON_TRANSLATION_SUCCEEDED_DURATION,
-            )
-            animateViewTranslationAndFade(
-                appIconView,
-                -1 * getTranslationAmount(),
+                iconContainerView,
+                -1 * translationYBy,
                 0f,
                 translationDuration = ICON_TRANSLATION_SUCCEEDED_DURATION,
                 alphaDuration = ICON_TRANSLATION_SUCCEEDED_DURATION,
             )
         } else {
             rippleController.collapseRipple(rippleView, onAnimationEnd)
-            animateViewTranslationAndFade(iconRippleView, getTranslationAmount(), 0f)
-            animateViewTranslationAndFade(appIconView, getTranslationAmount(), 0f)
+            animateViewTranslationAndFade(iconContainerView, translationYBy, 0f)
         }
     }
 
@@ -248,15 +271,19 @@
 
     /** Animation of view translation and fading. */
     private fun animateViewTranslationAndFade(
-        view: View,
+        view: ViewGroup,
         translationYBy: Float,
         alphaEndValue: Float,
+        interpolator: TimeInterpolator? = null,
         translationDuration: Long = ICON_TRANSLATION_ANIM_DURATION,
         alphaDuration: Long = ICON_ALPHA_ANIM_DURATION,
+        onAnimationEnd: Runnable? = null,
     ) {
         view.animate()
             .translationYBy(translationYBy)
+            .setInterpolator(interpolator)
             .setDuration(translationDuration)
+            .withEndAction { onAnimationEnd?.run() }
             .start()
         view.animate()
             .alpha(alphaEndValue)
@@ -266,17 +293,42 @@
 
     /** Returns the amount that the chip will be translated by in its intro animation. */
     private fun getTranslationAmount(): Float {
-        return rippleController.getRippleSize() * 0.5f -
-            rippleController.getReceiverIconSize()
+        return rippleController.getRippleSize() * 0.5f
     }
 
     private fun View.getAppIconView(): CachingIconView {
         return this.requireViewById(R.id.app_icon)
     }
 
+    private fun View.getIconContainerView(): ViewGroup {
+        return this.requireViewById(R.id.icon_container_view)
+    }
+
+    private fun animateBouncingView(iconContainerView: ViewGroup, translationYBy: Float) {
+        if (bounceAnimator.isStarted) {
+            return
+        }
+
+        addViewToBounceAnimation(iconContainerView, translationYBy)
+
+        // In order not to announce description every time the view animate.
+        iconContainerView.accessibilityLiveRegion = ACCESSIBILITY_LIVE_REGION_NONE
+        bounceAnimator.start()
+    }
+
+    private fun addViewToBounceAnimation(view: View, translationYBy: Float) {
+        val prevTranslationY = view.translationY
+        bounceAnimator.addUpdateListener { updateListener ->
+            val progress = updateListener.animatedValue as Float
+            view.translationY = prevTranslationY + translationYBy * progress
+        }
+    }
+
     companion object {
         private const val ICON_TRANSLATION_ANIM_DURATION = 500L
+        private const val ICON_BOUNCE_ANIM_DURATION = 750L
         private const val ICON_TRANSLATION_SUCCEEDED_DURATION = 167L
+        private const val BOUNCE_TRANSLATION_RATIO = 0.15f
         private val ICON_ALPHA_ANIM_DURATION = 5.frames
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
index f1acae8..4ff082a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
@@ -34,7 +34,7 @@
 
     init {
         setupShader(RippleShader.RippleShape.CIRCLE)
-        setRippleFill(true)
+        setupRippleFadeParams()
         setSparkleStrength(0f)
         isStarted = false
     }
@@ -72,7 +72,7 @@
         animator.removeAllUpdateListeners()
 
         // Only show the outline as ripple expands and disappears when animation ends.
-        setRippleFill(false)
+        removeRippleFill()
 
         val startingPercentage = calculateStartingPercentage(newHeight)
         animator.duration = EXPAND_TO_FULL_DURATION
@@ -103,6 +103,38 @@
         return 1 - remainingPercentage
     }
 
+    private fun setupRippleFadeParams() {
+        with(rippleShader) {
+            // No fade out for the base ring.
+            baseRingFadeParams.fadeOutStart = 1f
+            baseRingFadeParams.fadeOutEnd = 1f
+
+            // No fade in and outs for the center fill, as we always draw it.
+            centerFillFadeParams.fadeInStart = 0f
+            centerFillFadeParams.fadeInEnd = 0f
+            centerFillFadeParams.fadeOutStart = 1f
+            centerFillFadeParams.fadeOutEnd = 1f
+        }
+    }
+
+    private fun removeRippleFill() {
+        with(rippleShader) {
+            // Set back to default because we modified them in [setupRippleFadeParams].
+            baseRingFadeParams.fadeOutStart = RippleShader.DEFAULT_BASE_RING_FADE_OUT_START
+            baseRingFadeParams.fadeOutEnd = RippleShader.DEFAULT_FADE_OUT_END
+
+            centerFillFadeParams.fadeInStart = RippleShader.DEFAULT_FADE_IN_START
+            centerFillFadeParams.fadeInEnd = RippleShader.DEFAULT_CENTER_FILL_FADE_IN_END
+
+            // To avoid a seam showing up, we should match either:
+            // 1. baseRingFadeParams#fadeInEnd and centerFillFadeParams#fadeOutStart
+            // 2. baseRingFadeParams#fadeOutStart and centerFillFadeOutStart
+            // Here we go with 1 to fade in the centerFill faster.
+            centerFillFadeParams.fadeOutStart = baseRingFadeParams.fadeInEnd
+            centerFillFadeParams.fadeOutEnd = RippleShader.DEFAULT_FADE_OUT_END
+        }
+    }
+
     companion object {
         const val DEFAULT_DURATION = 333L
         const val EXPAND_TO_FULL_DURATION = 1000L
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
index 1f27582..537dbb9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
@@ -136,9 +136,9 @@
         ),
     ) {
         override fun isValidNextState(nextState: ChipStateSender): Boolean {
-            return nextState == FAR_FROM_RECEIVER ||
-                    nextState == ALMOST_CLOSE_TO_START_CAST ||
-                    nextState == TRANSFER_TO_THIS_DEVICE_TRIGGERED
+            // Since _SUCCEEDED is the end of a transfer sequence, we should be able to move to any
+            // state that represents the beginning of a new sequence.
+            return stateIsStartOfSequence(nextState)
         }
     },
 
@@ -158,9 +158,9 @@
         ),
     ) {
         override fun isValidNextState(nextState: ChipStateSender): Boolean {
-            return nextState == FAR_FROM_RECEIVER ||
-                    nextState == ALMOST_CLOSE_TO_END_CAST ||
-                    nextState == TRANSFER_TO_RECEIVER_TRIGGERED
+            // Since _SUCCEEDED is the end of a transfer sequence, we should be able to move to any
+            // state that represents the beginning of a new sequence.
+            return stateIsStartOfSequence(nextState)
         }
     },
 
@@ -173,9 +173,9 @@
         endItem = SenderEndItem.Error,
     ) {
         override fun isValidNextState(nextState: ChipStateSender): Boolean {
-            return nextState == FAR_FROM_RECEIVER ||
-                    nextState == ALMOST_CLOSE_TO_START_CAST ||
-                    nextState == TRANSFER_TO_THIS_DEVICE_TRIGGERED
+            // Since _FAILED is the end of a transfer sequence, we should be able to move to any
+            // state that represents the beginning of a new sequence.
+            return stateIsStartOfSequence(nextState)
         }
     },
 
@@ -188,9 +188,9 @@
         endItem = SenderEndItem.Error,
     ) {
         override fun isValidNextState(nextState: ChipStateSender): Boolean {
-            return nextState == FAR_FROM_RECEIVER ||
-                    nextState == ALMOST_CLOSE_TO_END_CAST ||
-                    nextState == TRANSFER_TO_RECEIVER_TRIGGERED
+            // Since _FAILED is the end of a transfer sequence, we should be able to move to any
+            // state that represents the beginning of a new sequence.
+            return stateIsStartOfSequence(nextState)
         }
     },
 
@@ -210,9 +210,9 @@
         }
 
         override fun isValidNextState(nextState: ChipStateSender): Boolean {
-            return nextState == FAR_FROM_RECEIVER ||
-                    nextState.transferStatus == TransferStatus.NOT_STARTED ||
-                    nextState.transferStatus == TransferStatus.IN_PROGRESS
+            // When far away, we can go to any state that represents the start of a transfer
+            // sequence.
+            return stateIsStartOfSequence(nextState)
         }
     };
 
@@ -227,6 +227,20 @@
         return Text.Loaded(context.getString(stringResId!!, otherDeviceName))
     }
 
+    /**
+     * Returns true if moving from this state to [nextState] is a valid transition.
+     *
+     * In general, we expect a media transfer go to through a sequence of states:
+     * For push-to-receiver:
+     *   - ALMOST_CLOSE_TO_START_CAST => TRANSFER_TO_RECEIVER_TRIGGERED =>
+     *     TRANSFER_TO_RECEIVER_(SUCCEEDED|FAILED)
+     *   - ALMOST_CLOSE_TO_END_CAST => TRANSFER_TO_THIS_DEVICE_TRIGGERED =>
+     *     TRANSFER_TO_THIS_DEVICE_(SUCCEEDED|FAILED)
+     *
+     * This method should validate that the states go through approximately that sequence.
+     *
+     * See b/221265848 for more details.
+     */
     abstract fun isValidNextState(nextState: ChipStateSender): Boolean
 
     companion object {
@@ -276,6 +290,18 @@
 
             return currentState.isValidNextState(desiredState)
         }
+
+        /**
+         * Returns true if [state] represents a state at the beginning of a sequence and false
+         * otherwise.
+         */
+        private fun stateIsStartOfSequence(state: ChipStateSender): Boolean {
+            return state == FAR_FROM_RECEIVER ||
+                state.transferStatus == TransferStatus.NOT_STARTED ||
+                // It's possible to skip the NOT_STARTED phase and go immediately into the
+                // IN_PROGRESS phase.
+                state.transferStatus == TransferStatus.IN_PROGRESS
+        }
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
index 89ca5d3..6bb6906 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
@@ -161,7 +161,7 @@
                 routeInfo.name.toString()
             }
         val icon =
-            MediaTttUtils.getIconInfoFromPackageName(context, packageName) {
+            MediaTttUtils.getIconInfoFromPackageName(context, packageName, isReceiver = false) {
                 logger.logPackageNotFound(packageName)
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
index e665d83..3088d8b 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.media.MediaProjectionAppSelectorActivity
 import com.android.systemui.media.MediaProjectionAppSelectorActivity.Companion.EXTRA_HOST_APP_USER_HANDLE
+import com.android.systemui.media.MediaProjectionPermissionActivity
 import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerLabelLoader
 import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader
 import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
@@ -67,6 +68,11 @@
     fun provideMediaProjectionAppSelectorActivity(
         activity: MediaProjectionAppSelectorActivity
     ): Activity
+
+    @Binds
+    @IntoMap
+    @ClassKey(MediaProjectionPermissionActivity::class)
+    fun bindsMediaProjectionPermissionActivity(impl: MediaProjectionPermissionActivity): Activity
 }
 
 /**
@@ -104,6 +110,12 @@
         @Provides
         @MediaProjectionAppSelector
         @MediaProjectionAppSelectorScope
+        fun provideCallerPackageName(activity: MediaProjectionAppSelectorActivity): String? =
+            activity.callingPackage
+
+        @Provides
+        @MediaProjectionAppSelector
+        @MediaProjectionAppSelectorScope
         fun bindConfigurationController(
             activity: MediaProjectionAppSelectorActivity
         ): ConfigurationController = ConfigurationControllerImpl(activity)
@@ -149,6 +161,7 @@
 
     val controller: MediaProjectionAppSelectorController
     val recentsViewController: MediaProjectionRecentsViewController
+    val emptyStateProvider: MediaProjectionBlockerEmptyStateProvider
     @get:HostUserHandle val hostUserHandle: UserHandle
     @get:PersonalProfile val personalProfileUserHandle: UserHandle
 
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 52c7ca3..219629b 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorController.kt
@@ -36,16 +36,16 @@
     private val flags: FeatureFlags,
     @HostUserHandle private val hostUserHandle: UserHandle,
     @MediaProjectionAppSelector private val scope: CoroutineScope,
-    @MediaProjectionAppSelector private val appSelectorComponentName: ComponentName
+    @MediaProjectionAppSelector private val appSelectorComponentName: ComponentName,
+    @MediaProjectionAppSelector private val callerPackageName: String?
 ) {
 
     fun init() {
         scope.launch {
             val recentTasks = recentTaskListProvider.loadRecentTasks()
 
-            val tasks = recentTasks
-                .filterDevicePolicyRestrictedTasks()
-                .sortedTasks()
+            val tasks =
+                recentTasks.filterDevicePolicyRestrictedTasks().filterAppSelector().sortedTasks()
 
             view.bind(tasks)
         }
@@ -67,8 +67,13 @@
             filter { UserHandle.of(it.userId) == hostUserHandle }
         }
 
+    private fun List<RecentTask>.filterAppSelector(): List<RecentTask> = filter {
+        // Only take tasks that is not the app selector
+        it.topActivityComponent != appSelectorComponentName
+    }
+
     private fun List<RecentTask>.sortedTasks(): List<RecentTask> = sortedBy {
         // Show normal tasks first and only then tasks with opened app selector
-        it.topActivityComponent == appSelectorComponentName
+        it.topActivityComponent?.packageName == callerPackageName
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/motiontool/MotionToolModule.kt b/packages/SystemUI/src/com/android/systemui/motiontool/MotionToolModule.kt
index 1324d2c..c4a1ed4 100644
--- a/packages/SystemUI/src/com/android/systemui/motiontool/MotionToolModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/motiontool/MotionToolModule.kt
@@ -19,7 +19,6 @@
 import android.view.WindowManagerGlobal
 import com.android.app.motiontool.DdmHandleMotionTool
 import com.android.app.motiontool.MotionToolManager
-import com.android.app.viewcapture.ViewCapture
 import com.android.systemui.CoreStartable
 import dagger.Binds
 import dagger.Module
@@ -38,17 +37,12 @@
         }
 
         @Provides
-        fun provideMotionToolManager(
-            viewCapture: ViewCapture,
-            windowManagerGlobal: WindowManagerGlobal
-        ): MotionToolManager {
-            return MotionToolManager.getInstance(viewCapture, windowManagerGlobal)
+        fun provideMotionToolManager(windowManagerGlobal: WindowManagerGlobal): MotionToolManager {
+            return MotionToolManager.getInstance(windowManagerGlobal)
         }
 
         @Provides
         fun provideWindowManagerGlobal(): WindowManagerGlobal = WindowManagerGlobal.getInstance()
-
-        @Provides fun provideViewCapture(): ViewCapture = ViewCapture.getInstance()
     }
 
     @Binds
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 79b4b3a..d5d7325 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -30,7 +30,6 @@
 import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
-import static android.view.InsetsState.containsType;
 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
@@ -85,7 +84,6 @@
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.InsetsFrameProvider;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.Surface;
@@ -97,6 +95,7 @@
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.InternalInsetsInfo;
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
+import android.view.WindowInsets;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsController.Appearance;
 import android.view.WindowInsetsController.Behavior;
@@ -191,7 +190,7 @@
     private static final String EXTRA_TRANSIENT_STATE = "transient_state";
 
     /** Allow some time inbetween the long press for back and recents. */
-    private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
+    private static final int LOCK_TO_APP_GESTURE_TOLERANCE = 200;
     private static final long AUTODIM_TIMEOUT_MS = 2250;
 
     private final Context mContext;
@@ -1150,12 +1149,11 @@
     }
 
     @Override
-    public void showTransient(int displayId, @InternalInsetsType int[] types,
-            boolean isGestureOnSystemBar) {
+    public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) {
         if (displayId != mDisplayId) {
             return;
         }
-        if (!containsType(types, ITYPE_NAVIGATION_BAR)) {
+        if ((types & WindowInsets.Type.navigationBars()) == 0) {
             return;
         }
         if (!mTransientShown) {
@@ -1166,11 +1164,11 @@
     }
 
     @Override
-    public void abortTransient(int displayId, @InternalInsetsType int[] types) {
+    public void abortTransient(int displayId, @InsetsType int types) {
         if (displayId != mDisplayId) {
             return;
         }
-        if (!containsType(types, ITYPE_NAVIGATION_BAR)) {
+        if ((types & WindowInsets.Type.navigationBars()) == 0) {
             return;
         }
         clearTransient();
@@ -1439,7 +1437,7 @@
 
                     // If we recently long-pressed the other button then they were
                     // long-pressed 'together'
-                    if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
+                    if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERANCE) {
                         stopLockTaskMode = true;
                         return true;
                     } else if (v.getId() == btnId1) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index f3712e6..c3d7369 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -20,8 +20,6 @@
 import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
 import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.containsType;
 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 
@@ -41,7 +39,6 @@
 
 import android.app.StatusBarManager;
 import android.app.StatusBarManager.WindowVisibleState;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
@@ -52,6 +49,7 @@
 import android.util.Log;
 import android.view.Display;
 import android.view.View;
+import android.view.WindowInsets;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsController.Appearance;
 import android.view.WindowInsetsController.Behavior;
@@ -68,7 +66,6 @@
 import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -401,11 +398,11 @@
     }
 
     @Override
-    public void showTransient(int displayId, int[] types, boolean isGestureOnSystemBar) {
+    public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) {
         if (displayId != mDisplayId) {
             return;
         }
-        if (!containsType(types, ITYPE_EXTRA_NAVIGATION_BAR)) {
+        if ((types & WindowInsets.Type.navigationBars()) == 0) {
             return;
         }
         if (!mTaskbarTransientShowing) {
@@ -415,11 +412,11 @@
     }
 
     @Override
-    public void abortTransient(int displayId, int[] types) {
+    public void abortTransient(int displayId, @InsetsType int types) {
         if (displayId != mDisplayId) {
             return;
         }
-        if (!containsType(types, ITYPE_EXTRA_NAVIGATION_BAR)) {
+        if ((types & WindowInsets.Type.navigationBars()) == 0) {
             return;
         }
         clearTransient();
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 2822435..f335733 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
@@ -1,14 +1,20 @@
 package com.android.systemui.navigationbar.gestural
 
 import android.content.Context
+import android.content.res.Configuration
+import android.content.res.TypedArray
 import android.graphics.Canvas
 import android.graphics.Paint
 import android.graphics.Path
 import android.graphics.RectF
+import android.util.MathUtils.min
+import android.util.TypedValue
 import android.view.View
+import androidx.appcompat.view.ContextThemeWrapper
 import androidx.dynamicanimation.animation.FloatPropertyCompat
 import androidx.dynamicanimation.animation.SpringAnimation
 import androidx.dynamicanimation.animation.SpringForce
+import com.android.internal.R.style.Theme_DeviceDefault
 import com.android.internal.util.LatencyTracker
 import com.android.settingslib.Utils
 import com.android.systemui.navigationbar.gestural.BackPanelController.DelayedOnAnimationEndListener
@@ -16,7 +22,10 @@
 private const val TAG = "BackPanel"
 private const val DEBUG = false
 
-class BackPanel(context: Context, private val latencyTracker: LatencyTracker) : View(context) {
+class BackPanel(
+        context: Context,
+        private val latencyTracker: LatencyTracker
+) : View(context) {
 
     var arrowsPointLeft = false
         set(value) {
@@ -45,52 +54,54 @@
     /**
      * The length of the arrow measured horizontally. Used for animating [arrowPath]
      */
-    private var arrowLength = AnimatedFloat("arrowLength", SpringForce())
+    private var arrowLength = AnimatedFloat(
+            name = "arrowLength",
+            minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_PIXELS
+    )
 
     /**
      * The height of the arrow measured vertically from its center to its top (i.e. half the total
      * height). Used for animating [arrowPath]
      */
-    private var arrowHeight = AnimatedFloat("arrowHeight", SpringForce())
-
-    private val backgroundWidth = AnimatedFloat(
-        name = "backgroundWidth",
-        SpringForce().apply {
-            stiffness = 600f
-            dampingRatio = 0.65f
-        }
+    var arrowHeight = AnimatedFloat(
+            name = "arrowHeight",
+            minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_ROTATION_DEGREES
     )
 
-    private val backgroundHeight = AnimatedFloat(
-        name = "backgroundHeight",
-        SpringForce().apply {
-            stiffness = 600f
-            dampingRatio = 0.65f
-        }
+    val backgroundWidth = AnimatedFloat(
+            name = "backgroundWidth",
+            minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_PIXELS,
+            minimumValue = 0f,
+    )
+
+    val backgroundHeight = AnimatedFloat(
+            name = "backgroundHeight",
+            minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_PIXELS,
+            minimumValue = 0f,
     )
 
     /**
      * Corners of the background closer to the edge of the screen (where the arrow appeared from).
      * Used for animating [arrowBackgroundRect]
      */
-    private val backgroundEdgeCornerRadius = AnimatedFloat(
-        name = "backgroundEdgeCornerRadius",
-        SpringForce().apply {
-            stiffness = 400f
-            dampingRatio = SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY
-        }
-    )
+    val backgroundEdgeCornerRadius = AnimatedFloat("backgroundEdgeCornerRadius")
 
     /**
      * Corners of the background further from the edge of the screens (toward the direction the
      * arrow is being dragged). Used for animating [arrowBackgroundRect]
      */
-    private val backgroundFarCornerRadius = AnimatedFloat(
-        name = "backgroundDragCornerRadius",
-        SpringForce().apply {
-            stiffness = 2200f
-            dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY
-        }
+    val backgroundFarCornerRadius = AnimatedFloat("backgroundFarCornerRadius")
+
+    var scale = AnimatedFloat(
+            name = "scale",
+            minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_SCALE,
+            minimumValue = 0f
+    )
+
+    val scalePivotX = AnimatedFloat(
+            name = "scalePivotX",
+            minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_PIXELS,
+            minimumValue = backgroundWidth.pos / 2,
     )
 
     /**
@@ -98,34 +109,40 @@
      * background's margin relative to the screen edge. The arrow will be centered within the
      * background.
      */
-    private var horizontalTranslation = AnimatedFloat("horizontalTranslation", SpringForce())
+    var horizontalTranslation = AnimatedFloat(name = "horizontalTranslation")
 
-    private val currentAlpha: FloatPropertyCompat<BackPanel> =
-        object : FloatPropertyCompat<BackPanel>("currentAlpha") {
-            override fun setValue(panel: BackPanel, value: Float) {
-                panel.alpha = value
-            }
+    var arrowAlpha = AnimatedFloat(
+            name = "arrowAlpha",
+            minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_ALPHA,
+            minimumValue = 0f,
+            maximumValue = 1f
+    )
 
-            override fun getValue(panel: BackPanel): Float = panel.alpha
-        }
+    val backgroundAlpha = AnimatedFloat(
+            name = "backgroundAlpha",
+            minimumVisibleChange = SpringAnimation.MIN_VISIBLE_CHANGE_ALPHA,
+            minimumValue = 0f,
+            maximumValue = 1f
+    )
 
-    private val alphaAnimation = SpringAnimation(this, currentAlpha)
-        .setSpring(
-            SpringForce()
-                .setStiffness(60f)
-                .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)
-        )
+    private val allAnimatedFloat = setOf(
+            arrowLength,
+            arrowHeight,
+            backgroundWidth,
+            backgroundEdgeCornerRadius,
+            backgroundFarCornerRadius,
+            scalePivotX,
+            scale,
+            horizontalTranslation,
+            arrowAlpha,
+            backgroundAlpha
+    )
 
     /**
      * Canvas vertical translation. How far up/down the arrow and background appear relative to the
      * canvas.
      */
-    private var verticalTranslation: AnimatedFloat = AnimatedFloat(
-        name = "verticalTranslation",
-        SpringForce().apply {
-            stiffness = SpringForce.STIFFNESS_MEDIUM
-        }
-    )
+    var verticalTranslation = AnimatedFloat("verticalTranslation")
 
     /**
      * Use for drawing debug info. Can only be set if [DEBUG]=true
@@ -136,28 +153,67 @@
         }
 
     internal fun updateArrowPaint(arrowThickness: Float) {
-        // Arrow constants
+
         arrowPaint.strokeWidth = arrowThickness
 
-        arrowPaint.color =
-            Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
-        arrowBackgroundPaint.color = Utils.getColorAccentDefaultColor(context)
+        val isDeviceInNightTheme = resources.configuration.uiMode and
+                Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
+
+        val colorControlActivated = ContextThemeWrapper(context, Theme_DeviceDefault)
+                .run {
+                    val typedValue = TypedValue()
+                    val a: TypedArray = obtainStyledAttributes(typedValue.data,
+                            intArrayOf(android.R.attr.colorControlActivated))
+                    val color = a.getColor(0, 0)
+                    a.recycle()
+                    color
+                }
+
+        val colorPrimary =
+                Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
+
+        arrowPaint.color = Utils.getColorAccentDefaultColor(context)
+
+        arrowBackgroundPaint.color = if (isDeviceInNightTheme) {
+            colorPrimary
+        } else {
+            colorControlActivated
+        }
     }
 
-    private inner class AnimatedFloat(name: String, springForce: SpringForce) {
+    inner class AnimatedFloat(
+            name: String,
+            private val minimumVisibleChange: Float? = null,
+            private val minimumValue: Float? = null,
+            private val maximumValue: Float? = null,
+    ) {
+
         // The resting position when not stretched by a touch drag
         private var restingPosition = 0f
 
         // The current position as updated by the SpringAnimation
         var pos = 0f
-            set(v) {
+            private set(v) {
                 if (field != v) {
                     field = v
                     invalidate()
                 }
             }
 
-        val animation: SpringAnimation
+        private val animation: SpringAnimation
+        var spring: SpringForce
+            get() = animation.spring
+            set(value) {
+                animation.cancel()
+                animation.spring = value
+            }
+
+        val isRunning: Boolean
+            get() = animation.isRunning
+
+        fun addEndListener(listener: DelayedOnAnimationEndListener) {
+            animation.addEndListener(listener)
+        }
 
         init {
             val floatProp = object : FloatPropertyCompat<AnimatedFloat>(name) {
@@ -167,8 +223,12 @@
 
                 override fun getValue(animatedFloat: AnimatedFloat): Float = animatedFloat.pos
             }
-            animation = SpringAnimation(this, floatProp)
-            animation.spring = springForce
+            animation = SpringAnimation(this, floatProp).apply {
+                spring = SpringForce()
+                this@AnimatedFloat.minimumValue?.let { setMinValue(it) }
+                this@AnimatedFloat.maximumValue?.let { setMaxValue(it) }
+                this@AnimatedFloat.minimumVisibleChange?.let { minimumVisibleChange = it }
+            }
         }
 
         fun snapTo(newPosition: Float) {
@@ -178,8 +238,24 @@
             pos = newPosition
         }
 
-        fun stretchTo(stretchAmount: Float) {
-            animation.animateToFinalPosition(restingPosition + stretchAmount)
+        fun snapToRestingPosition() {
+            snapTo(restingPosition)
+        }
+
+
+        fun stretchTo(
+                stretchAmount: Float,
+                startingVelocity: Float? = null,
+                springForce: SpringForce? = null
+        ) {
+            animation.apply {
+                startingVelocity?.let {
+                    cancel()
+                    setStartVelocity(it)
+                }
+                springForce?.let { spring = springForce }
+                animateToFinalPosition(restingPosition + stretchAmount)
+            }
         }
 
         /**
@@ -188,18 +264,23 @@
          *
          * The [restingPosition] will remain unchanged. Only the animation is updated.
          */
-        fun stretchBy(finalPosition: Float, amount: Float) {
-            val stretchedAmount = amount * (finalPosition - restingPosition)
+        fun stretchBy(finalPosition: Float?, amount: Float) {
+            val stretchedAmount = amount * ((finalPosition ?: 0f) - restingPosition)
             animation.animateToFinalPosition(restingPosition + stretchedAmount)
         }
 
-        fun updateRestingPosition(pos: Float, animated: Boolean) {
+        fun updateRestingPosition(pos: Float?, animated: Boolean = true) {
+            if (pos == null) return
+
             restingPosition = pos
-            if (animated)
+            if (animated) {
                 animation.animateToFinalPosition(restingPosition)
-            else
+            } else {
                 snapTo(restingPosition)
+            }
         }
+
+        fun cancel() = animation.cancel()
     }
 
     init {
@@ -224,126 +305,203 @@
         return arrowPath
     }
 
-    fun addEndListener(endListener: DelayedOnAnimationEndListener): Boolean {
-        return if (alphaAnimation.isRunning) {
-            alphaAnimation.addEndListener(endListener)
-            true
-        } else if (horizontalTranslation.animation.isRunning) {
-            horizontalTranslation.animation.addEndListener(endListener)
+    fun addAnimationEndListener(
+            animatedFloat: AnimatedFloat,
+            endListener: DelayedOnAnimationEndListener
+    ): Boolean {
+        return if (animatedFloat.isRunning) {
+            animatedFloat.addEndListener(endListener)
             true
         } else {
-            endListener.runNow()
+            endListener.run()
             false
         }
     }
 
+    fun cancelAnimations() {
+        allAnimatedFloat.forEach { it.cancel() }
+    }
+
     fun setStretch(
-        horizontalTranslationStretchAmount: Float,
-        arrowStretchAmount: Float,
-        backgroundWidthStretchAmount: Float,
-        fullyStretchedDimens: EdgePanelParams.BackIndicatorDimens
+            horizontalTranslationStretchAmount: Float,
+            arrowStretchAmount: Float,
+            arrowAlphaStretchAmount: Float,
+            backgroundAlphaStretchAmount: Float,
+            backgroundWidthStretchAmount: Float,
+            backgroundHeightStretchAmount: Float,
+            edgeCornerStretchAmount: Float,
+            farCornerStretchAmount: Float,
+            fullyStretchedDimens: EdgePanelParams.BackIndicatorDimens
     ) {
         horizontalTranslation.stretchBy(
-            finalPosition = fullyStretchedDimens.horizontalTranslation,
-            amount = horizontalTranslationStretchAmount
+                finalPosition = fullyStretchedDimens.horizontalTranslation,
+                amount = horizontalTranslationStretchAmount
         )
         arrowLength.stretchBy(
-            finalPosition = fullyStretchedDimens.arrowDimens.length,
-            amount = arrowStretchAmount
+                finalPosition = fullyStretchedDimens.arrowDimens.length,
+                amount = arrowStretchAmount
         )
         arrowHeight.stretchBy(
-            finalPosition = fullyStretchedDimens.arrowDimens.height,
-            amount = arrowStretchAmount
+                finalPosition = fullyStretchedDimens.arrowDimens.height,
+                amount = arrowStretchAmount
+        )
+        arrowAlpha.stretchBy(
+                finalPosition = fullyStretchedDimens.arrowDimens.alpha,
+                amount = arrowAlphaStretchAmount
+        )
+        backgroundAlpha.stretchBy(
+                finalPosition = fullyStretchedDimens.backgroundDimens.alpha,
+                amount = backgroundAlphaStretchAmount
         )
         backgroundWidth.stretchBy(
-            finalPosition = fullyStretchedDimens.backgroundDimens.width,
-            amount = backgroundWidthStretchAmount
+                finalPosition = fullyStretchedDimens.backgroundDimens.width,
+                amount = backgroundWidthStretchAmount
+        )
+        backgroundHeight.stretchBy(
+                finalPosition = fullyStretchedDimens.backgroundDimens.height,
+                amount = backgroundHeightStretchAmount
+        )
+        backgroundEdgeCornerRadius.stretchBy(
+                finalPosition = fullyStretchedDimens.backgroundDimens.edgeCornerRadius,
+                amount = edgeCornerStretchAmount
+        )
+        backgroundFarCornerRadius.stretchBy(
+                finalPosition = fullyStretchedDimens.backgroundDimens.farCornerRadius,
+                amount = farCornerStretchAmount
         )
     }
 
+    fun popOffEdge(startingVelocity: Float) {
+        val heightStretchAmount = startingVelocity * 50
+        val widthStretchAmount = startingVelocity * 150
+        val scaleStretchAmount = startingVelocity * 0.8f
+        backgroundHeight.stretchTo(stretchAmount = 0f, startingVelocity = -heightStretchAmount)
+        backgroundWidth.stretchTo(stretchAmount = 0f, startingVelocity = widthStretchAmount)
+        scale.stretchTo(stretchAmount = 0f, startingVelocity = -scaleStretchAmount)
+    }
+
+    fun popScale(startingVelocity: Float) {
+        scalePivotX.snapTo(backgroundWidth.pos / 2)
+        scale.stretchTo(stretchAmount = 0f, startingVelocity = startingVelocity)
+    }
+
+    fun popArrowAlpha(startingVelocity: Float, springForce: SpringForce? = null) {
+        arrowAlpha.stretchTo(stretchAmount = 0f, startingVelocity = startingVelocity,
+                springForce = springForce)
+    }
+
     fun resetStretch() {
-        horizontalTranslation.stretchTo(0f)
-        arrowLength.stretchTo(0f)
-        arrowHeight.stretchTo(0f)
-        backgroundWidth.stretchTo(0f)
-        backgroundHeight.stretchTo(0f)
-        backgroundEdgeCornerRadius.stretchTo(0f)
-        backgroundFarCornerRadius.stretchTo(0f)
+        backgroundAlpha.snapTo(1f)
+        verticalTranslation.snapTo(0f)
+        scale.snapTo(1f)
+
+        horizontalTranslation.snapToRestingPosition()
+        arrowLength.snapToRestingPosition()
+        arrowHeight.snapToRestingPosition()
+        arrowAlpha.snapToRestingPosition()
+        backgroundWidth.snapToRestingPosition()
+        backgroundHeight.snapToRestingPosition()
+        backgroundEdgeCornerRadius.snapToRestingPosition()
+        backgroundFarCornerRadius.snapToRestingPosition()
     }
 
     /**
      * Updates resting arrow and background size not accounting for stretch
      */
     internal fun setRestingDimens(
-        restingParams: EdgePanelParams.BackIndicatorDimens,
-        animate: Boolean
+            restingParams: EdgePanelParams.BackIndicatorDimens,
+            animate: Boolean = true
     ) {
-        horizontalTranslation.updateRestingPosition(restingParams.horizontalTranslation, animate)
+        horizontalTranslation.updateRestingPosition(restingParams.horizontalTranslation)
+        scale.updateRestingPosition(restingParams.scale)
+        arrowAlpha.updateRestingPosition(restingParams.arrowDimens.alpha)
+        backgroundAlpha.updateRestingPosition(restingParams.backgroundDimens.alpha)
+
         arrowLength.updateRestingPosition(restingParams.arrowDimens.length, animate)
         arrowHeight.updateRestingPosition(restingParams.arrowDimens.height, animate)
+        scalePivotX.updateRestingPosition(restingParams.backgroundDimens.width, animate)
         backgroundWidth.updateRestingPosition(restingParams.backgroundDimens.width, animate)
         backgroundHeight.updateRestingPosition(restingParams.backgroundDimens.height, animate)
         backgroundEdgeCornerRadius.updateRestingPosition(
-            restingParams.backgroundDimens.edgeCornerRadius,
-            animate
+                restingParams.backgroundDimens.edgeCornerRadius, animate
         )
         backgroundFarCornerRadius.updateRestingPosition(
-            restingParams.backgroundDimens.farCornerRadius,
-            animate
+                restingParams.backgroundDimens.farCornerRadius, animate
         )
     }
 
     fun animateVertically(yPos: Float) = verticalTranslation.stretchTo(yPos)
 
-    fun setArrowStiffness(arrowStiffness: Float, arrowDampingRatio: Float) {
-        arrowLength.animation.spring.apply {
-            stiffness = arrowStiffness
-            dampingRatio = arrowDampingRatio
-        }
-        arrowHeight.animation.spring.apply {
-            stiffness = arrowStiffness
-            dampingRatio = arrowDampingRatio
-        }
+    fun setSpring(
+            horizontalTranslation: SpringForce? = null,
+            verticalTranslation: SpringForce? = null,
+            scale: SpringForce? = null,
+            arrowLength: SpringForce? = null,
+            arrowHeight: SpringForce? = null,
+            arrowAlpha: SpringForce? = null,
+            backgroundAlpha: SpringForce? = null,
+            backgroundFarCornerRadius: SpringForce? = null,
+            backgroundEdgeCornerRadius: SpringForce? = null,
+            backgroundWidth: SpringForce? = null,
+            backgroundHeight: SpringForce? = null,
+    ) {
+        arrowLength?.let { this.arrowLength.spring = it }
+        arrowHeight?.let { this.arrowHeight.spring = it }
+        arrowAlpha?.let { this.arrowAlpha.spring = it }
+        backgroundAlpha?.let { this.backgroundAlpha.spring = it }
+        backgroundFarCornerRadius?.let { this.backgroundFarCornerRadius.spring = it }
+        backgroundEdgeCornerRadius?.let { this.backgroundEdgeCornerRadius.spring = it }
+        scale?.let { this.scale.spring = it }
+        backgroundWidth?.let { this.backgroundWidth.spring = it }
+        backgroundHeight?.let { this.backgroundHeight.spring = it }
+        horizontalTranslation?.let { this.horizontalTranslation.spring = it }
+        verticalTranslation?.let { this.verticalTranslation.spring = it }
     }
 
     override fun hasOverlappingRendering() = false
 
     override fun onDraw(canvas: Canvas) {
-        var edgeCorner = backgroundEdgeCornerRadius.pos
+        val edgeCorner = backgroundEdgeCornerRadius.pos
         val farCorner = backgroundFarCornerRadius.pos
         val halfHeight = backgroundHeight.pos / 2
+        val canvasWidth = width
+        val backgroundWidth = backgroundWidth.pos
+        val scalePivotX = scalePivotX.pos
 
         canvas.save()
 
-        if (!isLeftPanel) canvas.scale(-1f, 1f, width / 2.0f, 0f)
+        if (!isLeftPanel) canvas.scale(-1f, 1f, canvasWidth / 2.0f, 0f)
 
         canvas.translate(
-            horizontalTranslation.pos,
-            height * 0.5f + verticalTranslation.pos
+                horizontalTranslation.pos,
+                height * 0.5f + verticalTranslation.pos
         )
 
+        canvas.scale(scale.pos, scale.pos, scalePivotX, 0f)
+
         val arrowBackground = arrowBackgroundRect.apply {
             left = 0f
             top = -halfHeight
-            right = backgroundWidth.pos
+            right = backgroundWidth
             bottom = halfHeight
         }.toPathWithRoundCorners(
-            topLeft = edgeCorner,
-            bottomLeft = edgeCorner,
-            topRight = farCorner,
-            bottomRight = farCorner
+                topLeft = edgeCorner,
+                bottomLeft = edgeCorner,
+                topRight = farCorner,
+                bottomRight = farCorner
         )
-        canvas.drawPath(arrowBackground, arrowBackgroundPaint)
+        canvas.drawPath(arrowBackground,
+                arrowBackgroundPaint.apply { alpha = (255 * backgroundAlpha.pos).toInt() })
 
         val dx = arrowLength.pos
         val dy = arrowHeight.pos
 
         // How far the arrow bounding box should be from the edge of the screen. Measured from
         // either the tip or the back of the arrow, whichever is closer
-        var arrowOffset = (backgroundWidth.pos - dx) / 2
+        val arrowOffset = (backgroundWidth - dx) / 2
         canvas.translate(
-            /* dx= */ arrowOffset,
-            /* dy= */ 0f /* pass 0 for the y position since the canvas was already translated */
+                /* dx= */ arrowOffset,
+                /* dy= */ 0f /* pass 0 for the y position since the canvas was already translated */
         )
 
         val arrowPointsAwayFromEdge = !arrowsPointLeft.xor(isLeftPanel)
@@ -355,6 +513,8 @@
         }
 
         val arrowPath = calculateArrowPath(dx = dx, dy = dy)
+        val arrowPaint = arrowPaint
+                .apply { alpha = (255 * min(arrowAlpha.pos, backgroundAlpha.pos)).toInt() }
         canvas.drawPath(arrowPath, arrowPaint)
         canvas.restore()
 
@@ -372,26 +532,17 @@
     }
 
     private fun RectF.toPathWithRoundCorners(
-        topLeft: Float = 0f,
-        topRight: Float = 0f,
-        bottomRight: Float = 0f,
-        bottomLeft: Float = 0f
+            topLeft: Float = 0f,
+            topRight: Float = 0f,
+            bottomRight: Float = 0f,
+            bottomLeft: Float = 0f
     ): Path = Path().apply {
         val corners = floatArrayOf(
-            topLeft, topLeft,
-            topRight, topRight,
-            bottomRight, bottomRight,
-            bottomLeft, bottomLeft
+                topLeft, topLeft,
+                topRight, topRight,
+                bottomRight, bottomRight,
+                bottomLeft, bottomLeft
         )
         addRoundRect(this@toPathWithRoundCorners, corners, Path.Direction.CW)
     }
-
-    fun cancelAlphaAnimations() {
-        alphaAnimation.cancel()
-        alpha = 1f
-    }
-
-    fun fadeOut() {
-        alphaAnimation.animateToFinalPosition(0f)
-    }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
index 1950c69..e0ba543 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -24,18 +24,16 @@
 import android.os.SystemClock
 import android.os.VibrationEffect
 import android.util.Log
-import android.util.MathUtils.constrain
-import android.util.MathUtils.saturate
+import android.util.MathUtils
 import android.view.Gravity
 import android.view.MotionEvent
 import android.view.VelocityTracker
-import android.view.View
 import android.view.ViewConfiguration
 import android.view.WindowManager
-import android.view.animation.DecelerateInterpolator
-import android.view.animation.PathInterpolator
+import androidx.annotation.VisibleForTesting
+import androidx.core.os.postDelayed
+import androidx.core.view.isVisible
 import androidx.dynamicanimation.animation.DynamicAnimation
-import androidx.dynamicanimation.animation.SpringForce
 import com.android.internal.util.LatencyTracker
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.MotionEventsHandlerBase
@@ -51,58 +49,42 @@
 import kotlin.math.sign
 
 private const val TAG = "BackPanelController"
-private const val DEBUG = false
-
 private const val ENABLE_FAILSAFE = true
 
-private const val FAILSAFE_DELAY_MS: Long = 350
+private const val PX_PER_SEC = 1000
+private const val PX_PER_MS = 1
 
-/**
- * The time required between the arrow-appears vibration effect and the back-committed vibration
- * effect. If the arrow is flung quickly, the phone only vibrates once. However, if the arrow is
- * held on the screen for a long time, it will vibrate a second time when the back gesture is
- * committed.
- */
-private const val GESTURE_DURATION_FOR_CLICK_MS = 400
+internal const val MIN_DURATION_ACTIVE_ANIMATION = 300L
+private const val MIN_DURATION_CANCELLED_ANIMATION = 200L
+private const val MIN_DURATION_COMMITTED_ANIMATION = 200L
+private const val MIN_DURATION_INACTIVE_BEFORE_FLUNG_ANIMATION = 50L
+private const val MIN_DURATION_CONSIDERED_AS_FLING = 100L
 
-/**
- * The min duration arrow remains on screen during a fling event.
- */
-private const val FLING_MIN_APPEARANCE_DURATION = 235L
+private const val FAILSAFE_DELAY_MS = 350L
+private const val POP_ON_FLING_DELAY = 160L
 
-/**
- * The min duration arrow remains on screen during a fling event.
- */
-private const val MIN_FLING_VELOCITY = 3000
+internal val VIBRATE_ACTIVATED_EFFECT =
+        VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)
 
-/**
- * The amount of rubber banding we do for the vertical translation
- */
-private const val RUBBER_BAND_AMOUNT = 15
+internal val VIBRATE_DEACTIVATED_EFFECT =
+        VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK)
 
-private const val ARROW_APPEAR_STIFFNESS = 600f
-private const val ARROW_APPEAR_DAMPING_RATIO = 0.4f
-private const val ARROW_DISAPPEAR_STIFFNESS = 1200f
-private const val ARROW_DISAPPEAR_DAMPING_RATIO = SpringForce.DAMPING_RATIO_NO_BOUNCY
+private const val DEBUG = false
 
-/**
- * The interpolator used to rubber band
- */
-private val RUBBER_BAND_INTERPOLATOR = PathInterpolator(1.0f / 5.0f, 1.0f, 1.0f, 1.0f)
-
-private val DECELERATE_INTERPOLATOR = DecelerateInterpolator()
-
-private val DECELERATE_INTERPOLATOR_SLOW = DecelerateInterpolator(0.7f)
-
-class BackPanelController private constructor(
-    context: Context,
-    private val windowManager: WindowManager,
-    private val viewConfiguration: ViewConfiguration,
-    @Main private val mainHandler: Handler,
-    private val vibratorHelper: VibratorHelper,
-    private val configurationController: ConfigurationController,
-    latencyTracker: LatencyTracker
-) : ViewController<BackPanel>(BackPanel(context, latencyTracker)), NavigationEdgeBackPlugin {
+class BackPanelController internal constructor(
+        context: Context,
+        private val windowManager: WindowManager,
+        private val viewConfiguration: ViewConfiguration,
+        @Main private val mainHandler: Handler,
+        private val vibratorHelper: VibratorHelper,
+        private val configurationController: ConfigurationController,
+        private val latencyTracker: LatencyTracker
+) : ViewController<BackPanel>(
+        BackPanel(
+                context,
+                latencyTracker
+        )
+), NavigationEdgeBackPlugin {
 
     /**
      * Injectable instance to create a new BackPanelController.
@@ -111,44 +93,44 @@
      * BackPanelController, and we need to match EdgeBackGestureHandler's context.
      */
     class Factory @Inject constructor(
-        private val windowManager: WindowManager,
-        private val viewConfiguration: ViewConfiguration,
-        @Main private val mainHandler: Handler,
-        private val vibratorHelper: VibratorHelper,
-        private val configurationController: ConfigurationController,
-        private val latencyTracker: LatencyTracker
+            private val windowManager: WindowManager,
+            private val viewConfiguration: ViewConfiguration,
+            @Main private val mainHandler: Handler,
+            private val vibratorHelper: VibratorHelper,
+            private val configurationController: ConfigurationController,
+            private val latencyTracker: LatencyTracker
     ) {
         /** Construct a [BackPanelController].  */
         fun create(context: Context): BackPanelController {
             val backPanelController = BackPanelController(
-                context,
-                windowManager,
-                viewConfiguration,
-                mainHandler,
-                vibratorHelper,
-                configurationController,
-                latencyTracker
+                    context,
+                    windowManager,
+                    viewConfiguration,
+                    mainHandler,
+                    vibratorHelper,
+                    configurationController,
+                    latencyTracker
             )
             backPanelController.init()
             return backPanelController
         }
     }
 
-    private var params: EdgePanelParams = EdgePanelParams(resources)
-    private var currentState: GestureState = GestureState.GONE
+    @VisibleForTesting
+    internal var params: EdgePanelParams = EdgePanelParams(resources)
+    @VisibleForTesting
+    internal var currentState: GestureState = GestureState.GONE
     private var previousState: GestureState = GestureState.GONE
 
-    // Phone should only vibrate the first time the arrow is activated
-    private var hasHapticPlayed = false
-
     // Screen attributes
     private lateinit var layoutParams: WindowManager.LayoutParams
     private val displaySize = Point()
 
     private lateinit var backCallback: NavigationEdgeBackPlugin.BackCallback
-
+    private var previousXTranslationOnActiveOffset = 0f
     private var previousXTranslation = 0f
     private var totalTouchDelta = 0f
+    private var touchDeltaStartX = 0f
     private var velocityTracker: VelocityTracker? = null
         set(value) {
             if (field != value) field?.recycle()
@@ -162,8 +144,18 @@
     // The x,y position of the first touch event
     private var startX = 0f
     private var startY = 0f
+    private var startIsLeft: Boolean? = null
 
-    private var gestureStartTime = 0L
+    private var gestureSinceActionDown = 0L
+    private var gestureEntryTime = 0L
+    private var gestureActiveTime = 0L
+    private var gestureInactiveOrEntryTime = 0L
+    private var gestureArrowStrokeVisibleTime = 0L
+
+    private val elapsedTimeSinceActionDown
+        get() = SystemClock.uptimeMillis() - gestureSinceActionDown
+    private val elapsedTimeSinceEntry
+        get() = SystemClock.uptimeMillis() - gestureEntryTime
 
     // Whether the current gesture has moved a sufficiently large amount,
     // so that we can unambiguously start showing the ENTRY animation
@@ -171,7 +163,7 @@
 
     private val failsafeRunnable = Runnable { onFailsafe() }
 
-    private enum class GestureState {
+    internal enum class GestureState {
         /* Arrow is off the screen and invisible */
         GONE,
 
@@ -192,17 +184,6 @@
 
         /* back action currently cancelling, arrow soon to be GONE */
         CANCELLED;
-
-        /**
-         * @return true if the current state responds to touch move events in some way (e.g. by
-         * stretching the back indicator)
-         */
-        fun isInteractive(): Boolean {
-            return when (this) {
-                ENTRY, ACTIVE, INACTIVE -> true
-                GONE, FLUNG, COMMITTED, CANCELLED -> false
-            }
-        }
     }
 
     /**
@@ -210,50 +191,43 @@
      * runnable is not called if the animation is cancelled
      */
     inner class DelayedOnAnimationEndListener internal constructor(
-        private val handler: Handler,
-        private val runnable: Runnable,
-        private val minDuration: Long
+            private val handler: Handler,
+            private val runnableDelay: Long,
+            val runnable: Runnable,
     ) : DynamicAnimation.OnAnimationEndListener {
+
         override fun onAnimationEnd(
-            animation: DynamicAnimation<*>,
-            canceled: Boolean,
-            value: Float,
-            velocity: Float
+                animation: DynamicAnimation<*>,
+                canceled: Boolean,
+                value: Float,
+                velocity: Float
         ) {
             animation.removeEndListener(this)
+
             if (!canceled) {
-                // Total elapsed time of the gesture and the animation
-                val totalElapsedTime = SystemClock.uptimeMillis() - gestureStartTime
+
                 // The delay between finishing this animation and starting the runnable
-                val delay = max(0, minDuration - totalElapsedTime)
+                val delay = max(0, runnableDelay - elapsedTimeSinceEntry)
+
                 handler.postDelayed(runnable, delay)
             }
         }
 
-        internal fun runNow() {
-            runnable.run()
-        }
+        internal fun run() = runnable.run()
     }
 
-    private val setCommittedEndListener =
-        DelayedOnAnimationEndListener(
-            mainHandler,
-            { updateArrowState(GestureState.COMMITTED) },
-            minDuration = FLING_MIN_APPEARANCE_DURATION
-        )
+    private val onEndSetCommittedStateListener = DelayedOnAnimationEndListener(mainHandler, 0L) {
+        updateArrowState(GestureState.COMMITTED)
+    }
 
-    private val setGoneEndListener =
-        DelayedOnAnimationEndListener(
-            mainHandler,
-            {
+
+    private val onEndSetGoneStateListener =
+            DelayedOnAnimationEndListener(mainHandler, runnableDelay = 0L) {
                 cancelFailsafe()
                 updateArrowState(GestureState.GONE)
-            },
-            minDuration = 0
-        )
+            }
 
-    // Vibration
-    private var vibrationTime: Long = 0
+    private val playAnimationThenSetGoneOnAlphaEnd = Runnable { playAnimationThenSetGoneEnd() }
 
     // Minimum of the screen's width or the predefined threshold
     private var fullyStretchedThreshold = 0f
@@ -280,7 +254,7 @@
         updateConfiguration()
         updateArrowDirection(configurationController.isLayoutRtl)
         updateArrowState(GestureState.GONE, force = true)
-        updateRestingArrowDimens(animated = false, currentState)
+        updateRestingArrowDimens()
         configurationController.addCallback(configurationListener)
     }
 
@@ -297,22 +271,57 @@
         velocityTracker!!.addMovement(event)
         when (event.actionMasked) {
             MotionEvent.ACTION_DOWN -> {
-                resetOnDown()
+                gestureSinceActionDown = SystemClock.uptimeMillis()
+                cancelAllPendingAnimations()
                 startX = event.x
                 startY = event.y
-                gestureStartTime = SystemClock.uptimeMillis()
+
+                updateArrowState(GestureState.GONE)
+                updateYStartPosition(startY)
+
+                // reset animation properties
+                startIsLeft = mView.isLeftPanel
+                hasPassedDragSlop = false
+                mView.resetStretch()
             }
             MotionEvent.ACTION_MOVE -> {
-                // only go to the ENTRY state after some minimum motion has occurred
                 if (dragSlopExceeded(event.x, startX)) {
                     handleMoveEvent(event)
                 }
             }
             MotionEvent.ACTION_UP -> {
-                if (currentState == GestureState.ACTIVE) {
-                    updateArrowState(if (isFlung()) GestureState.FLUNG else GestureState.COMMITTED)
-                } else if (currentState != GestureState.GONE) { // if invisible, skip animation
-                    updateArrowState(GestureState.CANCELLED)
+                when (currentState) {
+                    GestureState.ENTRY -> {
+                        if (isFlungAwayFromEdge(endX = event.x)) {
+                            updateArrowState(GestureState.ACTIVE)
+                            updateArrowState(GestureState.FLUNG)
+                        } else {
+                            updateArrowState(GestureState.CANCELLED)
+                        }
+                    }
+                    GestureState.INACTIVE -> {
+                        if (isFlungAwayFromEdge(endX = event.x)) {
+                            mainHandler.postDelayed(MIN_DURATION_INACTIVE_BEFORE_FLUNG_ANIMATION) {
+                                updateArrowState(GestureState.ACTIVE)
+                                updateArrowState(GestureState.FLUNG)
+                            }
+                        } else {
+                            updateArrowState(GestureState.CANCELLED)
+                        }
+                    }
+                    GestureState.ACTIVE -> {
+                        if (elapsedTimeSinceEntry < MIN_DURATION_CONSIDERED_AS_FLING) {
+                            updateArrowState(GestureState.FLUNG)
+                        } else {
+                            updateArrowState(GestureState.COMMITTED)
+                        }
+                    }
+                    GestureState.GONE,
+                    GestureState.FLUNG,
+                    GestureState.COMMITTED,
+                    GestureState.CANCELLED -> {
+                        updateArrowState(GestureState.CANCELLED)
+                    }
                 }
                 velocityTracker = null
             }
@@ -326,6 +335,14 @@
         }
     }
 
+    private fun cancelAllPendingAnimations() {
+        cancelFailsafe()
+        mView.cancelAnimations()
+        mainHandler.removeCallbacks(onEndSetCommittedStateListener.runnable)
+        mainHandler.removeCallbacks(onEndSetGoneStateListener.runnable)
+        mainHandler.removeCallbacks(playAnimationThenSetGoneOnAlphaEnd)
+    }
+
     /**
      * Returns false until the current gesture exceeds the touch slop threshold,
      * and returns true thereafter (we reset on the subsequent back gesture).
@@ -336,7 +353,7 @@
     private fun dragSlopExceeded(curX: Float, startX: Float): Boolean {
         if (hasPassedDragSlop) return true
 
-        if (abs(curX - startX) > viewConfiguration.scaledTouchSlop) {
+        if (abs(curX - startX) > viewConfiguration.scaledEdgeSlop) {
             // Reset the arrow to the side
             updateArrowState(GestureState.ENTRY)
 
@@ -349,39 +366,46 @@
     }
 
     private fun updateArrowStateOnMove(yTranslation: Float, xTranslation: Float) {
-        if (!currentState.isInteractive())
-            return
+
+        val isWithinYActivationThreshold = xTranslation * 2 >= yTranslation
 
         when (currentState) {
-            // Check if we should transition from ENTRY to ACTIVE
-            GestureState.ENTRY ->
-                if (xTranslation > params.swipeTriggerThreshold) {
+            GestureState.ENTRY -> {
+                if (xTranslation > params.staticTriggerThreshold) {
                     updateArrowState(GestureState.ACTIVE)
                 }
+            }
+            GestureState.ACTIVE -> {
+                val isPastDynamicDeactivationThreshold =
+                        totalTouchDelta <= params.deactivationSwipeTriggerThreshold
+                val isMinDurationElapsed =
+                        elapsedTimeSinceActionDown > MIN_DURATION_ACTIVE_ANIMATION
 
-            // Abort if we had continuous motion toward the edge for a while, OR the direction
-            // in Y is bigger than X * 2
-            GestureState.ACTIVE ->
-                if ((totalTouchDelta < 0 && -totalTouchDelta > params.minDeltaForSwitch) ||
-                    (yTranslation > xTranslation * 2)
+                if (isMinDurationElapsed && (!isWithinYActivationThreshold ||
+                                isPastDynamicDeactivationThreshold)
                 ) {
                     updateArrowState(GestureState.INACTIVE)
                 }
+            }
+            GestureState.INACTIVE -> {
+                val isPastStaticThreshold =
+                        xTranslation > params.staticTriggerThreshold
+                val isPastDynamicReactivationThreshold = totalTouchDelta > 0 &&
+                        abs(totalTouchDelta) >=
+                        params.reactivationTriggerThreshold
 
-            //  Re-activate if we had continuous motion away from the edge for a while
-            GestureState.INACTIVE ->
-                if (totalTouchDelta > 0 && totalTouchDelta > params.minDeltaForSwitch) {
+                if (isPastStaticThreshold &&
+                        isPastDynamicReactivationThreshold &&
+                        isWithinYActivationThreshold
+                ) {
                     updateArrowState(GestureState.ACTIVE)
                 }
-
-            // By default assume the current direction is kept
+            }
             else -> {}
         }
     }
 
     private fun handleMoveEvent(event: MotionEvent) {
-        if (!currentState.isInteractive())
-            return
 
         val x = event.x
         val y = event.y
@@ -401,23 +425,44 @@
         previousXTranslation = xTranslation
 
         if (abs(xDelta) > 0) {
-            if (sign(xDelta) == sign(totalTouchDelta)) {
+            val range =
+                params.run { deactivationSwipeTriggerThreshold..reactivationTriggerThreshold }
+            val isTouchInContinuousDirection =
+                    sign(xDelta) == sign(totalTouchDelta) || totalTouchDelta in range
+
+            if (isTouchInContinuousDirection) {
                 // Direction has NOT changed, so keep counting the delta
                 totalTouchDelta += xDelta
             } else {
                 // Direction has changed, so reset the delta
                 totalTouchDelta = xDelta
+                touchDeltaStartX = x
             }
         }
 
         updateArrowStateOnMove(yTranslation, xTranslation)
+
         when (currentState) {
-            GestureState.ACTIVE ->
-                stretchActiveBackIndicator(fullScreenStretchProgress(xTranslation))
-            GestureState.ENTRY ->
-                stretchEntryBackIndicator(preThresholdStretchProgress(xTranslation))
-            GestureState.INACTIVE ->
-                mView.resetStretch()
+            GestureState.ACTIVE -> {
+                stretchActiveBackIndicator(fullScreenProgress(xTranslation))
+            }
+            GestureState.ENTRY -> {
+                val progress = staticThresholdProgress(xTranslation)
+                stretchEntryBackIndicator(progress)
+
+                params.arrowStrokeAlphaSpring.get(progress).takeIf { it.isNewState }?.let {
+                    mView.popArrowAlpha(0f, it.value)
+                }
+            }
+            GestureState.INACTIVE -> {
+                val progress = reactivationThresholdProgress(totalTouchDelta)
+                stretchInactiveBackIndicator(progress)
+
+                params.arrowStrokeAlphaSpring.get(progress).takeIf { it.isNewState }?.let {
+                    gestureArrowStrokeVisibleTime = SystemClock.uptimeMillis()
+                    mView.popArrowAlpha(0f, it.value)
+                }
+            }
             else -> {}
         }
 
@@ -428,21 +473,22 @@
     private fun setVerticalTranslation(yOffset: Float) {
         val yTranslation = abs(yOffset)
         val maxYOffset = (mView.height - params.entryIndicator.backgroundDimens.height) / 2f
-        val yProgress = saturate(yTranslation / (maxYOffset * RUBBER_BAND_AMOUNT))
-        mView.animateVertically(
-            RUBBER_BAND_INTERPOLATOR.getInterpolation(yProgress) * maxYOffset *
+        val rubberbandAmount = 15f
+        val yProgress = MathUtils.saturate(yTranslation / (maxYOffset * rubberbandAmount))
+        val yPosition = params.translationInterpolator.getInterpolation(yProgress) *
+                maxYOffset *
                 sign(yOffset)
-        )
+        mView.animateVertically(yPosition)
     }
 
     /**
-     * @return the relative position of the drag from the time after the arrow is activated until
+     * Tracks the relative position of the drag from the time after the arrow is activated until
      * the arrow is fully stretched (between 0.0 - 1.0f)
      */
-    private fun fullScreenStretchProgress(xTranslation: Float): Float {
-        return saturate(
-            (xTranslation - params.swipeTriggerThreshold) /
-                (fullyStretchedThreshold - params.swipeTriggerThreshold)
+    private fun fullScreenProgress(xTranslation: Float): Float {
+        return MathUtils.saturate(
+                (xTranslation - previousXTranslationOnActiveOffset) /
+                        (fullyStretchedThreshold - previousXTranslationOnActiveOffset)
         )
     }
 
@@ -450,26 +496,74 @@
      * Tracks the relative position of the drag from the entry until the threshold where the arrow
      * activates (between 0.0 - 1.0f)
      */
-    private fun preThresholdStretchProgress(xTranslation: Float): Float {
-        return saturate(xTranslation / params.swipeTriggerThreshold)
+    private fun staticThresholdProgress(xTranslation: Float): Float {
+        return MathUtils.saturate(xTranslation / params.staticTriggerThreshold)
+    }
+
+    private fun reactivationThresholdProgress(totalTouchDelta: Float): Float {
+        return MathUtils.saturate(totalTouchDelta / params.reactivationTriggerThreshold)
     }
 
     private fun stretchActiveBackIndicator(progress: Float) {
-        val rubberBandIterpolation = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress)
         mView.setStretch(
-            horizontalTranslationStretchAmount = rubberBandIterpolation,
-            arrowStretchAmount = rubberBandIterpolation,
-            backgroundWidthStretchAmount = DECELERATE_INTERPOLATOR_SLOW.getInterpolation(progress),
-            params.fullyStretchedIndicator
+                horizontalTranslationStretchAmount = params.translationInterpolator
+                        .getInterpolation(progress),
+                arrowStretchAmount = params.arrowAngleInterpolator.getInterpolation(progress),
+                backgroundWidthStretchAmount = params.activeWidthInterpolator
+                        .getInterpolation(progress),
+                backgroundAlphaStretchAmount = 1f,
+                backgroundHeightStretchAmount = 1f,
+                arrowAlphaStretchAmount = 1f,
+                edgeCornerStretchAmount = 1f,
+                farCornerStretchAmount = 1f,
+                fullyStretchedDimens = params.fullyStretchedIndicator
         )
     }
 
     private fun stretchEntryBackIndicator(progress: Float) {
         mView.setStretch(
-            horizontalTranslationStretchAmount = 0f,
-            arrowStretchAmount = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress),
-            backgroundWidthStretchAmount = DECELERATE_INTERPOLATOR.getInterpolation(progress),
-            params.preThresholdIndicator
+                horizontalTranslationStretchAmount = 0f,
+                arrowStretchAmount = params.arrowAngleInterpolator
+                        .getInterpolation(progress),
+                backgroundWidthStretchAmount = params.entryWidthInterpolator
+                        .getInterpolation(progress),
+                backgroundHeightStretchAmount = params.heightInterpolator
+                        .getInterpolation(progress),
+                backgroundAlphaStretchAmount = 1f,
+                arrowAlphaStretchAmount = params.arrowStrokeAlphaInterpolator.get(progress).value,
+                edgeCornerStretchAmount = params.edgeCornerInterpolator.getInterpolation(progress),
+                farCornerStretchAmount = params.farCornerInterpolator.getInterpolation(progress),
+                fullyStretchedDimens = params.preThresholdIndicator
+        )
+    }
+
+    private var previousPreThresholdWidthInterpolator = params.entryWidthTowardsEdgeInterpolator
+    fun preThresholdWidthStretchAmount(progress: Float): Float {
+        val interpolator = run {
+            val isPastSlop = abs(totalTouchDelta) > ViewConfiguration.get(context).scaledTouchSlop
+            if (isPastSlop) {
+                if (totalTouchDelta > 0) {
+                    params.entryWidthInterpolator
+                } else params.entryWidthTowardsEdgeInterpolator
+            } else {
+                previousPreThresholdWidthInterpolator
+            }.also { previousPreThresholdWidthInterpolator = it }
+        }
+        return interpolator.getInterpolation(progress).coerceAtLeast(0f)
+    }
+
+    private fun stretchInactiveBackIndicator(progress: Float) {
+        mView.setStretch(
+                horizontalTranslationStretchAmount = 0f,
+                arrowStretchAmount = params.arrowAngleInterpolator.getInterpolation(progress),
+                backgroundWidthStretchAmount = preThresholdWidthStretchAmount(progress),
+                backgroundHeightStretchAmount = params.heightInterpolator
+                        .getInterpolation(progress),
+                backgroundAlphaStretchAmount = 1f,
+                arrowAlphaStretchAmount = params.arrowStrokeAlphaInterpolator.get(progress).value,
+                edgeCornerStretchAmount = params.edgeCornerInterpolator.getInterpolation(progress),
+                farCornerStretchAmount = params.farCornerInterpolator.getInterpolation(progress),
+                fullyStretchedDimens = params.preThresholdIndicator
         )
     }
 
@@ -487,8 +581,7 @@
         }
     }
 
-    override fun setInsets(insetLeft: Int, insetRight: Int) {
-    }
+    override fun setInsets(insetLeft: Int, insetRight: Int) = Unit
 
     override fun setBackCallback(callback: NavigationEdgeBackPlugin.BackCallback) {
         backCallback = callback
@@ -500,65 +593,57 @@
     }
 
     override fun setMotionEventsHandler(motionEventsHandler: MotionEventsHandlerBase?) {
-        TODO("Not yet implemented")
+        // TODO(255697805): Integrate MotionEventHandler for trackpad.
     }
 
-    private fun isFlung() = velocityTracker!!.run {
-        computeCurrentVelocity(1000)
-        abs(xVelocity) > MIN_FLING_VELOCITY
+    private fun isDragAwayFromEdge(velocityPxPerSecThreshold: Int = 0) = velocityTracker!!.run {
+        computeCurrentVelocity(PX_PER_SEC)
+        val velocity = xVelocity.takeIf { mView.isLeftPanel } ?: (xVelocity * -1)
+        velocity > velocityPxPerSecThreshold
     }
 
-    private fun playFlingBackAnimation() {
-        playAnimation(setCommittedEndListener)
+    private fun isFlungAwayFromEdge(endX: Float, startX: Float = touchDeltaStartX): Boolean {
+        val minDistanceConsideredForFling = ViewConfiguration.get(context).scaledTouchSlop
+        val flingDistance = abs(endX - startX)
+        val isPastFlingVelocity = isDragAwayFromEdge(
+                velocityPxPerSecThreshold =
+                ViewConfiguration.get(context).scaledMinimumFlingVelocity)
+        return flingDistance > minDistanceConsideredForFling && isPastFlingVelocity
     }
 
-    private fun playCommitBackAnimation() {
-        // Check if we should vibrate again
-        if (previousState != GestureState.FLUNG) {
-            velocityTracker!!.computeCurrentVelocity(1000)
-            val isSlow = abs(velocityTracker!!.xVelocity) < 500
-            val hasNotVibratedRecently =
-                SystemClock.uptimeMillis() - vibrationTime >= GESTURE_DURATION_FOR_CLICK_MS
-            if (isSlow || hasNotVibratedRecently) {
-                vibratorHelper.vibrate(VibrationEffect.EFFECT_CLICK)
-            }
-        }
-        // Dispatch the actual back trigger
-        if (DEBUG) Log.d(TAG, "playCommitBackAnimation() invoked triggerBack() on backCallback")
-        backCallback.triggerBack()
-
-        playAnimation(setGoneEndListener)
-    }
-
-    private fun playCancelBackAnimation() {
-        backCallback.cancelBack()
-        playAnimation(setGoneEndListener)
-    }
-
-    /**
-     * @return true if the animation is running, false otherwise. Some transitions don't animate
-     */
-    private fun playAnimation(endListener: DelayedOnAnimationEndListener) {
-        updateRestingArrowDimens(animated = true, currentState)
-
-        if (!mView.addEndListener(endListener)) {
+    private fun playHorizontalAnimationThen(onEnd: DelayedOnAnimationEndListener) {
+        updateRestingArrowDimens()
+        if (!mView.addAnimationEndListener(mView.horizontalTranslation, onEnd)) {
             scheduleFailsafe()
         }
     }
 
-    private fun resetOnDown() {
-        hasPassedDragSlop = false
-        hasHapticPlayed = false
-        totalTouchDelta = 0f
-        vibrationTime = 0
-        cancelFailsafe()
+    private fun playAnimationThenSetGoneEnd() {
+        updateRestingArrowDimens()
+        if (!mView.addAnimationEndListener(mView.backgroundAlpha, onEndSetGoneStateListener)) {
+            scheduleFailsafe()
+        }
     }
 
-    private fun updateYPosition(touchY: Float) {
+    private fun playWithBackgroundWidthAnimation(
+            onEnd: DelayedOnAnimationEndListener,
+            delay: Long = 0L
+    ) {
+        if (delay == 0L) {
+            updateRestingArrowDimens()
+            if (!mView.addAnimationEndListener(mView.backgroundWidth, onEnd)) {
+                scheduleFailsafe()
+            }
+        } else {
+            mainHandler.postDelayed(delay) { playWithBackgroundWidthAnimation(onEnd, delay = 0L) }
+        }
+    }
+
+    private fun updateYStartPosition(touchY: Float) {
         var yPosition = touchY - params.fingerOffset
         yPosition = max(yPosition, params.minArrowYPosition.toFloat())
         yPosition -= layoutParams.height / 2.0f
-        layoutParams.y = constrain(yPosition.toInt(), 0, displaySize.y)
+        layoutParams.y = MathUtils.constrain(yPosition.toInt(), 0, displaySize.y)
     }
 
     override fun setDisplaySize(displaySize: Point) {
@@ -569,53 +654,135 @@
     /**
      * Updates resting arrow and background size not accounting for stretch
      */
-    private fun updateRestingArrowDimens(animated: Boolean, currentState: GestureState) {
-        if (animated) {
-            when (currentState) {
-                GestureState.ENTRY, GestureState.ACTIVE, GestureState.FLUNG ->
-                    mView.setArrowStiffness(ARROW_APPEAR_STIFFNESS, ARROW_APPEAR_DAMPING_RATIO)
-                GestureState.CANCELLED -> mView.fadeOut()
-                else ->
-                    mView.setArrowStiffness(
-                        ARROW_DISAPPEAR_STIFFNESS,
-                        ARROW_DISAPPEAR_DAMPING_RATIO
-                    )
+    private fun updateRestingArrowDimens() {
+        when (currentState) {
+            GestureState.GONE,
+            GestureState.ENTRY -> {
+                mView.setSpring(
+                        arrowLength = params.entryIndicator.arrowDimens.lengthSpring,
+                        arrowHeight = params.entryIndicator.arrowDimens.heightSpring,
+                        arrowAlpha = params.entryIndicator.arrowDimens.alphaSpring,
+                        scale = params.entryIndicator.scaleSpring,
+                        verticalTranslation = params.entryIndicator.verticalTranslationSpring,
+                        horizontalTranslation = params.entryIndicator.horizontalTranslationSpring,
+                        backgroundAlpha = params.entryIndicator.backgroundDimens.alphaSpring,
+                        backgroundWidth = params.entryIndicator.backgroundDimens.widthSpring,
+                        backgroundHeight = params.entryIndicator.backgroundDimens.heightSpring,
+                        backgroundEdgeCornerRadius = params.entryIndicator.backgroundDimens
+                                .edgeCornerRadiusSpring,
+                        backgroundFarCornerRadius = params.entryIndicator.backgroundDimens
+                                .farCornerRadiusSpring,
+                )
             }
+            GestureState.INACTIVE -> {
+                mView.setSpring(
+                        arrowLength = params.preThresholdIndicator.arrowDimens.lengthSpring,
+                        arrowHeight = params.preThresholdIndicator.arrowDimens.heightSpring,
+                        horizontalTranslation = params.preThresholdIndicator
+                                .horizontalTranslationSpring,
+                        scale = params.preThresholdIndicator.scaleSpring,
+                        backgroundWidth = params.preThresholdIndicator.backgroundDimens
+                                .widthSpring,
+                        backgroundHeight = params.preThresholdIndicator.backgroundDimens
+                                .heightSpring,
+                        backgroundEdgeCornerRadius = params.preThresholdIndicator.backgroundDimens
+                                .edgeCornerRadiusSpring,
+                        backgroundFarCornerRadius = params.preThresholdIndicator.backgroundDimens
+                                .farCornerRadiusSpring,
+                )
+            }
+            GestureState.ACTIVE -> {
+                mView.setSpring(
+                        arrowLength = params.activeIndicator.arrowDimens.lengthSpring,
+                        arrowHeight = params.activeIndicator.arrowDimens.heightSpring,
+                        scale = params.activeIndicator.scaleSpring,
+                        horizontalTranslation = params.activeIndicator.horizontalTranslationSpring,
+                        backgroundWidth = params.activeIndicator.backgroundDimens.widthSpring,
+                        backgroundHeight = params.activeIndicator.backgroundDimens.heightSpring,
+                        backgroundEdgeCornerRadius = params.activeIndicator.backgroundDimens
+                                .edgeCornerRadiusSpring,
+                        backgroundFarCornerRadius = params.activeIndicator.backgroundDimens
+                                .farCornerRadiusSpring,
+                )
+            }
+            GestureState.FLUNG -> {
+                mView.setSpring(
+                        arrowLength = params.flungIndicator.arrowDimens.lengthSpring,
+                        arrowHeight = params.flungIndicator.arrowDimens.heightSpring,
+                        backgroundWidth = params.flungIndicator.backgroundDimens.widthSpring,
+                        backgroundHeight = params.flungIndicator.backgroundDimens.heightSpring,
+                        backgroundEdgeCornerRadius = params.flungIndicator.backgroundDimens
+                                .edgeCornerRadiusSpring,
+                        backgroundFarCornerRadius = params.flungIndicator.backgroundDimens
+                                .farCornerRadiusSpring,
+                )
+            }
+            GestureState.COMMITTED -> {
+                mView.setSpring(
+                        arrowLength = params.committedIndicator.arrowDimens.lengthSpring,
+                        arrowHeight = params.committedIndicator.arrowDimens.heightSpring,
+                        scale = params.committedIndicator.scaleSpring,
+                        backgroundWidth = params.committedIndicator.backgroundDimens.widthSpring,
+                        backgroundHeight = params.committedIndicator.backgroundDimens.heightSpring,
+                        backgroundEdgeCornerRadius = params.committedIndicator.backgroundDimens
+                                .edgeCornerRadiusSpring,
+                        backgroundFarCornerRadius = params.committedIndicator.backgroundDimens
+                                .farCornerRadiusSpring,
+                )
+            }
+            else -> {}
         }
+
         mView.setRestingDimens(
-            restingParams = EdgePanelParams.BackIndicatorDimens(
-                horizontalTranslation = when (currentState) {
-                    GestureState.GONE -> -params.activeIndicator.backgroundDimens.width
-                    // Position the committed arrow slightly further off the screen so we  do not
-                    // see part of it bouncing
-                    GestureState.COMMITTED ->
-                        -params.activeIndicator.backgroundDimens.width * 1.5f
-                    GestureState.FLUNG -> params.fullyStretchedIndicator.horizontalTranslation
-                    GestureState.ACTIVE -> params.activeIndicator.horizontalTranslation
-                    GestureState.ENTRY, GestureState.INACTIVE, GestureState.CANCELLED ->
-                        params.entryIndicator.horizontalTranslation
-                },
-                arrowDimens = when (currentState) {
-                    GestureState.ACTIVE, GestureState.INACTIVE,
-                    GestureState.COMMITTED, GestureState.FLUNG -> params.activeIndicator.arrowDimens
-                    GestureState.CANCELLED -> params.cancelledArrowDimens
-                    GestureState.GONE, GestureState.ENTRY -> params.entryIndicator.arrowDimens
-                },
-                backgroundDimens = when (currentState) {
-                    GestureState.GONE, GestureState.ENTRY -> params.entryIndicator.backgroundDimens
-                    else ->
-                        params.activeIndicator.backgroundDimens.copy(
-                            edgeCornerRadius =
-                            if (currentState == GestureState.INACTIVE ||
-                                currentState == GestureState.CANCELLED
-                            )
-                                params.cancelledEdgeCornerRadius
-                            else
-                                params.activeIndicator.backgroundDimens.edgeCornerRadius
-                        )
-                }
-            ),
-            animate = animated
+                animate = !(currentState == GestureState.FLUNG ||
+                        currentState == GestureState.COMMITTED),
+                restingParams = EdgePanelParams.BackIndicatorDimens(
+                        scale = when (currentState) {
+                            GestureState.ACTIVE,
+                            GestureState.FLUNG,
+                            -> params.activeIndicator.scale
+                            GestureState.COMMITTED -> params.committedIndicator.scale
+                            else -> params.preThresholdIndicator.scale
+                        },
+                        scalePivotX = when (currentState) {
+                            GestureState.GONE,
+                            GestureState.ENTRY,
+                            GestureState.INACTIVE,
+                            GestureState.CANCELLED -> params.preThresholdIndicator.scalePivotX
+                            else -> params.committedIndicator.scalePivotX
+                        },
+                        horizontalTranslation = when (currentState) {
+                            GestureState.GONE -> {
+                                params.activeIndicator.backgroundDimens.width?.times(-1)
+                            }
+                            GestureState.ENTRY,
+                            GestureState.INACTIVE -> params.entryIndicator.horizontalTranslation
+                            GestureState.FLUNG -> params.activeIndicator.horizontalTranslation
+                            GestureState.ACTIVE -> params.activeIndicator.horizontalTranslation
+                            GestureState.CANCELLED -> {
+                                params.cancelledIndicator.horizontalTranslation
+                            }
+                            else -> null
+                        },
+                        arrowDimens = when (currentState) {
+                            GestureState.GONE,
+                            GestureState.ENTRY,
+                            GestureState.INACTIVE -> params.entryIndicator.arrowDimens
+                            GestureState.ACTIVE -> params.activeIndicator.arrowDimens
+                            GestureState.FLUNG,
+                            GestureState.COMMITTED -> params.committedIndicator.arrowDimens
+                            GestureState.CANCELLED -> params.cancelledIndicator.arrowDimens
+                        },
+                        backgroundDimens = when (currentState) {
+                            GestureState.GONE,
+                            GestureState.ENTRY,
+                            GestureState.INACTIVE -> params.entryIndicator.backgroundDimens
+                            GestureState.ACTIVE -> params.activeIndicator.backgroundDimens
+                            GestureState.FLUNG -> params.activeIndicator.backgroundDimens
+                            GestureState.COMMITTED -> params.committedIndicator.backgroundDimens
+                            GestureState.CANCELLED -> params.cancelledIndicator.backgroundDimens
+                        }
+                )
         )
     }
 
@@ -628,42 +795,123 @@
     private fun updateArrowState(newState: GestureState, force: Boolean = false) {
         if (!force && currentState == newState) return
 
-        if (DEBUG) Log.d(TAG, "updateArrowState $currentState -> $newState")
         previousState = currentState
         currentState = newState
-        if (currentState == GestureState.GONE) {
-            mView.cancelAlphaAnimations()
-            mView.visibility = View.GONE
-        } else {
-            mView.visibility = View.VISIBLE
+
+        when (currentState) {
+            GestureState.CANCELLED -> {
+                backCallback.cancelBack()
+            }
+            GestureState.FLUNG,
+            GestureState.COMMITTED -> {
+                // When flung, trigger back immediately but don't fire again
+                // once state resolves to committed.
+                if (previousState != GestureState.FLUNG) backCallback.triggerBack()
+            }
+            GestureState.ENTRY,
+            GestureState.INACTIVE -> {
+                backCallback.setTriggerBack(false)
+            }
+            GestureState.ACTIVE -> {
+                backCallback.setTriggerBack(true)
+            }
+            GestureState.GONE -> { }
         }
 
         when (currentState) {
             // Transitioning to GONE never animates since the arrow is (presumably) already off the
             // screen
-            GestureState.GONE -> updateRestingArrowDimens(animated = false, currentState)
+            GestureState.GONE -> {
+                updateRestingArrowDimens()
+                mView.isVisible = false
+            }
             GestureState.ENTRY -> {
-                updateYPosition(startY)
-                updateRestingArrowDimens(animated = true, currentState)
+                mView.isVisible = true
+
+                updateRestingArrowDimens()
+                gestureEntryTime = SystemClock.uptimeMillis()
+                gestureInactiveOrEntryTime = SystemClock.uptimeMillis()
             }
             GestureState.ACTIVE -> {
-                updateRestingArrowDimens(animated = true, currentState)
-                // Vibrate the first time we transition to ACTIVE
-                if (!hasHapticPlayed) {
-                    hasHapticPlayed = true
-                    vibrationTime = SystemClock.uptimeMillis()
-                    vibratorHelper.vibrate(VibrationEffect.EFFECT_TICK)
+                previousXTranslationOnActiveOffset = previousXTranslation
+                gestureActiveTime = SystemClock.uptimeMillis()
+
+                updateRestingArrowDimens()
+
+                vibratorHelper.cancel()
+                mainHandler.postDelayed(10L) {
+                    vibratorHelper.vibrate(VIBRATE_ACTIVATED_EFFECT)
+                }
+
+                val startingVelocity = convertVelocityToSpringStartingVelocity(
+                    valueOnFastVelocity = 0f,
+                    valueOnSlowVelocity = if (previousState == GestureState.ENTRY) 2f else 4.5f
+                )
+
+                when (previousState) {
+                    GestureState.ENTRY,
+                    GestureState.INACTIVE -> {
+                        mView.popOffEdge(startingVelocity)
+                    }
+                    GestureState.COMMITTED -> {
+                        // if previous state was committed then this activation
+                        // was due to a quick second swipe. Don't pop the arrow this time
+                    }
+                    else -> { }
                 }
             }
+
             GestureState.INACTIVE -> {
-                updateRestingArrowDimens(animated = true, currentState)
+                gestureInactiveOrEntryTime = SystemClock.uptimeMillis()
+
+                val startingVelocity = convertVelocityToSpringStartingVelocity(
+                        valueOnFastVelocity = -1.05f,
+                        valueOnSlowVelocity = -1.50f
+                )
+                mView.popOffEdge(startingVelocity)
+
+                vibratorHelper.vibrate(VIBRATE_DEACTIVATED_EFFECT)
+                updateRestingArrowDimens()
             }
-            GestureState.FLUNG -> playFlingBackAnimation()
-            GestureState.COMMITTED -> playCommitBackAnimation()
-            GestureState.CANCELLED -> playCancelBackAnimation()
+            GestureState.FLUNG -> {
+                mainHandler.postDelayed(POP_ON_FLING_DELAY) { mView.popScale(1.9f) }
+                playHorizontalAnimationThen(onEndSetCommittedStateListener)
+            }
+            GestureState.COMMITTED -> {
+                if (previousState == GestureState.FLUNG) {
+                    playAnimationThenSetGoneEnd()
+                } else {
+                    mView.popScale(3f)
+                    mainHandler.postDelayed(
+                            playAnimationThenSetGoneOnAlphaEnd,
+                            MIN_DURATION_COMMITTED_ANIMATION
+                    )
+                }
+            }
+            GestureState.CANCELLED -> {
+                val delay = max(0, MIN_DURATION_CANCELLED_ANIMATION - elapsedTimeSinceEntry)
+                playWithBackgroundWidthAnimation(onEndSetGoneStateListener, delay)
+
+                params.arrowStrokeAlphaSpring.get(0f).takeIf { it.isNewState }?.let {
+                    mView.popArrowAlpha(0f, it.value)
+                }
+                mainHandler.postDelayed(10L) { vibratorHelper.cancel() }
+            }
         }
     }
 
+    private fun convertVelocityToSpringStartingVelocity(
+            valueOnFastVelocity: Float,
+            valueOnSlowVelocity: Float,
+    ): Float {
+        val factor = velocityTracker?.run {
+            computeCurrentVelocity(PX_PER_MS)
+            MathUtils.smoothStep(0f, 3f, abs(xVelocity))
+        } ?: valueOnFastVelocity
+
+        return MathUtils.lerp(valueOnFastVelocity, valueOnSlowVelocity, 1 - factor)
+    }
+
     private fun scheduleFailsafe() {
         if (!ENABLE_FAILSAFE) return
         cancelFailsafe()
@@ -690,24 +938,24 @@
     init {
         if (DEBUG) mView.drawDebugInfo = { canvas ->
             val debugStrings = listOf(
-                "$currentState",
-                "startX=$startX",
-                "startY=$startY",
-                "xDelta=${"%.1f".format(totalTouchDelta)}",
-                "xTranslation=${"%.1f".format(previousXTranslation)}",
-                "pre=${"%.0f".format(preThresholdStretchProgress(previousXTranslation) * 100)}%",
-                "post=${"%.0f".format(fullScreenStretchProgress(previousXTranslation) * 100)}%"
+                    "$currentState",
+                    "startX=$startX",
+                    "startY=$startY",
+                    "xDelta=${"%.1f".format(totalTouchDelta)}",
+                    "xTranslation=${"%.1f".format(previousXTranslation)}",
+                    "pre=${"%.0f".format(staticThresholdProgress(previousXTranslation) * 100)}%",
+                    "post=${"%.0f".format(fullScreenProgress(previousXTranslation) * 100)}%"
             )
             val debugPaint = Paint().apply {
                 color = Color.WHITE
             }
             val debugInfoBottom = debugStrings.size * 32f + 4f
             canvas.drawRect(
-                4f,
-                4f,
-                canvas.width.toFloat(),
-                debugStrings.size * 32f + 4f,
-                debugPaint
+                    4f,
+                    4f,
+                    canvas.width.toFloat(),
+                    debugStrings.size * 32f + 4f,
+                    debugPaint
             )
             debugPaint.apply {
                 color = Color.BLACK
@@ -733,9 +981,71 @@
                 canvas.drawLine(x, debugInfoBottom, x, canvas.height.toFloat(), debugPaint)
             }
 
-            drawVerticalLine(x = params.swipeTriggerThreshold, color = Color.BLUE)
+            drawVerticalLine(x = params.staticTriggerThreshold, color = Color.BLUE)
+            drawVerticalLine(x = params.deactivationSwipeTriggerThreshold, color = Color.BLUE)
             drawVerticalLine(x = startX, color = Color.GREEN)
             drawVerticalLine(x = previousXTranslation, color = Color.DKGRAY)
         }
     }
 }
+
+/**
+ * In addition to a typical step function which returns one or two
+ * values based on a threshold, `Step` also gracefully handles quick
+ * changes in input near the threshold value that would typically
+ * result in the output rapidly changing.
+ *
+ * In the context of Back arrow, the arrow's stroke opacity should
+ * always appear transparent or opaque. Using a typical Step function,
+ * this would resulting in a flickering appearance as the output would
+ * change rapidly. `Step` addresses this by moving the threshold after
+ * it is crossed so it cannot be easily crossed again with small changes
+ * in touch events.
+ */
+class Step<T>(
+        private val threshold: Float,
+        private val factor: Float = 1.1f,
+        private val postThreshold: T,
+        private val preThreshold: T
+) {
+
+    data class Value<T>(val value: T, val isNewState: Boolean)
+
+    private val lowerFactor = 2 - factor
+
+    private lateinit var startValue: Value<T>
+    private lateinit var previousValue: Value<T>
+    private var hasCrossedUpperBoundAtLeastOnce = false
+    private var progress: Float = 0f
+
+    init {
+        reset()
+    }
+
+    fun reset() {
+        hasCrossedUpperBoundAtLeastOnce = false
+        progress = 0f
+        startValue = Value(preThreshold, false)
+        previousValue = startValue
+    }
+
+    fun get(progress: Float): Value<T> {
+        this.progress = progress
+
+        val hasCrossedUpperBound = progress > threshold * factor
+        val hasCrossedLowerBound = progress > threshold * lowerFactor
+
+        return when {
+            hasCrossedUpperBound && !hasCrossedUpperBoundAtLeastOnce -> {
+                hasCrossedUpperBoundAtLeastOnce = true
+                Value(postThreshold, true)
+            }
+            hasCrossedLowerBound -> previousValue.copy(isNewState = false)
+            hasCrossedUpperBoundAtLeastOnce -> {
+                hasCrossedUpperBoundAtLeastOnce = false
+                Value(preThreshold, true)
+            }
+            else -> startValue
+        }.also { previousValue = it }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
index d56537b..0c00022 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
@@ -1,52 +1,82 @@
 package com.android.systemui.navigationbar.gestural
 
 import android.content.res.Resources
+import android.util.TypedValue
+import androidx.core.animation.PathInterpolator
+import androidx.dynamicanimation.animation.SpringForce
 import com.android.systemui.R
 
 data class EdgePanelParams(private var resources: Resources) {
 
     data class ArrowDimens(
-        val length: Float = 0f,
-        val height: Float = 0f
+            val length: Float = 0f,
+            val height: Float = 0f,
+            val alpha: Float = 0f,
+            var alphaSpring: SpringForce? = null,
+            val heightSpring: SpringForce? = null,
+            val lengthSpring: SpringForce? = null,
     )
 
     data class BackgroundDimens(
-        val width: Float = 0f,
-        val height: Float = 0f,
-        val edgeCornerRadius: Float = 0f,
-        val farCornerRadius: Float = 0f
+            val width: Float? = 0f,
+            val height: Float = 0f,
+            val edgeCornerRadius: Float = 0f,
+            val farCornerRadius: Float = 0f,
+            val alpha: Float = 0f,
+            val widthSpring: SpringForce? = null,
+            val heightSpring: SpringForce? = null,
+            val farCornerRadiusSpring: SpringForce? = null,
+            val edgeCornerRadiusSpring: SpringForce? = null,
+            val alphaSpring: SpringForce? = null,
     )
 
     data class BackIndicatorDimens(
-        val horizontalTranslation: Float = 0f,
-        val arrowDimens: ArrowDimens = ArrowDimens(),
-        val backgroundDimens: BackgroundDimens = BackgroundDimens()
+            val horizontalTranslation: Float? = 0f,
+            val scale: Float = 0f,
+            val scalePivotX: Float = 0f,
+            val arrowDimens: ArrowDimens,
+            val backgroundDimens: BackgroundDimens,
+            val verticalTranslationSpring: SpringForce? = null,
+            val horizontalTranslationSpring: SpringForce? = null,
+            val scaleSpring: SpringForce? = null,
     )
 
-    var arrowThickness: Float = 0f
+    lateinit var entryIndicator: BackIndicatorDimens
         private set
-    var entryIndicator = BackIndicatorDimens()
+    lateinit var activeIndicator: BackIndicatorDimens
         private set
-    var activeIndicator = BackIndicatorDimens()
+    lateinit var cancelledIndicator: BackIndicatorDimens
         private set
-    var preThresholdIndicator = BackIndicatorDimens()
+    lateinit var flungIndicator: BackIndicatorDimens
         private set
-    var fullyStretchedIndicator = BackIndicatorDimens()
+    lateinit var committedIndicator: BackIndicatorDimens
         private set
-    var cancelledEdgeCornerRadius: Float = 0f
+    lateinit var preThresholdIndicator: BackIndicatorDimens
         private set
-    var cancelledArrowDimens = ArrowDimens()
+    lateinit var fullyStretchedIndicator: BackIndicatorDimens
+        private set
 
     // navigation bar edge constants
     var arrowPaddingEnd: Int = 0
         private set
+    var arrowThickness: Float = 0f
+        private set
+    lateinit var arrowStrokeAlphaSpring: Step<SpringForce>
+        private set
+    lateinit var arrowStrokeAlphaInterpolator: Step<Float>
+        private set
 
     // The closest to y
     var minArrowYPosition: Int = 0
         private set
     var fingerOffset: Int = 0
         private set
-    var swipeTriggerThreshold: Float = 0f
+    var staticTriggerThreshold: Float = 0f
+        private set
+    var reactivationTriggerThreshold: Float = 0f
+        private set
+    var deactivationSwipeTriggerThreshold: Float = 0f
+        get() = -field
         private set
     var swipeProgressThreshold: Float = 0f
         private set
@@ -55,6 +85,26 @@
     var minDeltaForSwitch: Int = 0
         private set
 
+    var minDragToStartAnimation: Float = 0f
+        private set
+
+    lateinit var entryWidthInterpolator: PathInterpolator
+        private set
+    lateinit var entryWidthTowardsEdgeInterpolator: PathInterpolator
+        private set
+    lateinit var activeWidthInterpolator: PathInterpolator
+        private set
+    lateinit var arrowAngleInterpolator: PathInterpolator
+        private set
+    lateinit var translationInterpolator: PathInterpolator
+        private set
+    lateinit var farCornerInterpolator: PathInterpolator
+        private set
+    lateinit var edgeCornerInterpolator: PathInterpolator
+        private set
+    lateinit var heightInterpolator: PathInterpolator
+        private set
+
     init {
         update(resources)
     }
@@ -63,6 +113,10 @@
         return resources.getDimension(id)
     }
 
+    private fun getDimenFloat(id: Int): Float {
+        return TypedValue().run { resources.getValue(id, this, true); float }
+    }
+
     private fun getPx(id: Int): Int {
         return resources.getDimensionPixelSize(id)
     }
@@ -73,72 +127,200 @@
         arrowPaddingEnd = getPx(R.dimen.navigation_edge_panel_padding)
         minArrowYPosition = getPx(R.dimen.navigation_edge_arrow_min_y)
         fingerOffset = getPx(R.dimen.navigation_edge_finger_offset)
-        swipeTriggerThreshold = getDimen(R.dimen.navigation_edge_action_drag_threshold)
+        staticTriggerThreshold = getDimen(R.dimen.navigation_edge_action_drag_threshold)
+        reactivationTriggerThreshold =
+                getDimen(R.dimen.navigation_edge_action_reactivation_drag_threshold)
+        deactivationSwipeTriggerThreshold =
+                getDimen(R.dimen.navigation_edge_action_deactivation_drag_threshold)
         swipeProgressThreshold = getDimen(R.dimen.navigation_edge_action_progress_threshold)
         minDeltaForSwitch = getPx(R.dimen.navigation_edge_minimum_x_delta_for_switch)
+        minDragToStartAnimation =
+                getDimen(R.dimen.navigation_edge_action_min_distance_to_start_animation)
+
+        entryWidthInterpolator = PathInterpolator(.19f, 1.27f, .71f, .86f)
+        entryWidthTowardsEdgeInterpolator = PathInterpolator(1f, -3f, 1f, 1.2f)
+        activeWidthInterpolator = PathInterpolator(.15f, .48f, .46f, .89f)
+        arrowAngleInterpolator = entryWidthInterpolator
+        translationInterpolator = PathInterpolator(0.2f, 1.0f, 1.0f, 1.0f)
+        farCornerInterpolator = PathInterpolator(.03f, .19f, .14f, 1.09f)
+        edgeCornerInterpolator = PathInterpolator(0f, 1.11f, .85f, .84f)
+        heightInterpolator = PathInterpolator(1f, .05f, .9f, -0.29f)
+
+        val showArrowOnProgressValue = .2f
+        val showArrowOnProgressValueFactor = 1.05f
+
+        val entryActiveHorizontalTranslationSpring = createSpring(675f, 0.8f)
+        val activeCommittedArrowLengthSpring = createSpring(1500f, 0.29f)
+        val activeCommittedArrowHeightSpring = createSpring(1500f, 0.29f)
+        val flungCommittedEdgeCornerSpring = createSpring(10000f, 1f)
+        val flungCommittedFarCornerSpring = createSpring(10000f, 1f)
+        val flungCommittedWidthSpring = createSpring(10000f, 1f)
+        val flungCommittedHeightSpring = createSpring(10000f, 1f)
 
         entryIndicator = BackIndicatorDimens(
-            horizontalTranslation = getDimen(R.dimen.navigation_edge_entry_margin),
-            arrowDimens = ArrowDimens(
-                length = getDimen(R.dimen.navigation_edge_entry_arrow_length),
-                height = getDimen(R.dimen.navigation_edge_entry_arrow_height),
-            ),
-            backgroundDimens = BackgroundDimens(
-                width = getDimen(R.dimen.navigation_edge_entry_background_width),
-                height = getDimen(R.dimen.navigation_edge_entry_background_height),
-                edgeCornerRadius = getDimen(R.dimen.navigation_edge_entry_edge_corners),
-                farCornerRadius = getDimen(R.dimen.navigation_edge_entry_far_corners)
-            )
+                horizontalTranslation = getDimen(R.dimen.navigation_edge_entry_margin),
+                scale = getDimenFloat(R.dimen.navigation_edge_entry_scale),
+                scalePivotX = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
+                horizontalTranslationSpring = entryActiveHorizontalTranslationSpring,
+                verticalTranslationSpring = createSpring(10000f, 0.9f),
+                scaleSpring = createSpring(120f, 0.8f),
+                arrowDimens = ArrowDimens(
+                        length = getDimen(R.dimen.navigation_edge_entry_arrow_length),
+                        height = getDimen(R.dimen.navigation_edge_entry_arrow_height),
+                        alpha = 0f,
+                        alphaSpring = createSpring(200f, 1f),
+                        lengthSpring = createSpring(600f, 0.4f),
+                        heightSpring = createSpring(600f, 0.4f),
+                ),
+                backgroundDimens = BackgroundDimens(
+                        alpha = 1f,
+                        width = getDimen(R.dimen.navigation_edge_entry_background_width),
+                        height = getDimen(R.dimen.navigation_edge_entry_background_height),
+                        edgeCornerRadius = getDimen(R.dimen.navigation_edge_entry_edge_corners),
+                        farCornerRadius = getDimen(R.dimen.navigation_edge_entry_far_corners),
+                        alphaSpring = createSpring(900f, 1f),
+                        widthSpring = createSpring(450f, 0.65f),
+                        heightSpring = createSpring(1500f, 0.45f),
+                        farCornerRadiusSpring = createSpring(300f, 0.5f),
+                        edgeCornerRadiusSpring = createSpring(150f, 0.5f),
+                )
         )
 
         activeIndicator = BackIndicatorDimens(
-            horizontalTranslation = getDimen(R.dimen.navigation_edge_active_margin),
-            arrowDimens = ArrowDimens(
-                length = getDimen(R.dimen.navigation_edge_active_arrow_length),
-                height = getDimen(R.dimen.navigation_edge_active_arrow_height),
-            ),
-            backgroundDimens = BackgroundDimens(
-                width = getDimen(R.dimen.navigation_edge_active_background_width),
-                height = getDimen(R.dimen.navigation_edge_active_background_height),
-                edgeCornerRadius = getDimen(R.dimen.navigation_edge_active_edge_corners),
-                farCornerRadius = getDimen(R.dimen.navigation_edge_active_far_corners)
-
-            )
+                horizontalTranslation = getDimen(R.dimen.navigation_edge_active_margin),
+                scale = getDimenFloat(R.dimen.navigation_edge_active_scale),
+                horizontalTranslationSpring = entryActiveHorizontalTranslationSpring,
+                scaleSpring = createSpring(450f, 0.415f),
+                arrowDimens = ArrowDimens(
+                        length = getDimen(R.dimen.navigation_edge_active_arrow_length),
+                        height = getDimen(R.dimen.navigation_edge_active_arrow_height),
+                        alpha = 1f,
+                        lengthSpring = activeCommittedArrowLengthSpring,
+                        heightSpring = activeCommittedArrowHeightSpring,
+                ),
+                backgroundDimens = BackgroundDimens(
+                        alpha = 1f,
+                        width = getDimen(R.dimen.navigation_edge_active_background_width),
+                        height = getDimen(R.dimen.navigation_edge_active_background_height),
+                        edgeCornerRadius = getDimen(R.dimen.navigation_edge_active_edge_corners),
+                        farCornerRadius = getDimen(R.dimen.navigation_edge_active_far_corners),
+                        widthSpring = createSpring(375f, 0.675f),
+                        heightSpring = createSpring(10000f, 1f),
+                        edgeCornerRadiusSpring = createSpring(600f, 0.36f),
+                        farCornerRadiusSpring = createSpring(2500f, 0.855f),
+                )
         )
 
         preThresholdIndicator = BackIndicatorDimens(
-            horizontalTranslation = getDimen(R.dimen.navigation_edge_pre_threshold_margin),
-            arrowDimens = ArrowDimens(
-                length = entryIndicator.arrowDimens.length,
-                height = entryIndicator.arrowDimens.height,
-            ),
-            backgroundDimens = BackgroundDimens(
-                width = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
-                height = getDimen(R.dimen.navigation_edge_pre_threshold_background_height),
-                edgeCornerRadius = getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners),
-                farCornerRadius = getDimen(R.dimen.navigation_edge_pre_threshold_far_corners)
-            )
+                horizontalTranslation = getDimen(R.dimen.navigation_edge_pre_threshold_margin),
+                scale = getDimenFloat(R.dimen.navigation_edge_pre_threshold_scale),
+                scalePivotX = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
+                scaleSpring = createSpring(120f, 0.8f),
+                horizontalTranslationSpring = createSpring(6000f, 1f),
+                arrowDimens = ArrowDimens(
+                        length = getDimen(R.dimen.navigation_edge_pre_threshold_arrow_length),
+                        height = getDimen(R.dimen.navigation_edge_pre_threshold_arrow_height),
+                        alpha = 1f,
+                        lengthSpring = createSpring(100f, 0.6f),
+                        heightSpring = createSpring(100f, 0.6f),
+                ),
+                backgroundDimens = BackgroundDimens(
+                        alpha = 1f,
+                        width = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
+                        height = getDimen(R.dimen.navigation_edge_pre_threshold_background_height),
+                        edgeCornerRadius =
+                                getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners),
+                        farCornerRadius =
+                                getDimen(R.dimen.navigation_edge_pre_threshold_far_corners),
+                        widthSpring = createSpring(200f, 0.65f),
+                        heightSpring = createSpring(1500f, 0.45f),
+                        farCornerRadiusSpring = createSpring(200f, 1f),
+                        edgeCornerRadiusSpring = createSpring(150f, 0.5f),
+                )
+        )
+
+        committedIndicator = activeIndicator.copy(
+                horizontalTranslation = null,
+                arrowDimens = activeIndicator.arrowDimens.copy(
+                        lengthSpring = activeCommittedArrowLengthSpring,
+                        heightSpring = activeCommittedArrowHeightSpring,
+                ),
+                backgroundDimens = activeIndicator.backgroundDimens.copy(
+                        alpha = 0f,
+                        // explicitly set to null to preserve previous width upon state change
+                        width = null,
+                        widthSpring = flungCommittedWidthSpring,
+                        heightSpring = flungCommittedHeightSpring,
+                        edgeCornerRadiusSpring = flungCommittedEdgeCornerSpring,
+                        farCornerRadiusSpring = flungCommittedFarCornerSpring,
+                ),
+                scale = 0.85f,
+                scaleSpring = createSpring(650f, 1f),
+        )
+
+        flungIndicator = committedIndicator.copy(
+                arrowDimens = committedIndicator.arrowDimens.copy(
+                        lengthSpring = createSpring(850f, 0.46f),
+                        heightSpring = createSpring(850f, 0.46f),
+                ),
+                backgroundDimens = committedIndicator.backgroundDimens.copy(
+                        widthSpring = flungCommittedWidthSpring,
+                        heightSpring = flungCommittedHeightSpring,
+                        edgeCornerRadiusSpring = flungCommittedEdgeCornerSpring,
+                        farCornerRadiusSpring = flungCommittedFarCornerSpring,
+                )
+        )
+
+        cancelledIndicator = entryIndicator.copy(
+                backgroundDimens = entryIndicator.backgroundDimens.copy(width = 0f)
         )
 
         fullyStretchedIndicator = BackIndicatorDimens(
-            horizontalTranslation = getDimen(R.dimen.navigation_edge_stretch_margin),
-            arrowDimens = ArrowDimens(
-                length = getDimen(R.dimen.navigation_edge_stretched_arrow_length),
-                height = getDimen(R.dimen.navigation_edge_stretched_arrow_height),
-            ),
-            backgroundDimens = BackgroundDimens(
-                width = getDimen(R.dimen.navigation_edge_stretch_background_width),
-                height = getDimen(R.dimen.navigation_edge_stretch_background_height),
-                edgeCornerRadius = getDimen(R.dimen.navigation_edge_stretch_edge_corners),
-                farCornerRadius = getDimen(R.dimen.navigation_edge_stretch_far_corners)
+                horizontalTranslation = getDimen(R.dimen.navigation_edge_stretch_margin),
+                scale = getDimenFloat(R.dimen.navigation_edge_stretch_scale),
+                horizontalTranslationSpring = null,
+                verticalTranslationSpring = null,
+                scaleSpring = null,
+                arrowDimens = ArrowDimens(
+                        length = getDimen(R.dimen.navigation_edge_stretched_arrow_length),
+                        height = getDimen(R.dimen.navigation_edge_stretched_arrow_height),
+                        alpha = 1f,
+                        alphaSpring = null,
+                        heightSpring = null,
+                        lengthSpring = null,
+                ),
+                backgroundDimens = BackgroundDimens(
+                        alpha = 1f,
+                        width = getDimen(R.dimen.navigation_edge_stretch_background_width),
+                        height = getDimen(R.dimen.navigation_edge_stretch_background_height),
+                        edgeCornerRadius = getDimen(R.dimen.navigation_edge_stretch_edge_corners),
+                        farCornerRadius = getDimen(R.dimen.navigation_edge_stretch_far_corners),
+                        alphaSpring = null,
+                        widthSpring = null,
+                        heightSpring = null,
+                        edgeCornerRadiusSpring = null,
+                        farCornerRadiusSpring = null,
+                )
+        )
+
+        arrowStrokeAlphaInterpolator = Step(
+                threshold = showArrowOnProgressValue,
+                factor = showArrowOnProgressValueFactor,
+                postThreshold = 1f,
+                preThreshold = 0f
+        )
+
+        entryIndicator.arrowDimens.alphaSpring?.let { alphaSpring ->
+            arrowStrokeAlphaSpring = Step(
+                    threshold = showArrowOnProgressValue,
+                    factor = showArrowOnProgressValueFactor,
+                    postThreshold = alphaSpring,
+                    preThreshold = SpringForce().setStiffness(2000f).setDampingRatio(1f)
             )
-        )
-
-        cancelledEdgeCornerRadius = getDimen(R.dimen.navigation_edge_cancelled_edge_corners)
-
-        cancelledArrowDimens = ArrowDimens(
-            length = getDimen(R.dimen.navigation_edge_cancelled_arrow_length),
-            height = getDimen(R.dimen.navigation_edge_cancelled_arrow_height)
-        )
+        }
     }
 }
+
+fun createSpring(stiffness: Float, dampingRatio: Float): SpringForce {
+    return SpringForce().setStiffness(stiffness).setDampingRatio(dampingRatio)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
index 335172e..30d2d7a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.navigationbar.gestural;
 
-import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
+import static android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE;
 
 import android.content.Context;
 import android.view.MotionEvent;
@@ -24,14 +24,12 @@
 
 public final class Utilities {
 
-    private static final int TRACKPAD_GESTURE_SCALE = 60;
+    private static final int TRACKPAD_GESTURE_SCALE = 200;
 
     public static boolean isTrackpadMotionEvent(boolean isTrackpadGestureBackEnabled,
             MotionEvent event) {
-        // TODO: ideally should use event.getClassification(), but currently only the move
-        // events get assigned the correct classification.
         return isTrackpadGestureBackEnabled
-                && (event.getSource() & SOURCE_TOUCHSCREEN) != SOURCE_TOUCHSCREEN;
+                && event.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE;
     }
 
     public static int getTrackpadScale(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 6bfe1a0..be615d6 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -20,9 +20,12 @@
 import android.content.ActivityNotFoundException
 import android.content.ComponentName
 import android.content.Context
+import android.content.Intent
 import android.content.pm.PackageManager
 import android.os.UserManager
 import android.util.Log
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
 import com.android.systemui.util.kotlin.getOrNull
@@ -42,11 +45,12 @@
 @Inject
 constructor(
     private val context: Context,
-    private val intentResolver: NoteTaskIntentResolver,
+    private val resolver: NoteTaskInfoResolver,
     private val optionalBubbles: Optional<Bubbles>,
     private val optionalKeyguardManager: Optional<KeyguardManager>,
     private val optionalUserManager: Optional<UserManager>,
     @NoteTaskEnabledKey private val isEnabled: Boolean,
+    private val uiEventLogger: UiEventLogger,
 ) {
 
     /**
@@ -64,7 +68,9 @@
      *
      * That will let users open other apps in full screen, and take contextual notes.
      */
-    fun showNoteTask(isInMultiWindowMode: Boolean = false) {
+    @JvmOverloads
+    fun showNoteTask(isInMultiWindowMode: Boolean = false, uiEvent: ShowNoteTaskUiEvent? = null) {
+
         if (!isEnabled) return
 
         val bubbles = optionalBubbles.getOrNull() ?: return
@@ -74,9 +80,12 @@
         // TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
         if (!userManager.isUserUnlocked) return
 
-        val intent = intentResolver.resolveIntent() ?: return
+        val noteTaskInfo = resolver.resolveInfo() ?: return
+
+        uiEvent?.let { uiEventLogger.log(it, noteTaskInfo.uid, noteTaskInfo.packageName) }
 
         // TODO(b/266686199): We should handle when app not available. For now, we log.
+        val intent = noteTaskInfo.toCreateNoteIntent()
         try {
             if (isInMultiWindowMode || keyguardManager.isKeyguardLocked) {
                 context.startActivity(intent)
@@ -84,9 +93,7 @@
                 bubbles.showOrHideAppBubble(intent)
             }
         } catch (e: ActivityNotFoundException) {
-            val message =
-                "Activity not found for action: ${NoteTaskIntentResolver.ACTION_CREATE_NOTE}."
-            Log.e(TAG, message, e)
+            Log.e(TAG, "Activity not found for action: $ACTION_CREATE_NOTE.", e)
         }
     }
 
@@ -114,10 +121,47 @@
         )
     }
 
+    /** IDs of UI events accepted by [showNoteTask]. */
+    enum class ShowNoteTaskUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
+        @UiEvent(doc = "User opened a note by tapping on the lockscreen shortcut.")
+        NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE(1294),
+
+        /* ktlint-disable max-line-length */
+        @UiEvent(
+            doc =
+                "User opened a note by pressing the stylus tail button while the screen was unlocked."
+        )
+        NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON(1295),
+        @UiEvent(
+            doc =
+                "User opened a note by pressing the stylus tail button while the screen was locked."
+        )
+        NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1296),
+        @UiEvent(doc = "User opened a note by tapping on an app shortcut.")
+        NOTE_OPENED_VIA_SHORTCUT(1297);
+
+        override fun getId() = _id
+    }
+
     companion object {
         private val TAG = NoteTaskController::class.simpleName.orEmpty()
 
+        private fun NoteTaskInfoResolver.NoteTaskInfo.toCreateNoteIntent(): Intent {
+            return Intent(ACTION_CREATE_NOTE)
+                .setPackage(packageName)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint
+                // was used to start it.
+                .putExtra(INTENT_EXTRA_USE_STYLUS_MODE, true)
+        }
+
         // TODO(b/254604589): Use final KeyEvent.KEYCODE_* instead.
         const val NOTE_TASK_KEY_EVENT = 311
+
+        // TODO(b/265912743): Use Intent.ACTION_CREATE_NOTE instead.
+        const val ACTION_CREATE_NOTE = "android.intent.action.CREATE_NOTE"
+
+        // TODO(b/265912743): Use Intent.INTENT_EXTRA_USE_STYLUS_MODE instead.
+        const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
new file mode 100644
index 0000000..bd822d4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.notetask
+
+import android.app.role.RoleManager
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.UserHandle
+import android.util.Log
+import javax.inject.Inject
+
+internal class NoteTaskInfoResolver
+@Inject
+constructor(
+    private val context: Context,
+    private val roleManager: RoleManager,
+    private val packageManager: PackageManager,
+) {
+    fun resolveInfo(): NoteTaskInfo? {
+        // TODO(b/267634412): Select UserHandle depending on where the user initiated note-taking.
+        val user = context.user
+        val packageName = roleManager.getRoleHoldersAsUser(ROLE_NOTES, user).firstOrNull()
+
+        if (packageName.isNullOrEmpty()) return null
+
+        return NoteTaskInfo(packageName, packageManager.getUidOf(packageName, user))
+    }
+
+    /** Package name and kernel user-ID of a note-taking app. */
+    data class NoteTaskInfo(val packageName: String, val uid: Int)
+
+    companion object {
+        private val TAG = NoteTaskInfoResolver::class.simpleName.orEmpty()
+
+        private val EMPTY_APPLICATION_INFO_FLAGS = PackageManager.ApplicationInfoFlags.of(0)!!
+
+        /**
+         * Returns the kernel user-ID of [packageName] for a [user]. Returns zero if the app cannot
+         * be found.
+         */
+        private fun PackageManager.getUidOf(packageName: String, user: UserHandle): Int {
+            val applicationInfo =
+                try {
+                    getApplicationInfoAsUser(packageName, EMPTY_APPLICATION_INFO_FLAGS, user)
+                } catch (e: PackageManager.NameNotFoundException) {
+                    Log.e(TAG, "Couldn't find notes app UID", e)
+                    return 0
+                }
+            return applicationInfo.uid
+        }
+
+        // TODO(b/265912743): Use RoleManager.NOTES_ROLE instead.
+        const val ROLE_NOTES = "android.app.role.NOTES"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
index d5f4a5a..d40bf2b 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
@@ -16,8 +16,10 @@
 
 package com.android.systemui.notetask
 
+import android.app.KeyguardManager
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.util.kotlin.getOrNull
 import com.android.wm.shell.bubbles.Bubbles
 import java.util.Optional
 import javax.inject.Inject
@@ -30,6 +32,7 @@
     private val noteTaskController: NoteTaskController,
     private val commandQueue: CommandQueue,
     @NoteTaskEnabledKey private val isEnabled: Boolean,
+    private val optionalKeyguardManager: Optional<KeyguardManager>,
 ) {
 
     @VisibleForTesting
@@ -37,11 +40,21 @@
         object : CommandQueue.Callbacks {
             override fun handleSystemKey(keyCode: Int) {
                 if (keyCode == NoteTaskController.NOTE_TASK_KEY_EVENT) {
-                    noteTaskController.showNoteTask()
+                    showNoteTask()
                 }
             }
         }
 
+    private fun showNoteTask() {
+        val uiEvent =
+            if (optionalKeyguardManager.isKeyguardLocked) {
+                NoteTaskController.ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+            } else {
+                NoteTaskController.ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+            }
+        noteTaskController.showNoteTask(uiEvent = uiEvent)
+    }
+
     fun initialize() {
         if (isEnabled && optionalBubbles.isPresent) {
             commandQueue.addCallback(callbacks)
@@ -49,3 +62,7 @@
         noteTaskController.setNoteTaskShortcutEnabled(isEnabled)
     }
 }
+
+private val Optional<KeyguardManager>.isKeyguardLocked: Boolean
+    // If there's no KeyguardManager, assume that the keyguard is not locked.
+    get() = getOrNull()?.isKeyguardLocked ?: false
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
deleted file mode 100644
index 11dc1d7..0000000
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.notetask
-
-import android.app.role.RoleManager
-import android.content.Context
-import android.content.Intent
-import javax.inject.Inject
-
-internal class NoteTaskIntentResolver
-@Inject
-constructor(
-    private val context: Context,
-    private val roleManager: RoleManager,
-) {
-
-    fun resolveIntent(): Intent? {
-        val packageName = roleManager.getRoleHoldersAsUser(ROLE_NOTES, context.user).firstOrNull()
-
-        if (packageName.isNullOrEmpty()) return null
-
-        return Intent(ACTION_CREATE_NOTE)
-            .setPackage(packageName)
-            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-            // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint was
-            // used to start it.
-            .putExtra(INTENT_EXTRA_USE_STYLUS_MODE, true)
-    }
-
-    companion object {
-        // TODO(b/265912743): Use Intent.ACTION_CREATE_NOTE instead.
-        const val ACTION_CREATE_NOTE = "android.intent.action.CREATE_NOTE"
-
-        // TODO(b/265912743): Use RoleManager.NOTES_ROLE instead.
-        const val ROLE_NOTES = "android.app.role.NOTES"
-
-        // TODO(b/265912743): Use Intent.INTENT_EXTRA_USE_STYLUS_MODE instead.
-        const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index ec6a16a..b8800a2 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -51,7 +51,7 @@
             featureFlags: FeatureFlags,
             roleManager: RoleManager,
         ): Boolean {
-            val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskIntentResolver.ROLE_NOTES)
+            val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskInfoResolver.ROLE_NOTES)
             val isFeatureEnabled = featureFlags.isEnabled(Flags.NOTE_TASKS)
             return isRoleAvailable && isFeatureEnabled
         }
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 cfbaa48..43869cc 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.PickerScreenState
 import com.android.systemui.notetask.NoteTaskController
+import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
 import com.android.systemui.notetask.NoteTaskEnabledKey
 import javax.inject.Inject
 import kotlinx.coroutines.flow.flowOf
@@ -64,7 +65,9 @@
         }
 
     override fun onTriggered(expandable: Expandable?): OnTriggeredResult {
-        noteTaskController.showNoteTask()
+        noteTaskController.showNoteTask(
+            uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+        )
         return OnTriggeredResult.Handled
     }
 }
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 f203e7a..3ac5bfa 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
@@ -21,7 +21,7 @@
 import android.os.Bundle
 import androidx.activity.ComponentActivity
 import com.android.systemui.notetask.NoteTaskController
-import com.android.systemui.notetask.NoteTaskIntentResolver
+import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
 import javax.inject.Inject
 
 /** Activity responsible for launching the note experience, and finish. */
@@ -34,7 +34,10 @@
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
-        noteTaskController.showNoteTask(isInMultiWindowMode)
+        noteTaskController.showNoteTask(
+            isInMultiWindowMode = isInMultiWindowMode,
+            uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT,
+        )
 
         finish()
     }
@@ -46,7 +49,7 @@
             return Intent(context, LaunchNoteTaskActivity::class.java).apply {
                 // Intent's action must be set in shortcuts, or an exception will be thrown.
                 // TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead.
-                action = NoteTaskIntentResolver.ACTION_CREATE_NOTE
+                action = NoteTaskController.ACTION_CREATE_NOTE
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 8d8903d..2522e1c 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -75,6 +75,8 @@
 import com.android.systemui.util.settings.GlobalSettings;
 import com.android.systemui.volume.Events;
 
+import dagger.Lazy;
+
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.text.NumberFormat;
@@ -83,8 +85,6 @@
 
 import javax.inject.Inject;
 
-import dagger.Lazy;
-
 /**
  */
 @SysUISingleton
@@ -132,7 +132,6 @@
     private static final String ACTION_AUTO_SAVER_NO_THANKS =
             "PNW.autoSaverNoThanks";
 
-    private static final String ACTION_ENABLE_SEVERE_BATTERY_DIALOG = "PNW.enableSevereDialog";
     private static final String EXTRA_SCHEDULED_BY_PERCENTAGE =
             "extra_scheduled_by_percentage";
     public static final String BATTERY_SAVER_SCHEDULE_SCREEN_INTENT_ACTION =
@@ -155,7 +154,6 @@
     private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
     private final Intent mOpenBatterySaverSettings =
             settings(Settings.ACTION_BATTERY_SAVER_SETTINGS);
-    private final boolean mUseSevereDialog;
 
     private int mBatteryLevel;
     private int mBucket;
@@ -177,7 +175,6 @@
     private ActivityStarter mActivityStarter;
     private final BroadcastSender mBroadcastSender;
     private final UiEventLogger mUiEventLogger;
-    private GlobalSettings mGlobalSettings;
     private final UserTracker mUserTracker;
     private final Lazy<BatteryController> mBatteryControllerLazy;
     private final DialogLaunchAnimator mDialogLaunchAnimator;
@@ -198,9 +195,7 @@
         mBroadcastSender = broadcastSender;
         mBatteryControllerLazy = batteryControllerLazy;
         mDialogLaunchAnimator = dialogLaunchAnimator;
-        mUseSevereDialog = mContext.getResources().getBoolean(R.bool.config_severe_battery_dialog);
         mUiEventLogger = uiEventLogger;
-        mGlobalSettings = globalSettings;
         mUserTracker = userTracker;
     }
 
@@ -287,20 +282,6 @@
     }
 
     protected void showWarningNotification() {
-        if (mGlobalSettings.getInt(Global.LOW_POWER_MODE_REMINDER_ENABLED, 1) == 0) {
-            return;
-        }
-        if (showSevereLowBatteryDialog()) {
-            mBroadcastSender.sendBroadcast(new Intent(ACTION_ENABLE_SEVERE_BATTERY_DIALOG)
-                    .setPackage(mContext.getPackageName())
-                    .putExtra(EXTRA_SCHEDULED_BY_PERCENTAGE, isScheduledByPercentage())
-                    .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
-                            | Intent.FLAG_RECEIVER_FOREGROUND));
-            // Reset the state once dialog been enabled
-            dismissLowBatteryNotification();
-            mPlaySound = false;
-            return;
-        }
         if (isScheduledByPercentage()) {
             return;
         }
@@ -349,10 +330,6 @@
         mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, n, UserHandle.ALL);
     }
 
-    private boolean showSevereLowBatteryDialog() {
-        return mBucket < -1 && mUseSevereDialog;
-    }
-
     /**
      * Checking battery saver schedule mode is set as "Based on percentage" or not.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java b/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
new file mode 100644
index 0000000..7db293d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
@@ -0,0 +1,27 @@
+/*
+ * 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.process;
+
+/**
+ * A simple wrapper that provides access to process-related details. This facilitates testing by
+ * providing a mockable target around these details.
+ */
+public class ProcessWrapper {
+    public int getUserHandleIdentifier() {
+        return android.os.Process.myUserHandle().getIdentifier();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/process/condition/UserProcessCondition.java b/packages/SystemUI/src/com/android/systemui/process/condition/UserProcessCondition.java
new file mode 100644
index 0000000..5a21ea0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/process/condition/UserProcessCondition.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.process.condition;
+
+import com.android.systemui.process.ProcessWrapper;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shared.condition.Condition;
+
+import javax.inject.Inject;
+
+/**
+ * {@link UserProcessCondition} provides a signal when the process handle belongs to the current
+ * user.
+ */
+public class UserProcessCondition extends Condition {
+    private final ProcessWrapper mProcessWrapper;
+    private final UserTracker mUserTracker;
+
+    @Inject
+    public UserProcessCondition(ProcessWrapper processWrapper, UserTracker userTracker) {
+        mProcessWrapper = processWrapper;
+        mUserTracker = userTracker;
+    }
+
+    @Override
+    protected void start() {
+        updateCondition(mUserTracker.getUserId()
+                == mProcessWrapper.getUserHandleIdentifier());
+    }
+
+    @Override
+    protected void stop() {
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
index 464b6e7..048d40c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
@@ -48,6 +48,7 @@
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_FOOTER_DOT
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS
@@ -158,6 +159,7 @@
         private const val DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT = false
         private const val DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS = true
         private const val DEFAULT_TASK_MANAGER_SHOW_USER_VISIBLE_JOBS = true
+        private const val DEFAULT_TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP = true
     }
 
     override var newChangesSinceDialogWasDismissed = false
@@ -173,6 +175,9 @@
 
     private var showUserVisibleJobs = DEFAULT_TASK_MANAGER_SHOW_USER_VISIBLE_JOBS
 
+    private var informJobSchedulerOfPendingAppStop =
+        DEFAULT_TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP
+
     override val includesUserVisibleJobs: Boolean
         get() = showUserVisibleJobs
 
@@ -233,6 +238,11 @@
                 NAMESPACE_SYSTEMUI,
                 TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, DEFAULT_TASK_MANAGER_SHOW_USER_VISIBLE_JOBS)
 
+            informJobSchedulerOfPendingAppStop = deviceConfigProxy.getBoolean(
+                NAMESPACE_SYSTEMUI,
+                TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP,
+                DEFAULT_TASK_MANAGER_INFORM_JOB_SCHEDULER_OF_PENDING_APP_STOP)
+
             try {
                 activityManager.registerForegroundServiceObserver(foregroundServiceObserver)
                 // Clumping FGS and user-visible jobs here and showing a single entry and button
@@ -262,10 +272,13 @@
                     showStopBtnForUserAllowlistedApps)
                 var wasShowingUserVisibleJobs = showUserVisibleJobs
                 showUserVisibleJobs = it.getBoolean(
-                        TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, showUserVisibleJobs)
+                    TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, showUserVisibleJobs)
                 if (showUserVisibleJobs != wasShowingUserVisibleJobs) {
                     onShowUserVisibleJobsFlagChanged()
                 }
+                informJobSchedulerOfPendingAppStop = it.getBoolean(
+                    TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
+                    informJobSchedulerOfPendingAppStop)
             }
 
             _isAvailable.value = deviceConfigProxy.getBoolean(
@@ -475,14 +488,11 @@
     private fun stopPackage(userId: Int, packageName: String, timeStarted: Long) {
         logEvent(stopped = true, packageName, userId, timeStarted)
         val userPackageKey = UserPackage(userId, packageName)
-        if (showUserVisibleJobs &&
-                runningTaskIdentifiers[userPackageKey]?.hasRunningJobs() == true) {
+        if (showUserVisibleJobs || informJobSchedulerOfPendingAppStop) {
             // TODO(255768978): allow fine-grained job control
-            jobScheduler.stopUserVisibleJobsForUser(packageName, userId)
+            jobScheduler.notePendingUserRequestedAppStop(packageName, userId, "task manager")
         }
-        if (runningTaskIdentifiers[userPackageKey]?.hasFgs() == true) {
-            activityManager.stopAppForUser(packageName, userId)
-        }
+        activityManager.stopAppForUser(packageName, userId)
     }
 
     private fun onShowUserVisibleJobsFlagChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
index 5bc209a..7316f46 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java
@@ -203,8 +203,7 @@
         // For now, restrict to debug users.
         return Build.isDebuggable()
                 && mDreamSupported
-                // TODO(b/257333623): Allow the Dock User to be non-SystemUser user in HSUM.
-                && (!mDreamOnlyEnabledForDockUser || mUserTracker.getUserHandle().isSystem());
+                && (!mDreamOnlyEnabledForDockUser || mUserTracker.getUserInfo().isMain());
     }
 
     @VisibleForTesting
@@ -224,7 +223,8 @@
 
     private ComponentName getActiveDream() {
         try {
-            final ComponentName[] dreams = mDreamManager.getDreamComponents();
+            final ComponentName[] dreams = mDreamManager.getDreamComponentsForUser(
+                                                mUserTracker.getUserId());
             return dreams != null && dreams.length > 0 ? dreams[0] : null;
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to get active dream", e);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 28dd986..d423048 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -259,17 +259,19 @@
                 Log.d(TAG, "setWifiIndicators: " + indicators);
             }
             mWifiInfo.mEnabled = indicators.enabled;
-            if (indicators.qsIcon == null) {
-                return;
-            }
-            mWifiInfo.mConnected = indicators.qsIcon.visible;
-            mWifiInfo.mWifiSignalIconId = indicators.qsIcon.icon;
-            mWifiInfo.mWifiSignalContentDescription = indicators.qsIcon.contentDescription;
-            mWifiInfo.mEnabled = indicators.enabled;
             mWifiInfo.mSsid = indicators.description;
             mWifiInfo.mIsTransient = indicators.isTransient;
             mWifiInfo.mStatusLabel = indicators.statusLabel;
-            refreshState(mWifiInfo);
+            if (indicators.qsIcon != null) {
+                mWifiInfo.mConnected = indicators.qsIcon.visible;
+                mWifiInfo.mWifiSignalIconId = indicators.qsIcon.icon;
+                mWifiInfo.mWifiSignalContentDescription = indicators.qsIcon.contentDescription;
+                refreshState(mWifiInfo);
+            } else {
+                mWifiInfo.mConnected = false;
+                mWifiInfo.mWifiSignalIconId = 0;
+                mWifiInfo.mWifiSignalContentDescription = null;
+            }
         }
 
         @Override
@@ -533,6 +535,9 @@
         if (DEBUG) {
             Log.d(TAG, "handleUpdateEthernetState: " + "EthernetCallbackInfo = " + cb.toString());
         }
+        if (!cb.mConnected) {
+            return;
+        }
         final Resources r = mContext.getResources();
         state.label = r.getString(R.string.quick_settings_internet_label);
         state.state = Tile.STATE_ACTIVE;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
index 64a8a14..ad00069 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -171,8 +171,9 @@
             getHost().collapsePanels();
         };
 
-        Dialog dialog = mController.createScreenRecordDialog(mContext, mFlags,
+        final Dialog dialog = mController.createScreenRecordDialog(mContext, mFlags,
                 mDialogLaunchAnimator, mActivityStarter, onStartRecordingClicked);
+
         ActivityStarter.OnDismissAction dismissAction = () -> {
             if (shouldAnimateFromView) {
                 mDialogLaunchAnimator.showFromView(dialog, view, new DialogCuj(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 206a620..039dafb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -800,6 +800,11 @@
     }
 
     @Override
+    public void onCarrierNetworkChange(boolean active) {
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+    }
+
+    @Override
     @WorkerThread
     public void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries,
             @Nullable WifiEntry connectedEntry, boolean hasMoreWifiEntries) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 534155c..f7e7366 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -206,6 +206,8 @@
     protected boolean mHasEthernet = false;
     @VisibleForTesting
     protected ConnectedWifiInternetMonitor mConnectedWifiInternetMonitor;
+    @VisibleForTesting
+    protected boolean mCarrierNetworkChangeMode;
 
     private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -507,10 +509,13 @@
     Drawable getSignalStrengthIcon(int subId, Context context, int level, int numLevels,
             int iconType, boolean cutOut) {
         boolean isForDds = subId == mDefaultDataSubId;
+        int levelDrawable =
+                mCarrierNetworkChangeMode ? SignalDrawable.getCarrierChangeState(numLevels)
+                        : SignalDrawable.getState(level, numLevels, cutOut);
         if (isForDds) {
-            mSignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut));
+            mSignalDrawable.setLevel(levelDrawable);
         } else {
-            mSecondarySignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut));
+            mSecondarySignalDrawable.setLevel(levelDrawable);
         }
 
         // Make the network type drawable
@@ -672,10 +677,13 @@
         }
 
         int resId = Objects.requireNonNull(mapIconSets(config).get(iconKey)).dataContentDescription;
+        SignalIcon.MobileIconGroup iconGroup;
         if (isCarrierNetworkActive()) {
-            SignalIcon.MobileIconGroup carrierMergedWifiIconGroup =
-                    TelephonyIcons.CARRIER_MERGED_WIFI;
-            resId = carrierMergedWifiIconGroup.dataContentDescription;
+            iconGroup = TelephonyIcons.CARRIER_MERGED_WIFI;
+            resId = iconGroup.dataContentDescription;
+        } else if (mCarrierNetworkChangeMode) {
+            iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
+            resId = iconGroup.dataContentDescription;
         }
 
         return resId != 0
@@ -1094,7 +1102,8 @@
             TelephonyCallback.DisplayInfoListener,
             TelephonyCallback.ServiceStateListener,
             TelephonyCallback.SignalStrengthsListener,
-            TelephonyCallback.UserMobileDataStateListener {
+            TelephonyCallback.UserMobileDataStateListener,
+            TelephonyCallback.CarrierNetworkListener{
 
         private final int mSubId;
         private InternetTelephonyCallback(int subId) {
@@ -1126,6 +1135,12 @@
         public void onUserMobileDataStateChanged(boolean enabled) {
             mCallback.onUserMobileDataStateChanged(enabled);
         }
+
+        @Override
+        public void onCarrierNetworkChange(boolean active) {
+            mCarrierNetworkChangeMode = active;
+            mCallback.onCarrierNetworkChange(active);
+        }
     }
 
     private class InternetOnSubscriptionChangedListener
@@ -1295,6 +1310,8 @@
 
         void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo);
 
+        void onCarrierNetworkChange(boolean active);
+
         void dismissDialog();
 
         void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries,
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
index 431b28f..acb6d96 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
@@ -38,6 +38,8 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver;
+import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.settings.UserContextProvider;
 import com.android.systemui.settings.UserTracker;
@@ -48,6 +50,8 @@
 
 import javax.inject.Inject;
 
+import dagger.Lazy;
+
 /**
  * Helper class to initiate a screen recording
  */
@@ -63,6 +67,8 @@
     private CountDownTimer mCountDownTimer = null;
     private final Executor mMainExecutor;
     private final BroadcastDispatcher mBroadcastDispatcher;
+    private final Context mContext;
+    private final FeatureFlags mFlags;
     private final UserContextProvider mUserContextProvider;
     private final UserTracker mUserTracker;
 
@@ -73,6 +79,8 @@
     private CopyOnWriteArrayList<RecordingStateChangeCallback> mListeners =
             new CopyOnWriteArrayList<>();
 
+    private final Lazy<ScreenCaptureDevicePolicyResolver> mDevicePolicyResolver;
+
     @VisibleForTesting
     final UserTracker.Callback mUserChangedCallback =
             new UserTracker.Callback() {
@@ -103,9 +111,15 @@
     @Inject
     public RecordingController(@Main Executor mainExecutor,
             BroadcastDispatcher broadcastDispatcher,
+            Context context,
+            FeatureFlags flags,
             UserContextProvider userContextProvider,
+            Lazy<ScreenCaptureDevicePolicyResolver> devicePolicyResolver,
             UserTracker userTracker) {
         mMainExecutor = mainExecutor;
+        mContext = context;
+        mFlags = flags;
+        mDevicePolicyResolver = devicePolicyResolver;
         mBroadcastDispatcher = broadcastDispatcher;
         mUserContextProvider = userContextProvider;
         mUserTracker = userTracker;
@@ -115,14 +129,30 @@
         mInteractiveBroadcastOption = options.toBundle();
     }
 
-    /** Create a dialog to show screen recording options to the user. */
+    /**
+     * MediaProjection host is SystemUI for the screen recorder, so return 'my user handle'
+     */
+    private UserHandle getHostUserHandle() {
+        return UserHandle.of(UserHandle.myUserId());
+    }
+
+    /** Create a dialog to show screen recording options to the user.
+     *  If screen capturing is currently not allowed it will return a dialog
+     *  that warns users about it. */
     public Dialog createScreenRecordDialog(Context context, FeatureFlags flags,
                                            DialogLaunchAnimator dialogLaunchAnimator,
                                            ActivityStarter activityStarter,
                                            @Nullable Runnable onStartRecordingClicked) {
+        if (mFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)
+                && mDevicePolicyResolver.get()
+                        .isScreenCaptureCompletelyDisabled(getHostUserHandle())) {
+            return new ScreenCaptureDisabledDialog(mContext);
+        }
+
         return flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)
-                ? new ScreenRecordPermissionDialog(context, this, activityStarter,
-                        dialogLaunchAnimator, mUserContextProvider, onStartRecordingClicked)
+                ? new ScreenRecordPermissionDialog(context,  getHostUserHandle(), this,
+                    activityStarter, dialogLaunchAnimator, mUserContextProvider,
+                    onStartRecordingClicked)
                 : new ScreenRecordDialog(context, this, activityStarter,
                 mUserContextProvider, flags, dialogLaunchAnimator, onStartRecordingClicked);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index 68e3dcd..dd21be9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -42,6 +42,7 @@
 /** Dialog to select screen recording options */
 class ScreenRecordPermissionDialog(
     context: Context?,
+    private val hostUserHandle: UserHandle,
     private val controller: RecordingController,
     private val activityStarter: ActivityStarter,
     private val dialogLaunchAnimator: DialogLaunchAnimator,
@@ -79,11 +80,9 @@
                     CaptureTargetResultReceiver()
                 )
 
-                // Send SystemUI's user handle as the host app user handle because SystemUI
-                // is the 'host app' (the app that receives screen capture data)
                 intent.putExtra(
                     MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
-                    UserHandle.of(UserHandle.myUserId())
+                    hostUserHandle
                 )
 
                 val animationController = dialogLaunchAnimator.createActivityLaunchController(v!!)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt
index 1e531ba..ad66514 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt
@@ -3,101 +3,133 @@
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
 import android.animation.ValueAnimator
-import android.graphics.drawable.Drawable
+import android.os.UserHandle
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewGroup.MarginLayoutParams
 import android.view.ViewTreeObserver
 import android.view.animation.AccelerateDecelerateInterpolator
-import android.widget.ImageView
-import android.widget.TextView
 import androidx.constraintlayout.widget.Guideline
 import com.android.systemui.R
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import javax.inject.Inject
 
 /**
  * MessageContainerController controls the display of content in the screenshot message container.
  */
 class MessageContainerController
+@Inject
 constructor(
-    parent: ViewGroup,
+    private val workProfileMessageController: WorkProfileMessageController,
+    private val screenshotDetectionController: ScreenshotDetectionController,
+    private val featureFlags: FeatureFlags,
 ) {
-    private val guideline: Guideline = parent.requireViewById(R.id.guideline)
-    private val messageContainer: ViewGroup =
-        parent.requireViewById(R.id.screenshot_message_container)
+    private lateinit var container: ViewGroup
+    private lateinit var guideline: Guideline
+    private lateinit var workProfileFirstRunView: ViewGroup
+    private lateinit var detectionNoticeView: ViewGroup
+    private var animateOut: Animator? = null
 
-    /**
-     * Show a notification under the screenshot view indicating that a work profile screenshot has
-     * been taken and which app can be used to view it.
-     *
-     * @param appName The name of the app to use to view screenshots
-     * @param appIcon Optional icon for the relevant files app
-     * @param onDismiss Runnable to be run when the user dismisses this message
-     */
-    fun showWorkProfileMessage(appName: CharSequence, appIcon: Drawable?, onDismiss: Runnable) {
-        // Eventually this container will support multiple notification types, but for now just make
-        // sure we don't double inflate.
-        if (messageContainer.childCount == 0) {
-            View.inflate(
-                messageContainer.context,
-                R.layout.screenshot_work_profile_first_run,
-                messageContainer
-            )
+    fun setView(screenshotView: ViewGroup) {
+        container = screenshotView.requireViewById(R.id.screenshot_message_container)
+        guideline = screenshotView.requireViewById(R.id.guideline)
+
+        workProfileFirstRunView = container.requireViewById(R.id.work_profile_first_run)
+        detectionNoticeView = container.requireViewById(R.id.screenshot_detection_notice)
+
+        // Restore to starting state.
+        container.visibility = View.GONE
+        guideline.setGuidelineEnd(0)
+        workProfileFirstRunView.visibility = View.GONE
+        detectionNoticeView.visibility = View.GONE
+    }
+
+    // Minimal implementation for use when Flags.SCREENSHOT_METADATA isn't turned on.
+    fun onScreenshotTaken(userHandle: UserHandle) {
+        if (featureFlags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY)) {
+            val workProfileData = workProfileMessageController.onScreenshotTaken(userHandle)
+            if (workProfileData != null) {
+                workProfileFirstRunView.visibility = View.VISIBLE
+                detectionNoticeView.visibility = View.GONE
+
+                workProfileMessageController.populateView(
+                    workProfileFirstRunView,
+                    workProfileData,
+                    this::animateOutMessageContainer
+                )
+                animateInMessageContainer()
+            }
         }
-        if (appIcon != null) {
-            // Replace the default icon if one is provided.
-            val imageView: ImageView =
-                messageContainer.requireViewById<ImageView>(R.id.screenshot_message_icon)
-            imageView.setImageDrawable(appIcon)
+    }
+
+    fun onScreenshotTaken(screenshot: ScreenshotData) {
+        if (featureFlags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY)) {
+            val workProfileData =
+                workProfileMessageController.onScreenshotTaken(screenshot.userHandle)
+            var notifiedApps: List<CharSequence> = listOf()
+            if (featureFlags.isEnabled(Flags.SCREENSHOT_DETECTION)) {
+                notifiedApps = screenshotDetectionController.maybeNotifyOfScreenshot(screenshot)
+            }
+
+            // If work profile first run needs to show, bias towards that, otherwise show screenshot
+            // detection notification if needed.
+            if (workProfileData != null) {
+                workProfileFirstRunView.visibility = View.VISIBLE
+                detectionNoticeView.visibility = View.GONE
+                workProfileMessageController.populateView(
+                    workProfileFirstRunView,
+                    workProfileData,
+                    this::animateOutMessageContainer
+                )
+                animateInMessageContainer()
+            } else if (notifiedApps.isNotEmpty()) {
+                detectionNoticeView.visibility = View.VISIBLE
+                workProfileFirstRunView.visibility = View.GONE
+                screenshotDetectionController.populateView(detectionNoticeView, notifiedApps)
+                animateInMessageContainer()
+            }
         }
-        val messageContent =
-            messageContainer.requireViewById<TextView>(R.id.screenshot_message_content)
-        messageContent.text =
-            messageContainer.context.getString(
-                R.string.screenshot_work_profile_notification,
-                appName
-            )
-        messageContainer.requireViewById<View>(R.id.message_dismiss_button).setOnClickListener {
-            animateOutMessageContainer()
-            onDismiss.run()
-        }
+    }
+
+    private fun animateInMessageContainer() {
+        if (container.visibility == View.VISIBLE) return
 
         // Need the container to be fully measured before animating in (to know animation offset
         // destination)
-        messageContainer.viewTreeObserver.addOnPreDrawListener(
+        container.visibility = View.VISIBLE
+        container.viewTreeObserver.addOnPreDrawListener(
             object : ViewTreeObserver.OnPreDrawListener {
                 override fun onPreDraw(): Boolean {
-                    messageContainer.viewTreeObserver.removeOnPreDrawListener(this)
-                    animateInMessageContainer()
+                    container.viewTreeObserver.removeOnPreDrawListener(this)
+                    getAnimator(true).start()
                     return false
                 }
             }
         )
     }
 
-    private fun animateInMessageContainer() {
-        if (messageContainer.visibility == View.VISIBLE) return
-
-        messageContainer.visibility = View.VISIBLE
-        getAnimator(true).start()
-    }
-
     private fun animateOutMessageContainer() {
-        getAnimator(false).apply {
-            addListener(
-                object : AnimatorListenerAdapter() {
-                    override fun onAnimationEnd(animation: Animator) {
-                        super.onAnimationEnd(animation)
-                        messageContainer.visibility = View.INVISIBLE
+        if (animateOut != null) return
+
+        animateOut =
+            getAnimator(false).apply {
+                addListener(
+                    object : AnimatorListenerAdapter() {
+                        override fun onAnimationEnd(animation: Animator) {
+                            super.onAnimationEnd(animation)
+                            container.visibility = View.GONE
+                            animateOut = null
+                        }
                     }
-                }
-            )
-            start()
-        }
+                )
+                start()
+            }
     }
 
     private fun getAnimator(animateIn: Boolean): Animator {
-        val params = messageContainer.layoutParams as MarginLayoutParams
-        val offset = messageContainer.height + params.topMargin + params.bottomMargin
+        val params = container.layoutParams as MarginLayoutParams
+        val offset = container.height + params.topMargin + params.bottomMargin
         val anim = if (animateIn) ValueAnimator.ofFloat(0f, 1f) else ValueAnimator.ofFloat(1f, 0f)
         with(anim) {
             duration = ScreenshotView.SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS
@@ -105,7 +137,7 @@
             addUpdateListener { valueAnimator: ValueAnimator ->
                 val interpolation = valueAnimator.animatedValue as Float
                 guideline.setGuidelineEnd((interpolation * offset).toInt())
-                messageContainer.alpha = interpolation
+                container.alpha = interpolation
             }
         }
         return anim
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index ab13962..72a8e23 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -282,7 +282,6 @@
     private final TimeoutHandler mScreenshotHandler;
     private final ActionIntentExecutor mActionExecutor;
     private final UserManager mUserManager;
-    private final WorkProfileMessageController mWorkProfileMessageController;
     private final AssistContentRequester mAssistContentRequester;
 
     private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
@@ -293,7 +292,7 @@
     };
 
     private ScreenshotView mScreenshotView;
-    private MessageContainerController mMessageContainerController;
+    private final MessageContainerController mMessageContainerController;
     private Bitmap mScreenBitmap;
     private SaveImageInBackgroundTask mSaveInBgTask;
     private boolean mScreenshotTakenInPortrait;
@@ -332,8 +331,8 @@
             ScreenshotNotificationSmartActionsProvider screenshotNotificationSmartActionsProvider,
             ActionIntentExecutor actionExecutor,
             UserManager userManager,
-            WorkProfileMessageController workProfileMessageController,
             AssistContentRequester assistContentRequester,
+            MessageContainerController messageContainerController,
             DisplayTracker displayTracker
     ) {
         mScreenshotSmartActions = screenshotSmartActions;
@@ -367,7 +366,7 @@
         mFlags = flags;
         mActionExecutor = actionExecutor;
         mUserManager = userManager;
-        mWorkProfileMessageController = workProfileMessageController;
+        mMessageContainerController = messageContainerController;
         mAssistContentRequester = assistContentRequester;
 
         mAccessibilityManager = AccessibilityManager.getInstance(mContext);
@@ -468,7 +467,11 @@
             }
         }
 
-        prepareAnimation(screenshot.getScreenBounds(), showFlash);
+        prepareAnimation(screenshot.getScreenBounds(), showFlash, () -> {
+            if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
+                mMessageContainerController.onScreenshotTaken(screenshot);
+            }
+        });
 
         if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
             mScreenshotView.badgeScreenshot(mContext.getPackageManager().getUserBadgedIcon(
@@ -632,7 +635,9 @@
         // Inflate the screenshot layout
         mScreenshotView = (ScreenshotView)
                 LayoutInflater.from(mContext).inflate(R.layout.screenshot, null);
-        mMessageContainerController = new MessageContainerController(mScreenshotView);
+        if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
+            mMessageContainerController.setView(mScreenshotView);
+        }
         mScreenshotView.addOnAttachStateChangeListener(
                 new View.OnAttachStateChangeListener() {
                     @Override
@@ -782,7 +787,11 @@
         enqueueScrollCaptureRequest(owner);
 
         attachWindow();
-        prepareAnimation(screenRect, showFlash);
+        prepareAnimation(screenRect, showFlash, () -> {
+            if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
+                mMessageContainerController.onScreenshotTaken(owner);
+            }
+        });
 
         if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
             mScreenshotView.badgeScreenshot(mContext.getPackageManager().getUserBadgedIcon(
@@ -799,7 +808,8 @@
         mScreenshotHandler.cancelTimeout(); // restarted after animation
     }
 
-    private void prepareAnimation(Rect screenRect, boolean showFlash) {
+    private void prepareAnimation(Rect screenRect, boolean showFlash,
+            Runnable onAnimationComplete) {
         mScreenshotView.getViewTreeObserver().addOnPreDrawListener(
                 new ViewTreeObserver.OnPreDrawListener() {
                     @Override
@@ -808,7 +818,7 @@
                             Log.d(TAG, "onPreDraw: startAnimation");
                         }
                         mScreenshotView.getViewTreeObserver().removeOnPreDrawListener(this);
-                        startAnimation(screenRect, showFlash);
+                        startAnimation(screenRect, showFlash, onAnimationComplete);
                         return true;
                     }
                 });
@@ -1089,13 +1099,22 @@
     /**
      * Starts the animation after taking the screenshot
      */
-    private void startAnimation(Rect screenRect, boolean showFlash) {
+    private void startAnimation(Rect screenRect, boolean showFlash, Runnable onAnimationComplete) {
         if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
             mScreenshotAnimation.cancel();
         }
 
         mScreenshotAnimation =
                 mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash);
+        if (onAnimationComplete != null) {
+            mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    super.onAnimationEnd(animation);
+                    onAnimationComplete.run();
+                }
+            });
+        }
 
         // Play the shutter sound to notify that we've taken a screenshot
         playCameraSound();
@@ -1194,10 +1213,6 @@
 
     private void doPostAnimation(ScreenshotController.SavedImageData imageData) {
         mScreenshotView.setChipIntents(imageData);
-        if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
-            mWorkProfileMessageController.onScreenshotTaken(imageData.owner,
-                    mMessageContainerController);
-        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
index c43e4b4..e9be88a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt
@@ -8,6 +8,7 @@
 import android.os.UserHandle
 import android.view.WindowManager.ScreenshotSource
 import android.view.WindowManager.ScreenshotType
+import androidx.annotation.VisibleForTesting
 import com.android.internal.util.ScreenshotRequest
 
 /** ScreenshotData represents the current state of a single screenshot being acquired. */
@@ -42,5 +43,10 @@
                 request.bitmap,
             )
         }
+
+        @VisibleForTesting
+        fun forTesting(): ScreenshotData {
+            return ScreenshotData(0, 0, null, null, null, 0, Insets.NONE, null)
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotDetectionController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotDetectionController.kt
new file mode 100644
index 0000000..48aa60f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotDetectionController.kt
@@ -0,0 +1,68 @@
+/*
+ * 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.content.pm.PackageManager
+import android.view.Display
+import android.view.IWindowManager
+import android.view.ViewGroup
+import android.view.WindowManager
+import android.widget.TextView
+import com.android.systemui.R
+import javax.inject.Inject
+
+class ScreenshotDetectionController
+@Inject
+constructor(
+    private val windowManager: IWindowManager,
+    private val packageManager: PackageManager,
+) {
+    /**
+     * Notify potentially listening apps of the screenshot. Return a list of the names of the apps
+     * notified.
+     */
+    fun maybeNotifyOfScreenshot(data: ScreenshotData): List<CharSequence> {
+        // No notification for screenshots from overview.
+        if (data.source == WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW) return listOf()
+
+        // Notify listeners, retrieve a list of listening components.
+        val components = windowManager.notifyScreenshotListeners(Display.DEFAULT_DISPLAY)
+
+        // Convert component names to app names.
+        return components.map {
+            packageManager
+                .getActivityInfo(it, PackageManager.ComponentInfoFlags.of(0))
+                .loadLabel(packageManager)
+        }
+    }
+
+    fun populateView(view: ViewGroup, appNames: List<CharSequence>) {
+        assert(appNames.isNotEmpty())
+
+        val textView: TextView = view.requireViewById(R.id.screenshot_detection_notice_text)
+        if (appNames.size == 1) {
+            textView.text =
+                view.resources.getString(R.string.screenshot_detected_template, appNames[0])
+        } else {
+            textView.text =
+                view.resources.getString(
+                    R.string.screenshot_detected_multiple_template,
+                    appNames[0]
+                )
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index c891686..7a62bae 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -46,6 +46,8 @@
     SCREENSHOT_SAVED(306),
     @UiEvent(doc = "screenshot failed to save")
     SCREENSHOT_NOT_SAVED(336),
+    @UiEvent(doc = "failed to capture screenshot")
+    SCREENSHOT_CAPTURE_FAILED(1281),
     @UiEvent(doc = "screenshot preview tapped")
     SCREENSHOT_PREVIEW_TAPPED(307),
     @UiEvent(doc = "screenshot edit button tapped")
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 4214c8f..8035d19 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -26,6 +26,7 @@
 import static com.android.systemui.screenshot.LogConfig.DEBUG_DISMISS;
 import static com.android.systemui.screenshot.LogConfig.DEBUG_SERVICE;
 import static com.android.systemui.screenshot.LogConfig.logTag;
+import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_CAPTURE_FAILED;
 import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_DISMISSED_OTHER;
 
 import android.annotation.MainThread;
@@ -202,6 +203,7 @@
         // animation and error notification.
         if (!mUserManager.isUserUnlocked()) {
             Log.w(TAG, "Skipping screenshot because storage is locked!");
+            logFailedRequest(request);
             mNotificationsController.notifyScreenshotError(
                     R.string.screenshot_failed_to_save_user_locked_text);
             callback.reportError();
@@ -212,6 +214,7 @@
             mBgExecutor.execute(() -> {
                 Log.w(TAG, "Skipping screenshot because an IT admin has disabled "
                         + "screenshots on the device");
+                logFailedRequest(request);
                 String blockedByAdminText = mDevicePolicyManager.getResources().getString(
                         SCREENSHOT_BLOCKED_BY_ADMIN,
                         () -> mContext.getString(R.string.screenshot_blocked_by_admin));
@@ -225,38 +228,43 @@
         if (mFeatureFlags.isEnabled(Flags.SCREENSHOT_METADATA)) {
             Log.d(TAG, "Processing screenshot data");
             ScreenshotData screenshotData = ScreenshotData.fromRequest(request);
-            mProcessor.processAsync(screenshotData,
-                    (data) -> dispatchToController(data, onSaved, callback));
+            try {
+                mProcessor.processAsync(screenshotData,
+                        (data) -> dispatchToController(data, onSaved, callback));
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to process screenshot request!", e);
+                logFailedRequest(request);
+                mNotificationsController.notifyScreenshotError(
+                        R.string.screenshot_failed_to_capture_text);
+                callback.reportError();
+            }
         } else {
-            mProcessor.processAsync(request,
-                    (r) -> dispatchToController(r, onSaved, callback));
+            try {
+                mProcessor.processAsync(request,
+                        (r) -> dispatchToController(r, onSaved, callback));
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to process screenshot request!", e);
+                logFailedRequest(request);
+                mNotificationsController.notifyScreenshotError(
+                        R.string.screenshot_failed_to_capture_text);
+                callback.reportError();
+            }
         }
     }
 
     private void dispatchToController(ScreenshotData screenshot,
             Consumer<Uri> uriConsumer, RequestCallback callback) {
-
         mUiEventLogger.log(ScreenshotEvent.getScreenshotSource(screenshot.getSource()), 0,
                 screenshot.getPackageNameString());
-
-        if (screenshot.getType() == WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
-                && screenshot.getBitmap() == null) {
-            Log.e(TAG, "Got null bitmap from screenshot message");
-            mNotificationsController.notifyScreenshotError(
-                    R.string.screenshot_failed_to_capture_text);
-            callback.reportError();
-            return;
-        }
-
         mScreenshot.handleScreenshot(screenshot, uriConsumer, callback);
     }
 
     private void dispatchToController(ScreenshotRequest request,
             Consumer<Uri> uriConsumer, RequestCallback callback) {
-
         ComponentName topComponent = request.getTopComponent();
-        mUiEventLogger.log(ScreenshotEvent.getScreenshotSource(request.getSource()), 0,
-                topComponent == null ? "" : topComponent.getPackageName());
+        String packageName = topComponent == null ? "" : topComponent.getPackageName();
+        mUiEventLogger.log(
+                ScreenshotEvent.getScreenshotSource(request.getSource()), 0, packageName);
 
         switch (request.getType()) {
             case WindowManager.TAKE_SCREENSHOT_FULLSCREEN:
@@ -275,21 +283,22 @@
                 int taskId = request.getTaskId();
                 int userId = request.getUserId();
 
-                if (screenshot == null) {
-                    Log.e(TAG, "Got null bitmap from screenshot message");
-                    mNotificationsController.notifyScreenshotError(
-                            R.string.screenshot_failed_to_capture_text);
-                    callback.reportError();
-                } else {
-                    mScreenshot.handleImageAsScreenshot(screenshot, screenBounds, insets,
-                            taskId, userId, topComponent, uriConsumer, callback);
-                }
+                mScreenshot.handleImageAsScreenshot(screenshot, screenBounds, insets,
+                        taskId, userId, topComponent, uriConsumer, callback);
                 break;
             default:
-                Log.w(TAG, "Invalid screenshot option: " + request.getType());
+                Log.wtf(TAG, "Invalid screenshot option: " + request.getType());
         }
     }
 
+    private void logFailedRequest(ScreenshotRequest request) {
+        ComponentName topComponent = request.getTopComponent();
+        String packageName = topComponent == null ? "" : topComponent.getPackageName();
+        mUiEventLogger.log(
+                ScreenshotEvent.getScreenshotSource(request.getSource()), 0, packageName);
+        mUiEventLogger.log(SCREENSHOT_CAPTURE_FAILED, 0, packageName);
+    }
+
     private static void sendComplete(Messenger target) {
         try {
             if (DEBUG_CALLBACK) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
index b4a07d4..1b728b8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
@@ -23,13 +23,16 @@
 import android.os.UserHandle
 import android.os.UserManager
 import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
 import com.android.systemui.R
 import javax.inject.Inject
 
 /**
- * Handles all the non-UI portions of the work profile first run:
- * - Track whether the user has already dismissed it.
- * - Load the proper icon and app name.
+ * Handles work profile first run, determining whether a first run UI should be shown and populating
+ * that UI if needed.
  */
 class WorkProfileMessageController
 @Inject
@@ -40,10 +43,12 @@
 ) {
 
     /**
-     * Determine if a message should be shown to the user, send message details to
-     * MessageContainerController if appropriate.
+     * @return a populated WorkProfileFirstRunData object if a work profile first run message should
+     * be shown
      */
-    fun onScreenshotTaken(userHandle: UserHandle, messageContainer: MessageContainerController) {
+    fun onScreenshotTaken(userHandle: UserHandle?): WorkProfileFirstRunData? {
+        if (userHandle == null) return null
+
         if (userManager.isManagedProfile(userHandle.identifier) && !messageAlreadyDismissed()) {
             var badgedIcon: Drawable? = null
             var label: CharSequence? = null
@@ -62,12 +67,27 @@
             }
 
             // If label wasn't loaded, use a default
-            val badgedLabel =
-                packageManager.getUserBadgedLabel(label ?: defaultFileAppName(), userHandle)
+            return WorkProfileFirstRunData(label ?: defaultFileAppName(), badgedIcon)
+        }
+        return null
+    }
 
-            messageContainer.showWorkProfileMessage(badgedLabel, badgedIcon) {
-                onMessageDismissed()
-            }
+    /**
+     * Use the provided WorkProfileFirstRunData to populate the work profile first run UI in the
+     * given view.
+     */
+    fun populateView(view: ViewGroup, data: WorkProfileFirstRunData, animateOut: () -> Unit) {
+        if (data.icon != null) {
+            // Replace the default icon if one is provided.
+            val imageView: ImageView = view.requireViewById<ImageView>(R.id.screenshot_message_icon)
+            imageView.setImageDrawable(data.icon)
+        }
+        val messageContent = view.requireViewById<TextView>(R.id.screenshot_message_content)
+        messageContent.text =
+            view.context.getString(R.string.screenshot_work_profile_notification, data.appName)
+        view.requireViewById<View>(R.id.message_dismiss_button).setOnClickListener {
+            animateOut()
+            onMessageDismissed()
         }
     }
 
@@ -91,6 +111,8 @@
 
     private fun defaultFileAppName() = context.getString(R.string.screenshot_default_files_app_name)
 
+    data class WorkProfileFirstRunData constructor(val appName: CharSequence, val icon: Drawable?)
+
     companion object {
         const val TAG = "WorkProfileMessageCtrl"
         const val SHARED_PREFERENCES_NAME = "com.android.systemui.screenshot"
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java
new file mode 100644
index 0000000..f8d86a0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java
@@ -0,0 +1,289 @@
+/*
+ * 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 static com.android.systemui.screenshot.AppClipsTrampolineActivity.ACTION_FINISH_FROM_TRAMPOLINE;
+import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_RESULT_RECEIVER;
+import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
+import static com.android.systemui.screenshot.AppClipsTrampolineActivity.PERMISSION_SELF;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+
+import androidx.activity.ComponentActivity;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+
+import javax.inject.Inject;
+
+/**
+ * An {@link Activity} to take a screenshot for the App Clips flow and presenting a screenshot
+ * editing tool.
+ *
+ * <p>An App Clips flow includes:
+ * <ul>
+ *     <li>Checking if calling activity meets the prerequisites. This is done by
+ *     {@link AppClipsTrampolineActivity}.
+ *     <li>Performing the screenshot.
+ *     <li>Showing a screenshot editing tool.
+ *     <li>Returning the screenshot to the {@link AppClipsTrampolineActivity} so that it can return
+ *     the screenshot to the calling activity after explicit user consent.
+ * </ul>
+ *
+ * <p>This {@link Activity} runs in its own separate process to isolate memory intensive image
+ * editing from SysUI process.
+ *
+ * TODO(b/267309532): Polish UI and animations.
+ */
+public final class AppClipsActivity extends ComponentActivity {
+
+    private final AppClipsViewModel.Factory mViewModelFactory;
+    private final BroadcastReceiver mBroadcastReceiver;
+    private final IntentFilter mIntentFilter;
+
+    private View mLayout;
+    private View mRoot;
+    private ImageView mPreview;
+    private CropView mCropView;
+    private MagnifierView mMagnifierView;
+    private Button mSave;
+    private Button mCancel;
+    private AppClipsViewModel mViewModel;
+
+    private ResultReceiver mResultReceiver;
+
+    @Inject
+    public AppClipsActivity(AppClipsViewModel.Factory viewModelFactory) {
+        mViewModelFactory = viewModelFactory;
+
+        mBroadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                // Trampoline activity was dismissed so finish this activity.
+                if (ACTION_FINISH_FROM_TRAMPOLINE.equals(intent.getAction())) {
+                    if (!isFinishing()) {
+                        // Nullify the ResultReceiver so that result cannot be sent as trampoline
+                        // activity is already finishing.
+                        mResultReceiver = null;
+                        finish();
+                    }
+                }
+            }
+        };
+
+        mIntentFilter = new IntentFilter(ACTION_FINISH_FROM_TRAMPOLINE);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        overridePendingTransition(0, 0);
+        super.onCreate(savedInstanceState);
+
+        // Register the broadcast receiver that informs when the trampoline activity is dismissed.
+        registerReceiver(mBroadcastReceiver, mIntentFilter, PERMISSION_SELF, null,
+                RECEIVER_NOT_EXPORTED);
+
+        Intent intent = getIntent();
+        mResultReceiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER, ResultReceiver.class);
+        if (mResultReceiver == null) {
+            setErrorThenFinish(Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED);
+            return;
+        }
+
+        // Inflate layout but don't add it yet as it should be added after the screenshot is ready
+        // for preview.
+        mLayout = getLayoutInflater().inflate(R.layout.app_clips_screenshot, null);
+        mRoot = mLayout.findViewById(R.id.root);
+
+        mSave = mLayout.findViewById(R.id.save);
+        mCancel = mLayout.findViewById(R.id.cancel);
+        mSave.setOnClickListener(this::onClick);
+        mCancel.setOnClickListener(this::onClick);
+
+        mMagnifierView = mLayout.findViewById(R.id.magnifier);
+        mCropView = mLayout.findViewById(R.id.crop_view);
+        mCropView.setCropInteractionListener(mMagnifierView);
+
+        mPreview = mLayout.findViewById(R.id.preview);
+        mPreview.addOnLayoutChangeListener(
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
+                        updateImageDimensions());
+
+        mViewModel = new ViewModelProvider(this, mViewModelFactory).get(AppClipsViewModel.class);
+        mViewModel.getScreenshot().observe(this, this::setScreenshot);
+        mViewModel.getResultLiveData().observe(this, this::setResultThenFinish);
+        mViewModel.getErrorLiveData().observe(this, this::setErrorThenFinish);
+
+        if (savedInstanceState == null) {
+            mViewModel.performScreenshot();
+        }
+    }
+
+    @Override
+    public void finish() {
+        super.finish();
+        overridePendingTransition(0, 0);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+
+        unregisterReceiver(mBroadcastReceiver);
+
+        // If neither error nor result was set, it implies that the activity is finishing due to
+        // some other reason such as user dismissing this activity using back gesture. Inform error.
+        if (isFinishing() && mViewModel.getErrorLiveData().getValue() == null
+                && mViewModel.getResultLiveData().getValue() == null) {
+            // Set error but don't finish as the activity is already finishing.
+            setError(Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED);
+        }
+    }
+
+    private void setScreenshot(Bitmap screenshot) {
+        // Set background, status and navigation bar colors as the activity is no longer
+        // translucent.
+        int colorBackgroundFloating = Utils.getColorAttr(this,
+                android.R.attr.colorBackgroundFloating).getDefaultColor();
+        mRoot.setBackgroundColor(colorBackgroundFloating);
+
+        BitmapDrawable drawable = new BitmapDrawable(getResources(), screenshot);
+        mPreview.setImageDrawable(drawable);
+        mPreview.setAlpha(1f);
+
+        mMagnifierView.setDrawable(drawable, screenshot.getWidth(), screenshot.getHeight());
+
+        // Screenshot is now available so set content view.
+        setContentView(mLayout);
+    }
+
+    private void onClick(View view) {
+        mSave.setEnabled(false);
+        mCancel.setEnabled(false);
+
+        int id = view.getId();
+        if (id == R.id.save) {
+            saveScreenshotThenFinish();
+        } else {
+            setErrorThenFinish(Intent.CAPTURE_CONTENT_FOR_NOTE_USER_CANCELED);
+        }
+    }
+
+    private void saveScreenshotThenFinish() {
+        Drawable drawable = mPreview.getDrawable();
+        if (drawable == null) {
+            setErrorThenFinish(Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED);
+            return;
+        }
+
+        Rect bounds = mCropView.getCropBoundaries(drawable.getIntrinsicWidth(),
+                drawable.getIntrinsicHeight());
+
+        if (bounds.isEmpty()) {
+            setErrorThenFinish(Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED);
+            return;
+        }
+
+        updateImageDimensions();
+        mViewModel.saveScreenshotThenFinish(drawable, bounds);
+    }
+
+    private void setResultThenFinish(Uri uri) {
+        if (mResultReceiver == null) {
+            return;
+        }
+
+        Bundle data = new Bundle();
+        data.putInt(Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE,
+                Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS);
+        data.putParcelable(EXTRA_SCREENSHOT_URI, uri);
+        try {
+            mResultReceiver.send(Activity.RESULT_OK, data);
+        } catch (Exception e) {
+            // Do nothing.
+        }
+
+        // Nullify the ResultReceiver before finishing to avoid resending the result.
+        mResultReceiver = null;
+        finish();
+    }
+
+    private void setErrorThenFinish(int errorCode) {
+        setError(errorCode);
+        finish();
+    }
+
+    private void setError(int errorCode) {
+        if (mResultReceiver == null) {
+            return;
+        }
+
+        Bundle data = new Bundle();
+        data.putInt(Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE, errorCode);
+        try {
+            mResultReceiver.send(RESULT_OK, data);
+        } catch (Exception e) {
+            // Do nothing.
+        }
+
+        // Nullify the ResultReceiver to avoid resending the result.
+        mResultReceiver = null;
+    }
+
+    private void updateImageDimensions() {
+        Drawable drawable = mPreview.getDrawable();
+        if (drawable == null) {
+            return;
+        }
+
+        Rect bounds = drawable.getBounds();
+        float imageRatio = bounds.width() / (float) bounds.height();
+        int previewWidth = mPreview.getWidth() - mPreview.getPaddingLeft()
+                - mPreview.getPaddingRight();
+        int previewHeight = mPreview.getHeight() - mPreview.getPaddingTop()
+                - mPreview.getPaddingBottom();
+        float viewRatio = previewWidth / (float) previewHeight;
+
+        if (imageRatio > viewRatio) {
+            // Image is full width and height is constrained, compute extra padding to inform
+            // CropView.
+            int imageHeight = (int) (previewHeight * viewRatio / imageRatio);
+            int extraPadding = (previewHeight - imageHeight) / 2;
+            mCropView.setExtraPadding(extraPadding, extraPadding);
+            mCropView.setImageWidth(previewWidth);
+        } else {
+            // Image is full height.
+            mCropView.setExtraPadding(mPreview.getPaddingTop(), mPreview.getPaddingBottom());
+            mCropView.setImageWidth((int) (previewHeight * imageRatio));
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java
new file mode 100644
index 0000000..65fb4c9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java
@@ -0,0 +1,65 @@
+/*
+ * 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.appclips;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.view.Display;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.infra.AndroidFuture;
+import com.android.internal.infra.ServiceConnector;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Application;
+
+import javax.inject.Inject;
+
+/** An intermediary singleton object to help communicating with the cross process service. */
+@SysUISingleton
+public class AppClipsCrossProcessHelper {
+
+    private final ServiceConnector<IAppClipsScreenshotHelperService> mProxyConnector;
+
+    @Inject
+    public AppClipsCrossProcessHelper(@Application Context context) {
+        mProxyConnector = new ServiceConnector.Impl<IAppClipsScreenshotHelperService>(context,
+                new Intent(context, AppClipsScreenshotHelperService.class),
+                Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
+                        | Context.BIND_NOT_VISIBLE, context.getUserId(),
+                IAppClipsScreenshotHelperService.Stub::asInterface);
+    }
+
+    /**
+     * Returns a {@link Bitmap} captured in the SysUI process, {@code null} in case of an error.
+     *
+     * <p>Note: The SysUI process captures a {@link ScreenshotHardwareBufferInternal} which is ok to
+     * pass around but not a {@link Bitmap}.
+     */
+    @Nullable
+    public Bitmap takeScreenshot() {
+        try {
+            AndroidFuture<ScreenshotHardwareBufferInternal> future =
+                    mProxyConnector.postForResult(
+                            service -> service.takeScreenshot(Display.DEFAULT_DISPLAY));
+            return future.get().createBitmapThenCloseBuffer();
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
new file mode 100644
index 0000000..6f8c365
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
@@ -0,0 +1,69 @@
+/*
+ * 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.appclips;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.window.ScreenCapture.ScreenshotHardwareBuffer;
+import android.window.ScreenCapture.ScreenshotSync;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.screenshot.AppClipsActivity;
+import com.android.wm.shell.bubbles.Bubbles;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+/**
+ * A helper service that runs in SysUI process and helps {@link AppClipsActivity} which runs in its
+ * own separate process take a screenshot.
+ */
+public class AppClipsScreenshotHelperService extends Service {
+
+    private final Optional<Bubbles> mOptionalBubbles;
+
+    @Inject
+    public AppClipsScreenshotHelperService(Optional<Bubbles> optionalBubbles) {
+        mOptionalBubbles = optionalBubbles;
+    }
+
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        return new IAppClipsScreenshotHelperService.Stub() {
+            @Override
+            @Nullable
+            public ScreenshotHardwareBufferInternal takeScreenshot(int displayId) {
+                if (mOptionalBubbles.isEmpty()) {
+                    return null;
+                }
+
+                ScreenshotSync screenshotSync =
+                        mOptionalBubbles.get().getScreenshotExcludingBubble(displayId);
+                ScreenshotHardwareBuffer screenshotHardwareBuffer = screenshotSync.get();
+                if (screenshotHardwareBuffer == null) {
+                    return null;
+                }
+
+                return new ScreenshotHardwareBufferInternal(screenshotHardwareBuffer);
+            }
+        };
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java
new file mode 100644
index 0000000..d0b7ad3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java
@@ -0,0 +1,110 @@
+/*
+ * 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.appclips;
+
+import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
+
+import android.app.Activity;
+import android.app.Service;
+import android.app.StatusBarManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.IBinder;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.statusbar.IAppClipsService;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Application;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.wm.shell.bubbles.Bubbles;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+/**
+ * A service that communicates with {@link StatusBarManager} to support the
+ * {@link StatusBarManager#canLaunchCaptureContentActivityForNote(Activity)} API.
+ */
+public class AppClipsService extends Service {
+
+    @Application private final Context mContext;
+    private final FeatureFlags mFeatureFlags;
+    private final Optional<Bubbles> mOptionalBubbles;
+    private final DevicePolicyManager mDevicePolicyManager;
+    private final boolean mAreTaskAndTimeIndependentPrerequisitesMet;
+
+    @Inject
+    public AppClipsService(@Application Context context, FeatureFlags featureFlags,
+            Optional<Bubbles> optionalBubbles, DevicePolicyManager devicePolicyManager) {
+        mContext = context;
+        mFeatureFlags = featureFlags;
+        mOptionalBubbles = optionalBubbles;
+        mDevicePolicyManager = devicePolicyManager;
+
+        mAreTaskAndTimeIndependentPrerequisitesMet = checkIndependentVariables();
+    }
+
+    private boolean checkIndependentVariables() {
+        if (!mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)) {
+            return false;
+        }
+
+        if (mOptionalBubbles.isEmpty()) {
+            return false;
+        }
+
+        return isComponentValid();
+    }
+
+    private boolean isComponentValid() {
+        ComponentName componentName;
+        try {
+            componentName = ComponentName.unflattenFromString(
+                    mContext.getString(R.string.config_screenshotAppClipsActivityComponent));
+        } catch (Resources.NotFoundException e) {
+            return false;
+        }
+
+        return componentName != null
+                && !componentName.getPackageName().isEmpty()
+                && !componentName.getClassName().isEmpty();
+    }
+
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        return new IAppClipsService.Stub() {
+            @Override
+            public boolean canLaunchCaptureContentActivityForNote(int taskId) {
+                if (!mAreTaskAndTimeIndependentPrerequisitesMet) {
+                    return false;
+                }
+
+                if (!mOptionalBubbles.get().isAppBubbleTaskId(taskId)) {
+                    return false;
+                }
+
+                return !mDevicePolicyManager.getScreenCaptureDisabled(null);
+            }
+        };
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
new file mode 100644
index 0000000..4759cc6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
@@ -0,0 +1,233 @@
+/*
+ * 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 static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED;
+import static android.content.Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE;
+import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
+
+import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.ResultReceiver;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.notetask.NoteTaskController;
+import com.android.wm.shell.bubbles.Bubbles;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+/**
+ * A trampoline activity that is responsible for:
+ * <ul>
+ *     <li>Performing precondition checks before starting the actual screenshot activity.
+ *     <li>Communicating with the screenshot activity and the calling activity.
+ * </ul>
+ *
+ * <p>As this activity is started in a bubble app, the windowing for this activity is restricted
+ * to the parent bubble app. The screenshot editing activity, see {@link AppClipsActivity}, is
+ * started in a regular activity window using {@link Intent#FLAG_ACTIVITY_NEW_TASK}. However,
+ * {@link Activity#startActivityForResult(Intent, int)} is not compatible with
+ * {@link Intent#FLAG_ACTIVITY_NEW_TASK}. So, this activity acts as a trampoline activity to
+ * abstract the complexity of communication with the screenshot editing activity for a simpler
+ * developer experience.
+ *
+ * TODO(b/267309532): Polish UI and animations.
+ */
+public class AppClipsTrampolineActivity extends Activity {
+
+    private static final String TAG = AppClipsTrampolineActivity.class.getSimpleName();
+    public static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
+    public static final String EXTRA_SCREENSHOT_URI = TAG + "SCREENSHOT_URI";
+    public static final String ACTION_FINISH_FROM_TRAMPOLINE = TAG + "FINISH_FROM_TRAMPOLINE";
+    static final String EXTRA_RESULT_RECEIVER = TAG + "RESULT_RECEIVER";
+
+    private final DevicePolicyManager mDevicePolicyManager;
+    private final FeatureFlags mFeatureFlags;
+    private final Optional<Bubbles> mOptionalBubbles;
+    private final NoteTaskController mNoteTaskController;
+    private final ResultReceiver mResultReceiver;
+
+    private Intent mKillAppClipsBroadcastIntent;
+
+    @Inject
+    public AppClipsTrampolineActivity(DevicePolicyManager devicePolicyManager, FeatureFlags flags,
+            Optional<Bubbles> optionalBubbles, NoteTaskController noteTaskController,
+            @Main Handler mainHandler) {
+        mDevicePolicyManager = devicePolicyManager;
+        mFeatureFlags = flags;
+        mOptionalBubbles = optionalBubbles;
+        mNoteTaskController = noteTaskController;
+
+        mResultReceiver = createResultReceiver(mainHandler);
+    }
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (savedInstanceState != null) {
+            return;
+        }
+
+        if (!mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)) {
+            finish();
+            return;
+        }
+
+        if (mOptionalBubbles.isEmpty()) {
+            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+            return;
+        }
+
+        if (!mOptionalBubbles.get().isAppBubbleTaskId(getTaskId())) {
+            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED);
+            return;
+        }
+
+        if (mDevicePolicyManager.getScreenCaptureDisabled(null)) {
+            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN);
+            return;
+        }
+
+        ComponentName componentName;
+        try {
+            componentName = ComponentName.unflattenFromString(
+                    getString(R.string.config_screenshotAppClipsActivityComponent));
+        } catch (Resources.NotFoundException e) {
+            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+            return;
+        }
+
+        if (componentName == null || componentName.getPackageName().isEmpty()
+                || componentName.getClassName().isEmpty()) {
+            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+            return;
+        }
+
+        Intent intent = new Intent().setComponent(componentName).addFlags(
+                Intent.FLAG_ACTIVITY_NEW_TASK).putExtra(EXTRA_RESULT_RECEIVER, mResultReceiver);
+        try {
+            // Start the App Clips activity.
+            startActivity(intent);
+
+            // Set up the broadcast intent that will inform the above App Clips activity to finish
+            // when this trampoline activity is finished.
+            mKillAppClipsBroadcastIntent =
+                    new Intent(ACTION_FINISH_FROM_TRAMPOLINE)
+                            .setComponent(componentName)
+                            .setPackage(componentName.getPackageName());
+        } catch (ActivityNotFoundException e) {
+            setErrorResultAndFinish(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+
+        if (isFinishing() && mKillAppClipsBroadcastIntent != null) {
+            sendBroadcast(mKillAppClipsBroadcastIntent, PERMISSION_SELF);
+        }
+    }
+
+    private void setErrorResultAndFinish(int errorCode) {
+        setResult(RESULT_OK,
+                new Intent().putExtra(EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE, errorCode));
+        finish();
+    }
+
+    private class AppClipsResultReceiver extends ResultReceiver {
+
+        AppClipsResultReceiver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+            if (isFinishing()) {
+                // It's too late, trampoline activity is finishing or already finished.
+                // Return early.
+                return;
+            }
+
+            // Package the response that should be sent to the calling activity.
+            Intent convertedData = new Intent();
+            int statusCode = CAPTURE_CONTENT_FOR_NOTE_FAILED;
+            if (resultData != null) {
+                statusCode = resultData.getInt(EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE,
+                        CAPTURE_CONTENT_FOR_NOTE_FAILED);
+            }
+            convertedData.putExtra(EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE, statusCode);
+
+            if (statusCode == CAPTURE_CONTENT_FOR_NOTE_SUCCESS) {
+                Uri uri = resultData.getParcelable(EXTRA_SCREENSHOT_URI, Uri.class);
+                convertedData.setData(uri).addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+            }
+
+            // Broadcast no longer required, setting it to null.
+            mKillAppClipsBroadcastIntent = null;
+
+            // Expand the note bubble before returning the result. As App Clips API is only
+            // available when in a bubble, isInMultiWindowMode is always false below.
+            mNoteTaskController.showNoteTask(false);
+            setResult(RESULT_OK, convertedData);
+            finish();
+        }
+    }
+
+    /**
+     * @return a {@link ResultReceiver} by initializing an {@link AppClipsResultReceiver} and
+     * converting it into a generic {@link ResultReceiver} to pass across a different but trusted
+     * process.
+     */
+    private ResultReceiver createResultReceiver(@Main Handler handler) {
+        AppClipsResultReceiver appClipsResultReceiver = new AppClipsResultReceiver(handler);
+        Parcel parcel = Parcel.obtain();
+        appClipsResultReceiver.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        ResultReceiver resultReceiver  = ResultReceiver.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+        return resultReceiver;
+    }
+
+    /** This is a test only API for mocking response from {@link AppClipsActivity}. */
+    @VisibleForTesting
+    public ResultReceiver getResultReceiverForTest() {
+        return mResultReceiver;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java
new file mode 100644
index 0000000..5a7b5f9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java
@@ -0,0 +1,184 @@
+/*
+ * 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 static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
+import android.graphics.RecordingCanvas;
+import android.graphics.Rect;
+import android.graphics.RenderNode;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Process;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.screenshot.appclips.AppClipsCrossProcessHelper;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.time.ZonedDateTime;
+import java.util.UUID;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+/** A {@link ViewModel} to help with the App Clips screenshot flow. */
+final class AppClipsViewModel extends ViewModel {
+
+    private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
+    private final ImageExporter mImageExporter;
+    @Main
+    private final Executor mMainExecutor;
+    @Background
+    private final Executor mBgExecutor;
+
+    private final MutableLiveData<Bitmap> mScreenshotLiveData;
+    private final MutableLiveData<Uri> mResultLiveData;
+    private final MutableLiveData<Integer> mErrorLiveData;
+
+    AppClipsViewModel(AppClipsCrossProcessHelper appClipsCrossProcessHelper,
+            ImageExporter imageExporter, @Main Executor mainExecutor,
+            @Background Executor bgExecutor) {
+        mAppClipsCrossProcessHelper = appClipsCrossProcessHelper;
+        mImageExporter = imageExporter;
+        mMainExecutor = mainExecutor;
+        mBgExecutor = bgExecutor;
+
+        mScreenshotLiveData = new MutableLiveData<>();
+        mResultLiveData = new MutableLiveData<>();
+        mErrorLiveData = new MutableLiveData<>();
+    }
+
+    /** Grabs a screenshot and updates the {@link Bitmap} set in screenshot {@link LiveData}. */
+    void performScreenshot() {
+        mBgExecutor.execute(() -> {
+            Bitmap screenshot = mAppClipsCrossProcessHelper.takeScreenshot();
+            mMainExecutor.execute(() -> {
+                if (screenshot == null) {
+                    mErrorLiveData.setValue(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+                } else {
+                    mScreenshotLiveData.setValue(screenshot);
+                }
+            });
+        });
+    }
+
+    /** Returns a {@link LiveData} that holds the captured screenshot. */
+    LiveData<Bitmap> getScreenshot() {
+        return mScreenshotLiveData;
+    }
+
+    /** Returns a {@link LiveData} that holds the {@link Uri} where screenshot is saved. */
+    LiveData<Uri> getResultLiveData() {
+        return mResultLiveData;
+    }
+
+    /**
+     * Returns a {@link LiveData} that holds the error codes for
+     * {@link Intent#EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE}.
+     */
+    LiveData<Integer> getErrorLiveData() {
+        return mErrorLiveData;
+    }
+
+    /**
+     * Saves the provided {@link Drawable} to storage then informs the result {@link Uri} to
+     * {@link LiveData}.
+     */
+    void saveScreenshotThenFinish(Drawable screenshotDrawable, Rect bounds) {
+        mBgExecutor.execute(() -> {
+            // Render the screenshot bitmap in background.
+            Bitmap screenshotBitmap = renderBitmap(screenshotDrawable, bounds);
+
+            // Export and save the screenshot in background.
+            // TODO(b/267310185): Save to work profile UserHandle.
+            ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export(
+                    mBgExecutor, UUID.randomUUID(), screenshotBitmap, ZonedDateTime.now(),
+                    Process.myUserHandle());
+
+            // Get the result and update state on main thread.
+            exportFuture.addListener(() -> {
+                try {
+                    ImageExporter.Result result = exportFuture.get();
+                    if (result.uri == null) {
+                        mErrorLiveData.setValue(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+                        return;
+                    }
+
+                    mResultLiveData.setValue(result.uri);
+                } catch (CancellationException | InterruptedException | ExecutionException e) {
+                    mErrorLiveData.setValue(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+                }
+            }, mMainExecutor);
+        });
+    }
+
+    private static Bitmap renderBitmap(Drawable drawable, Rect bounds) {
+        final RenderNode output = new RenderNode("Screenshot save");
+        output.setPosition(0, 0, bounds.width(), bounds.height());
+        RecordingCanvas canvas = output.beginRecording();
+        canvas.translate(-bounds.left, -bounds.top);
+        canvas.clipRect(bounds);
+        drawable.draw(canvas);
+        output.endRecording();
+        return HardwareRenderer.createHardwareBitmap(output, bounds.width(), bounds.height());
+    }
+
+    /** Helper factory to help with injecting {@link AppClipsViewModel}. */
+    static final class Factory implements ViewModelProvider.Factory {
+
+        private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
+        private final ImageExporter mImageExporter;
+        @Main
+        private final Executor mMainExecutor;
+        @Background
+        private final Executor mBgExecutor;
+
+        @Inject
+        Factory(AppClipsCrossProcessHelper appClipsCrossProcessHelper,  ImageExporter imageExporter,
+                @Main Executor mainExecutor, @Background Executor bgExecutor) {
+            mAppClipsCrossProcessHelper = appClipsCrossProcessHelper;
+            mImageExporter = imageExporter;
+            mMainExecutor = mainExecutor;
+            mBgExecutor = bgExecutor;
+        }
+
+        @NonNull
+        @Override
+        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
+            if (modelClass != AppClipsViewModel.class) {
+                throw new IllegalArgumentException();
+            }
+
+            //noinspection unchecked
+            return (T) new AppClipsViewModel(mAppClipsCrossProcessHelper, mImageExporter,
+                    mMainExecutor, mBgExecutor);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/IAppClipsScreenshotHelperService.aidl b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/IAppClipsScreenshotHelperService.aidl
new file mode 100644
index 0000000..640e742
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/IAppClipsScreenshotHelperService.aidl
@@ -0,0 +1,29 @@
+/**
+ * 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.appclips;
+
+import android.os.Bundle;
+
+import com.android.systemui.screenshot.appclips.ScreenshotHardwareBufferInternal;
+
+/**
+ * A helper service that runs in SysUI process and helps {@link AppClipsActivity} which runs in its
+ * own separate process take a screenshot.
+ */
+interface IAppClipsScreenshotHelperService {
+    @nullable ScreenshotHardwareBufferInternal takeScreenshot(in int displayId);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.aidl b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.aidl
new file mode 100644
index 0000000..3a7b944
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.appclips;
+
+parcelable ScreenshotHardwareBufferInternal;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.java
new file mode 100644
index 0000000..3b107f1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.java
@@ -0,0 +1,96 @@
+/*
+ * 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.appclips;
+
+import android.graphics.Bitmap;
+import android.graphics.ColorSpace;
+import android.graphics.ParcelableColorSpace;
+import android.hardware.HardwareBuffer;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.window.ScreenCapture.ScreenshotHardwareBuffer;
+
+/**
+ * An internal version of {@link ScreenshotHardwareBuffer} that helps with parceling the information
+ * necessary for creating a {@link Bitmap}.
+ */
+public class ScreenshotHardwareBufferInternal implements Parcelable {
+
+    public static final Creator<ScreenshotHardwareBufferInternal> CREATOR =
+            new Creator<>() {
+                @Override
+                public ScreenshotHardwareBufferInternal createFromParcel(Parcel in) {
+                    return new ScreenshotHardwareBufferInternal(in);
+                }
+
+                @Override
+                public ScreenshotHardwareBufferInternal[] newArray(int size) {
+                    return new ScreenshotHardwareBufferInternal[size];
+                }
+            };
+    private final HardwareBuffer mHardwareBuffer;
+    private final ParcelableColorSpace mParcelableColorSpace;
+
+    public ScreenshotHardwareBufferInternal(
+            ScreenshotHardwareBuffer screenshotHardwareBuffer) {
+        mHardwareBuffer = screenshotHardwareBuffer.getHardwareBuffer();
+        mParcelableColorSpace = new ParcelableColorSpace(
+                screenshotHardwareBuffer.getColorSpace());
+    }
+
+    private ScreenshotHardwareBufferInternal(Parcel in) {
+        mHardwareBuffer = in.readParcelable(HardwareBuffer.class.getClassLoader(),
+                HardwareBuffer.class);
+        mParcelableColorSpace = in.readParcelable(ParcelableColorSpace.class.getClassLoader(),
+                ParcelableColorSpace.class);
+    }
+
+    /**
+     * Returns a {@link Bitmap} represented by the underlying data and successively closes the
+     * internal {@link HardwareBuffer}. See,
+     * {@link Bitmap#wrapHardwareBuffer(HardwareBuffer, ColorSpace)} and
+     * {@link HardwareBuffer#close()} for more information.
+     */
+    public Bitmap createBitmapThenCloseBuffer() {
+        Bitmap bitmap = Bitmap.wrapHardwareBuffer(mHardwareBuffer,
+                mParcelableColorSpace.getColorSpace());
+        mHardwareBuffer.close();
+        return bitmap;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mHardwareBuffer, flags);
+        dest.writeParcelable(mParcelableColorSpace, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ScreenshotHardwareBufferInternal)) {
+            return false;
+        }
+
+        ScreenshotHardwareBufferInternal other = (ScreenshotHardwareBufferInternal) obj;
+        return mHardwareBuffer.equals(other.mHardwareBuffer) && mParcelableColorSpace.equals(
+                other.mParcelableColorSpace);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
index fdb0100..22e238c0 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
@@ -24,6 +24,8 @@
 import com.android.systemui.screenshot.ScreenshotPolicyImpl;
 import com.android.systemui.screenshot.ScreenshotProxyService;
 import com.android.systemui.screenshot.TakeScreenshotService;
+import com.android.systemui.screenshot.appclips.AppClipsScreenshotHelperService;
+import com.android.systemui.screenshot.appclips.AppClipsService;
 
 import dagger.Binds;
 import dagger.Module;
@@ -52,4 +54,13 @@
     @Binds
     abstract ImageCapture bindImageCaptureImpl(ImageCaptureImpl capture);
 
+    @Binds
+    @IntoMap
+    @ClassKey(AppClipsScreenshotHelperService.class)
+    abstract Service bindAppClipsScreenshotHelperService(AppClipsScreenshotHelperService service);
+
+    @Binds
+    @IntoMap
+    @ClassKey(AppClipsService.class)
+    abstract Service bindAppClipsService(AppClipsService service);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index cf60c93..f53f824 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -685,6 +685,7 @@
     private boolean mInstantExpanding;
     private boolean mAnimateAfterExpanding;
     private boolean mIsFlinging;
+    private boolean mLastFlingWasExpanding;
     private String mViewName;
     private float mInitialExpandY;
     private float mInitialExpandX;
@@ -2142,6 +2143,7 @@
     @VisibleForTesting
     void flingToHeight(float vel, boolean expand, float target,
             float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
+        mLastFlingWasExpanding = expand;
         mHeadsUpTouchHelper.notifyFling(!expand);
         mKeyguardStateController.notifyPanelFlingStart(!expand /* flingingToDismiss */);
         setClosingWithAlphaFadeout(!expand && !isOnKeyguard() && getFadeoutAlpha() == 1.0f);
@@ -2531,7 +2533,7 @@
         }
         // defer touches on QQS to shade while shade is collapsing. Added margin for error
         // as sometimes the qsExpansionFraction can be a tiny value instead of 0 when in QQS.
-        if (!mSplitShadeEnabled
+        if (!mSplitShadeEnabled && !mLastFlingWasExpanding
                 && computeQsExpansionFraction() <= 0.01 && getExpandedFraction() < 1.0) {
             mShadeLog.logMotionEvent(event,
                     "handleQsTouch: shade touched while collapsing, QS tracking disabled");
@@ -3151,17 +3153,11 @@
         }
         // The padding on this area is large enough that we can use a cheaper clipping strategy
         mKeyguardStatusViewController.setClipBounds(clipStatusView ? mLastQsClipBounds : null);
-        if (!qsVisible && mSplitShadeEnabled) {
-            // On the lockscreen when qs isn't visible, we don't want the bounds of the shade to
-            // be visible, otherwise you can see the bounds once swiping up to see bouncer
-            mScrimController.setNotificationsBounds(0, 0, 0, 0);
-        } else {
-            // Increase the height of the notifications scrim when not in split shade
-            // (e.g. portrait tablet) so the rounded corners are not visible at the bottom,
-            // in this case they are rendered off-screen
-            final int notificationsScrimBottom = mSplitShadeEnabled ? bottom : bottom + radius;
-            mScrimController.setNotificationsBounds(left, top, right, notificationsScrimBottom);
-        }
+        // Increase the height of the notifications scrim when not in split shade
+        // (e.g. portrait tablet) so the rounded corners are not visible at the bottom,
+        // in this case they are rendered off-screen
+        final int notificationsScrimBottom = mSplitShadeEnabled ? bottom : bottom + radius;
+        mScrimController.setNotificationsBounds(left, top, right, notificationsScrimBottom);
 
         if (mSplitShadeEnabled) {
             mKeyguardStatusBarViewController.setNoTopClipping();
@@ -3222,6 +3218,12 @@
     private int calculateQsBottomPosition(float qsExpansionFraction) {
         if (mTransitioningToFullShadeProgress > 0.0f) {
             return mTransitionToFullShadeQSPosition;
+        } else if (mSplitShadeEnabled) {
+            // in split shade - outside lockscreen transition handled above - we simply jump between
+            // two qs expansion values - either shade is closed and qs expansion is 0 or shade is
+            // open and qs expansion is 1
+            int qsBottomTarget = mQs.getDesiredHeight() + mLargeScreenShadeHeaderHeight;
+            return qsExpansionFraction > 0 ? qsBottomTarget : 0;
         } else {
             int qsBottomYFrom = (int) getHeaderTranslation() + mQs.getQsMinExpansionHeight();
             int expandedTopMargin = mUseLargeScreenShadeHeader ? mLargeScreenShadeHeaderHeight : 0;
@@ -4125,7 +4127,7 @@
 
                     if (didFaceAuthRun) {
                         mUpdateMonitor.requestActiveUnlock(
-                                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
+                                ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT,
                                 "lockScreenEmptySpaceTap");
                     } else {
                         mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_HINT,
@@ -4958,8 +4960,12 @@
             beginJankMonitoring();
         }
         mInitialOffsetOnTouch = expandedHeight;
-        mInitialExpandY = newY;
-        mInitialExpandX = newX;
+        if (!mTracking || isFullyCollapsed()) {
+            mInitialExpandY = newY;
+            mInitialExpandX = newX;
+        } else {
+            mShadeLog.d("not setting mInitialExpandY in startExpandMotion");
+        }
         mInitialTouchFromKeyguard = mKeyguardStateController.isShowing();
         if (startTracking) {
             mTouchSlopExceeded = true;
@@ -6131,6 +6137,11 @@
 
             switch (event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
+                    if (mTracking) {
+                        // TODO(b/247126247) fix underlying issue. Should be ACTION_POINTER_DOWN.
+                        mShadeLog.d("Don't intercept down event while already tracking");
+                        return false;
+                    }
                     mCentralSurfaces.userActivity();
                     mAnimatingOnDown = mHeightAnimator != null && !mIsSpringBackAnimation;
                     mMinExpandHeight = 0.0f;
@@ -6143,8 +6154,12 @@
                                 + " false");
                         return true;
                     }
-                    mInitialExpandY = y;
-                    mInitialExpandX = x;
+                    if (!mTracking || isFullyCollapsed()) {
+                        mInitialExpandY = y;
+                        mInitialExpandX = x;
+                    } else {
+                        mShadeLog.d("not setting mInitialExpandY in onInterceptTouch");
+                    }
                     mTouchStartedInEmptyArea = !isInContentBounds(x, y);
                     mTouchSlopExceeded = mTouchSlopExceededBeforeDown;
                     mMotionAborted = false;
@@ -6214,6 +6229,11 @@
                             "onTouch: duplicate down event detected... ignoring");
                     return true;
                 }
+                if (mTracking) {
+                    // TODO(b/247126247) fix underlying issue. Should be ACTION_POINTER_DOWN.
+                    mShadeLog.d("Don't handle down event while already tracking");
+                    return true;
+                }
                 mLastTouchDownTime = event.getDownTime();
             }
 
@@ -6333,7 +6353,8 @@
             final float x = event.getX(pointerIndex);
             final float y = event.getY(pointerIndex);
 
-            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            if (event.getActionMasked() == MotionEvent.ACTION_DOWN
+                    || event.getActionMasked() == MotionEvent.ACTION_MOVE) {
                 mGestureWaitForTouchSlop = shouldGestureWaitForTouchSlop();
                 mIgnoreXTouchSlop = true;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/OWNERS b/packages/SystemUI/src/com/android/systemui/shade/OWNERS
index d71fbf6..c8b6a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/shade/OWNERS
@@ -7,6 +7,7 @@
 per-file NotificationsQuickSettingsContainer.java = kozynski@google.com, asc@google.com
 per-file NotificationsQSContainerController.kt = kozynski@google.com, asc@google.com
 per-file *ShadeHeader* = kozynski@google.com, asc@google.com
+per-file *Shade* = justinweir@google.com
 
 per-file NotificationShadeWindowViewController.java = pixel@google.com, cinek@google.com, juliacr@google.com
 per-file NotificationShadeWindowView.java = pixel@google.com, cinek@google.com, juliacr@google.com
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 393279b..641131e 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -44,6 +44,11 @@
         const val DREAM_SMARTSPACE_PRECONDITION = "dream_smartspace_precondition"
 
         /**
+         * The BcSmartspaceDataPlugin for the standalone date (+alarm+dnd).
+         */
+        const val DATE_SMARTSPACE_DATA_PLUGIN = "date_smartspace_data_plugin"
+
+        /**
          * The BcSmartspaceDataPlugin for the standalone weather.
          */
         const val WEATHER_SMARTSPACE_DATA_PLUGIN = "weather_smartspace_data_plugin"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 3aaad87..2cf1f53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -53,7 +53,6 @@
 import android.os.RemoteException;
 import android.util.Pair;
 import android.util.SparseArray;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsController.Appearance;
 import android.view.WindowInsetsController.Behavior;
@@ -371,22 +370,22 @@
                 String packageName, LetterboxDetails[] letterboxDetails) { }
 
         /**
-         * @see IStatusBar#showTransient(int, int[], boolean).
+         * @see IStatusBar#showTransient(int, int, boolean).
          */
-        default void showTransient(int displayId, @InternalInsetsType int[] types) { }
+        default void showTransient(int displayId, @InsetsType int types) { }
 
         /**
-         * @see IStatusBar#showTransient(int, int[], boolean).
+         * @see IStatusBar#showTransient(int, int, boolean).
          */
-        default void showTransient(int displayId, @InternalInsetsType int[] types,
+        default void showTransient(int displayId, @InsetsType int types,
                 boolean isGestureOnSystemBar) {
             showTransient(displayId, types);
         }
 
         /**
-         * @see IStatusBar#abortTransient(int, int[]).
+         * @see IStatusBar#abortTransient(int, int).
          */
-        default void abortTransient(int displayId, @InternalInsetsType int[] types) { }
+        default void abortTransient(int displayId, @InsetsType int types) { }
 
         /**
          * Called to notify System UI that a warning about the device going to sleep
@@ -1131,17 +1130,23 @@
     }
 
     @Override
-    public void showTransient(int displayId, int[] types, boolean isGestureOnSystemBar) {
+    public void showTransient(int displayId, int types, boolean isGestureOnSystemBar) {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_SHOW_TRANSIENT, displayId, isGestureOnSystemBar ? 1 : 0,
-                    types).sendToTarget();
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = displayId;
+            args.argi2 = types;
+            args.argi3 = isGestureOnSystemBar ? 1 : 0;
+            mHandler.obtainMessage(MSG_SHOW_TRANSIENT, args).sendToTarget();
         }
     }
 
     @Override
-    public void abortTransient(int displayId, int[] types) {
+    public void abortTransient(int displayId, int types) {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_ABORT_TRANSIENT, displayId, 0, types).sendToTarget();
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = displayId;
+            args.argi2 = types;
+            mHandler.obtainMessage(MSG_ABORT_TRANSIENT, args).sendToTarget();
         }
     }
 
@@ -1644,17 +1649,21 @@
                     args.recycle();
                     break;
                 case MSG_SHOW_TRANSIENT: {
-                    final int displayId = msg.arg1;
-                    final int[] types = (int[]) msg.obj;
-                    final boolean isGestureOnSystemBar = msg.arg2 != 0;
+                    args = (SomeArgs) msg.obj;
+                    final int displayId = args.argi1;
+                    final int types = args.argi2;
+                    final boolean isGestureOnSystemBar = args.argi3 != 0;
+                    args.recycle();
                     for (int i = 0; i < mCallbacks.size(); i++) {
                         mCallbacks.get(i).showTransient(displayId, types, isGestureOnSystemBar);
                     }
                     break;
                 }
                 case MSG_ABORT_TRANSIENT: {
-                    final int displayId = msg.arg1;
-                    final int[] types = (int[]) msg.obj;
+                    args = (SomeArgs) msg.obj;
+                    final int displayId = args.argi1;
+                    final int types = args.argi2;
+                    args.recycle();
                     for (int i = 0; i < mCallbacks.size(); i++) {
                         mCallbacks.get(i).abortTransient(displayId, types);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 1c4e319..dff79c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -26,6 +26,7 @@
 import static android.view.View.VISIBLE;
 
 import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
+import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED;
 import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION;
@@ -95,6 +96,7 @@
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.log.LogLevel;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
@@ -127,7 +129,7 @@
 @SysUISingleton
 public class KeyguardIndicationController {
 
-    private static final String TAG = "KeyguardIndication";
+    public static final String TAG = "KeyguardIndication";
     private static final boolean DEBUG_CHARGING_SPEED = false;
 
     private static final int MSG_SHOW_ACTION_TO_UNLOCK = 1;
@@ -327,9 +329,11 @@
         mInitialTextColorState = mTopIndicationView != null
                 ? mTopIndicationView.getTextColors() : ColorStateList.valueOf(Color.WHITE);
         mRotateTextViewController = new KeyguardIndicationRotateTextViewController(
-            mLockScreenIndicationView,
-            mExecutor,
-            mStatusBarStateController);
+                mLockScreenIndicationView,
+                mExecutor,
+                mStatusBarStateController,
+                mKeyguardLogger
+        );
         updateDeviceEntryIndication(false /* animate */);
         updateOrganizedOwnedDevice();
         if (mBroadcastReceiver == null) {
@@ -551,23 +555,23 @@
                             .build(),
                     true
             );
-            if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) {
-                mRotateTextViewController.updateIndication(
-                        INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
-                        new KeyguardIndication.Builder()
-                                .setMessage(mBiometricMessageFollowUp)
-                                .setMinVisibilityMillis(IMPORTANT_MSG_MIN_DURATION)
-                                .setTextColor(mInitialTextColorState)
-                                .build(),
-                        true
-                );
-            } else {
-                mRotateTextViewController.hideIndication(
-                        INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP);
-            }
         } else {
-            mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE);
-            mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP);
+            mRotateTextViewController.hideIndication(
+                    INDICATION_TYPE_BIOMETRIC_MESSAGE);
+        }
+        if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) {
+            mRotateTextViewController.updateIndication(
+                    INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
+                    new KeyguardIndication.Builder()
+                            .setMessage(mBiometricMessageFollowUp)
+                            .setMinVisibilityMillis(IMPORTANT_MSG_MIN_DURATION)
+                            .setTextColor(mInitialTextColorState)
+                            .build(),
+                    true
+            );
+        } else {
+            mRotateTextViewController.hideIndication(
+                    INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP);
         }
     }
 
@@ -796,7 +800,8 @@
      */
     private void showBiometricMessage(CharSequence biometricMessage,
             @Nullable CharSequence biometricMessageFollowUp) {
-        if (TextUtils.equals(biometricMessage, mBiometricMessage)) {
+        if (TextUtils.equals(biometricMessage, mBiometricMessage)
+                && TextUtils.equals(biometricMessageFollowUp, mBiometricMessageFollowUp)) {
             return;
         }
 
@@ -805,7 +810,8 @@
 
         mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK);
         hideBiometricMessageDelayed(
-                mBiometricMessageFollowUp != null
+                !TextUtils.isEmpty(mBiometricMessage)
+                        && !TextUtils.isEmpty(mBiometricMessageFollowUp)
                         ? IMPORTANT_MSG_MIN_DURATION * 2
                         : DEFAULT_HIDE_DELAY_MS
         );
@@ -839,6 +845,7 @@
      * may continuously be cycled through.
      */
     protected final void updateDeviceEntryIndication(boolean animate) {
+        mKeyguardLogger.logUpdateDeviceEntryIndication(animate, mVisible, mDozing);
         if (!mVisible) {
             return;
         }
@@ -1103,6 +1110,8 @@
                     && msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
             final boolean faceAuthFailed = biometricSourceType == FACE
                     && msgId == BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; // ran through matcher & failed
+            final boolean fpAuthFailed = biometricSourceType == FINGERPRINT
+                    && msgId == BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; // ran matcher & failed
             final boolean isUnlockWithFingerprintPossible = canUnlockWithFingerprint();
             final boolean isCoExFaceAcquisitionMessage =
                     faceAuthSoftError && isUnlockWithFingerprintPossible;
@@ -1125,6 +1134,22 @@
                             mContext.getString(R.string.keyguard_face_failed),
                             mContext.getString(R.string.keyguard_suggest_fingerprint)
                     );
+                } else if (fpAuthFailed
+                        && mKeyguardUpdateMonitor.getUserUnlockedWithFace(getCurrentUser())) {
+                    // face had already previously unlocked the device, so instead of showing a
+                    // fingerprint error, tell them they have already unlocked with face auth
+                    // and how to enter their device
+                    showBiometricMessage(
+                            mContext.getString(R.string.keyguard_face_successful_unlock),
+                            mContext.getString(R.string.keyguard_unlock)
+                    );
+                } else if (fpAuthFailed
+                        && mKeyguardUpdateMonitor.getUserHasTrust(
+                                KeyguardUpdateMonitor.getCurrentUser())) {
+                    showBiometricMessage(
+                            getTrustGrantedIndication(),
+                            mContext.getString(R.string.keyguard_unlock)
+                    );
                 } else {
                     showBiometricMessage(helpString);
                 }
@@ -1408,6 +1433,7 @@
         public void onKeyguardShowingChanged() {
             // All transient messages are gone the next time keyguard is shown
             if (!mKeyguardStateController.isShowing()) {
+                mKeyguardLogger.log(TAG, LogLevel.DEBUG, "clear messages");
                 mTopIndicationView.clearMessages();
                 mRotateTextViewController.clearMessages();
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 5b62d30..93aff7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -31,15 +31,19 @@
 import android.os.UserHandle
 import android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS
 import android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS
+import android.provider.Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED
 import android.util.Log
 import android.view.ContextThemeWrapper
 import android.view.View
 import android.view.ViewGroup
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.settingslib.Utils
+import com.android.systemui.Dumpable
 import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.plugins.ActivityStarter
@@ -52,12 +56,16 @@
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shared.regionsampling.RegionSampler
 import com.android.systemui.shared.regionsampling.UpdateColorCallback
+import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DATE_SMARTSPACE_DATA_PLUGIN
 import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
+import com.android.systemui.plugins.Weather
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.util.concurrency.Execution
 import com.android.systemui.util.settings.SecureSettings
+import java.io.PrintWriter
+import java.time.Instant
 import java.util.Optional
 import java.util.concurrent.Executor
 import javax.inject.Inject
@@ -80,20 +88,25 @@
         private val statusBarStateController: StatusBarStateController,
         private val deviceProvisionedController: DeviceProvisionedController,
         private val bypassController: KeyguardBypassController,
+        private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+        private val dumpManager: DumpManager,
         private val execution: Execution,
         @Main private val uiExecutor: Executor,
         @Background private val bgExecutor: Executor,
         @Main private val handler: Handler,
+        @Named(DATE_SMARTSPACE_DATA_PLUGIN)
+        optionalDatePlugin: Optional<BcSmartspaceDataPlugin>,
         @Named(WEATHER_SMARTSPACE_DATA_PLUGIN)
         optionalWeatherPlugin: Optional<BcSmartspaceDataPlugin>,
         optionalPlugin: Optional<BcSmartspaceDataPlugin>,
         optionalConfigPlugin: Optional<BcSmartspaceConfigPlugin>,
-) {
+) : Dumpable {
     companion object {
         private const val TAG = "LockscreenSmartspaceController"
     }
 
     private var session: SmartspaceSession? = null
+    private val datePlugin: BcSmartspaceDataPlugin? = optionalDatePlugin.orElse(null)
     private val weatherPlugin: BcSmartspaceDataPlugin? = optionalWeatherPlugin.orElse(null)
     private val plugin: BcSmartspaceDataPlugin? = optionalPlugin.orElse(null)
     private val configPlugin: BcSmartspaceConfigPlugin? = optionalConfigPlugin.orElse(null)
@@ -161,6 +174,17 @@
             }
             isContentUpdatedOnce = true
         }
+
+        val now = Instant.now()
+        val weatherTarget = targets.find { t ->
+            t.featureType == SmartspaceTarget.FEATURE_WEATHER &&
+                    now.isAfter(Instant.ofEpochMilli(t.creationTimeMillis)) &&
+                    now.isBefore(Instant.ofEpochMilli(t.expiryTimeMillis))
+        }
+        if (weatherTarget != null) {
+            val weatherData = Weather.fromBundle(weatherTarget.baseAction.extras)
+            keyguardUpdateMonitor.sendWeatherData(weatherData)
+        }
     }
 
     private val userTrackerCallback = object : UserTracker.Callback {
@@ -211,6 +235,7 @@
 
     init {
         deviceProvisionedController.addCallback(deviceProvisionedListener)
+        dumpManager.registerDumpable(this)
     }
 
     fun isEnabled(): Boolean {
@@ -223,7 +248,18 @@
         execution.assertIsMainThread()
 
         return featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED) &&
-                weatherPlugin != null
+                datePlugin != null && weatherPlugin != null
+    }
+
+    fun isWeatherEnabled(): Boolean {
+       execution.assertIsMainThread()
+       val defaultValue = context.getResources().getBoolean(
+               com.android.internal.R.bool.config_lockscreenWeatherEnabledByDefault)
+       val showWeather = secureSettings.getIntForUser(
+           LOCK_SCREEN_WEATHER_ENABLED,
+           if (defaultValue) 1 else 0,
+           userTracker.userId) == 1
+       return showWeather
     }
 
     private fun updateBypassEnabled() {
@@ -232,6 +268,25 @@
     }
 
     /**
+     * Constructs the date view and connects it to the smartspace service.
+     */
+    fun buildAndConnectDateView(parent: ViewGroup): View? {
+        execution.assertIsMainThread()
+
+        if (!isEnabled()) {
+            throw RuntimeException("Cannot build view when not enabled")
+        }
+        if (!isDateWeatherDecoupled()) {
+            throw RuntimeException("Cannot build date view when not decoupled")
+        }
+
+        val view = buildView(parent, datePlugin)
+        connectSession()
+
+        return view
+    }
+
+    /**
      * Constructs the weather view and connects it to the smartspace service.
      */
     fun buildAndConnectWeatherView(parent: ViewGroup): View? {
@@ -309,7 +364,7 @@
     }
 
     private fun connectSession() {
-        if (weatherPlugin == null && plugin == null) return
+        if (datePlugin == null && weatherPlugin == null && plugin == null) return
         if (session != null || smartspaceViews.isEmpty()) {
             return
         }
@@ -347,6 +402,7 @@
         statusBarStateController.addCallback(statusBarStateListener)
         bypassController.registerOnBypassStateChangedListener(bypassStateChangedListener)
 
+        datePlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
         weatherPlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
         plugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
 
@@ -384,6 +440,8 @@
         bypassController.unregisterOnBypassStateChangedListener(bypassStateChangedListener)
         session = null
 
+        datePlugin?.registerSmartspaceEventNotifier(null)
+
         weatherPlugin?.registerSmartspaceEventNotifier(null)
         weatherPlugin?.onTargetsAvailable(emptyList())
 
@@ -491,4 +549,11 @@
         }
         return null
     }
+
+    override fun dump(pw: PrintWriter, args: Array<out String>) {
+        pw.println("Region Samplers: ${regionSamplers.size}")
+        regionSamplers.map { (_, sampler) ->
+            sampler.dump(pw)
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
index 0c95eab..058042c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
@@ -71,9 +71,11 @@
      * marking them as relevant for setup are allowed to show when device is unprovisioned
      */
     private boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
-        // system_server checks the permission so systemui can just check whether the
-        // extra exists
-        return sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
+        final boolean hasPermission = checkUidPermission(
+                Manifest.permission.NOTIFICATION_DURING_SETUP,
+                sbn.getUid()) == PackageManager.PERMISSION_GRANTED;
+        return hasPermission
+                && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
     }
 
     private int checkUidPermission(String permission, int uid) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 5f6a5cb..26f97de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -63,7 +63,7 @@
  * are not.
  */
 public class NotificationLogger implements StateListener {
-    private static final String TAG = "NotificationLogger";
+    static final String TAG = "NotificationLogger";
     private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
 
     /** The minimum delay in ms between reports of notification visibility. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
index ec8501a..cc1103d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
@@ -18,6 +18,7 @@
 package com.android.systemui.statusbar.notification.logging
 
 import android.app.StatsManager
+import android.util.Log
 import android.util.StatsEvent
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
@@ -25,6 +26,7 @@
 import com.android.systemui.shared.system.SysUiStatsLog
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.util.traceSection
+import java.lang.Exception
 import java.util.concurrent.Executor
 import javax.inject.Inject
 import kotlin.math.roundToInt
@@ -82,43 +84,56 @@
                 return StatsManager.PULL_SKIP
             }
 
-            // Notifications can only be retrieved on the main thread, so switch to that thread.
-            val notifications = getAllNotificationsOnMainThread()
-            val notificationMemoryUse =
-                NotificationMemoryMeter.notificationMemoryUse(notifications)
-                    .sortedWith(
-                        compareBy(
-                            { it.packageName },
-                            { it.objectUsage.style },
-                            { it.notificationKey }
+            try {
+                // Notifications can only be retrieved on the main thread, so switch to that thread.
+                val notifications = getAllNotificationsOnMainThread()
+                val notificationMemoryUse =
+                    NotificationMemoryMeter.notificationMemoryUse(notifications)
+                        .sortedWith(
+                            compareBy(
+                                { it.packageName },
+                                { it.objectUsage.style },
+                                { it.notificationKey }
+                            )
+                        )
+                val usageData = aggregateMemoryUsageData(notificationMemoryUse)
+                usageData.forEach { (_, use) ->
+                    data.add(
+                        SysUiStatsLog.buildStatsEvent(
+                            SysUiStatsLog.NOTIFICATION_MEMORY_USE,
+                            use.uid,
+                            use.style,
+                            use.count,
+                            use.countWithInflatedViews,
+                            toKb(use.smallIconObject),
+                            use.smallIconBitmapCount,
+                            toKb(use.largeIconObject),
+                            use.largeIconBitmapCount,
+                            toKb(use.bigPictureObject),
+                            use.bigPictureBitmapCount,
+                            toKb(use.extras),
+                            toKb(use.extenders),
+                            toKb(use.smallIconViews),
+                            toKb(use.largeIconViews),
+                            toKb(use.systemIconViews),
+                            toKb(use.styleViews),
+                            toKb(use.customViews),
+                            toKb(use.softwareBitmaps),
+                            use.seenCount
                         )
                     )
-            val usageData = aggregateMemoryUsageData(notificationMemoryUse)
-            usageData.forEach { (_, use) ->
-                data.add(
-                    SysUiStatsLog.buildStatsEvent(
-                        SysUiStatsLog.NOTIFICATION_MEMORY_USE,
-                        use.uid,
-                        use.style,
-                        use.count,
-                        use.countWithInflatedViews,
-                        toKb(use.smallIconObject),
-                        use.smallIconBitmapCount,
-                        toKb(use.largeIconObject),
-                        use.largeIconBitmapCount,
-                        toKb(use.bigPictureObject),
-                        use.bigPictureBitmapCount,
-                        toKb(use.extras),
-                        toKb(use.extenders),
-                        toKb(use.smallIconViews),
-                        toKb(use.largeIconViews),
-                        toKb(use.systemIconViews),
-                        toKb(use.styleViews),
-                        toKb(use.customViews),
-                        toKb(use.softwareBitmaps),
-                        use.seenCount
-                    )
-                )
+                }
+            } catch (e: InterruptedException) {
+                // This can happen if the device is sleeping or view walking takes too long.
+                // The statsd collector will interrupt the thread and we need to handle it
+                // gracefully.
+                Log.w(NotificationLogger.TAG, "Timed out when measuring notification memory.", e)
+                return@traceSection StatsManager.PULL_SKIP
+            } catch (e: Exception) {
+                // Error while collecting data, this should not crash prod SysUI. Just
+                // log WTF and move on.
+                Log.wtf(NotificationLogger.TAG, "Failed to measure notification memory.", e)
+                return@traceSection StatsManager.PULL_SKIP
             }
 
             return StatsManager.PULL_SUCCESS
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt
index 2d04211..6491223 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt
@@ -184,19 +184,21 @@
     private fun computeDrawableUse(drawable: Drawable, seenObjects: HashSet<Int>): Int =
         when (drawable) {
             is BitmapDrawable -> {
-                val ref = System.identityHashCode(drawable.bitmap)
-                if (seenObjects.contains(ref)) {
-                    0
-                } else {
-                    seenObjects.add(ref)
-                    drawable.bitmap.allocationByteCount
-                }
+                drawable.bitmap?.let {
+                    val ref = System.identityHashCode(it)
+                    if (seenObjects.contains(ref)) {
+                        0
+                    } else {
+                        seenObjects.add(ref)
+                        it.allocationByteCount
+                    }
+                } ?: 0
             }
             else -> 0
         }
 
     private fun isDrawableSoftwareBitmap(drawable: Drawable) =
-        drawable is BitmapDrawable && drawable.bitmap.config != Bitmap.Config.HARDWARE
+        drawable is BitmapDrawable && drawable.bitmap?.config != Bitmap.Config.HARDWARE
 
     private fun identifierForView(view: View) =
         if (view.id == View.NO_ID) {
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 4a023c4..d93c12b 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
@@ -1051,7 +1051,7 @@
     }
 
     /**
-     * @return one of the static enum types in this view, calculated form the current state
+     * @return one of the static enum types in this view, calculated from the current state
      */
     public int calculateVisibleType() {
         if (mUserExpanding) {
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 aab36da..1fb7eb5 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
@@ -147,7 +147,7 @@
     private boolean mShadeNeedsToClose = false;
 
     @VisibleForTesting
-    static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
+    static final float RUBBER_BAND_FACTOR_NORMAL = 0.1f;
     private static final float RUBBER_BAND_FACTOR_AFTER_EXPAND = 0.15f;
     private static final float RUBBER_BAND_FACTOR_ON_PANEL_EXPAND = 0.21f;
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 856d7de..fecaa3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.containsType;
-
 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
 
@@ -36,8 +33,8 @@
 import android.os.Vibrator;
 import android.util.Log;
 import android.util.Slog;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.KeyEvent;
+import android.view.WindowInsets;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsController.Appearance;
 import android.view.WindowInsetsController.Behavior;
@@ -168,11 +165,11 @@
     }
 
     @Override
-    public void abortTransient(int displayId, @InternalInsetsType int[] types) {
+    public void abortTransient(int displayId, @InsetsType int types) {
         if (displayId != mDisplayId) {
             return;
         }
-        if (!containsType(types, ITYPE_STATUS_BAR)) {
+        if ((types & WindowInsets.Type.statusBars()) == 0) {
             return;
         }
         mCentralSurfaces.clearTransient();
@@ -489,12 +486,11 @@
     }
 
     @Override
-    public void showTransient(int displayId, @InternalInsetsType int[] types,
-            boolean isGestureOnSystemBar) {
+    public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) {
         if (displayId != mDisplayId) {
             return;
         }
-        if (!containsType(types, ITYPE_STATUS_BAR)) {
+        if ((types & WindowInsets.Type.statusBars()) == 0) {
             return;
         }
         mCentralSurfaces.showTransientUnchecked();
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 e595ddf..1966a66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -21,8 +21,6 @@
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.WindowVisibleState;
 import static android.app.StatusBarManager.windowStateToString;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.containsType;
 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
@@ -100,6 +98,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewRootImpl;
+import android.view.WindowInsets;
 import android.view.WindowInsetsController.Appearance;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
@@ -943,7 +942,7 @@
         // Set up the initial notification state. This needs to happen before CommandQueue.disable()
         setUpPresenter();
 
-        if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) {
+        if ((result.mTransientBarTypes & WindowInsets.Type.statusBars()) != 0) {
             showTransientUnchecked();
         }
         mCommandQueueCallbacks.onSystemBarAttributesChanged(mDisplayId, result.mAppearance,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index c248a50..b88531e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -352,7 +352,7 @@
     }
 
     private boolean willAnimateFromLockScreenToAod() {
-        return getAlwaysOn() && mKeyguardVisible;
+        return shouldControlScreenOff() && mKeyguardVisible;
     }
 
     private boolean getBoolean(String propName, int resId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 01af486..c163a89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -89,14 +89,19 @@
     private float mPanelExpansion;
 
     /**
-     * Burn-in prevention x translation.
+     * Max burn-in prevention x translation.
      */
-    private int mBurnInPreventionOffsetX;
+    private int mMaxBurnInPreventionOffsetX;
 
     /**
-     * Burn-in prevention y translation for clock layouts.
+     * Max burn-in prevention y translation for clock layouts.
      */
-    private int mBurnInPreventionOffsetYClock;
+    private int mMaxBurnInPreventionOffsetYClock;
+
+    /**
+     * Current burn-in prevention y translation.
+     */
+    private float mCurrentBurnInOffsetY;
 
     /**
      * Doze/AOD transition amount.
@@ -155,9 +160,9 @@
 
         mContainerTopPadding =
                 res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
-        mBurnInPreventionOffsetX = res.getDimensionPixelSize(
+        mMaxBurnInPreventionOffsetX = res.getDimensionPixelSize(
                 R.dimen.burn_in_prevention_offset_x);
-        mBurnInPreventionOffsetYClock = res.getDimensionPixelSize(
+        mMaxBurnInPreventionOffsetYClock = res.getDimensionPixelSize(
                 R.dimen.burn_in_prevention_offset_y_clock);
     }
 
@@ -215,7 +220,10 @@
         if (mBypassEnabled) {
             return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount);
         } else if (mIsSplitShade) {
-            return clockYPosition - mSplitShadeTopNotificationsMargin + mUserSwitchHeight;
+            // mCurrentBurnInOffsetY is subtracted to make notifications not follow clock adjustment
+            // for burn-in. It can make pulsing notification go too high and it will get clipped
+            return clockYPosition - mSplitShadeTopNotificationsMargin + mUserSwitchHeight
+                    - (int) mCurrentBurnInOffsetY;
         } else {
             return clockYPosition + mKeyguardStatusHeight;
         }
@@ -255,11 +263,11 @@
 
         // This will keep the clock at the top but out of the cutout area
         float shift = 0;
-        if (clockY - mBurnInPreventionOffsetYClock < mCutoutTopInset) {
-            shift = mCutoutTopInset - (clockY - mBurnInPreventionOffsetYClock);
+        if (clockY - mMaxBurnInPreventionOffsetYClock < mCutoutTopInset) {
+            shift = mCutoutTopInset - (clockY - mMaxBurnInPreventionOffsetYClock);
         }
 
-        int burnInPreventionOffsetY = mBurnInPreventionOffsetYClock; // requested offset
+        int burnInPreventionOffsetY = mMaxBurnInPreventionOffsetYClock; // requested offset
         final boolean hasUdfps = mUdfpsTop > -1;
         if (hasUdfps && !mIsClockTopAligned) {
             // ensure clock doesn't overlap with the udfps icon
@@ -267,8 +275,8 @@
                 // sometimes the clock textView extends beyond udfps, so let's just use the
                 // space above the KeyguardStatusView/clock as our burn-in offset
                 burnInPreventionOffsetY = (int) (clockY - mCutoutTopInset) / 2;
-                if (mBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
-                    burnInPreventionOffsetY = mBurnInPreventionOffsetYClock;
+                if (mMaxBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
+                    burnInPreventionOffsetY = mMaxBurnInPreventionOffsetYClock;
                 }
                 shift = -burnInPreventionOffsetY;
             } else {
@@ -276,16 +284,18 @@
                 float lowerSpace = mUdfpsTop - mClockBottom;
                 // center the burn-in offset within the upper + lower space
                 burnInPreventionOffsetY = (int) (lowerSpace + upperSpace) / 2;
-                if (mBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
-                    burnInPreventionOffsetY = mBurnInPreventionOffsetYClock;
+                if (mMaxBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
+                    burnInPreventionOffsetY = mMaxBurnInPreventionOffsetYClock;
                 }
                 shift = (lowerSpace - upperSpace) / 2;
             }
         }
 
+        float fullyDarkBurnInOffset = burnInPreventionOffsetY(burnInPreventionOffsetY);
         float clockYDark = clockY
-                + burnInPreventionOffsetY(burnInPreventionOffsetY)
+                + fullyDarkBurnInOffset
                 + shift;
+        mCurrentBurnInOffsetY = MathUtils.lerp(0, fullyDarkBurnInOffset, darkAmount);
         return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mOverStretchAmount);
     }
 
@@ -325,7 +335,7 @@
     }
 
     private float burnInPreventionOffsetX() {
-        return getBurnInOffset(mBurnInPreventionOffsetX, true /* xAxis */);
+        return getBurnInOffset(mMaxBurnInPreventionOffsetX, true /* xAxis */);
     }
 
     public static class Result {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index d24469e..b1553b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -165,6 +165,13 @@
         }
     }
 
+    /**
+     * Get the message that should be shown after the previous text animates out.
+     */
+    public CharSequence getMessage() {
+        return mMessage;
+    }
+
     private AnimatorSet getOutAnimator() {
         AnimatorSet animatorSet = new AnimatorSet();
         Animator fadeOut = ObjectAnimator.ofFloat(this, View.ALPHA, 0f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index 4550cb2..8ee2c6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -76,7 +76,7 @@
                 FaceAuthApiRequestReason.PICK_UP_GESTURE_TRIGGERED
             )
             keyguardUpdateMonitor.requestActiveUnlock(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE,
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE,
                 "KeyguardLiftController")
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 416bc71..5408afb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -163,7 +163,8 @@
         for (int i = currentSlots.size() - 1; i >= 0; i--) {
             Slot s = currentSlots.get(i);
             slotsToReAdd.put(s, s.getHolderList());
-            removeAllIconsForSlot(s.getName());
+            // Don't force here because the new pipeline properly handles the tuner settings
+            removeAllIconsForSlot(s.getName(), /* force */ false);
         }
 
         // Add them all back
@@ -285,7 +286,7 @@
         // Because of the way we cache the icon holders, we need to remove everything any time
         // we get a new set of subscriptions. This might change in the future, but is required
         // to support demo mode for now
-        removeAllIconsForSlot(slotName);
+        removeAllIconsForSlot(slotName, /* force */ true);
 
         Collections.reverse(subIds);
 
@@ -428,6 +429,14 @@
     /** */
     @Override
     public void removeIcon(String slot, int tag) {
+        // If the new pipeline is on for this icon, don't allow removal, since the new pipeline
+        // will never call this method
+        if (mStatusBarPipelineFlags.isIconControlledByFlags(slot)) {
+            Log.i(TAG, "Ignoring removal of (" + slot + "). "
+                    + "It should be controlled elsewhere");
+            return;
+        }
+
         if (mStatusBarIconList.getIconHolder(slot, tag) == null) {
             return;
         }
@@ -444,6 +453,18 @@
     /** */
     @Override
     public void removeAllIconsForSlot(String slotName) {
+        removeAllIconsForSlot(slotName, /* force */ false);
+    }
+
+    private void removeAllIconsForSlot(String slotName, Boolean force) {
+        // If the new pipeline is on for this icon, don't allow removal, since the new pipeline
+        // will never call this method
+        if (!force && mStatusBarPipelineFlags.isIconControlledByFlags(slotName)) {
+            Log.i(TAG, "Ignoring removal of (" + slotName + "). "
+                    + "It should be controlled elsewhere");
+            return;
+        }
+
         Slot slot = mStatusBarIconList.getSlot(slotName);
         if (!slot.hasIconsInSlot()) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
index 344d233..c1c6c88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.view.ViewStub;
 
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.LockIconView;
 import com.android.systemui.R;
 import com.android.systemui.battery.BatteryMeterView;
@@ -67,6 +68,7 @@
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.CarrierConfigTracker;
 import com.android.systemui.util.settings.SecureSettings;
@@ -299,7 +301,9 @@
             OperatorNameViewController.Factory operatorNameViewControllerFactory,
             SecureSettings secureSettings,
             @Main Executor mainExecutor,
-            DumpManager dumpManager
+            DumpManager dumpManager,
+            StatusBarWindowStateController statusBarWindowStateController,
+            KeyguardUpdateMonitor keyguardUpdateMonitor
     ) {
         return new CollapsedStatusBarFragment(statusBarFragmentComponentFactory,
                 ongoingCallController,
@@ -320,7 +324,9 @@
                 operatorNameViewControllerFactory,
                 secureSettings,
                 mainExecutor,
-                dumpManager);
+                dumpManager,
+                statusBarWindowStateController,
+                keyguardUpdateMonitor);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index cbd27cf..65becf7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -44,6 +44,7 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
@@ -72,6 +73,8 @@
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
+import com.android.systemui.statusbar.window.StatusBarWindowStateListener;
 import com.android.systemui.util.CarrierConfigTracker;
 import com.android.systemui.util.CarrierConfigTracker.CarrierConfigChangedListener;
 import com.android.systemui.util.CarrierConfigTracker.DefaultDataSubscriptionChangedListener;
@@ -129,6 +132,8 @@
     private final SecureSettings mSecureSettings;
     private final Executor mMainExecutor;
     private final DumpManager mDumpManager;
+    private final StatusBarWindowStateController mStatusBarWindowStateController;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
     private List<String> mBlockedIcons = new ArrayList<>();
     private Map<Startable, Startable.State> mStartableStates = new ArrayMap<>();
@@ -164,6 +169,22 @@
                 }
             };
 
+    /**
+     * Whether we've launched the secure camera over the lockscreen, but haven't yet received a
+     * status bar window state change afterward.
+     *
+     * We wait for this state change (which will tell us whether to show/hide the status bar icons)
+     * so that there is no flickering/jump cutting during the camera launch.
+     */
+    private boolean mWaitingForWindowStateChangeAfterCameraLaunch = false;
+
+    /**
+     * Listener that updates {@link #mWaitingForWindowStateChangeAfterCameraLaunch} when it receives
+     * a new status bar window state.
+     */
+    private final StatusBarWindowStateListener mStatusBarWindowStateListener = state ->
+            mWaitingForWindowStateChangeAfterCameraLaunch = false;
+
     @SuppressLint("ValidFragment")
     public CollapsedStatusBarFragment(
             StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
@@ -185,7 +206,9 @@
             OperatorNameViewController.Factory operatorNameViewControllerFactory,
             SecureSettings secureSettings,
             @Main Executor mainExecutor,
-            DumpManager dumpManager
+            DumpManager dumpManager,
+            StatusBarWindowStateController statusBarWindowStateController,
+            KeyguardUpdateMonitor keyguardUpdateMonitor
     ) {
         mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory;
         mOngoingCallController = ongoingCallController;
@@ -207,6 +230,20 @@
         mSecureSettings = secureSettings;
         mMainExecutor = mainExecutor;
         mDumpManager = dumpManager;
+        mStatusBarWindowStateController = statusBarWindowStateController;
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mStatusBarWindowStateController.addListener(mStatusBarWindowStateListener);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mStatusBarWindowStateController.removeListener(mStatusBarWindowStateListener);
     }
 
     @Override
@@ -254,6 +291,11 @@
         mCarrierConfigTracker.addDefaultDataSubscriptionChangedListener(mDefaultDataListener);
     }
 
+    @Override
+    public void onCameraLaunchGestureDetected(int source) {
+        mWaitingForWindowStateChangeAfterCameraLaunch = true;
+    }
+
     @VisibleForTesting
     void updateBlockedIcons() {
         mBlockedIcons.clear();
@@ -466,6 +508,27 @@
                 && mNotificationPanelViewController.hideStatusBarIconsWhenExpanded()) {
             return true;
         }
+
+        // When launching the camera over the lockscreen, the icons become visible momentarily
+        // before animating out, since we're not yet aware that the launching camera activity is
+        // fullscreen. Even once the activity finishes launching, it takes a short time before WM
+        // decides that the top app wants to hide the icons and tells us to hide them. To ensure
+        // that this high-visibility animation is smooth, keep the icons hidden during a camera
+        // launch until we receive a window state change which indicates that the activity is done
+        // launching and WM has decided to show/hide the icons. For extra safety (to ensure the
+        // icons don't remain hidden somehow) we double check that the camera is still showing, the
+        // status bar window isn't hidden, and we're still occluded as well, though these checks
+        // are typically unnecessary.
+        final boolean hideIconsForSecureCamera =
+                (mWaitingForWindowStateChangeAfterCameraLaunch ||
+                        !mStatusBarWindowStateController.windowIsShowing()) &&
+                        mKeyguardUpdateMonitor.isSecureCameraLaunchedOverKeyguard() &&
+                        mKeyguardStateController.isOccluded();
+
+        if (hideIconsForSecureCamera) {
+            return true;
+        }
+
         return mStatusBarHideIconsForBouncerManager.getShouldHideStatusBarIconsForBouncer();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
index 15fed32..4a684d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.pipeline
 
+import android.content.Context
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
@@ -23,7 +24,15 @@
 
 /** All flagging methods related to the new status bar pipeline (see b/238425913). */
 @SysUISingleton
-class StatusBarPipelineFlags @Inject constructor(private val featureFlags: FeatureFlags) {
+class StatusBarPipelineFlags
+@Inject
+constructor(
+    context: Context,
+    private val featureFlags: FeatureFlags,
+) {
+    private val mobileSlot = context.getString(com.android.internal.R.string.status_bar_mobile)
+    private val wifiSlot = context.getString(com.android.internal.R.string.status_bar_wifi)
+
     /** True if we should display the mobile icons using the new status bar data pipeline. */
     fun useNewMobileIcons(): Boolean = featureFlags.isEnabled(Flags.NEW_STATUS_BAR_MOBILE_ICONS)
 
@@ -54,4 +63,13 @@
      */
     fun useDebugColoring(): Boolean =
         featureFlags.isEnabled(Flags.NEW_STATUS_BAR_ICONS_DEBUG_COLORING)
+
+    /**
+     * For convenience in the StatusBarIconController, we want to gate some actions based on slot
+     * name and the flag together.
+     *
+     * @return true if this icon is controlled by any of the status bar pipeline flags
+     */
+    fun isIconControlledByFlags(slotName: String): Boolean =
+        slotName == wifiSlot && useNewWifiIcon() || slotName == mobileSlot && useNewMobileIcons()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileSummaryLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileSummaryLog.kt
new file mode 100644
index 0000000..2ac9ab3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileSummaryLog.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.dagger
+
+import javax.inject.Qualifier
+
+/**
+ * Logs for mobile data that's **the same across all connections**.
+ *
+ * This buffer should only be used for the mobile parent classes like [MobileConnectionsRepository]
+ * and [MobileIconsInteractor]. It should *not* be used for classes that represent an individual
+ * connection, like [MobileConnectionRepository] or [MobileIconInteractor].
+ */
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class MobileSummaryLog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index 0993ab370..60de1a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepositoryImpl
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigCoreStartable
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileRepositorySwitcher
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
@@ -82,6 +83,11 @@
     @ClassKey(MobileUiAdapter::class)
     abstract fun bindFeature(impl: MobileUiAdapter): CoreStartable
 
+    @Binds
+    @IntoMap
+    @ClassKey(CarrierConfigCoreStartable::class)
+    abstract fun bindCarrierConfigStartable(impl: CarrierConfigCoreStartable): CoreStartable
+
     companion object {
         @Provides
         @SysUISingleton
@@ -112,5 +118,12 @@
         fun provideAirplaneTableLogBuffer(factory: TableLogBufferFactory): TableLogBuffer {
             return factory.create("AirplaneTableLog", 30)
         }
+
+        @Provides
+        @SysUISingleton
+        @MobileSummaryLog
+        fun provideMobileSummaryLogBuffer(factory: TableLogBufferFactory): TableLogBuffer {
+            return factory.create("MobileSummaryLog", 100)
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
index 5479b92..85729c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
@@ -20,16 +20,21 @@
 import android.telephony.TelephonyManager.DATA_CONNECTING
 import android.telephony.TelephonyManager.DATA_DISCONNECTED
 import android.telephony.TelephonyManager.DATA_DISCONNECTING
+import android.telephony.TelephonyManager.DATA_HANDOVER_IN_PROGRESS
+import android.telephony.TelephonyManager.DATA_SUSPENDED
 import android.telephony.TelephonyManager.DATA_UNKNOWN
 import android.telephony.TelephonyManager.DataState
 
 /** Internal enum representation of the telephony data connection states */
-enum class DataConnectionState(@DataState val dataState: Int) {
-    Connected(DATA_CONNECTED),
-    Connecting(DATA_CONNECTING),
-    Disconnected(DATA_DISCONNECTED),
-    Disconnecting(DATA_DISCONNECTING),
-    Unknown(DATA_UNKNOWN),
+enum class DataConnectionState {
+    Connected,
+    Connecting,
+    Disconnected,
+    Disconnecting,
+    Suspended,
+    HandoverInProgress,
+    Unknown,
+    Invalid,
 }
 
 fun @receiver:DataState Int.toDataConnectionType(): DataConnectionState =
@@ -38,6 +43,8 @@
         DATA_CONNECTING -> DataConnectionState.Connecting
         DATA_DISCONNECTED -> DataConnectionState.Disconnected
         DATA_DISCONNECTING -> DataConnectionState.Disconnecting
+        DATA_SUSPENDED -> DataConnectionState.Suspended
+        DATA_HANDOVER_IN_PROGRESS -> DataConnectionState.HandoverInProgress
         DATA_UNKNOWN -> DataConnectionState.Unknown
-        else -> throw IllegalArgumentException("unknown data state received $this")
+        else -> DataConnectionState.Invalid
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
index 012b9ec..ed7f60b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
@@ -26,6 +26,7 @@
 import android.telephony.TelephonyCallback.SignalStrengthsListener
 import android.telephony.TelephonyDisplayInfo
 import android.telephony.TelephonyManager
+import androidx.annotation.VisibleForTesting
 import com.android.systemui.log.table.Diffable
 import com.android.systemui.log.table.TableRowLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
@@ -94,7 +95,7 @@
 ) : Diffable<MobileConnectionModel> {
     override fun logDiffs(prevVal: MobileConnectionModel, row: TableRowLogger) {
         if (prevVal.dataConnectionState != dataConnectionState) {
-            row.logChange(COL_CONNECTION_STATE, dataConnectionState.toString())
+            row.logChange(COL_CONNECTION_STATE, dataConnectionState.name)
         }
 
         if (prevVal.isEmergencyOnly != isEmergencyOnly) {
@@ -125,8 +126,12 @@
             row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
         }
 
-        if (prevVal.dataActivityDirection != dataActivityDirection) {
-            row.logChange(COL_ACTIVITY_DIRECTION, dataActivityDirection.toString())
+        if (prevVal.dataActivityDirection.hasActivityIn != dataActivityDirection.hasActivityIn) {
+            row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn)
+        }
+
+        if (prevVal.dataActivityDirection.hasActivityOut != dataActivityDirection.hasActivityOut) {
+            row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut)
         }
 
         if (prevVal.carrierNetworkChangeActive != carrierNetworkChangeActive) {
@@ -139,7 +144,7 @@
     }
 
     override fun logFull(row: TableRowLogger) {
-        row.logChange(COL_CONNECTION_STATE, dataConnectionState.toString())
+        row.logChange(COL_CONNECTION_STATE, dataConnectionState.name)
         row.logChange(COL_EMERGENCY, isEmergencyOnly)
         row.logChange(COL_ROAMING, isRoaming)
         row.logChange(COL_OPERATOR, operatorAlphaShort)
@@ -147,11 +152,13 @@
         row.logChange(COL_IS_GSM, isGsm)
         row.logChange(COL_CDMA_LEVEL, cdmaLevel)
         row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
-        row.logChange(COL_ACTIVITY_DIRECTION, dataActivityDirection.toString())
+        row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn)
+        row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut)
         row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
         row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
     }
 
+    @VisibleForTesting
     companion object {
         const val COL_EMERGENCY = "EmergencyOnly"
         const val COL_ROAMING = "Roaming"
@@ -161,7 +168,8 @@
         const val COL_CDMA_LEVEL = "CdmaLevel"
         const val COL_PRIMARY_LEVEL = "PrimaryLevel"
         const val COL_CONNECTION_STATE = "ConnectionState"
-        const val COL_ACTIVITY_DIRECTION = "DataActivity"
+        const val COL_ACTIVITY_DIRECTION_IN = "DataActivity.In"
+        const val COL_ACTIVITY_DIRECTION_OUT = "DataActivity.Out"
         const val COL_CARRIER_NETWORK_CHANGE = "CarrierNetworkChangeActive"
         const val COL_RESOLVED_NETWORK_TYPE = "NetworkType"
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectivityModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectivityModel.kt
index e618905..97a537a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectivityModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectivityModel.kt
@@ -17,6 +17,8 @@
 package com.android.systemui.statusbar.pipeline.mobile.data.model
 
 import android.net.NetworkCapabilities
+import com.android.systemui.log.table.Diffable
+import com.android.systemui.log.table.TableRowLogger
 
 /** Provides information about a mobile network connection */
 data class MobileConnectivityModel(
@@ -24,4 +26,24 @@
     val isConnected: Boolean = false,
     /** Whether the mobile transport is validated [NetworkCapabilities.NET_CAPABILITY_VALIDATED] */
     val isValidated: Boolean = false,
-)
+) : Diffable<MobileConnectivityModel> {
+    // TODO(b/267767715): Can we implement [logDiffs] and [logFull] generically for data classes?
+    override fun logDiffs(prevVal: MobileConnectivityModel, row: TableRowLogger) {
+        if (prevVal.isConnected != isConnected) {
+            row.logChange(COL_IS_CONNECTED, isConnected)
+        }
+        if (prevVal.isValidated != isValidated) {
+            row.logChange(COL_IS_VALIDATED, isValidated)
+        }
+    }
+
+    override fun logFull(row: TableRowLogger) {
+        row.logChange(COL_IS_CONNECTED, isConnected)
+        row.logChange(COL_IS_VALIDATED, isValidated)
+    }
+
+    companion object {
+        private const val COL_IS_CONNECTED = "isConnected"
+        private const val COL_IS_VALIDATED = "isValidated"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
new file mode 100644
index 0000000..8c82fba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.model
+
+import android.os.PersistableBundle
+import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL
+import android.telephony.CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL
+import androidx.annotation.VisibleForTesting
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/**
+ * Represents, for a given subscription ID, the set of keys about which SystemUI cares.
+ *
+ * Upon first creation, this config represents only the default configuration (see
+ * [android.telephony.CarrierConfigManager.getDefaultConfig]).
+ *
+ * Upon request (see
+ * [com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository]), an
+ * instance of this class may be created for a given subscription Id, and will default to
+ * representing the default carrier configuration. However, once a carrier config is received for
+ * this [subId], all fields will reflect those in the received config, using [PersistableBundle]'s
+ * default of false for any config that is not present in the override.
+ *
+ * To keep things relatively simple, this class defines a wrapper around each config key which
+ * exposes a StateFlow<Boolean> for each config we care about. It also tracks whether or not it is
+ * using the default config for logging purposes.
+ *
+ * NOTE to add new keys to be tracked:
+ * 1. Define a new `private val` wrapping the key using [BooleanCarrierConfig]
+ * 2. Define a public `val` exposing the wrapped flow using [BooleanCarrierConfig.config]
+ * 3. Add the new [BooleanCarrierConfig] to the list of tracked configs, so they are properly
+ * updated when a new carrier config comes down
+ */
+class SystemUiCarrierConfig
+internal constructor(
+    val subId: Int,
+    defaultConfig: PersistableBundle,
+) {
+    @VisibleForTesting
+    var isUsingDefault = true
+        private set
+
+    private val inflateSignalStrength =
+        BooleanCarrierConfig(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, defaultConfig)
+    /** Flow tracking the [KEY_INFLATE_SIGNAL_STRENGTH_BOOL] carrier config */
+    val shouldInflateSignalStrength: StateFlow<Boolean> = inflateSignalStrength.config
+
+    private val showOperatorName =
+        BooleanCarrierConfig(KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL, defaultConfig)
+    /** Flow tracking the [KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL] config */
+    val showOperatorNameInStatusBar: StateFlow<Boolean> = showOperatorName.config
+
+    private val trackedConfigs =
+        listOf(
+            inflateSignalStrength,
+            showOperatorName,
+        )
+
+    /** Ingest a new carrier config, and switch all of the tracked keys over to the new values */
+    fun processNewCarrierConfig(config: PersistableBundle) {
+        isUsingDefault = false
+        trackedConfigs.forEach { it.update(config) }
+    }
+
+    /** For dumpsys, shortcut if we haven't overridden any keys */
+    fun toStringConsideringDefaults(): String {
+        return if (isUsingDefault) {
+            "using defaults"
+        } else {
+            trackedConfigs.joinToString { it.toString() }
+        }
+    }
+
+    override fun toString(): String = trackedConfigs.joinToString { it.toString() }
+}
+
+/** Extracts [key] from the carrier config, and stores it in a flow */
+private class BooleanCarrierConfig(
+    val key: String,
+    defaultConfig: PersistableBundle,
+) {
+    private val _configValue = MutableStateFlow(defaultConfig.getBoolean(key))
+    val config = _configValue.asStateFlow()
+
+    fun update(config: PersistableBundle) {
+        _configValue.value = config.getBoolean(key)
+    }
+
+    override fun toString(): String {
+        return "$key=${config.value}"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigCoreStartable.kt
new file mode 100644
index 0000000..af58999
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigCoreStartable.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.statusbar.pipeline.mobile.data.repository
+
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.qualifiers.Application
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+/**
+ * Core startable which configures the [CarrierConfigRepository] to listen for updates for the
+ * lifetime of the process
+ */
+class CarrierConfigCoreStartable
+@Inject
+constructor(
+    private val carrierConfigRepository: CarrierConfigRepository,
+    @Application private val scope: CoroutineScope,
+) : CoreStartable {
+
+    override fun start() {
+        scope.launch { carrierConfigRepository.startObservingCarrierConfigUpdates() }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
new file mode 100644
index 0000000..5769f90
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.repository
+
+import android.content.IntentFilter
+import android.os.PersistableBundle
+import android.telephony.CarrierConfigManager
+import android.telephony.SubscriptionManager
+import android.util.SparseArray
+import androidx.annotation.VisibleForTesting
+import androidx.core.util.getOrElse
+import androidx.core.util.isEmpty
+import androidx.core.util.keyIterator
+import com.android.systemui.Dumpable
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import java.io.PrintWriter
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.shareIn
+
+/**
+ * Meant to be the source of truth regarding CarrierConfigs. These are configuration objects defined
+ * on a per-subscriptionId basis, and do not trigger a device configuration event.
+ *
+ * Designed to supplant [com.android.systemui.util.CarrierConfigTracker].
+ *
+ * See [SystemUiCarrierConfig] for details on how to add carrier config keys to be tracked
+ */
+@SysUISingleton
+class CarrierConfigRepository
+@Inject
+constructor(
+    broadcastDispatcher: BroadcastDispatcher,
+    private val carrierConfigManager: CarrierConfigManager,
+    dumpManager: DumpManager,
+    logger: ConnectivityPipelineLogger,
+    @Application scope: CoroutineScope,
+) : Dumpable {
+    private var isListening = false
+    private val defaultConfig: PersistableBundle by lazy { CarrierConfigManager.getDefaultConfig() }
+    // Used for logging the default config in the dumpsys
+    private val defaultConfigForLogs: SystemUiCarrierConfig by lazy {
+        SystemUiCarrierConfig(-1, defaultConfig)
+    }
+
+    private val configs = SparseArray<SystemUiCarrierConfig>()
+
+    init {
+        dumpManager.registerNormalDumpable(this)
+    }
+
+    @VisibleForTesting
+    val carrierConfigStream: SharedFlow<Pair<Int, PersistableBundle>> =
+        broadcastDispatcher
+            .broadcastFlow(IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
+                intent,
+                _ ->
+                intent.getIntExtra(
+                    CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
+                    SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                )
+            }
+            .onEach { logger.logCarrierConfigChanged(it) }
+            .filter { SubscriptionManager.isValidSubscriptionId(it) }
+            .mapNotNull { subId ->
+                val config = carrierConfigManager.getConfigForSubId(subId)
+                config?.let { subId to it }
+            }
+            .shareIn(scope, SharingStarted.WhileSubscribed())
+
+    /**
+     * Start this repository observing broadcasts for **all** carrier configuration updates. Must be
+     * called in order to keep SystemUI in sync with [CarrierConfigManager].
+     */
+    suspend fun startObservingCarrierConfigUpdates() {
+        isListening = true
+        carrierConfigStream.collect { updateCarrierConfig(it.first, it.second) }
+    }
+
+    /** Update or create the [SystemUiCarrierConfig] for subId with the override */
+    private fun updateCarrierConfig(subId: Int, config: PersistableBundle) {
+        val configToUpdate = getOrCreateConfigForSubId(subId)
+        configToUpdate.processNewCarrierConfig(config)
+    }
+
+    /** Gets a cached [SystemUiCarrierConfig], or creates a new one which will track the defaults */
+    fun getOrCreateConfigForSubId(subId: Int): SystemUiCarrierConfig {
+        return configs.getOrElse(subId) {
+            val config = SystemUiCarrierConfig(subId, defaultConfig)
+            val carrierConfig = carrierConfigManager.getConfigForSubId(subId)
+            if (carrierConfig != null) config.processNewCarrierConfig(carrierConfig)
+            configs.put(subId, config)
+            config
+        }
+    }
+
+    override fun dump(pw: PrintWriter, args: Array<out String>) {
+        pw.println("isListening: $isListening")
+        if (configs.isEmpty()) {
+            pw.println("no carrier configs loaded")
+        } else {
+            pw.println("Carrier configs by subId")
+            configs.keyIterator().forEach {
+                pw.println("  subId=$it")
+                pw.println("    config=${configs.get(it).toStringConsideringDefaults()}")
+            }
+            // Finally, print the default config
+            pw.println("Default config:")
+            pw.println("  $defaultConfigForLogs")
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt
index e0d156a..c640baa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.data.repository
 
-import android.provider.Settings
 import android.telephony.CarrierConfigManager
 import android.telephony.SubscriptionManager
 import com.android.settingslib.SignalIcon.MobileIconGroup
@@ -53,9 +52,6 @@
     /** Get or create a repository for the line of service for the given subscription ID */
     fun getRepoForSubId(subId: Int): MobileConnectionRepository
 
-    /** Observe changes to the [Settings.Global.MOBILE_DATA] setting */
-    val globalMobileDataSettingChangedEvent: Flow<Unit>
-
     /**
      * [Config] is an object that tracks relevant configuration flags for a given subscription ID.
      * In the case of [MobileMappings], it's hard-coded to check the default data subscription's
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
index b939856..7038a3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
@@ -156,9 +156,6 @@
                 realRepository.defaultMobileNetworkConnectivity.value
             )
 
-    override val globalMobileDataSettingChangedEvent: Flow<Unit> =
-        activeRepo.flatMapLatest { it.globalMobileDataSettingChangedEvent }
-
     override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
         if (isDemoMode.value) {
             return demoMobileConnectionsRepository.getRepoForSubId(subId)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
index 1088345..58cd36e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
@@ -185,8 +185,6 @@
         return CacheContainer(repo, lastMobileState = null)
     }
 
-    override val globalMobileDataSettingChangedEvent = MutableStateFlow(Unit)
-
     fun startProcessingCommands() {
         mobileDemoCommandJob =
             scope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
index c783b12..f5041d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
@@ -91,9 +91,6 @@
             .map { it.toMobileConnectionModel() }
             .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectionModel())
 
-    // TODO(b/238425913): Add logging to this class.
-    // TODO(b/238425913): Make sure SignalStrength.getEmptyState is used when appropriate.
-
     // Carrier merged is never roaming.
     override val cdmaRoaming: StateFlow<Boolean> = MutableStateFlow(false).asStateFlow()
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
index 0f30ae2..f17791b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
@@ -26,7 +26,6 @@
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
@@ -50,7 +49,6 @@
     override val tableLogBuffer: TableLogBuffer,
     private val defaultNetworkName: NetworkNameModel,
     private val networkNameSeparator: String,
-    private val globalMobileDataSettingChangedEvent: Flow<Unit>,
     @Application scope: CoroutineScope,
     private val mobileRepoFactory: MobileConnectionRepositoryImpl.Factory,
     private val carrierMergedRepoFactory: CarrierMergedConnectionRepository.Factory,
@@ -84,7 +82,6 @@
             tableLogBuffer,
             defaultNetworkName,
             networkNameSeparator,
-            globalMobileDataSettingChangedEvent,
         )
     }
 
@@ -120,11 +117,22 @@
     override val connectionInfo =
         activeRepo
             .flatMapLatest { it.connectionInfo }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                initialValue = activeRepo.value.connectionInfo.value,
+            )
             .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.connectionInfo.value)
 
     override val dataEnabled =
         activeRepo
             .flatMapLatest { it.dataEnabled }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = "dataEnabled",
+                initialValue = activeRepo.value.dataEnabled.value,
+            )
             .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.dataEnabled.value)
 
     override val numberOfLevels =
@@ -135,6 +143,11 @@
     override val networkName =
         activeRepo
             .flatMapLatest { it.networkName }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                initialValue = activeRepo.value.networkName.value,
+            )
             .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.networkName.value)
 
     class Factory
@@ -150,7 +163,6 @@
             startingIsCarrierMerged: Boolean,
             defaultNetworkName: NetworkNameModel,
             networkNameSeparator: String,
-            globalMobileDataSettingChangedEvent: Flow<Unit>,
         ): FullMobileConnectionRepository {
             val mobileLogger =
                 logFactory.getOrCreate(tableBufferLogName(subId), MOBILE_CONNECTION_BUFFER_SIZE)
@@ -161,7 +173,6 @@
                 mobileLogger,
                 defaultNetworkName,
                 networkNameSeparator,
-                globalMobileDataSettingChangedEvent,
                 scope,
                 mobileRepoFactory,
                 carrierMergedRepoFactory,
@@ -173,7 +184,7 @@
             const val MOBILE_CONNECTION_BUFFER_SIZE = 100
 
             /** Returns a log buffer name for a mobile connection with the given [subId]. */
-            fun tableBufferLogName(subId: Int): String = "MobileConnectionLog [$subId]"
+            fun tableBufferLogName(subId: Int): String = "MobileConnectionLog[$subId]"
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
index 3f2ce40..cfc4cc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
@@ -18,8 +18,6 @@
 
 import android.content.Context
 import android.content.IntentFilter
-import android.database.ContentObserver
-import android.provider.Settings.Global
 import android.telephony.CellSignalStrength
 import android.telephony.CellSignalStrengthCdma
 import android.telephony.ServiceState
@@ -38,20 +36,20 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.log.table.logDiffsForTable
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
 import com.android.systemui.statusbar.pipeline.mobile.data.model.toDataConnectionType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
-import com.android.systemui.util.settings.GlobalSettings
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
@@ -60,13 +58,14 @@
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.flow.merge
-import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.scan
+import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.flow.stateIn
 
 /**
@@ -81,13 +80,12 @@
     defaultNetworkName: NetworkNameModel,
     networkNameSeparator: String,
     private val telephonyManager: TelephonyManager,
-    private val globalSettings: GlobalSettings,
+    systemUiCarrierConfig: SystemUiCarrierConfig,
     broadcastDispatcher: BroadcastDispatcher,
-    globalMobileDataSettingChangedEvent: Flow<Unit>,
-    mobileMappingsProxy: MobileMappingsProxy,
+    private val mobileMappingsProxy: MobileMappingsProxy,
     bgDispatcher: CoroutineDispatcher,
     logger: ConnectivityPipelineLogger,
-    mobileLogger: TableLogBuffer,
+    override val tableLogBuffer: TableLogBuffer,
     scope: CoroutineScope,
 ) : MobileConnectionRepository {
     init {
@@ -101,10 +99,15 @@
 
     private val telephonyCallbackEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
 
-    override val tableLogBuffer: TableLogBuffer = mobileLogger
-
-    override val connectionInfo: StateFlow<MobileConnectionModel> = run {
-        var state = MobileConnectionModel()
+    /**
+     * This flow defines the single shared connection to system_server via TelephonyCallback. Any
+     * new callback should be added to this listener and funneled through callbackEvents via a data
+     * class. See [CallbackEvent] for defining new callbacks.
+     *
+     * The reason we need to do this is because TelephonyManager limits the number of registered
+     * listeners per-process, so we don't want to create a new listener for every callback.
+     */
+    private val callbackEvents: SharedFlow<CallbackEvent> =
         conflatedCallbackFlow {
                 val callback =
                     object :
@@ -114,41 +117,16 @@
                         TelephonyCallback.DataConnectionStateListener,
                         TelephonyCallback.DataActivityListener,
                         TelephonyCallback.CarrierNetworkListener,
-                        TelephonyCallback.DisplayInfoListener {
+                        TelephonyCallback.DisplayInfoListener,
+                        TelephonyCallback.DataEnabledListener {
                         override fun onServiceStateChanged(serviceState: ServiceState) {
                             logger.logOnServiceStateChanged(serviceState, subId)
-                            state =
-                                state.copy(
-                                    isEmergencyOnly = serviceState.isEmergencyOnly,
-                                    isRoaming = serviceState.roaming,
-                                    operatorAlphaShort = serviceState.operatorAlphaShort,
-                                    isInService = Utils.isInService(serviceState),
-                                )
-                            trySend(state)
+                            trySend(CallbackEvent.OnServiceStateChanged(serviceState))
                         }
 
                         override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
                             logger.logOnSignalStrengthsChanged(signalStrength, subId)
-                            val cdmaLevel =
-                                signalStrength
-                                    .getCellSignalStrengths(CellSignalStrengthCdma::class.java)
-                                    .let { strengths ->
-                                        if (!strengths.isEmpty()) {
-                                            strengths[0].level
-                                        } else {
-                                            CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
-                                        }
-                                    }
-
-                            val primaryLevel = signalStrength.level
-
-                            state =
-                                state.copy(
-                                    cdmaLevel = cdmaLevel,
-                                    primaryLevel = primaryLevel,
-                                    isGsm = signalStrength.isGsm,
-                                )
-                            trySend(state)
+                            trySend(CallbackEvent.OnSignalStrengthChanged(signalStrength))
                         }
 
                         override fun onDataConnectionStateChanged(
@@ -156,101 +134,131 @@
                             networkType: Int
                         ) {
                             logger.logOnDataConnectionStateChanged(dataState, networkType, subId)
-                            state =
-                                state.copy(dataConnectionState = dataState.toDataConnectionType())
-                            trySend(state)
+                            trySend(CallbackEvent.OnDataConnectionStateChanged(dataState))
                         }
 
                         override fun onDataActivity(direction: Int) {
                             logger.logOnDataActivity(direction, subId)
-                            state =
-                                state.copy(
-                                    dataActivityDirection = direction.toMobileDataActivityModel()
-                                )
-                            trySend(state)
+                            trySend(CallbackEvent.OnDataActivity(direction))
                         }
 
                         override fun onCarrierNetworkChange(active: Boolean) {
                             logger.logOnCarrierNetworkChange(active, subId)
-                            state = state.copy(carrierNetworkChangeActive = active)
-                            trySend(state)
+                            trySend(CallbackEvent.OnCarrierNetworkChange(active))
                         }
 
                         override fun onDisplayInfoChanged(
                             telephonyDisplayInfo: TelephonyDisplayInfo
                         ) {
                             logger.logOnDisplayInfoChanged(telephonyDisplayInfo, subId)
+                            trySend(CallbackEvent.OnDisplayInfoChanged(telephonyDisplayInfo))
+                        }
 
-                            val networkType =
-                                if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
-                                    UnknownNetworkType
-                                } else if (
-                                    telephonyDisplayInfo.overrideNetworkType ==
-                                        OVERRIDE_NETWORK_TYPE_NONE
-                                ) {
-                                    DefaultNetworkType(
-                                        mobileMappingsProxy.toIconKey(
-                                            telephonyDisplayInfo.networkType
-                                        )
-                                    )
-                                } else {
-                                    OverrideNetworkType(
-                                        mobileMappingsProxy.toIconKeyOverride(
-                                            telephonyDisplayInfo.overrideNetworkType
-                                        )
-                                    )
-                                }
-                            state = state.copy(resolvedNetworkType = networkType)
-                            trySend(state)
+                        override fun onDataEnabledChanged(enabled: Boolean, reason: Int) {
+                            logger.logOnDataEnabledChanged(enabled, subId)
+                            trySend(CallbackEvent.OnDataEnabledChanged(enabled))
                         }
                     }
                 telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback)
                 awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
             }
-            .onEach { telephonyCallbackEvent.tryEmit(Unit) }
-            .logDiffsForTable(
-                mobileLogger,
-                columnPrefix = "MobileConnection ($subId)",
-                initialValue = state,
-            )
-            .stateIn(scope, SharingStarted.WhileSubscribed(), state)
+            .shareIn(scope, SharingStarted.WhileSubscribed())
+
+    private fun updateConnectionState(
+        prevState: MobileConnectionModel,
+        callbackEvent: CallbackEvent,
+    ): MobileConnectionModel =
+        when (callbackEvent) {
+            is CallbackEvent.OnServiceStateChanged -> {
+                val serviceState = callbackEvent.serviceState
+                prevState.copy(
+                    isEmergencyOnly = serviceState.isEmergencyOnly,
+                    isRoaming = serviceState.roaming,
+                    operatorAlphaShort = serviceState.operatorAlphaShort,
+                    isInService = Utils.isInService(serviceState),
+                )
+            }
+            is CallbackEvent.OnSignalStrengthChanged -> {
+                val signalStrength = callbackEvent.signalStrength
+                val cdmaLevel =
+                    signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java).let {
+                        strengths ->
+                        if (!strengths.isEmpty()) {
+                            strengths[0].level
+                        } else {
+                            CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
+                        }
+                    }
+
+                val primaryLevel = signalStrength.level
+
+                prevState.copy(
+                    cdmaLevel = cdmaLevel,
+                    primaryLevel = primaryLevel,
+                    isGsm = signalStrength.isGsm,
+                )
+            }
+            is CallbackEvent.OnDataConnectionStateChanged -> {
+                prevState.copy(dataConnectionState = callbackEvent.dataState.toDataConnectionType())
+            }
+            is CallbackEvent.OnDataActivity -> {
+                prevState.copy(
+                    dataActivityDirection = callbackEvent.direction.toMobileDataActivityModel()
+                )
+            }
+            is CallbackEvent.OnCarrierNetworkChange -> {
+                prevState.copy(carrierNetworkChangeActive = callbackEvent.active)
+            }
+            is CallbackEvent.OnDisplayInfoChanged -> {
+                val telephonyDisplayInfo = callbackEvent.telephonyDisplayInfo
+                val networkType =
+                    if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
+                        UnknownNetworkType
+                    } else if (
+                        telephonyDisplayInfo.overrideNetworkType == OVERRIDE_NETWORK_TYPE_NONE
+                    ) {
+                        DefaultNetworkType(
+                            mobileMappingsProxy.toIconKey(telephonyDisplayInfo.networkType)
+                        )
+                    } else {
+                        OverrideNetworkType(
+                            mobileMappingsProxy.toIconKeyOverride(
+                                telephonyDisplayInfo.overrideNetworkType
+                            )
+                        )
+                    }
+                prevState.copy(resolvedNetworkType = networkType)
+            }
+            is CallbackEvent.OnDataEnabledChanged -> {
+                // Not part of this object, handled in a separate flow
+                prevState
+            }
+        }
+
+    override val connectionInfo = run {
+        val initial = MobileConnectionModel()
+        callbackEvents
+            .scan(initial, ::updateConnectionState)
+            .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
     }
 
-    // This will become variable based on [CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL]
-    // once it's wired up inside of [CarrierConfigTracker].
-    override val numberOfLevels: StateFlow<Int> =
-        flowOf(DEFAULT_NUM_LEVELS)
-            .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS)
-
-    /** Produces whenever the mobile data setting changes for this subId */
-    private val localMobileDataSettingChangedEvent: Flow<Unit> = conflatedCallbackFlow {
-        val observer =
-            object : ContentObserver(null) {
-                override fun onChange(selfChange: Boolean) {
-                    trySend(Unit)
+    override val numberOfLevels =
+        systemUiCarrierConfig.shouldInflateSignalStrength
+            .map { shouldInflate ->
+                if (shouldInflate) {
+                    DEFAULT_NUM_LEVELS + 1
+                } else {
+                    DEFAULT_NUM_LEVELS
                 }
             }
-
-        globalSettings.registerContentObserver(
-            globalSettings.getUriFor("${Global.MOBILE_DATA}$subId"),
-            /* notifyForDescendants */ true,
-            observer
-        )
-
-        awaitClose { context.contentResolver.unregisterContentObserver(observer) }
-    }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS)
 
     /**
      * There are a few cases where we will need to poll [TelephonyManager] so we can update some
      * internal state where callbacks aren't provided. Any of those events should be merged into
      * this flow, which can be used to trigger the polling.
      */
-    private val telephonyPollingEvent: Flow<Unit> =
-        merge(
-            telephonyCallbackEvent,
-            localMobileDataSettingChangedEvent,
-            globalMobileDataSettingChangedEvent,
-        )
+    private val telephonyPollingEvent: Flow<Unit> = callbackEvents.map { Unit }
 
     override val cdmaRoaming: StateFlow<Boolean> =
         telephonyPollingEvent
@@ -268,30 +276,15 @@
                     intent.toNetworkNameModel(networkNameSeparator) ?: defaultNetworkName
                 }
             }
-            .distinctUntilChanged()
-            .logDiffsForTable(
-                mobileLogger,
-                columnPrefix = "",
-                initialValue = defaultNetworkName,
-            )
             .stateIn(scope, SharingStarted.WhileSubscribed(), defaultNetworkName)
 
-    override val dataEnabled: StateFlow<Boolean> = run {
-        val initial = dataConnectionAllowed()
-        telephonyPollingEvent
-            .mapLatest { dataConnectionAllowed() }
-            .distinctUntilChanged()
-            .logDiffsForTable(
-                mobileLogger,
-                columnPrefix = "",
-                columnName = "dataEnabled",
-                initialValue = initial,
-            )
+    override val dataEnabled = run {
+        val initial = telephonyManager.isDataConnectionAllowed
+        callbackEvents
+            .mapNotNull { (it as? CallbackEvent.OnDataEnabledChanged)?.enabled }
             .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
     }
 
-    private fun dataConnectionAllowed(): Boolean = telephonyManager.isDataConnectionAllowed
-
     class Factory
     @Inject
     constructor(
@@ -299,7 +292,7 @@
         private val context: Context,
         private val telephonyManager: TelephonyManager,
         private val logger: ConnectivityPipelineLogger,
-        private val globalSettings: GlobalSettings,
+        private val carrierConfigRepository: CarrierConfigRepository,
         private val mobileMappingsProxy: MobileMappingsProxy,
         @Background private val bgDispatcher: CoroutineDispatcher,
         @Application private val scope: CoroutineScope,
@@ -309,7 +302,6 @@
             mobileLogger: TableLogBuffer,
             defaultNetworkName: NetworkNameModel,
             networkNameSeparator: String,
-            globalMobileDataSettingChangedEvent: Flow<Unit>,
         ): MobileConnectionRepository {
             return MobileConnectionRepositoryImpl(
                 context,
@@ -317,9 +309,8 @@
                 defaultNetworkName,
                 networkNameSeparator,
                 telephonyManager.createForSubscriptionId(subId),
-                globalSettings,
+                carrierConfigRepository.getOrCreateConfigForSubId(subId),
                 broadcastDispatcher,
-                globalMobileDataSettingChangedEvent,
                 mobileMappingsProxy,
                 bgDispatcher,
                 logger,
@@ -329,3 +320,17 @@
         }
     }
 }
+
+/**
+ * Wrap every [TelephonyCallback] we care about in a data class so we can accept them in a single
+ * shared flow and then split them back out into other flows.
+ */
+private sealed interface CallbackEvent {
+    data class OnServiceStateChanged(val serviceState: ServiceState) : CallbackEvent
+    data class OnSignalStrengthChanged(val signalStrength: SignalStrength) : CallbackEvent
+    data class OnDataConnectionStateChanged(val dataState: Int) : CallbackEvent
+    data class OnDataActivity(val direction: Int) : CallbackEvent
+    data class OnCarrierNetworkChange(val active: Boolean) : CallbackEvent
+    data class OnDisplayInfoChanged(val telephonyDisplayInfo: TelephonyDisplayInfo) : CallbackEvent
+    data class OnDataEnabledChanged(val enabled: Boolean) : CallbackEvent
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index 39ad31f..c660d31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -19,14 +19,12 @@
 import android.annotation.SuppressLint
 import android.content.Context
 import android.content.IntentFilter
-import android.database.ContentObserver
 import android.net.ConnectivityManager
 import android.net.ConnectivityManager.NetworkCallback
 import android.net.Network
 import android.net.NetworkCapabilities
 import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
 import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
-import android.provider.Settings.Global.MOBILE_DATA
 import android.telephony.CarrierConfigManager
 import android.telephony.SubscriptionInfo
 import android.telephony.SubscriptionManager
@@ -44,6 +42,9 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.statusbar.pipeline.dagger.MobileSummaryLog
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
@@ -54,7 +55,6 @@
 import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
 import com.android.systemui.util.kotlin.pairwise
-import com.android.systemui.util.settings.GlobalSettings
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
@@ -85,9 +85,9 @@
     private val subscriptionManager: SubscriptionManager,
     private val telephonyManager: TelephonyManager,
     private val logger: ConnectivityPipelineLogger,
+    @MobileSummaryLog private val tableLogger: TableLogBuffer,
     mobileMappingsProxy: MobileMappingsProxy,
     broadcastDispatcher: BroadcastDispatcher,
-    private val globalSettings: GlobalSettings,
     private val context: Context,
     @Background private val bgDispatcher: CoroutineDispatcher,
     @Application private val scope: CoroutineScope,
@@ -118,6 +118,12 @@
                 }
             }
             .distinctUntilChanged()
+            .logDiffsForTable(
+                tableLogger,
+                LOGGING_PREFIX,
+                columnName = "carrierMergedSubId",
+                initialValue = null,
+            )
             .stateIn(scope, started = SharingStarted.WhileSubscribed(), null)
 
     private val mobileSubscriptionsChangeEvent: Flow<Unit> = conflatedCallbackFlow {
@@ -143,8 +149,14 @@
     override val subscriptions: StateFlow<List<SubscriptionModel>> =
         merge(mobileSubscriptionsChangeEvent, carrierMergedSubId)
             .mapLatest { fetchSubscriptionsList().map { it.toSubscriptionModel() } }
-            .logInputChange(logger, "onSubscriptionsChanged")
             .onEach { infos -> updateRepos(infos) }
+            .distinctUntilChanged()
+            .logDiffsForTable(
+                tableLogger,
+                LOGGING_PREFIX,
+                columnName = "subscriptions",
+                initialValue = listOf(),
+            )
             .stateIn(scope, started = SharingStarted.WhileSubscribed(), listOf())
 
     /** StateFlow that keeps track of the current active mobile data subscription */
@@ -161,7 +173,12 @@
                 awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
             }
             .distinctUntilChanged()
-            .logInputChange(logger, "onActiveDataSubscriptionIdChanged")
+            .logDiffsForTable(
+                tableLogger,
+                LOGGING_PREFIX,
+                columnName = "activeSubId",
+                initialValue = INVALID_SUBSCRIPTION_ID,
+            )
             .stateIn(scope, started = SharingStarted.WhileSubscribed(), INVALID_SUBSCRIPTION_ID)
 
     private val defaultDataSubIdChangeEvent: MutableSharedFlow<Unit> =
@@ -175,7 +192,12 @@
                 intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, INVALID_SUBSCRIPTION_ID)
             }
             .distinctUntilChanged()
-            .logInputChange(logger, "ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED")
+            .logDiffsForTable(
+                tableLogger,
+                LOGGING_PREFIX,
+                columnName = "defaultSubId",
+                initialValue = SubscriptionManager.getDefaultDataSubscriptionId(),
+            )
             .onEach { defaultDataSubIdChangeEvent.tryEmit(Unit) }
             .stateIn(
                 scope,
@@ -222,29 +244,6 @@
             ?: createRepositoryForSubId(subId).also { subIdRepositoryCache[subId] = it }
     }
 
-    /**
-     * In single-SIM devices, the [MOBILE_DATA] setting is phone-wide. For multi-SIM, the individual
-     * connection repositories also observe the URI for [MOBILE_DATA] + subId.
-     */
-    override val globalMobileDataSettingChangedEvent: Flow<Unit> =
-        conflatedCallbackFlow {
-                val observer =
-                    object : ContentObserver(null) {
-                        override fun onChange(selfChange: Boolean) {
-                            trySend(Unit)
-                        }
-                    }
-
-                globalSettings.registerContentObserver(
-                    globalSettings.getUriFor(MOBILE_DATA),
-                    true,
-                    observer
-                )
-
-                awaitClose { context.contentResolver.unregisterContentObserver(observer) }
-            }
-            .logInputChange(logger, "globalMobileDataSettingChangedEvent")
-
     @SuppressLint("MissingPermission")
     override val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel> =
         conflatedCallbackFlow {
@@ -274,7 +273,11 @@
                 awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
             }
             .distinctUntilChanged()
-            .logInputChange(logger, "defaultMobileNetworkConnectivity")
+            .logDiffsForTable(
+                tableLogger,
+                columnPrefix = "$LOGGING_PREFIX.defaultConnection",
+                initialValue = MobileConnectivityModel(),
+            )
             .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectivityModel())
 
     /**
@@ -315,7 +318,6 @@
             isCarrierMerged(subId),
             defaultNetworkName,
             networkNameSeparator,
-            globalMobileDataSettingChangedEvent,
         )
     }
 
@@ -349,4 +351,8 @@
             subscriptionId = subscriptionId,
             isOpportunistic = isOpportunistic,
         )
+
+    companion object {
+        private const val LOGGING_PREFIX = "Repo"
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 9cdff96..9b7614c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -33,7 +33,9 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
 
 interface MobileIconInteractor {
@@ -109,6 +111,9 @@
 
     /** Based on [CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL], either 4 or 5 */
     val numberOfLevels: StateFlow<Int>
+
+    /** See [MobileIconsInteractor.isForceHidden]. */
+    val isForceHidden: Flow<Boolean>
 }
 
 /** Interactor for a single mobile connection. This connection _should_ have one subscription ID */
@@ -124,6 +129,7 @@
     defaultMobileIconGroup: StateFlow<MobileIconGroup>,
     defaultDataSubId: StateFlow<Int>,
     override val isDefaultConnectionFailed: StateFlow<Boolean>,
+    override val isForceHidden: Flow<Boolean>,
     connectionRepository: MobileConnectionRepository,
 ) : MobileIconInteractor {
     private val connectionInfo = connectionRepository.connectionInfo
@@ -181,6 +187,16 @@
                     else -> mapping[info.resolvedNetworkType.lookupKey] ?: defaultGroup
                 }
             }
+            .distinctUntilChanged()
+            .onEach {
+                // Doesn't use [logDiffsForTable] because [MobileIconGroup] can't implement the
+                // [Diffable] interface.
+                tableLogBuffer.logChange(
+                    prefix = "",
+                    columnName = "networkTypeIcon",
+                    value = it.name
+                )
+            }
             .stateIn(scope, SharingStarted.WhileSubscribed(), defaultMobileIconGroup.value)
 
     override val isEmergencyOnly: StateFlow<Boolean> =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
index 9ae38e9..94f7af4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
@@ -23,11 +23,17 @@
 import com.android.settingslib.mobile.TelephonyIcons
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.statusbar.pipeline.dagger.MobileSummaryLog
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
+import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
+import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
 import com.android.systemui.util.CarrierConfigTracker
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -37,9 +43,11 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.flow.transformLatest
@@ -85,6 +93,10 @@
     val isDefaultConnectionFailed: StateFlow<Boolean>
     /** True once the user has been set up */
     val isUserSetup: StateFlow<Boolean>
+
+    /** True if we're configured to force-hide the mobile icons and false otherwise. */
+    val isForceHidden: Flow<Boolean>
+
     /**
      * Vends out a [MobileIconInteractor] tracking the [MobileConnectionRepository] for the given
      * subId. Will throw if the ID is invalid
@@ -100,6 +112,9 @@
 constructor(
     private val mobileConnectionsRepo: MobileConnectionsRepository,
     private val carrierConfigTracker: CarrierConfigTracker,
+    private val logger: ConnectivityPipelineLogger,
+    @MobileSummaryLog private val tableLogger: TableLogBuffer,
+    connectivityRepository: ConnectivityRepository,
     userSetupRepo: UserSetupRepository,
     @Application private val scope: CoroutineScope,
 ) : MobileIconsInteractor {
@@ -168,6 +183,14 @@
                 }
             }
         }
+            .distinctUntilChanged()
+            .logDiffsForTable(
+                tableLogger,
+                LOGGING_PREFIX,
+                columnName = "filteredSubscriptions",
+                initialValue = listOf(),
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
 
     override val defaultDataSubId = mobileConnectionsRepo.defaultDataSubId
 
@@ -189,6 +212,12 @@
                 delay(2000)
                 emit(false)
             }
+            .logDiffsForTable(
+                tableLogger,
+                LOGGING_PREFIX,
+                columnName = "forcingValidation",
+                initialValue = false,
+            )
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
     override val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel> =
@@ -205,6 +234,12 @@
                     networkConnectivity
                 }
             }
+            .distinctUntilChanged()
+            .logDiffsForTable(
+                tableLogger,
+                columnPrefix = "$LOGGING_PREFIX.defaultConnection",
+                initialValue = mobileConnectionsRepo.defaultMobileNetworkConnectivity.value,
+            )
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
@@ -253,10 +288,21 @@
                     !connectivityModel.isValidated
                 }
             }
+            .logDiffsForTable(
+                tableLogger,
+                LOGGING_PREFIX,
+                columnName = "isDefaultConnectionFailed",
+                initialValue = false,
+            )
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
     override val isUserSetup: StateFlow<Boolean> = userSetupRepo.isUserSetupFlow
 
+    override val isForceHidden: Flow<Boolean> =
+        connectivityRepository.forceHiddenSlots
+            .map { it.contains(ConnectivitySlot.MOBILE) }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
     /** Vends out new [MobileIconInteractor] for a particular subId */
     override fun createMobileConnectionInteractorForSubId(subId: Int): MobileIconInteractor =
         MobileIconInteractorImpl(
@@ -269,6 +315,11 @@
             defaultMobileIconGroup,
             defaultDataSubId,
             isDefaultConnectionFailed,
+            isForceHidden,
             mobileConnectionsRepo.getRepoForSubId(subId),
         )
+
+    companion object {
+        private const val LOGGING_PREFIX = "Intr"
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
index 829a5ca..ef75713 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
@@ -23,6 +23,8 @@
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
+import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -30,7 +32,9 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 
@@ -51,13 +55,17 @@
     interactor: MobileIconsInteractor,
     private val iconController: StatusBarIconController,
     private val iconsViewModelFactory: MobileIconsViewModel.Factory,
+    private val logger: ConnectivityPipelineLogger,
     @Application private val scope: CoroutineScope,
     private val statusBarPipelineFlags: StatusBarPipelineFlags,
 ) : CoreStartable {
     private val mobileSubIds: Flow<List<Int>> =
-        interactor.filteredSubscriptions.mapLatest { subscriptions ->
-            subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId }
-        }
+        interactor.filteredSubscriptions
+            .mapLatest { subscriptions ->
+                subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId }
+            }
+            .distinctUntilChanged()
+            .onEach { logger.logUiAdapterSubIdsUpdated(it) }
 
     /**
      * We expose the list of tracked subscriptions as a flow of a list of ints, where each int is
@@ -72,6 +80,9 @@
     /** In order to keep the logs tame, we will reuse the same top-level mobile icons view model */
     val mobileIconsViewModel = iconsViewModelFactory.create(mobileSubIdsState)
 
+    private var isCollecting: Boolean = false
+    private var lastValue: List<Int>? = null
+
     override fun start() {
         // Only notify the icon controller if we want to *render* the new icons.
         // Note that this flow may still run if
@@ -79,8 +90,18 @@
         // get the logging data without rendering.
         if (statusBarPipelineFlags.useNewMobileIcons()) {
             scope.launch {
-                mobileSubIds.collectLatest { iconController.setNewMobileIconSubIds(it) }
+                isCollecting = true
+                mobileSubIds.collectLatest {
+                    logger.logUiAdapterSubIdsSentToIconController(it)
+                    lastValue = it
+                    iconController.setNewMobileIconSubIds(it)
+                }
             }
         }
     }
+
+    override fun dump(pw: PrintWriter, args: Array<out String>) {
+        pw.println("isCollecting=$isCollecting")
+        pw.println("Last values sent to icon controller: $lastValue")
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
index 3e81c7c..db585e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
@@ -29,6 +29,7 @@
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.settingslib.graph.SignalDrawable
 import com.android.systemui.R
+import com.android.systemui.common.ui.binder.ContentDescriptionViewBinder
 import com.android.systemui.common.ui.binder.IconViewBinder
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.statusbar.StatusBarIconView
@@ -90,10 +91,23 @@
                     }
                 }
 
+                launch { viewModel.isVisible.collect { isVisible -> view.isVisible = isVisible } }
+
                 // Set the icon for the triangle
                 launch {
-                    viewModel.iconId.distinctUntilChanged().collect { iconId ->
-                        mobileDrawable.level = iconId
+                    viewModel.icon.distinctUntilChanged().collect { icon ->
+                        mobileDrawable.level =
+                            SignalDrawable.getState(
+                                icon.level,
+                                icon.numberOfLevels,
+                                icon.showExclamationMark,
+                            )
+                    }
+                }
+
+                launch {
+                    viewModel.contentDescription.distinctUntilChanged().collect {
+                        ContentDescriptionViewBinder.bind(it, view)
                     }
                 }
 
@@ -141,8 +155,7 @@
 
         return object : ModernStatusBarViewBinding {
             override fun getShouldIconBeVisible(): Boolean {
-                // If this view model exists, then the icon should be visible.
-                return true
+                return viewModel.isVisible.value
             }
 
             override fun onVisibilityStateChanged(@StatusBarIconView.VisibleState state: Int) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/model/SignalIconModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/model/SignalIconModel.kt
new file mode 100644
index 0000000..16e1766
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/model/SignalIconModel.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.ui.model
+
+import com.android.systemui.log.table.Diffable
+import com.android.systemui.log.table.TableRowLogger
+
+/** A model that will be consumed by [SignalDrawable] to show the mobile triangle icon. */
+data class SignalIconModel(
+    val level: Int,
+    val numberOfLevels: Int,
+    val showExclamationMark: Boolean,
+) : Diffable<SignalIconModel> {
+    // TODO(b/267767715): Can we implement [logDiffs] and [logFull] generically for data classes?
+    override fun logDiffs(prevVal: SignalIconModel, row: TableRowLogger) {
+        if (prevVal.level != level) {
+            row.logChange(COL_LEVEL, level)
+        }
+        if (prevVal.numberOfLevels != numberOfLevels) {
+            row.logChange(COL_NUM_LEVELS, numberOfLevels)
+        }
+        if (prevVal.showExclamationMark != showExclamationMark) {
+            row.logChange(COL_SHOW_EXCLAMATION, showExclamationMark)
+        }
+    }
+
+    override fun logFull(row: TableRowLogger) {
+        row.logChange(COL_LEVEL, level)
+        row.logChange(COL_NUM_LEVELS, numberOfLevels)
+        row.logChange(COL_SHOW_EXCLAMATION, showExclamationMark)
+    }
+
+    companion object {
+        /** Creates a [SignalIconModel] representing an empty and invalidated state. */
+        fun createEmptyState(numberOfLevels: Int) =
+            SignalIconModel(level = 0, numberOfLevels, showExclamationMark = true)
+
+        private const val COL_LEVEL = "level"
+        private const val COL_NUM_LEVELS = "numLevels"
+        private const val COL_SHOW_EXCLAMATION = "showExclamation"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
index 5e935616..0496278 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
@@ -16,14 +16,17 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
 
+import com.android.settingslib.AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH
+import com.android.settingslib.AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH_NONE
 import com.android.settingslib.graph.SignalDrawable
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -35,14 +38,15 @@
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
 
 /** Common interface for all of the location-based mobile icon view models. */
 interface MobileIconViewModelCommon {
     val subscriptionId: Int
-    /** An int consumable by [SignalDrawable] for display */
-    val iconId: Flow<Int>
+    /** True if this view should be visible at all. */
+    val isVisible: StateFlow<Boolean>
+    val icon: Flow<SignalIconModel>
+    val contentDescription: Flow<ContentDescription>
     val roaming: Flow<Boolean>
     /** The RAT icon (LTE, 3G, 5G, etc) to be displayed. Null if we shouldn't show anything */
     val networkTypeIcon: Flow<Icon?>
@@ -70,7 +74,7 @@
 constructor(
     override val subscriptionId: Int,
     iconInteractor: MobileIconInteractor,
-    logger: ConnectivityPipelineLogger,
+    airplaneModeInteractor: AirplaneModeInteractor,
     constants: ConnectivityConstants,
     scope: CoroutineScope,
 ) : MobileIconViewModelCommon {
@@ -78,8 +82,28 @@
     private val showExclamationMark: Flow<Boolean> =
         iconInteractor.isDefaultDataEnabled.mapLatest { !it }
 
-    override val iconId: Flow<Int> = run {
-        val initial = SignalDrawable.getEmptyState(iconInteractor.numberOfLevels.value)
+    override val isVisible: StateFlow<Boolean> =
+        if (!constants.hasDataCapabilities) {
+                flowOf(false)
+            } else {
+                combine(
+                    airplaneModeInteractor.isAirplaneMode,
+                    iconInteractor.isForceHidden,
+                ) { isAirplaneMode, isForceHidden ->
+                    !isAirplaneMode && !isForceHidden
+                }
+            }
+            .distinctUntilChanged()
+            .logDiffsForTable(
+                iconInteractor.tableLogBuffer,
+                columnPrefix = "",
+                columnName = "visible",
+                initialValue = false,
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val icon: Flow<SignalIconModel> = run {
+        val initial = SignalIconModel.createEmptyState(iconInteractor.numberOfLevels.value)
         combine(
                 iconInteractor.level,
                 iconInteractor.numberOfLevels,
@@ -87,31 +111,55 @@
                 iconInteractor.isInService,
             ) { level, numberOfLevels, showExclamationMark, isInService ->
                 if (!isInService) {
-                    SignalDrawable.getEmptyState(numberOfLevels)
+                    SignalIconModel.createEmptyState(numberOfLevels)
                 } else {
-                    SignalDrawable.getState(level, numberOfLevels, showExclamationMark)
+                    SignalIconModel(level, numberOfLevels, showExclamationMark)
                 }
             }
             .distinctUntilChanged()
             .logDiffsForTable(
                 iconInteractor.tableLogBuffer,
-                columnPrefix = "",
-                columnName = "iconId",
+                columnPrefix = "icon",
                 initialValue = initial,
             )
             .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
     }
 
+    override val contentDescription: Flow<ContentDescription> = run {
+        val initial = ContentDescription.Resource(PHONE_SIGNAL_STRENGTH_NONE)
+        combine(
+                iconInteractor.level,
+                iconInteractor.isInService,
+            ) { level, isInService ->
+                val resId =
+                    when {
+                        isInService -> PHONE_SIGNAL_STRENGTH[level]
+                        else -> PHONE_SIGNAL_STRENGTH_NONE
+                    }
+                ContentDescription.Resource(resId)
+            }
+            .distinctUntilChanged()
+            .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
+    }
+
     private val showNetworkTypeIcon: Flow<Boolean> =
         combine(
-            iconInteractor.isDataConnected,
-            iconInteractor.isDataEnabled,
-            iconInteractor.isDefaultConnectionFailed,
-            iconInteractor.alwaysShowDataRatIcon,
-            iconInteractor.isConnected,
-        ) { dataConnected, dataEnabled, failedConnection, alwaysShow, connected ->
-            alwaysShow || (dataConnected && dataEnabled && !failedConnection && connected)
-        }
+                iconInteractor.isDataConnected,
+                iconInteractor.isDataEnabled,
+                iconInteractor.isDefaultConnectionFailed,
+                iconInteractor.alwaysShowDataRatIcon,
+                iconInteractor.isConnected,
+            ) { dataConnected, dataEnabled, failedConnection, alwaysShow, connected ->
+                alwaysShow || (dataConnected && dataEnabled && !failedConnection && connected)
+            }
+            .distinctUntilChanged()
+            .logDiffsForTable(
+                iconInteractor.tableLogBuffer,
+                columnPrefix = "",
+                columnName = "showNetworkTypeIcon",
+                initialValue = false,
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
     override val networkTypeIcon: Flow<Icon?> =
         combine(
@@ -129,14 +177,6 @@
                 }
             }
             .distinctUntilChanged()
-            .onEach {
-                // This is done as an onEach side effect since Icon is not Diffable (yet)
-                iconInteractor.tableLogBuffer.logChange(
-                    prefix = "",
-                    columnName = "networkTypeIcon",
-                    value = it.toString(),
-                )
-            }
             .stateIn(scope, SharingStarted.WhileSubscribed(), null)
 
     override val roaming: StateFlow<Boolean> =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
index 24370d2..185b668 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
@@ -17,9 +17,11 @@
 package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
 
 import androidx.annotation.VisibleForTesting
+import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.statusbar.phone.StatusBarLocation
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
@@ -39,6 +41,7 @@
 constructor(
     val subscriptionIdsFlow: StateFlow<List<Int>>,
     private val interactor: MobileIconsInteractor,
+    private val airplaneModeInteractor: AirplaneModeInteractor,
     private val logger: ConnectivityPipelineLogger,
     private val constants: ConnectivityConstants,
     @Application private val scope: CoroutineScope,
@@ -56,7 +59,7 @@
                 ?: MobileIconViewModel(
                         subId,
                         interactor.createMobileConnectionInteractorForSubId(subId),
-                        logger,
+                        airplaneModeInteractor,
                         constants,
                         scope,
                     )
@@ -74,10 +77,12 @@
         subIdsToRemove.forEach { mobileIconSubIdCache.remove(it) }
     }
 
+    @SysUISingleton
     class Factory
     @Inject
     constructor(
         private val interactor: MobileIconsInteractor,
+        private val airplaneModeInteractor: AirplaneModeInteractor,
         private val logger: ConnectivityPipelineLogger,
         private val constants: ConnectivityConstants,
         @Application private val scope: CoroutineScope,
@@ -87,6 +92,7 @@
             return MobileIconsViewModel(
                 subscriptionIdsFlow,
                 interactor,
+                airplaneModeInteractor,
                 logger,
                 constants,
                 scope,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
index 491f3a5..45036969 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.log.dagger.StatusBarConnectivityLog
 import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.toString
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
@@ -201,6 +202,47 @@
         )
     }
 
+    // TODO(b/238425913): We should split this class into mobile-specific and wifi-specific loggers.
+
+    fun logUiAdapterSubIdsUpdated(subs: List<Int>) {
+        buffer.log(
+            SB_LOGGING_TAG,
+            LogLevel.INFO,
+            { str1 = subs.toString() },
+            { "Sub IDs in MobileUiAdapter updated internally: $str1" },
+        )
+    }
+
+    fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) {
+        buffer.log(
+            SB_LOGGING_TAG,
+            LogLevel.INFO,
+            { str1 = subs.toString() },
+            { "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" },
+        )
+    }
+
+    fun logCarrierConfigChanged(subId: Int) {
+        buffer.log(
+            SB_LOGGING_TAG,
+            LogLevel.INFO,
+            { int1 = subId },
+            { "onCarrierConfigChanged: subId=$int1" },
+        )
+    }
+
+    fun logOnDataEnabledChanged(enabled: Boolean, subId: Int) {
+        buffer.log(
+            SB_LOGGING_TAG,
+            LogLevel.INFO,
+            {
+                int1 = subId
+                bool1 = enabled
+            },
+            { "onDataEnabledChanged: subId=$int1 enabled=$bool1" },
+        )
+    }
+
     companion object {
         const val SB_LOGGING_TAG = "SbConnectivity"
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
index cc0ec54..b1e2812 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
@@ -77,6 +77,17 @@
         return binding.getShouldIconBeVisible()
     }
 
+    /** See [StatusBarIconView.getDrawingRect]. */
+    override fun getDrawingRect(outRect: Rect) {
+        super.getDrawingRect(outRect)
+        val translationX = translationX.toInt()
+        val translationY = translationY.toInt()
+        outRect.left += translationX
+        outRect.right += translationX
+        outRect.top += translationY
+        outRect.bottom += translationY
+    }
+
     /**
      * Initializes this view.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index 8669047..c45b420 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -95,7 +95,7 @@
             .logDiffsForTable(
                 wifiTableLogBuffer,
                 columnPrefix = "",
-                columnName = "isWifiEnabled",
+                columnName = "isEnabled",
                 initialValue = wifiManager.isWifiEnabled,
             )
             .stateIn(
@@ -141,7 +141,7 @@
             .logDiffsForTable(
                 wifiTableLogBuffer,
                 columnPrefix = "",
-                columnName = "isWifiDefault",
+                columnName = "isDefault",
                 initialValue = false,
             )
             .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false)
@@ -212,7 +212,7 @@
             .distinctUntilChanged()
             .logDiffsForTable(
                 wifiTableLogBuffer,
-                columnPrefix = "wifiNetwork",
+                columnPrefix = "",
                 initialValue = WIFI_NETWORK_DEFAULT,
             )
             // There will be multiple wifi icons in different places that will frequently
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/model/WifiIcon.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/model/WifiIcon.kt
index e491d2b..094bcf9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/model/WifiIcon.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/model/WifiIcon.kt
@@ -53,4 +53,4 @@
     }
 }
 
-private const val COL_ICON = "wifiIcon"
+private const val COL_ICON = "icon"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index cc6fdcc..9ad36fd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -438,6 +438,11 @@
         }
 
         @Override
+        public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) {
+            update(false /* updateAlways */);
+        }
+
+        @Override
         public void onKeyguardVisibilityChanged(boolean visible) {
             update(false /* updateAlways */);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
index 60f6df6..8f424b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
@@ -61,6 +61,10 @@
         listeners.add(listener)
     }
 
+    fun removeListener(listener: StatusBarWindowStateListener) {
+        listeners.remove(listener)
+    }
+
     /** Returns true if the window is currently showing. */
     fun windowIsShowing() = windowState == WINDOW_STATE_SHOWING
 
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUiEvent.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUiEvent.kt
new file mode 100644
index 0000000..577292f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUiEvent.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.stylus
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+enum class StylusUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
+    @UiEvent(doc = "UiEvent for USI low battery notification shown")
+    STYLUS_LOW_BATTERY_NOTIFICATION_SHOWN(1298),
+    @UiEvent(doc = "UiEvent for USI low battery notification clicked")
+    STYLUS_LOW_BATTERY_NOTIFICATION_CLICKED(1299),
+    @UiEvent(doc = "UiEvent for USI low battery notification dismissed")
+    STYLUS_LOW_BATTERY_NOTIFICATION_DISMISSED(1300),
+    @UiEvent(doc = "UIEvent for Toast shown when stylus started charging")
+    STYLUS_STARTED_CHARGING(1302),
+    @UiEvent(doc = "UIEvent for Toast shown when stylus stopped charging")
+    STYLUS_STOPPED_CHARGING(1303);
+
+    override fun getId() = _id
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
index 9050dad..89453ad 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.stylus
 
 import android.Manifest
+import android.app.ActivityManager
 import android.app.PendingIntent
 import android.content.ActivityNotFoundException
 import android.content.BroadcastReceiver
@@ -32,6 +33,7 @@
 import androidx.core.app.NotificationCompat
 import androidx.core.app.NotificationManagerCompat
 import com.android.internal.annotations.VisibleForTesting
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
@@ -53,6 +55,7 @@
     private val notificationManager: NotificationManagerCompat,
     private val inputManager: InputManager,
     @Background private val handler: Handler,
+    private val uiEventLogger: UiEventLogger,
 ) {
 
     // These values must only be accessed on the handler.
@@ -79,12 +82,13 @@
 
     fun refresh() {
         handler.post refreshNotification@{
-            if (!suppressed && !hasConnectedBluetoothStylus() && isBatteryBelowThreshold()) {
+            val batteryBelowThreshold = isBatteryBelowThreshold()
+            if (!suppressed && !hasConnectedBluetoothStylus() && batteryBelowThreshold) {
                 showOrUpdateNotification()
                 return@refreshNotification
             }
 
-            if (!isBatteryBelowThreshold()) {
+            if (!batteryBelowThreshold) {
                 // Reset suppression when stylus battery is recharged, so that the next time
                 // it reaches a low battery, the notification will show again.
                 suppressed = false
@@ -143,6 +147,7 @@
                 .setAutoCancel(true)
                 .build()
 
+        logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_SHOWN)
         notificationManager.notify(USI_NOTIFICATION_ID, notification)
     }
 
@@ -168,8 +173,12 @@
         object : BroadcastReceiver() {
             override fun onReceive(context: Context, intent: Intent) {
                 when (intent.action) {
-                    ACTION_DISMISSED_LOW_BATTERY -> updateSuppression(true)
+                    ACTION_DISMISSED_LOW_BATTERY -> {
+                        logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_DISMISSED)
+                        updateSuppression(true)
+                    }
                     ACTION_CLICKED_LOW_BATTERY -> {
+                        logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_CLICKED)
                         updateSuppression(true)
                         if (inputDeviceId == null) return
 
@@ -195,6 +204,15 @@
             }
         }
 
+    private fun logUiEvent(metricId: StylusUiEvent) {
+        uiEventLogger.logWithPosition(
+            metricId,
+            ActivityManager.getCurrentUser(),
+            context.packageName,
+            (batteryCapacity * 100.0).toInt()
+        )
+    }
+
     companion object {
         // Low battery threshold matches CrOS, see:
         // https://source.chromium.org/chromium/chromium/src/+/main:ash/system/power/peripheral_battery_notifier.cc;l=41
@@ -203,10 +221,14 @@
         private val USI_NOTIFICATION_ID = R.string.stylus_battery_low_percentage
 
         @VisibleForTesting const val ACTION_DISMISSED_LOW_BATTERY = "StylusUsiPowerUI.dismiss"
+
         @VisibleForTesting const val ACTION_CLICKED_LOW_BATTERY = "StylusUsiPowerUI.click"
+
         @VisibleForTesting
         const val ACTION_STYLUS_USI_DETAILS = "com.android.settings.STYLUS_USI_DETAILS_SETTINGS"
+
         @VisibleForTesting const val KEY_DEVICE_INPUT_ID = "device_input_id"
+
         @VisibleForTesting const val KEY_SETTINGS_FRAGMENT_ARGS = ":settings:show_fragment_args"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
index ec6965a..899b0c2 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
@@ -80,6 +80,26 @@
         )
     }
 
+    /** Logs that there was a failure to animate the view in. */
+    fun logAnimateInFailure() {
+        buffer.log(
+            tag,
+            LogLevel.WARNING,
+            {},
+            { "View's appearance animation failed. Forcing view display manually." },
+        )
+    }
+
+    /** Logs that there was a failure to animate the view out. */
+    fun logAnimateOutFailure() {
+        buffer.log(
+            tag,
+            LogLevel.WARNING,
+            {},
+            { "View's disappearance animation failed." },
+        )
+    }
+
     fun logViewHidden(info: T) {
         buffer.log(
             tag,
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
new file mode 100644
index 0000000..01a81de
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
@@ -0,0 +1,83 @@
+/*
+ * 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.temporarydisplay.chipbar
+
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.animation.ViewHierarchyAnimator
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.util.children
+import javax.inject.Inject
+
+/**
+ * A class controlling chipbar animations. Typically delegates to [ViewHierarchyAnimator].
+ *
+ * Used so that animations can be mocked out in tests.
+ */
+@SysUISingleton
+open class ChipbarAnimator @Inject constructor() {
+    /**
+     * Animates [innerView] and its children into view.
+     *
+     * @return true if the animation was successfully started and false if the animation can't be
+     * run for any reason.
+     *
+     * See [ViewHierarchyAnimator.animateAddition].
+     */
+    open fun animateViewIn(innerView: ViewGroup, onAnimationEnd: Runnable): Boolean {
+        return ViewHierarchyAnimator.animateAddition(
+            innerView,
+            ViewHierarchyAnimator.Hotspot.TOP,
+            Interpolators.EMPHASIZED_DECELERATE,
+            duration = ANIMATION_IN_DURATION,
+            includeMargins = true,
+            includeFadeIn = true,
+            onAnimationEnd = onAnimationEnd,
+        )
+    }
+
+    /**
+     * Animates [innerView] and its children out of view.
+     *
+     * @return true if the animation was successfully started and false if the animation can't be
+     * run for any reason.
+     *
+     * See [ViewHierarchyAnimator.animateRemoval].
+     */
+    open fun animateViewOut(innerView: ViewGroup, onAnimationEnd: Runnable): Boolean {
+        return ViewHierarchyAnimator.animateRemoval(
+            innerView,
+            ViewHierarchyAnimator.Hotspot.TOP,
+            Interpolators.EMPHASIZED_ACCELERATE,
+            ANIMATION_OUT_DURATION,
+            includeMargins = true,
+            onAnimationEnd,
+        )
+    }
+
+    /** Force shows this view and all child views. Should be used in case [animateViewIn] fails. */
+    fun forceDisplayView(innerView: View) {
+        innerView.alpha = 1f
+        if (innerView is ViewGroup) {
+            innerView.children.forEach { forceDisplayView(it) }
+        }
+    }
+}
+
+private const val ANIMATION_IN_DURATION = 500L
+private const val ANIMATION_OUT_DURATION = 250L
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
index 46f13cc..696134c 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
@@ -32,8 +32,6 @@
 import com.android.internal.widget.CachingIconView
 import com.android.systemui.Gefingerpoken
 import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.animation.ViewHierarchyAnimator
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription
 import com.android.systemui.common.shared.model.Text.Companion.loadText
@@ -78,6 +76,7 @@
     configurationController: ConfigurationController,
     dumpManager: DumpManager,
     powerManager: PowerManager,
+    private val chipbarAnimator: ChipbarAnimator,
     private val falsingManager: FalsingManager,
     private val falsingCollector: FalsingCollector,
     private val swipeChipbarAwayGestureHandler: SwipeChipbarAwayGestureHandler?,
@@ -206,23 +205,17 @@
     }
 
     override fun animateViewIn(view: ViewGroup) {
+        // We can only request focus once the animation finishes.
         val onAnimationEnd = Runnable {
             maybeGetAccessibilityFocus(view.getTag(INFO_TAG) as ChipbarInfo?, view)
         }
-        val added =
-            ViewHierarchyAnimator.animateAddition(
-                view.getInnerView(),
-                ViewHierarchyAnimator.Hotspot.TOP,
-                Interpolators.EMPHASIZED_DECELERATE,
-                duration = ANIMATION_IN_DURATION,
-                includeMargins = true,
-                includeFadeIn = true,
-                // We can only request focus once the animation finishes.
-                onAnimationEnd = onAnimationEnd,
-            )
-        // If the view doesn't get animated, the [onAnimationEnd] runnable won't get run. So, just
-        // run it immediately.
-        if (!added) {
+        val animatedIn = chipbarAnimator.animateViewIn(view.getInnerView(), onAnimationEnd)
+
+        // If the view doesn't get animated, the [onAnimationEnd] runnable won't get run and the
+        // views would remain un-displayed. So, just force-set/run those items immediately.
+        if (!animatedIn) {
+            logger.logAnimateInFailure()
+            chipbarAnimator.forceDisplayView(view.getInnerView())
             onAnimationEnd.run()
         }
     }
@@ -230,18 +223,11 @@
     override fun animateViewOut(view: ViewGroup, removalReason: String?, onAnimationEnd: Runnable) {
         val innerView = view.getInnerView()
         innerView.accessibilityLiveRegion = ACCESSIBILITY_LIVE_REGION_NONE
-        val removed =
-            ViewHierarchyAnimator.animateRemoval(
-                innerView,
-                ViewHierarchyAnimator.Hotspot.TOP,
-                Interpolators.EMPHASIZED_ACCELERATE,
-                ANIMATION_OUT_DURATION,
-                includeMargins = true,
-                onAnimationEnd,
-            )
+        val removed = chipbarAnimator.animateViewOut(innerView, onAnimationEnd)
         // If the view doesn't get animated, the [onAnimationEnd] runnable won't get run. So, just
         // run it immediately.
         if (!removed) {
+            logger.logAnimateOutFailure()
             onAnimationEnd.run()
         }
 
@@ -299,8 +285,6 @@
     }
 }
 
-private const val ANIMATION_IN_DURATION = 500L
-private const val ANIMATION_OUT_DURATION = 250L
 @IdRes private val INFO_TAG = R.id.tag_chipbar_info
 private const val SWIPE_UP_GESTURE_REASON = "SWIPE_UP_GESTURE_DETECTED"
 private const val TAG = "ChipbarCoordinator"
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 9f6e602..6b507ba 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -115,6 +115,7 @@
     private final SecureSettings mSecureSettings;
     private final Executor mMainExecutor;
     private final Handler mBgHandler;
+    private final boolean mIsMonochromaticEnabled;
     private final Context mContext;
     private final boolean mIsMonetEnabled;
     private final UserTracker mUserTracker;
@@ -356,14 +357,24 @@
     };
 
     @Inject
-    public ThemeOverlayController(Context context, BroadcastDispatcher broadcastDispatcher,
-            @Background Handler bgHandler, @Main Executor mainExecutor,
-            @Background Executor bgExecutor, ThemeOverlayApplier themeOverlayApplier,
-            SecureSettings secureSettings, WallpaperManager wallpaperManager,
-            UserManager userManager, DeviceProvisionedController deviceProvisionedController,
-            UserTracker userTracker, DumpManager dumpManager, FeatureFlags featureFlags,
-            @Main Resources resources, WakefulnessLifecycle wakefulnessLifecycle) {
+    public ThemeOverlayController(
+            Context context,
+            BroadcastDispatcher broadcastDispatcher,
+            @Background Handler bgHandler,
+            @Main Executor mainExecutor,
+            @Background Executor bgExecutor,
+            ThemeOverlayApplier themeOverlayApplier,
+            SecureSettings secureSettings,
+            WallpaperManager wallpaperManager,
+            UserManager userManager,
+            DeviceProvisionedController deviceProvisionedController,
+            UserTracker userTracker,
+            DumpManager dumpManager,
+            FeatureFlags featureFlags,
+            @Main Resources resources,
+            WakefulnessLifecycle wakefulnessLifecycle) {
         mContext = context;
+        mIsMonochromaticEnabled = featureFlags.isEnabled(Flags.MONOCHROMATIC_THEME);
         mIsMonetEnabled = featureFlags.isEnabled(Flags.MONET);
         mDeviceProvisionedController = deviceProvisionedController;
         mBroadcastDispatcher = broadcastDispatcher;
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index 8cb4deb..5cf01af 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -17,8 +17,11 @@
 
 package com.android.systemui.user.data.repository
 
+import android.app.IActivityManager
+import android.app.UserSwitchObserver
 import android.content.Context
 import android.content.pm.UserInfo
+import android.os.IRemoteCallback
 import android.os.UserHandle
 import android.os.UserManager
 import android.provider.Settings
@@ -30,6 +33,8 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.user.data.model.UserSwitcherSettingsModel
 import com.android.systemui.util.settings.GlobalSettings
@@ -68,6 +73,12 @@
     /** [UserInfo] of the currently-selected user. */
     val selectedUserInfo: Flow<UserInfo>
 
+    /** Whether user switching is currently in progress. */
+    val userSwitchingInProgress: Flow<Boolean>
+
+    /** User ID of the main user. */
+    val mainUserId: Int
+
     /** User ID of the last non-guest selected user. */
     val lastSelectedNonGuestUserId: Int
 
@@ -108,6 +119,8 @@
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val globalSettings: GlobalSettings,
     private val tracker: UserTracker,
+    private val activityManager: IActivityManager,
+    featureFlags: FeatureFlags,
 ) : UserRepository {
 
     private val _userSwitcherSettings = MutableStateFlow(runBlocking { getSettings() })
@@ -120,7 +133,9 @@
     private val _selectedUserInfo = MutableStateFlow<UserInfo?>(null)
     override val selectedUserInfo: Flow<UserInfo> = _selectedUserInfo.filterNotNull()
 
-    override var lastSelectedNonGuestUserId: Int = UserHandle.USER_SYSTEM
+    override var mainUserId: Int = UserHandle.USER_NULL
+        private set
+    override var lastSelectedNonGuestUserId: Int = UserHandle.USER_NULL
         private set
 
     override val isGuestUserAutoCreated: Boolean =
@@ -129,6 +144,10 @@
     private var _isGuestUserResetting: Boolean = false
     override var isGuestUserResetting: Boolean = _isGuestUserResetting
 
+    private val _isUserSwitchingInProgress = MutableStateFlow(false)
+    override val userSwitchingInProgress: Flow<Boolean>
+        get() = _isUserSwitchingInProgress
+
     override val isGuestUserCreationScheduled = AtomicBoolean()
 
     override val isStatusBarUserChipEnabled: Boolean =
@@ -141,6 +160,9 @@
     init {
         observeSelectedUser()
         observeUserSettings()
+        if (featureFlags.isEnabled(FACE_AUTH_REFACTOR)) {
+            observeUserSwitching()
+        }
     }
 
     override fun refreshUsers() {
@@ -155,6 +177,11 @@
                         // The guest user is always last, regardless of creation time.
                         .sortedBy { it.isGuest }
             }
+
+            if (mainUserId == UserHandle.USER_NULL) {
+                val mainUser = withContext(backgroundDispatcher) { manager.mainUser }
+                mainUser?.let { mainUserId = it.identifier }
+            }
         }
     }
 
@@ -166,6 +193,28 @@
         return _userSwitcherSettings.value.isSimpleUserSwitcher
     }
 
+    private fun observeUserSwitching() {
+        conflatedCallbackFlow {
+                val callback =
+                    object : UserSwitchObserver() {
+                        override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback) {
+                            trySendWithFailureLogging(true, TAG, "userSwitching started")
+                        }
+
+                        override fun onUserSwitchComplete(newUserId: Int) {
+                            trySendWithFailureLogging(false, TAG, "userSwitching completed")
+                        }
+                    }
+                activityManager.registerUserSwitchObserver(callback, TAG)
+                trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
+                awaitClose { activityManager.unregisterUserSwitchObserver(callback) }
+            }
+            .onEach { _isUserSwitchingInProgress.value = it }
+            // TODO (b/262838215), Make this stateIn and initialize directly in field declaration
+            //  once the flag is launched
+            .launchIn(applicationScope)
+    }
+
     private fun observeSelectedUser() {
         conflatedCallbackFlow {
                 fun send() {
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
index a374885..0a07439 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
@@ -139,11 +139,11 @@
         }
 
         applicationScope.launch {
-            var newUserId = UserHandle.USER_SYSTEM
+            var newUserId = repository.mainUserId
             if (targetUserId == UserHandle.USER_NULL) {
                 // When a target user is not specified switch to last non guest user:
                 val lastSelectedNonGuestUserHandle = repository.lastSelectedNonGuestUserId
-                if (lastSelectedNonGuestUserHandle != UserHandle.USER_SYSTEM) {
+                if (lastSelectedNonGuestUserHandle != repository.mainUserId) {
                     val info =
                         withContext(backgroundDispatcher) {
                             manager.getUserInfo(lastSelectedNonGuestUserHandle)
@@ -215,8 +215,11 @@
             // Create a new guest in the foreground, and then immediately switch to it
             val newGuestId = create(showDialog, dismissDialog)
             if (newGuestId == UserHandle.USER_NULL) {
-                Log.e(TAG, "Could not create new guest, switching back to system user")
-                switchUser(UserHandle.USER_SYSTEM)
+                Log.e(TAG, "Could not create new guest, switching back to main user")
+                val mainUser = withContext(backgroundDispatcher) { manager.mainUser?.identifier }
+
+                mainUser?.let { switchUser(it) }
+
                 withContext(backgroundDispatcher) {
                     manager.removeUserWhenPossible(
                         UserHandle.of(currentUser.id),
diff --git a/packages/SystemUI/src/com/android/systemui/util/BackupManagerProxy.kt b/packages/SystemUI/src/com/android/systemui/util/BackupManagerProxy.kt
new file mode 100644
index 0000000..f542434
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/BackupManagerProxy.kt
@@ -0,0 +1,17 @@
+package com.android.systemui.util
+
+import android.app.backup.BackupManager
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+/** Wrapper around [BackupManager] useful for testing. */
+@SysUISingleton
+class BackupManagerProxy @Inject constructor() {
+
+    /** Wrapped version of [BackupManager.dataChanged] */
+    fun dataChanged(packageName: String) = BackupManager.dataChanged(packageName)
+
+    /** Wrapped version of [BackupManager.dataChangedForUser] */
+    fun dataChangedForUser(userId: Int, packageName: String) =
+        BackupManager.dataChangedForUser(userId, packageName)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/ConditionalCoreStartable.java b/packages/SystemUI/src/com/android/systemui/util/condition/ConditionalCoreStartable.java
new file mode 100644
index 0000000..b41bca0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/condition/ConditionalCoreStartable.java
@@ -0,0 +1,84 @@
+/*
+ * 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.condition;
+
+import com.android.systemui.CoreStartable;
+import com.android.systemui.shared.condition.Condition;
+import com.android.systemui.shared.condition.Monitor;
+
+import java.util.Set;
+
+/**
+ * {@link ConditionalCoreStartable} is a {@link com.android.systemui.CoreStartable} abstract
+ * implementation where conditions must be met before routines are executed.
+ */
+public abstract class ConditionalCoreStartable implements CoreStartable {
+    private final Monitor mMonitor;
+    private final Set<Condition> mConditionSet;
+    private Monitor.Subscription.Token mStartToken;
+    private Monitor.Subscription.Token mBootCompletedToken;
+
+    public ConditionalCoreStartable(Monitor monitor) {
+        this(monitor, null);
+    }
+
+    public ConditionalCoreStartable(Monitor monitor, Set<Condition> conditionSet) {
+        mMonitor = monitor;
+        mConditionSet = conditionSet;
+    }
+
+    @Override
+    public final void start() {
+        if (mConditionSet == null || mConditionSet.isEmpty()) {
+            onStart();
+            return;
+        }
+
+        mStartToken = mMonitor.addSubscription(
+                new Monitor.Subscription.Builder(allConditionsMet -> {
+                    if (allConditionsMet) {
+                        mMonitor.removeSubscription(mStartToken);
+                        mStartToken = null;
+                        onStart();
+                    }
+                }).addConditions(mConditionSet)
+                        .build());
+    }
+
+    protected abstract void onStart();
+
+    @Override
+    public final void onBootCompleted() {
+        if (mConditionSet == null || mConditionSet.isEmpty()) {
+            bootCompleted();
+            return;
+        }
+
+        mBootCompletedToken = mMonitor.addSubscription(
+                new Monitor.Subscription.Builder(allConditionsMet -> {
+                    if (allConditionsMet) {
+                        mMonitor.removeSubscription(mBootCompletedToken);
+                        mBootCompletedToken = null;
+                        bootCompleted();
+                    }
+                }).addConditions(mConditionSet)
+                        .build());
+    }
+
+    protected void bootCompleted() {
+    }
+}
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 2c1e681..ed2772a 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -159,6 +159,12 @@
             android:enabled="false"
             tools:replace="android:authorities"
             android:grantUriPermissions="true" />
+
+        <activity
+            android:name="com.android.systemui.screenshot.appclips.AppClipsTrampolineActivityTest$AppClipsTrampolineActivityTestable"
+            android:exported="false"
+            android:permission="com.android.systemui.permission.SELF"
+            android:excludeFromRecents="true" />
     </application>
 
     <instrumentation android:name="android.testing.TestableInstrumentation"
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
index 39cc34b..e8d50ca 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
@@ -21,6 +21,8 @@
 import android.hardware.biometrics.BiometricFaceConstants
 import android.net.Uri
 import android.os.Handler
+import android.os.PowerManager
+import android.os.PowerManager.WAKE_REASON_BIOMETRIC
 import android.os.UserHandle
 import android.provider.Settings
 import androidx.test.filters.SmallTest
@@ -48,6 +50,8 @@
     private val fakeFaceErrorsUri = Uri.Builder().appendPath("face-errors").build()
     private val fakeFaceAcquiredUri = Uri.Builder().appendPath("face-acquired").build()
     private val fakeUnlockIntentBioEnroll = Uri.Builder().appendPath("unlock-intent-bio").build()
+    private val fakeWakeupsConsideredUnlockIntents =
+        Uri.Builder().appendPath("wakeups-considered-unlock-intent").build()
 
     @Mock
     private lateinit var secureSettings: SecureSettings
@@ -82,6 +86,9 @@
         `when`(secureSettings.getUriFor(
                 Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED))
                 .thenReturn(fakeUnlockIntentBioEnroll)
+        `when`(secureSettings.getUriFor(
+            Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS))
+            .thenReturn(fakeWakeupsConsideredUnlockIntents)
 
         activeUnlockConfig = ActiveUnlockConfig(
                 handler,
@@ -92,18 +99,18 @@
     }
 
     @Test
-    fun testRegsitersForSettingsChanges() {
+    fun registersForSettingsChanges() {
         verifyRegisterSettingObserver()
     }
 
     @Test
-    fun testOnWakeupSettingChanged() {
+    fun onWakeupSettingChanged() {
         verifyRegisterSettingObserver()
 
         // GIVEN no active unlock settings enabled
         assertFalse(
                 activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE)
+                        ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE)
         )
 
         // WHEN unlock on wake is allowed
@@ -114,26 +121,26 @@
         // THEN active unlock triggers allowed on: wake, unlock-intent, and biometric failure
         assertTrue(
                 activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE)
+                        ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE)
         )
         assertTrue(
                 activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT)
+                        ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT)
         )
         assertTrue(
                 activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL)
+                        ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL)
         )
     }
 
     @Test
-    fun testOnUnlockIntentSettingChanged() {
+    fun onUnlockIntentSettingChanged() {
         verifyRegisterSettingObserver()
 
         // GIVEN no active unlock settings enabled
         assertFalse(
                 activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT)
+                        ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT)
         )
 
         // WHEN unlock on biometric failed is allowed
@@ -143,15 +150,15 @@
 
         // THEN active unlock triggers allowed on: biometric failure ONLY
         assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE))
         assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT))
         assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL))
     }
 
     @Test
-    fun testOnBioFailSettingChanged() {
+    fun onBioFailSettingChanged() {
         verifyRegisterSettingObserver()
 
         // GIVEN no active unlock settings enabled and triggering unlock intent on biometric
@@ -161,7 +168,7 @@
                 0)).thenReturn("")
         updateSetting(fakeUnlockIntentBioEnroll)
         assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL))
 
         // WHEN unlock on biometric failed is allowed
         `when`(secureSettings.getIntForUser(Settings.Secure.ACTIVE_UNLOCK_ON_BIOMETRIC_FAIL,
@@ -170,15 +177,15 @@
 
         // THEN active unlock triggers allowed on: biometric failure ONLY
         assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.WAKE))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE))
         assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT))
         assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL))
     }
 
     @Test
-    fun testFaceErrorSettingsChanged() {
+    fun faceErrorSettingsChanged() {
         verifyRegisterSettingObserver()
 
         // GIVEN unlock on biometric fail
@@ -200,7 +207,7 @@
     }
 
     @Test
-    fun testFaceAcquiredSettingsChanged() {
+    fun faceAcquiredSettingsChanged() {
         verifyRegisterSettingObserver()
 
         // GIVEN unlock on biometric fail
@@ -228,7 +235,7 @@
     }
 
     @Test
-    fun testTriggerOnUnlockIntentWhenBiometricEnrolledNone() {
+    fun triggerOnUnlockIntentWhenBiometricEnrolledNone() {
         verifyRegisterSettingObserver()
 
         // GIVEN unlock on biometric fail
@@ -244,16 +251,16 @@
         // WHEN unlock intent is allowed when NO biometrics are enrolled (0)
         `when`(secureSettings.getStringForUser(
                 Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED,
-                0)).thenReturn("${ActiveUnlockConfig.BIOMETRIC_TYPE_NONE}")
+                0)).thenReturn("${ActiveUnlockConfig.BiometricType.NONE.intValue}")
         updateSetting(fakeUnlockIntentBioEnroll)
 
         // THEN active unlock triggers allowed on unlock intent
         assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT))
     }
 
     @Test
-    fun testTriggerOnUnlockIntentWhenBiometricEnrolledFingerprintOrFaceOnly() {
+    fun triggerOnUnlockIntentWhenBiometricEnrolledFingerprintOrFaceOnly() {
         verifyRegisterSettingObserver()
 
         // GIVEN unlock on biometric fail
@@ -263,7 +270,7 @@
 
         // GIVEN fingerprint and face are both enrolled
         activeUnlockConfig.keyguardUpdateMonitor = keyguardUpdateMonitor
-        `when`(keyguardUpdateMonitor.isFaceEnrolled()).thenReturn(true)
+        `when`(keyguardUpdateMonitor.isFaceEnrolled).thenReturn(true)
         `when`(keyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(0)).thenReturn(true)
 
         // WHEN unlock intent is allowed when ONLY fingerprint is enrolled or NO biometircs
@@ -271,29 +278,99 @@
         `when`(secureSettings.getStringForUser(
                 Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED,
                 0)).thenReturn(
-                "${ActiveUnlockConfig.BIOMETRIC_TYPE_ANY_FACE}" +
-                        "|${ActiveUnlockConfig.BIOMETRIC_TYPE_ANY_FINGERPRINT}")
+                "${ActiveUnlockConfig.BiometricType.ANY_FACE.intValue}" +
+                        "|${ActiveUnlockConfig.BiometricType.ANY_FINGERPRINT.intValue}")
         updateSetting(fakeUnlockIntentBioEnroll)
 
         // THEN active unlock triggers NOT allowed on unlock intent
         assertFalse(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT))
 
         // WHEN fingerprint ONLY enrolled
-        `when`(keyguardUpdateMonitor.isFaceEnrolled()).thenReturn(false)
+        `when`(keyguardUpdateMonitor.isFaceEnrolled).thenReturn(false)
         `when`(keyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(0)).thenReturn(true)
 
         // THEN active unlock triggers allowed on unlock intent
         assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT))
 
         // WHEN face ONLY enrolled
-        `when`(keyguardUpdateMonitor.isFaceEnrolled()).thenReturn(true)
+        `when`(keyguardUpdateMonitor.isFaceEnrolled).thenReturn(true)
         `when`(keyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(0)).thenReturn(false)
 
         // THEN active unlock triggers allowed on unlock intent
         assertTrue(activeUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT))
+    }
+
+    @Test
+    fun isWakeupConsideredUnlockIntent_singleValue() {
+        verifyRegisterSettingObserver()
+
+        // GIVEN lift is considered an unlock intent
+        `when`(secureSettings.getStringForUser(
+            Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS,
+            0)).thenReturn(PowerManager.WAKE_REASON_LIFT.toString())
+        updateSetting(fakeWakeupsConsideredUnlockIntents)
+
+        // THEN only WAKE_REASON_LIFT is considered an unlock intent
+        for (wakeReason in 0..WAKE_REASON_BIOMETRIC) {
+            if (wakeReason == PowerManager.WAKE_REASON_LIFT) {
+                assertTrue(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason))
+            } else {
+                assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason))
+            }
+        }
+    }
+
+    @Test
+    fun isWakeupConsideredUnlockIntent_multiValue() {
+        verifyRegisterSettingObserver()
+
+        // GIVEN lift and tap are considered an unlock intent
+        `when`(secureSettings.getStringForUser(
+            Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS,
+            0)).thenReturn(
+            PowerManager.WAKE_REASON_LIFT.toString() +
+                    "|" +
+                    PowerManager.WAKE_REASON_TAP.toString()
+        )
+        updateSetting(fakeWakeupsConsideredUnlockIntents)
+
+        // THEN WAKE_REASON_LIFT and WAKE_REASON TAP are considered an unlock intent
+        for (wakeReason in 0..WAKE_REASON_BIOMETRIC) {
+            if (wakeReason == PowerManager.WAKE_REASON_LIFT ||
+                wakeReason == PowerManager.WAKE_REASON_TAP) {
+                assertTrue(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason))
+            } else {
+                assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason))
+            }
+        }
+        assertTrue(activeUnlockConfig.isWakeupConsideredUnlockIntent(PowerManager.WAKE_REASON_LIFT))
+        assertTrue(activeUnlockConfig.isWakeupConsideredUnlockIntent(PowerManager.WAKE_REASON_TAP))
+        assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(
+            PowerManager.WAKE_REASON_UNFOLD_DEVICE))
+    }
+
+    @Test
+    fun isWakeupConsideredUnlockIntent_emptyValues() {
+        verifyRegisterSettingObserver()
+
+        // GIVEN lift and tap are considered an unlock intent
+        `when`(secureSettings.getStringForUser(
+            Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS,
+            0)).thenReturn(" ")
+        updateSetting(fakeWakeupsConsideredUnlockIntents)
+
+        // THEN no wake up gestures are considered an unlock intent
+        for (wakeReason in 0..WAKE_REASON_BIOMETRIC) {
+            assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason))
+        }
+        assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(
+            PowerManager.WAKE_REASON_LIFT))
+        assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(PowerManager.WAKE_REASON_TAP))
+        assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(
+            PowerManager.WAKE_REASON_UNFOLD_DEVICE))
     }
 
     private fun updateSetting(uri: Uri) {
@@ -312,6 +389,7 @@
         verifyRegisterSettingObserver(fakeFaceErrorsUri)
         verifyRegisterSettingObserver(fakeFaceAcquiredUri)
         verifyRegisterSettingObserver(fakeUnlockIntentBioEnroll)
+        verifyRegisterSettingObserver(fakeWakeupsConsideredUnlockIntents)
     }
 
     private fun verifyRegisterSettingObserver(uri: Uri) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index b9c23d4..f7fec80 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -32,10 +32,12 @@
 import com.android.systemui.plugins.ClockEvents
 import com.android.systemui.plugins.ClockFaceController
 import com.android.systemui.plugins.ClockFaceEvents
+import com.android.systemui.plugins.ClockTickRate
 import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.concurrency.DelayableExecutor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.capture
@@ -56,7 +58,7 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.junit.MockitoJUnit
-import java.util.*
+import java.util.TimeZone
 import java.util.concurrent.Executor
 import org.mockito.Mockito.`when` as whenever
 
@@ -72,7 +74,7 @@
     @Mock private lateinit var animations: ClockAnimations
     @Mock private lateinit var events: ClockEvents
     @Mock private lateinit var clock: ClockController
-    @Mock private lateinit var mainExecutor: Executor
+    @Mock private lateinit var mainExecutor: DelayableExecutor
     @Mock private lateinit var bgExecutor: Executor
     @Mock private lateinit var featureFlags: FeatureFlags
     @Mock private lateinit var smallClockController: ClockFaceController
@@ -97,11 +99,15 @@
         whenever(largeClockController.events).thenReturn(largeClockEvents)
         whenever(clock.events).thenReturn(events)
         whenever(clock.animations).thenReturn(animations)
+        whenever(smallClockEvents.tickRate).thenReturn(ClockTickRate.PER_MINUTE)
+        whenever(largeClockEvents.tickRate).thenReturn(ClockTickRate.PER_MINUTE)
 
         repository = FakeKeyguardRepository()
 
         underTest = ClockEventController(
-            KeyguardInteractor(repository = repository, commandQueue = commandQueue),
+            KeyguardInteractor(repository = repository,
+                    commandQueue = commandQueue,
+                    featureFlags = featureFlags),
             KeyguardTransitionInteractor(repository = transitionRepository),
             broadcastDispatcher,
             batteryController,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index a4180fd..ccc4e4a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -33,6 +33,7 @@
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
@@ -47,6 +48,7 @@
 import com.android.systemui.plugins.ClockController;
 import com.android.systemui.plugins.ClockEvents;
 import com.android.systemui.plugins.ClockFaceController;
+import com.android.systemui.plugins.ClockFaceEvents;
 import com.android.systemui.plugins.log.LogBuffer;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shared.clocks.AnimatableClockView;
@@ -99,6 +101,8 @@
     @Mock
     private ClockEvents mClockEvents;
     @Mock
+    private ClockFaceEvents mClockFaceEvents;
+    @Mock
     DumpManager mDumpManager;
     @Mock
     ClockEventController mClockEventController;
@@ -118,6 +122,11 @@
     @Mock
     private LogBuffer mLogBuffer;
 
+    private final View mFakeDateView = (View) (new ViewGroup(mContext) {
+        @Override
+        protected void onLayout(boolean changed, int l, int t, int r, int b) {}
+    });
+    private final View mFakeWeatherView = new View(mContext);
     private final View mFakeSmartspaceView = new View(mContext);
 
     private KeyguardClockSwitchController mController;
@@ -145,6 +154,8 @@
         when(mLargeClockView.getContext()).thenReturn(getContext());
 
         when(mView.isAttachedToWindow()).thenReturn(true);
+        when(mSmartspaceController.buildAndConnectDateView(any())).thenReturn(mFakeDateView);
+        when(mSmartspaceController.buildAndConnectWeatherView(any())).thenReturn(mFakeWeatherView);
         when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView);
         mExecutor = new FakeExecutor(new FakeSystemClock());
         mController = new KeyguardClockSwitchController(
@@ -168,6 +179,8 @@
         when(mClockController.getLargeClock()).thenReturn(mLargeClockController);
         when(mClockController.getSmallClock()).thenReturn(mSmallClockController);
         when(mClockController.getEvents()).thenReturn(mClockEvents);
+        when(mSmallClockController.getEvents()).thenReturn(mClockFaceEvents);
+        when(mLargeClockController.getEvents()).thenReturn(mClockFaceEvents);
         when(mClockController.getAnimations()).thenReturn(mClockAnimations);
         when(mClockRegistry.createCurrentClock()).thenReturn(mClockController);
         when(mClockEventController.getClock()).thenReturn(mClockController);
@@ -252,6 +265,19 @@
     }
 
     @Test
+    public void onLocaleListChanged_rebuildsSmartspaceViews_whenDecouplingEnabled() {
+        when(mSmartspaceController.isEnabled()).thenReturn(true);
+        when(mSmartspaceController.isDateWeatherDecoupled()).thenReturn(true);
+        mController.init();
+
+        mController.onLocaleListChanged();
+        // Should be called once on initial setup, then once again for locale change
+        verify(mSmartspaceController, times(2)).buildAndConnectDateView(mView);
+        verify(mSmartspaceController, times(2)).buildAndConnectWeatherView(mView);
+        verify(mSmartspaceController, times(2)).buildAndConnectView(mView);
+    }
+
+    @Test
     public void testSmartspaceDisabledShowsKeyguardStatusArea() {
         when(mSmartspaceController.isEnabled()).thenReturn(false);
         mController.init();
@@ -274,8 +300,9 @@
         ArgumentCaptor<ContentObserver> observerCaptor =
                 ArgumentCaptor.forClass(ContentObserver.class);
         mController.init();
-        verify(mSecureSettings).registerContentObserverForUser(any(String.class),
-                anyBoolean(), observerCaptor.capture(), eq(UserHandle.USER_ALL));
+        verify(mSecureSettings).registerContentObserverForUser(
+                eq(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK),
+                    anyBoolean(), observerCaptor.capture(), eq(UserHandle.USER_ALL));
         ContentObserver observer = observerCaptor.getValue();
         mExecutor.runAllReady();
 
@@ -321,6 +348,22 @@
         assertEquals(0, mController.getClockBottom(10));
     }
 
+    @Test
+    public void testChangeLockscreenWeatherEnabledSetsWeatherViewVisible() {
+        when(mSmartspaceController.isWeatherEnabled()).thenReturn(true);
+        ArgumentCaptor<ContentObserver> observerCaptor =
+                ArgumentCaptor.forClass(ContentObserver.class);
+        mController.init();
+        verify(mSecureSettings).registerContentObserverForUser(
+                eq(Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED), anyBoolean(),
+                    observerCaptor.capture(), eq(UserHandle.USER_ALL));
+        ContentObserver observer = observerCaptor.getValue();
+        mExecutor.runAllReady();
+        // When a settings change has occurred, check that view is visible.
+        observer.onChange(true);
+        mExecutor.runAllReady();
+        assertEquals(View.VISIBLE, mFakeWeatherView.getVisibility());
+    }
 
     private void verifyAttachment(VerificationMode times) {
         verify(mClockRegistry, times).registerClockChangeListener(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index d912793..082c8cc 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -134,4 +134,10 @@
     keyguardPasswordViewController.startAppearAnimation()
     verify(mKeyguardMessageAreaController, never()).setMessage(anyString(), anyBoolean())
   }
+
+  @Test
+  fun testMessageIsSetWhenReset() {
+    keyguardPasswordViewController.resetState()
+    verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_password)
+  }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
index b742100..0881e61 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
@@ -120,4 +120,10 @@
     public void testGetInitialMessageResId() {
         assertThat(mKeyguardPinViewController.getInitialMessageResId()).isNotEqualTo(0);
     }
+
+    @Test
+    public void testMessageIsSetWhenReset() {
+        mKeyguardPinViewController.resetState();
+        verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pin);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index cdb7bbb..a1af8e8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -27,11 +27,14 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.classifier.FalsingCollectorFake
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.statusbar.policy.DevicePostureController
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
 import org.mockito.Mockito
@@ -71,6 +74,11 @@
     private val falsingCollector: FalsingCollector = FalsingCollectorFake()
     @Mock lateinit var postureController: DevicePostureController
 
+    @Mock lateinit var featureFlags: FeatureFlags
+    @Mock lateinit var passwordTextView: PasswordTextView
+    @Mock lateinit var deleteButton: NumPadButton
+    @Mock lateinit var enterButton: View
+
     lateinit var pinViewController: KeyguardPinViewController
 
     @Before
@@ -82,7 +90,13 @@
                 keyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea::class.java))
             )
             .thenReturn(keyguardMessageAreaController)
+        `when`(keyguardPinView.passwordTextViewId).thenReturn(R.id.pinEntry)
+        `when`(keyguardPinView.findViewById<PasswordTextView>(R.id.pinEntry))
+            .thenReturn(passwordTextView)
         `when`(keyguardPinView.resources).thenReturn(context.resources)
+        `when`(keyguardPinView.findViewById<NumPadButton>(R.id.delete_button))
+            .thenReturn(deleteButton)
+        `when`(keyguardPinView.findViewById<View>(R.id.key_enter)).thenReturn(enterButton)
         pinViewController =
             KeyguardPinViewController(
                 keyguardPinView,
@@ -95,7 +109,8 @@
                 liftToActivateListener,
                 mEmergencyButtonController,
                 falsingCollector,
-                postureController
+                postureController,
+                featureFlags
             )
     }
 
@@ -112,4 +127,18 @@
         pinViewController.startAppearAnimation()
         verify(keyguardMessageAreaController, Mockito.never()).setMessage(anyString(), anyBoolean())
     }
+
+    @Test
+    fun startAppearAnimation_withAutoPinConfirmation() {
+        `when`(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
+        `when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
+        `when`(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
+        `when`(passwordTextView.text).thenReturn("")
+
+        pinViewController.startAppearAnimation()
+        verify(deleteButton).visibility = View.INVISIBLE
+        verify(enterButton).visibility = View.INVISIBLE
+        verify(passwordTextView).setUsePinShapes(true)
+        verify(passwordTextView).setIsPinHinting(true)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 075ef9d..0d65f12 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -583,6 +583,8 @@
         verify(mKeyguardSecurityViewFlipperController).clearViews();
         verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
                 any(KeyguardSecurityCallback.class));
+        verify(mView).reset();
+        verify(mKeyguardSecurityViewFlipperController).reset();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 4d95a22..ed9b5cf 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -685,12 +685,36 @@
         // WHEN fingerprint is locked out
         fingerprintErrorLockedOut();
 
-        // THEN unlocking with fingeprint is not allowed
+        // THEN unlocking with fingerprint is not allowed
         Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
                 BiometricSourceType.FINGERPRINT));
     }
 
     @Test
+    public void trustAgentHasTrust() {
+        // WHEN user has trust
+        mKeyguardUpdateMonitor.onTrustChanged(true, true, getCurrentUser(), 0, null);
+
+        // THEN user is considered as "having trust" and bouncer can be skipped
+        Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
+        Assert.assertTrue(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser()));
+    }
+
+    @Test
+    public void trustAgentHasTrust_fingerprintLockout() {
+        // GIVEN user has trust
+        mKeyguardUpdateMonitor.onTrustChanged(true, true, getCurrentUser(), 0, null);
+        Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
+
+        // WHEN fingerprint is locked out
+        fingerprintErrorLockedOut();
+
+        // THEN user is NOT considered as "having trust" and bouncer cannot be skipped
+        Assert.assertFalse(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
+        Assert.assertFalse(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser()));
+    }
+
+    @Test
     public void testTriesToAuthenticate_whenBouncer() {
         setKeyguardBouncerVisibility(true);
 
@@ -2182,7 +2206,7 @@
 
         // GIVEN active unlock triggers on biometric failures
         when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL))
                 .thenReturn(true);
 
         // WHEN fingerprint fails
@@ -2205,7 +2229,7 @@
 
         // GIVEN active unlock triggers on biometric failures
         when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL))
                 .thenReturn(true);
 
         // WHEN face fails & bypass is not allowed
@@ -2229,7 +2253,7 @@
 
         // GIVEN active unlock triggers on biometric failures
         when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL))
                 .thenReturn(true);
 
         // WHEN face fails & bypass is not allowed
@@ -2251,7 +2275,7 @@
 
         // GIVEN active unlock triggers on biometric failures
         when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin(
-                ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.BIOMETRIC_FAIL))
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.BIOMETRIC_FAIL))
                 .thenReturn(true);
 
         // WHEN face fails & on the bouncer
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
index 05bd1e4..3d0d036 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -159,7 +159,9 @@
                 mAuthRippleController,
                 mResources,
                 new KeyguardTransitionInteractor(mTransitionRepository),
-                new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue),
+                new KeyguardInteractor(new FakeKeyguardRepository(),
+                        mCommandQueue,
+                        mFeatureFlags),
                 mFeatureFlags
         );
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt
new file mode 100644
index 0000000..42e12df
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeHintingViewTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.LayoutInflater
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class PinShapeHintingViewTest : SysuiTestCase() {
+    lateinit var underTest: PinShapeHintingView
+
+    @Before
+    fun setup() {
+        underTest =
+            LayoutInflater.from(context).inflate(R.layout.keyguard_pin_shape_hinting_view, null)
+                as PinShapeHintingView
+    }
+
+    @Test
+    fun testAppend() {
+        // Add more when animation part is complete
+        underTest.append()
+        Truth.assertThat(underTest.childCount).isEqualTo(6)
+    }
+
+    @Test
+    fun testDelete() {
+        underTest.delete()
+        Truth.assertThat(underTest.childCount).isEqualTo(6)
+    }
+
+    @Test
+    fun testReset() {
+        for (i in 0 until 3) {
+            underTest.append()
+        }
+        underTest.reset()
+        Truth.assertThat(underTest.childCount).isEqualTo(6)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt
new file mode 100644
index 0000000..c04fd39
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/PinShapeNonHintingViewTest.kt
@@ -0,0 +1,74 @@
+/*
+ * 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.keyguard
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.LayoutInflater
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class PinShapeNonHintingViewTest : SysuiTestCase() {
+    lateinit var underTest: PinShapeNonHintingView
+
+    @Before
+    fun setup() {
+        underTest =
+            LayoutInflater.from(context).inflate(R.layout.keyguard_pin_shape_non_hinting_view, null)
+                as PinShapeNonHintingView
+    }
+
+    @Test
+    fun testAppend() {
+        // Add more when animation part is complete
+        underTest.append()
+        Truth.assertThat(underTest.childCount).isEqualTo(1)
+    }
+
+    @Test
+    fun testDelete() {
+        for (i in 0 until 3) {
+            underTest.append()
+        }
+        underTest.delete()
+
+        underTest.postDelayed(
+            { Truth.assertThat(underTest.childCount).isEqualTo(2) },
+            PasswordTextView.DISAPPEAR_DURATION + 100L
+        )
+    }
+
+    @Test
+    fun testReset() {
+        for (i in 0 until 3) {
+            underTest.append()
+        }
+        underTest.reset()
+        underTest.postDelayed(
+            { Truth.assertThat(underTest.childCount).isEqualTo(0) },
+            PasswordTextView.DISAPPEAR_DURATION + 100L
+        )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
index 32edf8f..babbe45 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
@@ -11,6 +11,7 @@
 import com.android.systemui.flags.Flag
 import com.android.systemui.flags.FlagListenable
 import com.android.systemui.flags.Flags
+import com.android.systemui.flags.ReleasedFlag
 import com.android.systemui.flags.UnreleasedFlag
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.mockito.any
@@ -102,7 +103,7 @@
     @Test
     fun initialize_enablesUnbundledChooser_whenFlagEnabled() {
         // Arrange
-        whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
+        setFlagMock(true)
 
         // Act
         chooserSelector.start()
@@ -118,7 +119,7 @@
     @Test
     fun initialize_disablesUnbundledChooser_whenFlagDisabled() {
         // Arrange
-        whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
+        setFlagMock(false)
 
         // Act
         chooserSelector.start()
@@ -134,7 +135,7 @@
     @Test
     fun enablesUnbundledChooser_whenFlagBecomesEnabled() {
         // Arrange
-        whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
+        setFlagMock(false)
         chooserSelector.start()
         verify(mockFeatureFlags).addListener(
                 eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
@@ -147,7 +148,7 @@
         )
 
         // Act
-        whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
+        setFlagMock(true)
         flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.name))
 
         // Assert
@@ -161,7 +162,7 @@
     @Test
     fun disablesUnbundledChooser_whenFlagBecomesDisabled() {
         // Arrange
-        whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(true)
+        setFlagMock(true)
         chooserSelector.start()
         verify(mockFeatureFlags).addListener(
                 eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
@@ -174,7 +175,7 @@
         )
 
         // Act
-        whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
+        setFlagMock(false)
         flagListener.value.onFlagChanged(TestFlagEvent(Flags.CHOOSER_UNBUNDLED.name))
 
         // Assert
@@ -188,7 +189,7 @@
     @Test
     fun doesNothing_whenAnotherFlagChanges() {
         // Arrange
-        whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
+        setFlagMock(false)
         chooserSelector.start()
         verify(mockFeatureFlags).addListener(
                 eq<Flag<*>>(Flags.CHOOSER_UNBUNDLED),
@@ -197,13 +198,17 @@
         clearInvocations(mockPackageManager)
 
         // Act
-        whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(false)
         flagListener.value.onFlagChanged(TestFlagEvent("other flag"))
 
         // Assert
         verifyZeroInteractions(mockPackageManager)
     }
 
+    private fun setFlagMock(enabled: Boolean) {
+        whenever(mockFeatureFlags.isEnabled(any<UnreleasedFlag>())).thenReturn(enabled)
+        whenever(mockFeatureFlags.isEnabled(any<ReleasedFlag>())).thenReturn(enabled)
+    }
+
     private class TestFlagEvent(override val flagName: String) : FlagListenable.FlagEvent {
         override fun requestNoRestart() {}
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index e918c1c..4cf5a4b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -21,6 +21,7 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.systemui.dump.LogBufferHelperKt.logcatLogBuffer;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -33,8 +34,10 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -88,6 +91,7 @@
 import com.android.systemui.decor.PrivacyDotCornerDecorProviderImpl;
 import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
 import com.android.systemui.decor.RoundedCornerResDelegate;
+import com.android.systemui.log.ScreenDecorationsLogger;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.settings.FakeDisplayTracker;
 import com.android.systemui.settings.UserTracker;
@@ -102,8 +106,12 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -117,7 +125,7 @@
     private WindowManager mWindowManager;
     private DisplayManager mDisplayManager;
     private SecureSettings mSecureSettings;
-    private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+    private FakeExecutor mExecutor;
     private final FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
     private FakeThreadFactory mThreadFactory;
     private ArrayList<DecorProvider> mPrivacyDecorProviders;
@@ -159,6 +167,8 @@
     private PrivacyDotViewController.ShowingListener mPrivacyDotShowingListener;
     @Mock
     private CutoutDecorProviderFactory mCutoutFactory;
+    @Captor
+    private ArgumentCaptor<AuthController.Callback> mAuthControllerCallback;
     private List<DecorProvider> mMockCutoutList;
 
     @Before
@@ -167,6 +177,7 @@
 
         Handler mainHandler = new Handler(TestableLooper.get(this).getLooper());
         mSecureSettings = new FakeSettings();
+        mExecutor = new FakeExecutor(new FakeSystemClock());
         mThreadFactory = new FakeThreadFactory(mExecutor);
         mThreadFactory.setHandler(mainHandler);
 
@@ -219,11 +230,14 @@
                 mAuthController,
                 mStatusBarStateController,
                 mKeyguardUpdateMonitor,
-                mExecutor));
+                mExecutor,
+                new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer"))));
 
         mScreenDecorations = spy(new ScreenDecorations(mContext, mExecutor, mSecureSettings,
                 mTunerService, mUserTracker, mDisplayTracker, mDotViewController, mThreadFactory,
-                mPrivacyDotDecorProviderFactory, mFaceScanningProviderFactory) {
+                mPrivacyDotDecorProviderFactory, mFaceScanningProviderFactory,
+                new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")),
+                mAuthController) {
             @Override
             public void start() {
                 super.start();
@@ -1161,6 +1175,44 @@
     }
 
     @Test
+    public void faceSensorLocationChangesReloadsFaceScanningOverlay() {
+        mFaceScanningProviders = new ArrayList<>();
+        mFaceScanningProviders.add(mFaceScanningDecorProvider);
+        when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders);
+        when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(true);
+        ScreenDecorations screenDecorations = new ScreenDecorations(mContext, mExecutor,
+                mSecureSettings, mTunerService, mUserTracker, mDisplayTracker, mDotViewController,
+                mThreadFactory, mPrivacyDotDecorProviderFactory, mFaceScanningProviderFactory,
+                new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")), mAuthController);
+        screenDecorations.start();
+        verify(mAuthController).addCallback(mAuthControllerCallback.capture());
+        when(mContext.getDisplay()).thenReturn(mDisplay);
+        when(mDisplay.getDisplayInfo(any())).thenAnswer(new Answer<Boolean>() {
+            @Override
+            public Boolean answer(InvocationOnMock invocation) throws Throwable {
+                DisplayInfo displayInfo = invocation.getArgument(0);
+                int modeId = 1;
+                displayInfo.modeId = modeId;
+                displayInfo.supportedModes = new Display.Mode[]{new Display.Mode(modeId, 1024, 1024,
+                        90)};
+                return false;
+            }
+        });
+        mExecutor.runAllReady();
+        clearInvocations(mFaceScanningDecorProvider);
+
+        AuthController.Callback callback = mAuthControllerCallback.getValue();
+        callback.onFaceSensorLocationChanged();
+        mExecutor.runAllReady();
+
+        verify(mFaceScanningDecorProvider).onReloadResAndMeasure(any(),
+                anyInt(),
+                anyInt(),
+                anyInt(),
+                any());
+    }
+
+    @Test
     public void testPrivacyDotShowingListenerWorkWellWithNullParameter() {
         mPrivacyDotShowingListener.onPrivacyDotShown(null);
         mPrivacyDotShowingListener.onPrivacyDotHidden(null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
index 84ea54c..de152e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -251,10 +251,51 @@
             throws RemoteException {
         enableWindowMagnificationWithoutAnimation();
 
+        final float targetScale = 1.0f;
+        final float targetCenterX = DEFAULT_CENTER_X + 100;
+        final float targetCenterY = DEFAULT_CENTER_Y + 100;
+
         mInstrumentation.runOnMainSync(() -> {
             Mockito.reset(mSpyController);
-            mWindowMagnificationAnimationController.enableWindowMagnification(1.0f,
-                    DEFAULT_CENTER_X + 100, DEFAULT_CENTER_Y + 100, mAnimationCallback);
+            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                    targetCenterX, targetCenterY, mAnimationCallback);
+            mCurrentScale.set(mController.getScale());
+            mCurrentCenterX.set(mController.getCenterX());
+            mCurrentCenterY.set(mController.getCenterY());
+        });
+
+        SystemClock.sleep(mWaitingAnimationPeriod);
+
+        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+                mScaleCaptor.capture(),
+                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
+        verifyStartValue(mScaleCaptor, mCurrentScale.get());
+        verifyStartValue(mCenterXCaptor, mCurrentCenterX.get());
+        verifyStartValue(mCenterYCaptor, mCurrentCenterY.get());
+        verifyStartValue(mOffsetXCaptor, 0f);
+        verifyStartValue(mOffsetYCaptor, 0f);
+
+        verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
+
+        verify(mAnimationCallback).onResult(true);
+        assertEquals(WindowMagnificationAnimationController.STATE_ENABLED,
+                mWindowMagnificationAnimationController.getState());
+    }
+
+    @Test
+    public void enableWindowMagnificationWithScaleLessThanOne_enabled_AnimationAndInvokeCallback()
+            throws RemoteException {
+        enableWindowMagnificationWithoutAnimation();
+
+        final float targetScale = 0.99f;
+        final float targetCenterX = DEFAULT_CENTER_X + 100;
+        final float targetCenterY = DEFAULT_CENTER_Y + 100;
+
+        mInstrumentation.runOnMainSync(() -> {
+            Mockito.reset(mSpyController);
+            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                    targetCenterX, targetCenterY, mAnimationCallback);
             mCurrentScale.set(mController.getScale());
             mCurrentCenterX.set(mController.getCenterX());
             mCurrentCenterY.set(mController.getCenterY());
@@ -275,6 +316,29 @@
         verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
 
         verify(mAnimationCallback).onResult(true);
+        assertEquals(WindowMagnificationAnimationController.STATE_DISABLED,
+                mWindowMagnificationAnimationController.getState());
+    }
+
+    @Test
+    public void
+            enableWindowMagnificationWithScaleLessThanOneAndWithoutCallBack_enabled_expectedValues()
+            throws RemoteException {
+        enableWindowMagnificationWithoutAnimation();
+
+        final float targetScale = 0.99f;
+        final float targetCenterX = DEFAULT_CENTER_X + 100;
+        final float targetCenterY = DEFAULT_CENTER_Y + 100;
+
+        mInstrumentation.runOnMainSync(() -> {
+            Mockito.reset(mSpyController);
+            mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+                    targetCenterX, targetCenterY, null);
+        });
+
+        verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
+        assertEquals(WindowMagnificationAnimationController.STATE_DISABLED,
+                mWindowMagnificationAnimationController.getState());
     }
 
     @Test
@@ -684,14 +748,54 @@
     }
 
     @Test
-    public void moveWindowMagnifier_enabled() {
+    public void moveWindowMagnifier_enabled_vertical_only_expectedValue() {
         enableWindowMagnificationWithoutAnimation();
 
+        // should move vertically since offsetY/offsetX > HORIZONTAL_LOCK_BASE
+        final float offsetX = 50.0f;
+        final float offsetY =
+                (float) Math.ceil(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE)
+                + 1.0f;
         mInstrumentation.runOnMainSync(
-                () -> mController.moveWindowMagnifier(100f, 200f));
+                () -> mController.moveWindowMagnifier(offsetX, offsetY));
 
-        verify(mSpyController).moveWindowMagnifier(100f, 200f);
-        verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + 100f, DEFAULT_CENTER_Y + 100f);
+        verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
+        verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y + offsetY);
+    }
+
+    @Test
+    public void moveWindowMagnifier_enabled_horinzontal_only_expectedValue() {
+        enableWindowMagnificationWithoutAnimation();
+
+        // should move vertically since offsetY/offsetX <= HORIZONTAL_LOCK_BASE
+        final float offsetX = 50.0f;
+        final float offsetY =
+                (float) Math.floor(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE)
+                        - 1.0f;
+        mInstrumentation.runOnMainSync(
+                () -> mController.moveWindowMagnifier(offsetX, offsetY));
+
+        verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
+        verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + offsetX, DEFAULT_CENTER_Y);
+    }
+
+    @Test
+    public void moveWindowMagnifier_enabled_setDiagonalEnabled_expectedValues() {
+        enableWindowMagnificationWithoutAnimation();
+
+        final float offsetX = 50.0f;
+        final float offsetY =
+                (float) Math.ceil(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE);
+        // while diagonal scrolling enabled,
+        //  should move with both offsetX and offsetY without regrading offsetY/offsetX
+        mInstrumentation.runOnMainSync(
+                () -> {
+                    mController.getMagnificationSettings().setDiagonalScrolling(true);
+                    mController.moveWindowMagnifier(offsetX, offsetY);
+                });
+
+        verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
+        verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + offsetX, DEFAULT_CENTER_Y + offsetY);
     }
 
     @Test
@@ -807,7 +911,7 @@
 
         @Override
         void moveWindowMagnifier(float offsetX, float offsetY) {
-            super.moveWindowMagnifier(offsetX, offsetX);
+            super.moveWindowMagnifier(offsetX, offsetY);
             mSpyController.moveWindowMagnifier(offsetX, offsetY);
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index 201f020..6e4a20a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -618,18 +618,18 @@
     public void performA11yActions_visible_expectedResults() {
         final int displayId = mContext.getDisplayId();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(1.5f, Float.NaN,
                     Float.NaN);
         });
 
         final View mirrorView = mWindowManager.getAttachedView();
         assertTrue(
                 mirrorView.performAccessibilityAction(R.id.accessibility_action_zoom_out, null));
-        // Minimum scale is 2.0.
-        verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(2.0f));
+        // Minimum scale is 1.0.
+        verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(1.0f));
 
         assertTrue(mirrorView.performAccessibilityAction(R.id.accessibility_action_zoom_in, null));
-        verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(3.5f));
+        verify(mWindowMagnifierCallback).onPerformScaleAction(eq(displayId), eq(2.5f));
 
         // TODO: Verify the final state when the mirror surface is visible.
         assertTrue(mirrorView.performAccessibilityAction(R.id.accessibility_action_move_up, null));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
index d803075..47c9191 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.accessibility;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
 
@@ -24,6 +26,7 @@
 
 import android.annotation.IdRes;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -183,6 +186,21 @@
         verify(mWindowMagnificationSettingsCallback).onSetDiagonalScrolling(!currentCheckedState);
     }
 
+    @Test
+    public void onConfigurationChanged_selectedButtonIsStillSelected() {
+        // Open view
+        mWindowMagnificationSettings.showSettingPanel();
+        View magnifierMediumButton = getInternalView(R.id.magnifier_medium_button);
+        magnifierMediumButton.performClick();
+
+        mWindowMagnificationSettings.onConfigurationChanged(ActivityInfo.CONFIG_UI_MODE);
+
+        // Since the view is re-inflated after onConfigurationChanged,
+        // we need to get the view again.
+        magnifierMediumButton = getInternalView(R.id.magnifier_medium_button);
+        assertThat(magnifierMediumButton.isSelected()).isTrue();
+    }
+
     private <T extends View> T getInternalView(@IdRes int idRes) {
         T view = mSettingView.findViewById(idRes);
         assertNotNull(view);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
index aac0b51..3da7261 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
@@ -19,8 +19,6 @@
 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
 
-import static com.android.systemui.flags.Flags.A11Y_FLOATING_MENU_FLING_SPRING_ANIMATIONS;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -46,7 +44,6 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
 import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
-import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.settings.FakeDisplayTracker;
 import com.android.systemui.util.settings.SecureSettings;
 
@@ -74,6 +71,7 @@
     public MockitoRule mockito = MockitoJUnit.rule();
 
     private Context mContextWrapper;
+    private WindowManager mWindowManager;
     private AccessibilityManager mAccessibilityManager;
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private AccessibilityFloatingMenuController mController;
@@ -97,6 +95,7 @@
             }
         };
 
+        mWindowManager = mContext.getSystemService(WindowManager.class);
         mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
         mLastButtonTargets = Settings.Secure.getStringForUser(mContextWrapper.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, UserHandle.USER_CURRENT);
@@ -158,7 +157,8 @@
     public void onKeyguardVisibilityChanged_showing_destroyWidget() {
         enableAccessibilityFloatingMenuConfig();
         mController = setUpController();
-        mController.mFloatingMenu = new AccessibilityFloatingMenu(mContextWrapper, mSecureSettings);
+        mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager,
+                mAccessibilityManager, mSecureSettings);
         captureKeyguardUpdateMonitorCallback();
         mKeyguardCallback.onUserUnlocked();
 
@@ -184,7 +184,8 @@
         final int fakeUserId = 1;
         enableAccessibilityFloatingMenuConfig();
         mController = setUpController();
-        mController.mFloatingMenu = new AccessibilityFloatingMenu(mContextWrapper, mSecureSettings);
+        mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager,
+                mAccessibilityManager, mSecureSettings);
         captureKeyguardUpdateMonitorCallback();
 
         mKeyguardCallback.onUserSwitching(fakeUserId);
@@ -197,7 +198,8 @@
         final int fakeUserId = 1;
         enableAccessibilityFloatingMenuConfig();
         mController = setUpController();
-        mController.mFloatingMenu = new AccessibilityFloatingMenu(mContextWrapper, mSecureSettings);
+        mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager,
+                mAccessibilityManager, mSecureSettings);
         captureKeyguardUpdateMonitorCallback();
         mKeyguardCallback.onUserUnlocked();
         mKeyguardCallback.onKeyguardVisibilityChanged(true);
@@ -318,40 +320,18 @@
     }
 
     @Test
-    public void onTargetsChanged_flingSpringAnimationsDisabled_floatingMenuIsCreated() {
-        Settings.Secure.putIntForUser(mContextWrapper.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU,
-                UserHandle.USER_CURRENT);
-        final FakeFeatureFlags featureFlags = new FakeFeatureFlags();
-        featureFlags.set(A11Y_FLOATING_MENU_FLING_SPRING_ANIMATIONS, false);
-
-        mController = setUpController();
-        mController.onAccessibilityButtonTargetsChanged(TEST_A11Y_BTN_TARGETS);
-
-        assertThat(mController.mFloatingMenu).isInstanceOf(AccessibilityFloatingMenu.class);
-    }
-
-    @Test
     public void onTargetsChanged_isFloatingViewLayerControllerCreated() {
         Settings.Secure.putIntForUser(mContextWrapper.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU,
                 UserHandle.USER_CURRENT);
-        final FakeFeatureFlags featureFlags = new FakeFeatureFlags();
-        featureFlags.set(A11Y_FLOATING_MENU_FLING_SPRING_ANIMATIONS, true);
 
-        mController = setUpController(featureFlags);
+        mController = setUpController();
         mController.onAccessibilityButtonTargetsChanged(TEST_A11Y_BTN_TARGETS);
 
         assertThat(mController.mFloatingMenu).isInstanceOf(MenuViewLayerController.class);
     }
 
     private AccessibilityFloatingMenuController setUpController() {
-        final FakeFeatureFlags featureFlags = new FakeFeatureFlags();
-        featureFlags.set(A11Y_FLOATING_MENU_FLING_SPRING_ANIMATIONS, false);
-        return setUpController(featureFlags);
-    }
-
-    private AccessibilityFloatingMenuController setUpController(FakeFeatureFlags featureFlags) {
         final WindowManager windowManager = mContext.getSystemService(WindowManager.class);
         final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
         final FakeDisplayTracker displayTracker = new FakeDisplayTracker(mContext);
@@ -361,7 +341,7 @@
         final AccessibilityFloatingMenuController controller =
                 new AccessibilityFloatingMenuController(mContextWrapper, windowManager,
                         displayManager, mAccessibilityManager, mTargetsObserver, mModeObserver,
-                        mKeyguardUpdateMonitor, featureFlags, mSecureSettings, displayTracker);
+                        mKeyguardUpdateMonitor, mSecureSettings, displayTracker);
         controller.init();
 
         return controller;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java
deleted file mode 100644
index 04345fd..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doReturn;
-
-import android.content.Context;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.accessibility.AccessibilityManager;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.util.settings.SecureSettings;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Tests for {@link AccessibilityFloatingMenu}. */
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class AccessibilityFloatingMenuTest extends SysuiTestCase {
-
-    @Rule
-    public MockitoRule mockito = MockitoJUnit.rule();
-
-    @Mock
-    private AccessibilityManager mAccessibilityManager;
-    @Mock
-    private SecureSettings mSecureSettings;
-
-    private AccessibilityFloatingMenuView mMenuView;
-    private AccessibilityFloatingMenu mMenu;
-
-    @Before
-    public void initMenu() {
-        final List<String> assignedTargets = new ArrayList<>();
-        mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);
-        assignedTargets.add(MAGNIFICATION_CONTROLLER_NAME);
-        doReturn(assignedTargets).when(mAccessibilityManager).getAccessibilityShortcutTargets(
-                anyInt());
-
-        final Position position = new Position(0, 0);
-        mMenuView = new AccessibilityFloatingMenuView(mContext, position);
-        mMenu = new AccessibilityFloatingMenu(mContext, mSecureSettings, mMenuView);
-    }
-
-    @Test
-    public void showMenuView_success() {
-        mMenu.show();
-
-        assertThat(mMenuView.isShowing()).isTrue();
-    }
-
-    @Test
-    public void hideMenuView_success() {
-        mMenu.show();
-        mMenu.hide();
-
-        assertThat(mMenuView.isShowing()).isFalse();
-    }
-
-    @Test
-    public void showMenuView_emptyTarget_notShow() {
-        final List<String> emptyTargets = new ArrayList<>();
-        doReturn(emptyTargets).when(mAccessibilityManager).getAccessibilityShortcutTargets(
-                anyInt());
-
-        mMenu.show();
-
-        assertThat(mMenuView.isShowing()).isFalse();
-    }
-
-    @After
-    public void tearDown() {
-        mMenu.hide();
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java
deleted file mode 100644
index bebd871..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.View.OVER_SCROLL_ALWAYS;
-import static android.view.View.OVER_SCROLL_NEVER;
-import static android.view.WindowInsets.Type.displayCutout;
-import static android.view.WindowInsets.Type.ime;
-import static android.view.WindowInsets.Type.systemBars;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyFloat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Insets;
-import android.graphics.Rect;
-import android.graphics.drawable.GradientDrawable;
-import android.graphics.drawable.LayerDrawable;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewPropertyAnimator;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.accessibility.dialog.AccessibilityTarget;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.accessibility.MotionEventHelper;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/** Tests for {@link AccessibilityFloatingMenuView}. */
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class AccessibilityFloatingMenuViewTest extends SysuiTestCase {
-
-    @Rule
-    public MockitoRule mockito = MockitoJUnit.rule();
-
-    private final MotionEventHelper mMotionEventHelper = new MotionEventHelper();
-    private final List<AccessibilityTarget> mTargets = new ArrayList<>(
-            Collections.singletonList(mock(AccessibilityTarget.class)));
-
-    private final Position mPlaceholderPosition = new Position(0.0f, 0.0f);
-
-    @Mock
-    private WindowManager mWindowManager;
-    @Mock
-    private ViewPropertyAnimator mAnimator;
-    @Mock
-    private WindowMetrics mWindowMetrics;
-    private MotionEvent mInterceptMotionEvent;
-    private AccessibilityFloatingMenuView mMenuView;
-    private RecyclerView mListView = new RecyclerView(mContext);
-
-    private int mMenuWindowHeight;
-    private int mMenuHalfWidth;
-    private int mMenuHalfHeight;
-    private int mDisplayHalfWidth;
-    private int mDisplayHalfHeight;
-    private int mMaxWindowX;
-    private int mMaxWindowY;
-    private final int mDisplayWindowWidth = 1080;
-    private final int mDisplayWindowHeight = 2340;
-
-    @Before
-    public void initMenuView() {
-        final WindowManager wm = mContext.getSystemService(WindowManager.class);
-        doAnswer(invocation -> wm.getMaximumWindowMetrics()).when(
-                mWindowManager).getMaximumWindowMetrics();
-        mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
-        when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
-        when(mWindowMetrics.getBounds()).thenReturn(new Rect(0, 0, mDisplayWindowWidth,
-                mDisplayWindowHeight));
-        when(mWindowMetrics.getWindowInsets()).thenReturn(fakeDisplayInsets());
-        mMenuView = spy(
-                new AccessibilityFloatingMenuView(mContext, mPlaceholderPosition, mListView));
-    }
-
-    @Before
-    public void setUpMatrices() {
-        final Resources res = mContext.getResources();
-        final int margin =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_margin);
-        final int padding =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_small_padding);
-        final int iconWidthHeight =
-                res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_small_width_height);
-        final int menuWidth = padding * 2 + iconWidthHeight;
-        final int menuHeight = (padding + iconWidthHeight) * mTargets.size() + padding;
-        mMenuHalfWidth = menuWidth / 2;
-        mMenuHalfHeight = menuHeight / 2;
-        mDisplayHalfWidth = mDisplayWindowWidth / 2;
-        mDisplayHalfHeight = mDisplayWindowHeight / 2;
-        int marginStartEnd =
-                mContext.getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT
-                        ? margin : 0;
-        mMaxWindowX = mDisplayWindowWidth - marginStartEnd - menuWidth;
-        mMenuWindowHeight = menuHeight + margin * 2;
-        mMaxWindowY = mDisplayWindowHeight - mMenuWindowHeight;
-    }
-
-    @Test
-    public void initListView_success() {
-        assertThat(mListView.getCompatAccessibilityDelegate()).isNotNull();
-        assertThat(mMenuView.getChildCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void showMenuView_success() {
-        mMenuView.show();
-
-        assertThat(mMenuView.isShowing()).isTrue();
-        verify(mWindowManager).addView(eq(mMenuView), any(WindowManager.LayoutParams.class));
-    }
-
-    @Test
-    public void showMenuView_showTwice_addViewOnce() {
-        mMenuView.show();
-        mMenuView.show();
-
-        assertThat(mMenuView.isShowing()).isTrue();
-        verify(mWindowManager, times(1)).addView(eq(mMenuView),
-                any(WindowManager.LayoutParams.class));
-    }
-
-    @Test
-    public void hideMenuView_success() {
-        mMenuView.show();
-        mMenuView.hide();
-
-        assertThat(mMenuView.isShowing()).isFalse();
-        verify(mWindowManager).removeView(eq(mMenuView));
-    }
-
-    @Test
-    public void hideMenuView_hideTwice_removeViewOnce() {
-        mMenuView.show();
-        mMenuView.hide();
-        mMenuView.hide();
-
-        assertThat(mMenuView.isShowing()).isFalse();
-        verify(mWindowManager, times(1)).removeView(eq(mMenuView));
-    }
-
-    @Test
-    public void hideMenuViewWhenStartingAnimation_animatorNotRunning() {
-        mMenuView.show();
-
-        mMenuView.mDragAnimator.start();
-        mMenuView.hide();
-
-        assertThat(mMenuView.mDragAnimator.isRunning()).isFalse();
-    }
-
-    @Test
-    public void onTargetsChanged_singleTarget_expectedRadii() {
-        final Position alignRightPosition = new Position(1.0f, 0.0f);
-        final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext,
-                alignRightPosition);
-        setupBasicMenuView(menuView);
-
-        menuView.onTargetsChanged(mTargets);
-
-        final View view = menuView.getChildAt(0);
-        final LayerDrawable layerDrawable = (LayerDrawable) view.getBackground();
-        final GradientDrawable gradientDrawable =
-                (GradientDrawable) layerDrawable.getDrawable(0);
-        final float smallRadius =
-                getContext().getResources().getDimensionPixelSize(
-                        R.dimen.accessibility_floating_menu_small_single_radius);
-        final float[] expectedRadii =
-                new float[]{smallRadius, smallRadius, 0.0f, 0.0f, 0.0f, 0.0f, smallRadius,
-                        smallRadius};
-        assertThat(gradientDrawable.getCornerRadii()).isEqualTo(expectedRadii);
-    }
-
-    @Test
-    public void setSizeType_alignRightAndLargeSize_expectedRadii() {
-        final RecyclerView listView = spy(new RecyclerView(mContext));
-        final Position alignRightPosition = new Position(1.0f, 0.0f);
-        final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext,
-                alignRightPosition, listView);
-        setupBasicMenuView(menuView);
-
-        menuView.setSizeType(/* largeSize */ 1);
-
-        final LayerDrawable layerDrawable =
-                (LayerDrawable) listView.getBackground();
-        final GradientDrawable gradientDrawable =
-                (GradientDrawable) layerDrawable.getDrawable(0);
-        final float largeRadius = getContext().getResources().getDimensionPixelSize(
-                R.dimen.accessibility_floating_menu_large_single_radius);
-        final float[] expectedRadii =
-                new float[] {largeRadius, largeRadius, 0.0f, 0.0f, 0.0f, 0.0f, largeRadius,
-                        largeRadius};
-        assertThat(gradientDrawable.getCornerRadii()).isEqualTo(expectedRadii);
-    }
-
-    @Test
-    public void setShapeType_halfCircle_translationX() {
-        final RecyclerView listView = spy(new RecyclerView(mContext));
-        final AccessibilityFloatingMenuView menuView =
-                new AccessibilityFloatingMenuView(mContext, mPlaceholderPosition, listView);
-        setupBasicMenuView(menuView);
-        doReturn(mAnimator).when(listView).animate();
-
-        menuView.setShapeType(/* halfOvalShape */ 1);
-
-        verify(mAnimator).translationX(anyFloat());
-    }
-
-    @Test
-    public void onTargetsChanged_fadeInOut() {
-        final InOrder inOrderMenuView = inOrder(mMenuView);
-
-        mMenuView.onTargetsChanged(mTargets);
-
-        inOrderMenuView.verify(mMenuView).fadeIn();
-        inOrderMenuView.verify(mMenuView).fadeOut();
-    }
-
-    @Test
-    public void setSizeType_fadeInOut() {
-        final InOrder inOrderMenuView = inOrder(mMenuView);
-
-        mMenuView.setSizeType(/* smallSize */ 0);
-
-        inOrderMenuView.verify(mMenuView).fadeIn();
-        inOrderMenuView.verify(mMenuView).fadeOut();
-    }
-
-    @Test
-    public void tapOnAndDragMenu_interceptUpEvent() {
-        final RecyclerView listView = new RecyclerView(mContext);
-        final TestAccessibilityFloatingMenu menuView =
-                new TestAccessibilityFloatingMenu(mContext, mPlaceholderPosition, listView);
-        setupBasicMenuView(menuView);
-        final int currentWindowX = menuView.mCurrentLayoutParams.x;
-        final int currentWindowY = menuView.mCurrentLayoutParams.y;
-        final MotionEvent downEvent =
-                mMotionEventHelper.obtainMotionEvent(0, 1,
-                        MotionEvent.ACTION_DOWN,
-                        currentWindowX + /* offsetXToMenuCenterX */ mMenuHalfWidth,
-                        currentWindowY + /* offsetYToMenuCenterY */ mMenuHalfHeight);
-        final MotionEvent moveEvent =
-                mMotionEventHelper.obtainMotionEvent(2, 3,
-                        MotionEvent.ACTION_MOVE,
-                        /* displayCenterX */mDisplayHalfWidth
-                                - /* offsetXToDisplayLeftHalfRegion */ 10,
-                        /* displayCenterY */ mDisplayHalfHeight);
-        final MotionEvent upEvent =
-                mMotionEventHelper.obtainMotionEvent(4, 5,
-                        MotionEvent.ACTION_UP,
-                        /* displayCenterX */ mDisplayHalfWidth
-                                - /* offsetXToDisplayLeftHalfRegion */ 10,
-                        /* displayCenterY */ mDisplayHalfHeight);
-
-        listView.dispatchTouchEvent(downEvent);
-        listView.dispatchTouchEvent(moveEvent);
-        listView.dispatchTouchEvent(upEvent);
-
-        assertThat(mInterceptMotionEvent.getAction()).isEqualTo(MotionEvent.ACTION_UP);
-    }
-
-    @Test
-    public void tapOnAndDragMenu_matchLocation() {
-        final float expectedX = 1.0f;
-        final float expectedY = 0.7f;
-        final Position position = new Position(expectedX, expectedY);
-        final RecyclerView listView = new RecyclerView(mContext);
-        final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext,
-                position, listView);
-        setupBasicMenuView(menuView);
-        final int currentWindowX = menuView.mCurrentLayoutParams.x;
-        final int currentWindowY = menuView.mCurrentLayoutParams.y;
-        final MotionEvent downEvent =
-                mMotionEventHelper.obtainMotionEvent(0, 1,
-                        MotionEvent.ACTION_DOWN,
-                        currentWindowX + /* offsetXToMenuCenterX */ mMenuHalfWidth,
-                        currentWindowY + /* offsetYToMenuCenterY */ mMenuHalfHeight);
-        final MotionEvent moveEvent =
-                mMotionEventHelper.obtainMotionEvent(2, 3,
-                        MotionEvent.ACTION_MOVE,
-                        /* displayCenterX */mDisplayHalfWidth
-                                + /* offsetXToDisplayRightHalfRegion */ 10,
-                        /* displayCenterY */ mDisplayHalfHeight);
-        final MotionEvent upEvent =
-                mMotionEventHelper.obtainMotionEvent(4, 5,
-                        MotionEvent.ACTION_UP,
-                        /* displayCenterX */ mDisplayHalfWidth
-                                + /* offsetXToDisplayRightHalfRegion */ 10,
-                        /* displayCenterY */ mDisplayHalfHeight);
-
-        listView.dispatchTouchEvent(downEvent);
-        listView.dispatchTouchEvent(moveEvent);
-        listView.dispatchTouchEvent(upEvent);
-        menuView.mDragAnimator.end();
-
-        assertThat((float) menuView.mCurrentLayoutParams.x).isWithin(1.0f).of(mMaxWindowX);
-        assertThat((float) menuView.mCurrentLayoutParams.y).isWithin(1.0f).of(
-                /* newWindowY = displayCenterY - offsetY */ mDisplayHalfHeight - mMenuHalfHeight);
-    }
-
-
-    @Test
-    public void tapOnAndDragMenuToDisplaySide_transformShapeHalfOval() {
-        final Position alignRightPosition = new Position(1.0f, 0.8f);
-        final RecyclerView listView = new RecyclerView(mContext);
-        final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext,
-                alignRightPosition, listView);
-        setupBasicMenuView(menuView);
-
-        final int currentWindowX = menuView.mCurrentLayoutParams.x;
-        final int currentWindowY = menuView.mCurrentLayoutParams.y;
-        final MotionEvent downEvent =
-                mMotionEventHelper.obtainMotionEvent(0, 1,
-                        MotionEvent.ACTION_DOWN,
-                        currentWindowX + /* offsetXToMenuCenterX */ mMenuHalfWidth,
-                        currentWindowY + /* offsetYToMenuCenterY */ mMenuHalfHeight);
-        final MotionEvent moveEvent =
-                mMotionEventHelper.obtainMotionEvent(2, 3,
-                        MotionEvent.ACTION_MOVE,
-                        /* downX */(currentWindowX + mMenuHalfWidth)
-                                + /* offsetXToDisplayRightSide */ mMenuHalfWidth,
-                        /* downY */ (currentWindowY +  mMenuHalfHeight));
-        final MotionEvent upEvent =
-                mMotionEventHelper.obtainMotionEvent(4, 5,
-                        MotionEvent.ACTION_UP,
-                        /* downX */(currentWindowX + mMenuHalfWidth)
-                                + /* offsetXToDisplayRightSide */ mMenuHalfWidth,
-                        /* downY */ (currentWindowY +  mMenuHalfHeight));
-
-        listView.dispatchTouchEvent(downEvent);
-        listView.dispatchTouchEvent(moveEvent);
-        listView.dispatchTouchEvent(upEvent);
-
-        assertThat(menuView.mShapeType).isEqualTo(/* halfOval */ 1);
-    }
-
-    @Test
-    public void onTargetsChanged_exceedAvailableHeight_overScrollAlways() {
-        doReturn(true).when(mMenuView).hasExceededMaxLayoutHeight();
-
-        mMenuView.onTargetsChanged(mTargets);
-
-        assertThat(mListView.getOverScrollMode()).isEqualTo(OVER_SCROLL_ALWAYS);
-    }
-
-    @Test
-    public void onTargetsChanged_notExceedAvailableHeight_overScrollNever() {
-        doReturn(false).when(mMenuView).hasExceededMaxLayoutHeight();
-
-        mMenuView.onTargetsChanged(mTargets);
-
-        assertThat(mListView.getOverScrollMode()).isEqualTo(OVER_SCROLL_NEVER);
-    }
-
-    @Test
-    public void showMenuView_insetsListener_overlapWithIme_menuViewShifted() {
-        final int offset = 200;
-
-        final Position alignRightPosition = new Position(1.0f, 0.8f);
-        final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext,
-                alignRightPosition);
-        setupBasicMenuView(menuView);
-        final WindowInsets imeInset = fakeImeInsetWith(menuView, offset);
-        when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
-        when(mWindowMetrics.getWindowInsets()).thenReturn(imeInset);
-        final int expectedLayoutY = menuView.mCurrentLayoutParams.y - offset;
-        menuView.dispatchApplyWindowInsets(imeInset);
-
-        assertThat(menuView.mCurrentLayoutParams.y).isEqualTo(expectedLayoutY);
-    }
-
-    @Test
-    public void hideIme_onMenuViewShifted_menuViewMovedBack() {
-        final int offset = 200;
-        setupBasicMenuView(mMenuView);
-        final WindowInsets imeInset = fakeImeInsetWith(mMenuView, offset);
-        when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
-        when(mWindowMetrics.getWindowInsets()).thenReturn(imeInset);
-        final int expectedLayoutY = mMenuView.mCurrentLayoutParams.y;
-        mMenuView.dispatchApplyWindowInsets(imeInset);
-
-        mMenuView.dispatchApplyWindowInsets(
-                new WindowInsets.Builder().setVisible(ime(), false).build());
-
-        assertThat(mMenuView.mCurrentLayoutParams.y).isEqualTo(expectedLayoutY);
-    }
-
-    @Test
-    public void showMenuAndIme_withHigherIme_alignDisplayTopEdge() {
-        final int offset = 99999;
-
-        setupBasicMenuView(mMenuView);
-        final WindowInsets imeInset = fakeImeInsetWith(mMenuView, offset);
-        when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
-        when(mWindowMetrics.getWindowInsets()).thenReturn(imeInset);
-        mMenuView.dispatchApplyWindowInsets(imeInset);
-
-        assertThat(mMenuView.mCurrentLayoutParams.y).isEqualTo(0);
-    }
-
-    @Test
-    public void testConstructor_withPosition_expectedPosition() {
-        final float expectedX = 1.0f;
-        final float expectedY = 0.7f;
-        final Position position = new Position(expectedX, expectedY);
-
-        final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext,
-                position);
-        setupBasicMenuView(menuView);
-
-        assertThat((float) menuView.mCurrentLayoutParams.x).isWithin(1.0f).of(mMaxWindowX);
-        assertThat((float) menuView.mCurrentLayoutParams.y).isWithin(1.0f).of(
-                expectedY * mMaxWindowY);
-    }
-
-    @After
-    public void tearDown() {
-        mInterceptMotionEvent = null;
-        mMotionEventHelper.recycleEvents();
-        mListView = null;
-    }
-
-    private void setupBasicMenuView(AccessibilityFloatingMenuView menuView) {
-        menuView.show();
-        menuView.onTargetsChanged(mTargets);
-        menuView.setSizeType(0);
-        menuView.setShapeType(0);
-    }
-
-    /**
-     * Based on the current menu status, fake the ime inset component {@link WindowInsets} used
-     * for testing.
-     *
-     * @param menuView {@link AccessibilityFloatingMenuView} that needs to be changed
-     * @param offset is used for the y-axis position of ime higher than the y-axis position of menu
-     * @return the ime inset
-     */
-    private WindowInsets fakeImeInsetWith(AccessibilityFloatingMenuView menuView, int offset) {
-        // Ensure the keyboard has overlapped on the menu view.
-        final int fakeImeHeight =
-                mDisplayWindowHeight - (menuView.mCurrentLayoutParams.y + mMenuWindowHeight)
-                        + offset;
-        return new WindowInsets.Builder()
-                .setVisible(ime(), true)
-                .setInsets(ime(), Insets.of(0, 0, 0, fakeImeHeight))
-                .build();
-    }
-
-    private WindowInsets fakeDisplayInsets() {
-        final int fakeStatusBarHeight = 75;
-        final int fakeNavigationBarHeight = 125;
-        return new WindowInsets.Builder()
-                .setVisible(systemBars() | displayCutout(), true)
-                .setInsets(systemBars() | displayCutout(),
-                        Insets.of(0, fakeStatusBarHeight, 0, fakeNavigationBarHeight))
-                .build();
-    }
-
-    private class TestAccessibilityFloatingMenu extends AccessibilityFloatingMenuView {
-        TestAccessibilityFloatingMenu(Context context, Position position, RecyclerView listView) {
-            super(context, position, listView);
-        }
-
-        @Override
-        public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView,
-                @NonNull MotionEvent event) {
-            final boolean intercept = super.onInterceptTouchEvent(recyclerView, event);
-
-            if (intercept) {
-                mInterceptMotionEvent = event;
-            }
-
-            return intercept;
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipViewTest.java
deleted file mode 100644
index 3553a0a..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipViewTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.MotionEvent;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.accessibility.MotionEventHelper;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/** Tests for {@link BaseTooltipView}. */
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class BaseTooltipViewTest extends SysuiTestCase {
-
-    @Mock
-    private WindowManager mWindowManager;
-
-    @Mock
-    private WindowMetrics mWindowMetrics;
-
-    private AccessibilityFloatingMenuView mMenuView;
-    private BaseTooltipView mToolTipView;
-
-    private final Position mPlaceholderPosition = new Position(0.0f, 0.0f);
-    private final MotionEventHelper mMotionEventHelper = new MotionEventHelper();
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        final WindowManager wm = mContext.getSystemService(WindowManager.class);
-        doAnswer(invocation -> wm.getMaximumWindowMetrics()).when(
-                mWindowManager).getMaximumWindowMetrics();
-        mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
-        when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
-        when(mWindowMetrics.getBounds()).thenReturn(new Rect());
-        when(mWindowMetrics.getWindowInsets()).thenReturn(new WindowInsets.Builder().build());
-
-        mMenuView = new AccessibilityFloatingMenuView(mContext, mPlaceholderPosition);
-        mToolTipView = new BaseTooltipView(mContext, mMenuView);
-    }
-
-    @Test
-    public void showToolTipView_success() {
-        mToolTipView.show();
-
-        verify(mWindowManager).addView(eq(mToolTipView), any(WindowManager.LayoutParams.class));
-    }
-
-    @Test
-    public void touchOutsideWhenToolTipViewShown_dismiss() {
-        final MotionEvent outsideEvent =
-                mMotionEventHelper.obtainMotionEvent(/* downTime= */ 0,
-                        /* eventTime= */1,
-                        MotionEvent.ACTION_OUTSIDE,
-                        /* x= */ 0,
-                        /* y= */ 0);
-
-        mToolTipView.show();
-        mToolTipView.dispatchTouchEvent(outsideEvent);
-
-        verify(mWindowManager).removeView(mToolTipView);
-    }
-
-    @Test
-    public void getAccessibilityActionList_matchResult() {
-        final AccessibilityNodeInfo infos = new AccessibilityNodeInfo();
-        mToolTipView.onInitializeAccessibilityNodeInfo(infos);
-
-        assertThat(infos.getActionList().size()).isEqualTo(1);
-    }
-
-    @Test
-    public void accessibilityAction_dismiss_success() {
-        final BaseTooltipView tooltipView =
-                spy(new BaseTooltipView(mContext, mMenuView));
-
-        final boolean isActionPerformed =
-                tooltipView.performAccessibilityAction(
-                        AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS.getId(),
-                        /* arguments= */ null);
-
-        assertThat(isActionPerformed).isTrue();
-        verify(tooltipView).hide();
-    }
-
-    @After
-    public void tearDown() {
-        mToolTipView.hide();
-        mMotionEventHelper.recycleEvents();
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DockTooltipViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DockTooltipViewTest.java
deleted file mode 100644
index 9eba49d..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DockTooltipViewTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.MotionEvent;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.accessibility.MotionEventHelper;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/** Tests for {@link DockTooltipView}. */
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class DockTooltipViewTest extends SysuiTestCase {
-
-    @Mock
-    private WindowManager mWindowManager;
-
-    @Mock
-    private WindowMetrics mWindowMetrics;
-
-    private AccessibilityFloatingMenuView mMenuView;
-    private DockTooltipView mDockTooltipView;
-    private final Position mPlaceholderPosition = new Position(0.0f, 0.0f);
-    private final MotionEventHelper mMotionEventHelper = new MotionEventHelper();
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        final WindowManager wm = mContext.getSystemService(WindowManager.class);
-        doAnswer(invocation -> wm.getMaximumWindowMetrics()).when(
-                mWindowManager).getMaximumWindowMetrics();
-        mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
-        when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
-        when(mWindowMetrics.getBounds()).thenReturn(new Rect());
-        when(mWindowMetrics.getWindowInsets()).thenReturn(new WindowInsets.Builder().build());
-
-        mMenuView = spy(new AccessibilityFloatingMenuView(mContext, mPlaceholderPosition));
-        mDockTooltipView = new DockTooltipView(mContext, mMenuView);
-    }
-
-    @Test
-    public void showTooltip_success() {
-        mDockTooltipView.show();
-
-        verify(mMenuView).startTranslateXAnimation();
-        verify(mWindowManager).addView(eq(mDockTooltipView), any(WindowManager.LayoutParams.class));
-    }
-
-    @Test
-    public void hideTooltip_success() {
-        mDockTooltipView.show();
-        mDockTooltipView.hide();
-
-        verify(mMenuView).stopTranslateXAnimation();
-        verify(mWindowManager).removeView(mDockTooltipView);
-    }
-
-    @Test
-    public void touchOutsideWhenToolTipViewShown_stopAnimation() {
-        final MotionEvent outsideEvent =
-                mMotionEventHelper.obtainMotionEvent(/* downTime= */ 0,
-                        /* eventTime= */ 1,
-                        MotionEvent.ACTION_OUTSIDE,
-                        /* x= */ 0,
-                        /* y= */ 0);
-
-        mDockTooltipView.show();
-        mDockTooltipView.dispatchTouchEvent(outsideEvent);
-
-        verify(mMenuView).stopTranslateXAnimation();
-    }
-
-    @After
-    public void tearDown() {
-        mMotionEventHelper.recycleEvents();
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/ItemDelegateCompatTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/ItemDelegateCompatTest.java
deleted file mode 100644
index ea104a7..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/ItemDelegateCompatTest.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate;
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-/** Tests for {@link ItemDelegateCompat}. */
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class ItemDelegateCompatTest extends SysuiTestCase {
-    @Rule
-    public MockitoRule mockito = MockitoJUnit.rule();
-
-    @Mock
-    private WindowManager mWindowManager;
-
-    @Mock
-    private WindowMetrics mWindowMetrics;
-    private RecyclerView mListView;
-    private AccessibilityFloatingMenuView mMenuView;
-    private ItemDelegateCompat mItemDelegateCompat;
-    private final Rect mAvailableBounds = new Rect(100, 200, 300, 400);
-    private final Position mPlaceholderPosition = new Position(0.0f, 0.0f);
-
-    @Before
-    public void setUp() {
-        final WindowManager wm = mContext.getSystemService(WindowManager.class);
-        doAnswer(invocation -> wm.getMaximumWindowMetrics()).when(
-                mWindowManager).getMaximumWindowMetrics();
-        mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
-        when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
-        when(mWindowMetrics.getBounds()).thenReturn(new Rect());
-        when(mWindowMetrics.getWindowInsets()).thenReturn(new WindowInsets.Builder().build());
-
-        mListView = new RecyclerView(mContext);
-        mMenuView =
-                spy(new AccessibilityFloatingMenuView(mContext, mPlaceholderPosition, mListView));
-        mItemDelegateCompat =
-                new ItemDelegateCompat(new RecyclerViewAccessibilityDelegate(mListView), mMenuView);
-    }
-
-    @Test
-    public void getAccessibilityActionList_matchResult() {
-        final AccessibilityNodeInfoCompat info =
-                new AccessibilityNodeInfoCompat(new AccessibilityNodeInfo());
-
-        mItemDelegateCompat.onInitializeAccessibilityNodeInfo(mListView, info);
-
-        assertThat(info.getActionList().size()).isEqualTo(5);
-    }
-
-    @Test
-    public void performAccessibilityMoveTopLeftAction_halfOval_success() {
-        doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds();
-        mMenuView.setShapeType(/* halfOvalShape */ 1);
-
-        final boolean moveTopLeftAction =
-                mItemDelegateCompat.performAccessibilityAction(mListView, R.id.action_move_top_left,
-                        null);
-
-        assertThat(moveTopLeftAction).isTrue();
-        assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0);
-        verify(mMenuView).snapToLocation(mAvailableBounds.left, mAvailableBounds.top);
-    }
-
-    @Test
-    public void performAccessibilityMoveTopRightAction_halfOval_success() {
-        doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds();
-        mMenuView.setShapeType(/* halfOvalShape */ 1);
-
-        final boolean moveTopRightAction =
-                mItemDelegateCompat.performAccessibilityAction(mListView,
-                        R.id.action_move_top_right, null);
-
-        assertThat(moveTopRightAction).isTrue();
-        assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0);
-        verify(mMenuView).snapToLocation(mAvailableBounds.right, mAvailableBounds.top);
-    }
-
-    @Test
-    public void performAccessibilityMoveBottomLeftAction_halfOval_success() {
-        doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds();
-        mMenuView.setShapeType(/* halfOvalShape */ 1);
-
-        final boolean moveBottomLeftAction =
-                mItemDelegateCompat.performAccessibilityAction(mListView,
-                        R.id.action_move_bottom_left, null);
-
-        assertThat(moveBottomLeftAction).isTrue();
-        assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0);
-        verify(mMenuView).snapToLocation(mAvailableBounds.left, mAvailableBounds.bottom);
-    }
-
-    @Test
-    public void performAccessibilityMoveBottomRightAction_halfOval_success() {
-        doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds();
-        mMenuView.setShapeType(/* halfOvalShape */ 1);
-
-        final boolean moveBottomRightAction =
-                mItemDelegateCompat.performAccessibilityAction(mListView,
-                        R.id.action_move_bottom_right, null);
-
-        assertThat(moveBottomRightAction).isTrue();
-        assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0);
-        verify(mMenuView).snapToLocation(mAvailableBounds.right, mAvailableBounds.bottom);
-    }
-
-    @Test
-    public void performAccessibilityMoveOutEdgeAction_halfOval_success() {
-        doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds();
-        mMenuView.setShapeType(/* halfOvalShape */ 1);
-
-        final boolean moveOutEdgeAndShowAction =
-                mItemDelegateCompat.performAccessibilityAction(mListView,
-                        R.id.action_move_out_edge_and_show, null);
-
-        assertThat(moveOutEdgeAndShowAction).isTrue();
-        assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0);
-    }
-
-    @Test
-    public void setupAccessibilityActions_oval_hasActionMoveToEdgeAndHide() {
-        final AccessibilityNodeInfoCompat info =
-                new AccessibilityNodeInfoCompat(new AccessibilityNodeInfo());
-        mMenuView.setShapeType(/* ovalShape */ 0);
-
-        mItemDelegateCompat.onInitializeAccessibilityNodeInfo(mListView, info);
-
-        assertThat(info.getActionList().stream().anyMatch(
-                action -> action.getId() == R.id.action_move_to_edge_and_hide)).isTrue();
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
index 728ea1e..5bb5e01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
@@ -165,14 +165,14 @@
     }
 
     @Test
-    public void tiggerDismissMenuAction_hideFloatingMenu() {
+    public void triggerDismissMenuAction_hideFloatingMenu() {
         mMenuViewLayer.mDismissMenuAction.run();
 
         verify(mFloatingMenu).hide();
     }
 
     @Test
-    public void tiggerDismissMenuAction_matchA11yButtonTargetsResult() {
+    public void triggerDismissMenuAction_matchA11yButtonTargetsResult() {
         mMenuViewLayer.mDismissMenuAction.run();
         verify(mSecureSettings).putStringForUser(
                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, /* value= */ "",
@@ -180,24 +180,8 @@
     }
 
     @Test
-    public void tiggerDismissMenuAction_matchEnabledA11yServicesResult() {
-        Settings.Secure.putString(mContext.getContentResolver(),
-                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString());
-        final ResolveInfo resolveInfo = new ResolveInfo();
-        final ServiceInfo serviceInfo = new ServiceInfo();
-        final ApplicationInfo applicationInfo = new ApplicationInfo();
-        resolveInfo.serviceInfo = serviceInfo;
-        serviceInfo.applicationInfo = applicationInfo;
-        applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
-        final AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
-        accessibilityServiceInfo.setResolveInfo(resolveInfo);
-        accessibilityServiceInfo.flags = AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
-        final List<AccessibilityServiceInfo> serviceInfoList = new ArrayList<>();
-        accessibilityServiceInfo.setComponentName(TEST_SELECT_TO_SPEAK_COMPONENT_NAME);
-        serviceInfoList.add(accessibilityServiceInfo);
-        when(mStubAccessibilityManager.getEnabledAccessibilityServiceList(
-                AccessibilityServiceInfo.FEEDBACK_ALL_MASK)).thenReturn(serviceInfoList);
+    public void triggerDismissMenuAction_matchEnabledA11yServicesResult() {
+        setupEnabledAccessibilityServiceList();
 
         mMenuViewLayer.mDismissMenuAction.run();
         final String value = Settings.Secure.getString(mContext.getContentResolver(),
@@ -207,6 +191,21 @@
     }
 
     @Test
+    public void triggerDismissMenuAction_hasHardwareKeyShortcut_keepEnabledStatus() {
+        setupEnabledAccessibilityServiceList();
+        final List<String> stubShortcutTargets = new ArrayList<>();
+        stubShortcutTargets.add(TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString());
+        when(mStubAccessibilityManager.getAccessibilityShortcutTargets(
+                AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY)).thenReturn(stubShortcutTargets);
+
+        mMenuViewLayer.mDismissMenuAction.run();
+        final String value = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+
+        assertThat(value).isEqualTo(TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString());
+    }
+
+    @Test
     public void showingImeInsetsChange_notOverlapOnIme_menuKeepOriginalPosition() {
         final float menuTop = STATUS_BAR_HEIGHT + 100;
         mMenuAnimationController.moveAndPersistPosition(new PointF(0, menuTop));
@@ -241,6 +240,27 @@
         assertThat(mMenuView.getTranslationY()).isEqualTo(menuTop);
     }
 
+    private void setupEnabledAccessibilityServiceList() {
+        Settings.Secure.putString(mContext.getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString());
+
+        final ResolveInfo resolveInfo = new ResolveInfo();
+        final ServiceInfo serviceInfo = new ServiceInfo();
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        resolveInfo.serviceInfo = serviceInfo;
+        serviceInfo.applicationInfo = applicationInfo;
+        applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
+        final AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
+        accessibilityServiceInfo.setResolveInfo(resolveInfo);
+        accessibilityServiceInfo.flags = AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
+        final List<AccessibilityServiceInfo> serviceInfoList = new ArrayList<>();
+        accessibilityServiceInfo.setComponentName(TEST_SELECT_TO_SPEAK_COMPONENT_NAME);
+        serviceInfoList.add(accessibilityServiceInfo);
+        when(mStubAccessibilityManager.getEnabledAccessibilityServiceList(
+                AccessibilityServiceInfo.FEEDBACK_ALL_MASK)).thenReturn(serviceInfoList);
+    }
+
     private void dispatchShowingImeInsets() {
         final WindowInsets fakeShowingImeInsets = fakeImeInsets(/* isImeVisible= */ true);
         doReturn(fakeShowingImeInsets).when(mWindowMetrics).getWindowInsets();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipViewTest.java
deleted file mode 100644
index 2fb0a90..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipViewTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.accessibility.floatingmenu;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.text.SpannableString;
-import android.text.method.LinkMovementMethod;
-import android.widget.TextView;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** Tests for {@link MigrationTooltipView}. */
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class MigrationTooltipViewTest extends SysuiTestCase {
-
-    private TextView mTextView;
-    private final Position mPlaceholderPosition = new Position(0.0f, 0.0f);
-
-    @Before
-    public void setUp() {
-        final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext,
-                mPlaceholderPosition);
-        final MigrationTooltipView toolTipView = new MigrationTooltipView(mContext, menuView);
-        mTextView = toolTipView.findViewById(R.id.text);
-    }
-
-    @Test
-    public void onCreate_setLinkMovementMethod() {
-        assertThat(mTextView.getMovementMethod()).isInstanceOf(LinkMovementMethod.class);
-    }
-
-    @Test
-    public void onCreate_setDescription_matchTextAndSpanNum() {
-        final CharSequence expectedTextWithoutSpan =
-                AnnotationLinkSpan.linkify(mContext.getText(
-                R.string.accessibility_floating_button_migration_tooltip)).toString();
-        final SpannableString spannableString = (SpannableString) mTextView.getText();
-        final int AnnotationLinkSpanNum =
-                spannableString.getSpans(/* queryStart= */ 0, spannableString.length(),
-                        AnnotationLinkSpan.class).length;
-
-        assertThat(AnnotationLinkSpanNum).isEqualTo(1);
-        assertThat(mTextView.getText().toString().contentEquals(expectedTextWithoutSpan)).isTrue();
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
index 1e62fd23..316de59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
@@ -268,6 +268,12 @@
         }
     }
 
+    @Test
+    fun showFromDialogDoesNotCrashWhenShownFromRandomDialog() {
+        val dialog = createDialogAndShowFromDialog(animateFrom = TestDialog(context))
+        dialog.dismiss()
+    }
+
     private fun createAndShowDialog(
         animator: DialogLaunchAnimator = dialogLaunchAnimator,
     ): TestDialog {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 5afe49e..0d00e8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -85,6 +85,7 @@
 import com.android.internal.R;
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.settingslib.udfps.UdfpsUtils;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.biometrics.domain.interactor.BiometricPromptCredentialInteractor;
 import com.android.systemui.biometrics.domain.interactor.LogContextInteractor;
@@ -167,6 +168,8 @@
     private BiometricPromptCredentialInteractor mBiometricPromptCredentialInteractor;
     @Mock
     private CredentialViewModel mCredentialViewModel;
+    @Mock
+    private UdfpsUtils mUdfpsUtils;
 
     @Captor
     private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mFpAuthenticatorsRegisteredCaptor;
@@ -958,7 +961,7 @@
                     mPanelInteractionDetector, mUserManager, mLockPatternUtils, mUdfpsLogger,
                     mLogContextInteractor, () -> mBiometricPromptCredentialInteractor,
                     () -> mCredentialViewModel, mInteractionJankMonitor, mHandler,
-                    mBackgroundExecutor, mVibratorHelper);
+                    mBackgroundExecutor, mVibratorHelper, mUdfpsUtils);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index fd931b0..41beada 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -52,18 +52,16 @@
 import androidx.test.filters.SmallTest
 import com.airbnb.lottie.LottieAnimationView
 import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.ViewMediatorCallback
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.SysuiTestableContext
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags.MODERN_ALTERNATE_BOUNCER
-import com.android.systemui.keyguard.data.repository.FakeBiometricRepository
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.recents.OverviewProxyService
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
@@ -111,7 +109,7 @@
     @Captor lateinit var overlayCaptor: ArgumentCaptor<View>
     @Captor lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
 
-    private lateinit var keyguardBouncerRepository: KeyguardBouncerRepository
+    private lateinit var keyguardBouncerRepository: FakeKeyguardBouncerRepository
     private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
     private val featureFlags = FakeFeatureFlags()
     private val executor = FakeExecutor(FakeSystemClock())
@@ -135,17 +133,11 @@
     @Before
     fun setup() {
         featureFlags.set(MODERN_ALTERNATE_BOUNCER, true)
-        keyguardBouncerRepository =
-            KeyguardBouncerRepository(
-                mock(ViewMediatorCallback::class.java),
-                FakeSystemClock(),
-                TestCoroutineScope(),
-                mock(TableLogBuffer::class.java),
-            )
+        keyguardBouncerRepository = FakeKeyguardBouncerRepository()
         alternateBouncerInteractor =
             AlternateBouncerInteractor(
                 keyguardBouncerRepository,
-                FakeBiometricRepository(),
+                FakeBiometricSettingsRepository(),
                 FakeDeviceEntryFingerprintAuthRepository(),
                 FakeSystemClock(),
                 mock(KeyguardUpdateMonitor::class.java),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 36ed6d5..bb037642 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -21,12 +21,9 @@
 import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
 import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_OTHER
 import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR
 import android.hardware.biometrics.BiometricOverlayConstants.ShowReason
 import android.hardware.fingerprint.FingerprintManager
 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
-import android.provider.Settings
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import android.view.LayoutInflater
@@ -38,6 +35,8 @@
 import android.view.accessibility.AccessibilityManager
 import androidx.test.filters.SmallTest
 import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.settingslib.udfps.UdfpsOverlayParams
+import com.android.settingslib.udfps.UdfpsUtils
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.ActivityLaunchAnimator
@@ -104,12 +103,12 @@
     @Mock private lateinit var controllerCallback: IUdfpsOverlayControllerCallback
     @Mock private lateinit var udfpsController: UdfpsController
     @Mock private lateinit var udfpsView: UdfpsView
-    @Mock private lateinit var udfpsEnrollView: UdfpsEnrollView
     @Mock private lateinit var udfpsKeyguardView: UdfpsKeyguardView
     @Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
     @Mock private lateinit var featureFlags: FeatureFlags
     @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
     @Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+    @Mock private lateinit var udfpsUtils: UdfpsUtils
     @Captor private lateinit var layoutParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
 
     private val onTouch = { _: View, _: MotionEvent, _: Boolean -> true }
@@ -118,18 +117,14 @@
 
     @Before
     fun setup() {
-        context.orCreateTestableResources.addOverride(R.integer.config_udfpsEnrollProgressBar, 20)
         whenever(inflater.inflate(R.layout.udfps_view, null, false))
             .thenReturn(udfpsView)
-        whenever(inflater.inflate(R.layout.udfps_enroll_view, null))
-            .thenReturn(udfpsEnrollView)
         whenever(inflater.inflate(R.layout.udfps_bp_view, null))
             .thenReturn(mock(UdfpsBpView::class.java))
         whenever(inflater.inflate(R.layout.udfps_keyguard_view, null))
             .thenReturn(udfpsKeyguardView)
         whenever(inflater.inflate(R.layout.udfps_fpm_empty_view, null))
             .thenReturn(mock(UdfpsFpmEmptyView::class.java))
-        whenever(udfpsEnrollView.context).thenReturn(context)
     }
 
     private fun withReason(
@@ -144,7 +139,7 @@
             configurationController, keyguardStateController, unlockedScreenOffAnimationController,
             udfpsDisplayMode, secureSettings, REQUEST_ID, reason,
             controllerCallback, onTouch, activityLaunchAnimator, featureFlags,
-            primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable
+            primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable, udfpsUtils
         )
         block()
     }
@@ -159,37 +154,6 @@
     }
 
     @Test
-    fun showUdfpsOverlay_settings() = withReason(REASON_AUTH_SETTINGS) { showUdfpsOverlay() }
-
-    @Test
-    fun showUdfpsOverlay_locate() = withReason(REASON_ENROLL_FIND_SENSOR) {
-        showUdfpsOverlay(isEnrollUseCase = true)
-    }
-
-    @Test
-    fun showUdfpsOverlay_locate_withEnrollmentUiRemoved() {
-        Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 1)
-        withReason(REASON_ENROLL_FIND_SENSOR, isDebuggable = true) {
-            showUdfpsOverlay(isEnrollUseCase = false)
-        }
-        Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 0)
-    }
-
-    @Test
-    fun showUdfpsOverlay_enroll() = withReason(REASON_ENROLL_ENROLLING) {
-        showUdfpsOverlay(isEnrollUseCase = true)
-    }
-
-    @Test
-    fun showUdfpsOverlay_enroll_withEnrollmentUiRemoved() {
-        Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 1)
-        withReason(REASON_ENROLL_ENROLLING, isDebuggable = true) {
-            showUdfpsOverlay(isEnrollUseCase = false)
-        }
-        Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 0)
-    }
-
-    @Test
     fun showUdfpsOverlay_other() = withReason(REASON_AUTH_OTHER) { showUdfpsOverlay() }
 
     private fun withRotation(@Rotation rotation: Int, block: () -> Unit) {
@@ -278,7 +242,7 @@
         }
     }
 
-    private fun showUdfpsOverlay(isEnrollUseCase: Boolean = false) {
+    private fun showUdfpsOverlay() {
         val didShow = controllerOverlay.show(udfpsController, overlayParams)
 
         verify(windowManager).addView(eq(controllerOverlay.overlayView), any())
@@ -290,12 +254,6 @@
         assertThat(controllerOverlay.isShowing).isTrue()
         assertThat(controllerOverlay.isHiding).isFalse()
         assertThat(controllerOverlay.overlayView).isNotNull()
-        if (isEnrollUseCase) {
-            verify(udfpsEnrollView).updateSensorLocation(eq(overlayParams.sensorBounds))
-            assertThat(controllerOverlay.enrollHelper).isNotNull()
-        } else {
-            assertThat(controllerOverlay.enrollHelper).isNull()
-        }
     }
 
     @Test
@@ -308,12 +266,6 @@
     fun hideUdfpsOverlay_settings() = withReason(REASON_AUTH_SETTINGS) { hideUdfpsOverlay() }
 
     @Test
-    fun hideUdfpsOverlay_locate() = withReason(REASON_ENROLL_FIND_SENSOR) { hideUdfpsOverlay() }
-
-    @Test
-    fun hideUdfpsOverlay_enroll() = withReason(REASON_ENROLL_ENROLLING) { hideUdfpsOverlay() }
-
-    @Test
     fun hideUdfpsOverlay_other() = withReason(REASON_AUTH_OTHER) { hideUdfpsOverlay() }
 
     private fun hideUdfpsOverlay() {
@@ -343,44 +295,6 @@
     }
 
     @Test
-    fun forwardEnrollProgressEvents() = withReason(REASON_ENROLL_ENROLLING) {
-        controllerOverlay.show(udfpsController, overlayParams)
-
-        with(EnrollListener(controllerOverlay)) {
-            controllerOverlay.onEnrollmentProgress(/* remaining */20)
-            controllerOverlay.onAcquiredGood()
-            assertThat(progress).isTrue()
-            assertThat(help).isFalse()
-            assertThat(acquired).isFalse()
-        }
-    }
-
-    @Test
-    fun forwardEnrollHelpEvents() = withReason(REASON_ENROLL_ENROLLING) {
-        controllerOverlay.show(udfpsController, overlayParams)
-
-        with(EnrollListener(controllerOverlay)) {
-            controllerOverlay.onEnrollmentHelp()
-            assertThat(progress).isFalse()
-            assertThat(help).isTrue()
-            assertThat(acquired).isFalse()
-        }
-    }
-
-    @Test
-    fun forwardEnrollAcquiredEvents() = withReason(REASON_ENROLL_ENROLLING) {
-        controllerOverlay.show(udfpsController, overlayParams)
-
-        with(EnrollListener(controllerOverlay)) {
-            controllerOverlay.onEnrollmentProgress(/* remaining */ 1)
-            controllerOverlay.onAcquiredGood()
-            assertThat(progress).isTrue()
-            assertThat(help).isFalse()
-            assertThat(acquired).isTrue()
-        }
-    }
-
-    @Test
     fun cancels() = withReason(REASON_AUTH_BP) {
         controllerOverlay.cancel()
         verify(controllerCallback).onUserCanceled()
@@ -400,131 +314,4 @@
         assertThat(controllerOverlay.matchesRequestId(REQUEST_ID)).isTrue()
         assertThat(controllerOverlay.matchesRequestId(REQUEST_ID + 1)).isFalse()
     }
-
-    @Test
-    fun testTouchOutsideAreaNoRotation() = withReason(REASON_ENROLL_ENROLLING) {
-        val touchHints =
-            context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
-        val rotation = Surface.ROTATION_0
-        // touch at 0 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                0.0f /* x */, 0.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[0])
-        // touch at 90 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                0.0f /* x */, -1.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[1])
-        // touch at 180 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                -1.0f /* x */, 0.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[2])
-        // touch at 270 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                0.0f /* x */, 1.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[3])
-    }
-
-    fun testTouchOutsideAreaNoRotation90Degrees() = withReason(REASON_ENROLL_ENROLLING) {
-        val touchHints =
-            context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
-        val rotation = Surface.ROTATION_90
-        // touch at 0 degrees -> 90 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                0.0f /* x */, 0.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[1])
-        // touch at 90 degrees -> 180 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                0.0f /* x */, -1.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[2])
-        // touch at 180 degrees -> 270 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                -1.0f /* x */, 0.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[3])
-        // touch at 270 degrees -> 0 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                0.0f /* x */, 1.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[0])
-    }
-
-    fun testTouchOutsideAreaNoRotation270Degrees() = withReason(REASON_ENROLL_ENROLLING) {
-        val touchHints =
-            context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
-        val rotation = Surface.ROTATION_270
-        // touch at 0 degrees -> 270 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                0.0f /* x */, 0.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[3])
-        // touch at 90 degrees -> 0 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                0.0f /* x */, -1.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[0])
-        // touch at 180 degrees -> 90 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                -1.0f /* x */, 0.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[1])
-        // touch at 270 degrees -> 180 degrees
-        assertThat(
-            controllerOverlay.onTouchOutsideOfSensorAreaImpl(
-                0.0f /* x */, 1.0f /* y */,
-                0.0f /* sensorX */, 0.0f /* sensorY */, rotation
-            )
-        ).isEqualTo(touchHints[2])
-    }
-}
-
-private class EnrollListener(
-    overlay: UdfpsControllerOverlay,
-    var progress: Boolean = false,
-    var help: Boolean = false,
-    var acquired: Boolean = false
-) : UdfpsEnrollHelper.Listener {
-
-    init {
-        overlay.enrollHelper!!.setListener(this)
-    }
-
-    override fun onEnrollmentProgress(remaining: Int, totalSteps: Int) {
-        progress = true
-    }
-
-    override fun onEnrollmentHelp(remaining: Int, totalSteps: Int) {
-        help = true
-    }
-
-    override fun onLastStepAcquired() {
-        acquired = true
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index dd7082a..17c262d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -71,6 +71,8 @@
 import com.android.internal.logging.InstanceIdSequence;
 import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.settingslib.udfps.UdfpsOverlayParams;
+import com.android.settingslib.udfps.UdfpsUtils;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.ActivityLaunchAnimator;
@@ -230,10 +232,12 @@
     private ScreenLifecycle.Observer mScreenObserver;
     private FingerprintSensorPropertiesInternal mOpticalProps;
     private FingerprintSensorPropertiesInternal mUltrasonicProps;
+    private UdfpsUtils mUdfpsUtils;
 
     @Before
     public void setUp() {
         Execution execution = new FakeExecution();
+        mUdfpsUtils = new UdfpsUtils();
 
         when(mLayoutInflater.inflate(R.layout.udfps_view, null, false))
                 .thenReturn(mUdfpsView);
@@ -305,7 +309,7 @@
                 mUnlockedScreenOffAnimationController, mSystemUIDialogManager, mLatencyTracker,
                 mActivityLaunchAnimator, alternateTouchProvider, mBiometricExecutor,
                 mPrimaryBouncerInteractor, mSinglePointerTouchProcessor, mSessionTracker,
-                mAlternateBouncerInteractor, mSecureSettings);
+                mAlternateBouncerInteractor, mSecureSettings, mUdfpsUtils);
         verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
         mOverlayController = mOverlayCaptor.getValue();
         verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsEnrollViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsEnrollViewTest.java
deleted file mode 100644
index 60a0258..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsEnrollViewTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.biometrics;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.res.Configuration;
-import android.graphics.Color;
-import android.testing.AndroidTestingRunner;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class UdfpsEnrollViewTest extends SysuiTestCase {
-
-    private static String ENROLL_PROGRESS_COLOR_LIGHT = "#699FF3";
-    private static String ENROLL_PROGRESS_COLOR_DARK = "#7DA7F1";
-
-    @Test
-    public void fingerprintUdfpsEnroll_usesCorrectThemeCheckmarkFillColor() {
-        final Configuration config = mContext.getResources().getConfiguration();
-        final boolean isDarkThemeOn = (config.uiMode & Configuration.UI_MODE_NIGHT_MASK)
-                == Configuration.UI_MODE_NIGHT_YES;
-        final int currentColor = mContext.getColor(R.color.udfps_enroll_progress);
-
-        assertThat(currentColor).isEqualTo(Color.parseColor(isDarkThemeOn
-                ? ENROLL_PROGRESS_COLOR_DARK : ENROLL_PROGRESS_COLOR_LIGHT));
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index 81a6bc2..c73ff1d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -26,9 +26,10 @@
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.keyguard.DismissCallbackRegistry
 import com.android.systemui.keyguard.data.BouncerView
-import com.android.systemui.keyguard.data.repository.BiometricRepository
+import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
+import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
@@ -65,7 +66,7 @@
         allowTestableLooperAsMainThread() // repeatWhenAttached requires the main thread
         MockitoAnnotations.initMocks(this)
         keyguardBouncerRepository =
-            KeyguardBouncerRepository(
+            KeyguardBouncerRepositoryImpl(
                 mock(com.android.keyguard.ViewMediatorCallback::class.java),
                 FakeSystemClock(),
                 TestCoroutineScope(),
@@ -91,7 +92,7 @@
         mAlternateBouncerInteractor =
             AlternateBouncerInteractor(
                 keyguardBouncerRepository,
-                mock(BiometricRepository::class.java),
+                mock(BiometricSettingsRepository::class.java),
                 mock(DeviceEntryFingerprintAuthRepository::class.java),
                 mock(SystemClock::class.java),
                 mock(KeyguardUpdateMonitor::class.java),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
index 44fa4eb..07b4a64 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
@@ -25,6 +25,7 @@
 import android.view.LayoutInflater
 import android.view.Surface
 import androidx.test.filters.SmallTest
+import com.android.settingslib.udfps.UdfpsOverlayParams
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.mockito.any
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt
index af46d9b..4b41537 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt
@@ -16,30 +16,23 @@
 
 package com.android.systemui.biometrics.udfps
 
-import android.graphics.Point
 import android.graphics.Rect
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.EllipseOverlapDetectorParams
 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.Mockito.spy
-import org.mockito.Mockito.`when` as whenEver
 
 @SmallTest
 @RunWith(Parameterized::class)
 class EllipseOverlapDetectorTest(val testCase: TestCase) : SysuiTestCase() {
-    val underTest = spy(EllipseOverlapDetector(neededPoints = 1))
-
-    @Before
-    fun setUp() {
-        // Use one single center point for testing, required or total number of points may change
-        whenEver(underTest.calculateSensorPoints(SENSOR))
-            .thenReturn(listOf(Point(SENSOR.centerX(), SENSOR.centerY())))
-    }
+    val underTest =
+        EllipseOverlapDetector(
+            EllipseOverlapDetectorParams(minOverlap = .4f, targetSize = .2f, stepSize = 1)
+        )
 
     @Test
     fun isGoodOverlap() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt
index 8e20303..c40fd4fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/SinglePointerTouchProcessorTest.kt
@@ -23,8 +23,8 @@
 import android.view.Surface
 import android.view.Surface.Rotation
 import androidx.test.filters.SmallTest
+import com.android.settingslib.udfps.UdfpsOverlayParams
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.UdfpsOverlayParams
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
index 71c335e..7177919 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.clipboardoverlay;
 
+import static com.android.systemui.flags.Flags.CLIPBOARD_MINIMIZED_LAYOUT;
+
 import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE;
 
 import static org.junit.Assert.assertEquals;
@@ -38,6 +40,7 @@
 
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.flags.FakeFeatureFlags;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -60,6 +63,7 @@
     private ClipboardOverlayController mOverlayController;
     @Mock
     private ClipboardToast mClipboardToast;
+    private FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
     @Mock
     private UiEventLogger mUiEventLogger;
 
@@ -93,8 +97,10 @@
         when(mClipboardManager.getPrimaryClip()).thenReturn(mSampleClipData);
         when(mClipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource);
 
+        mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, true);
+
         mClipboardListener = new ClipboardListener(getContext(), mOverlayControllerProvider,
-                mClipboardToast, mClipboardManager, mUiEventLogger);
+                mClipboardToast, mClipboardManager, mFeatureFlags, mUiEventLogger);
     }
 
 
@@ -187,4 +193,34 @@
         verify(mClipboardToast, times(1)).showCopiedToast();
         verifyZeroInteractions(mOverlayControllerProvider);
     }
+
+    @Test
+    public void test_minimizedLayoutFlagOff_usesLegacy() {
+        mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, false);
+
+        mClipboardListener.start();
+        mClipboardListener.onPrimaryClipChanged();
+
+        verify(mOverlayControllerProvider).get();
+
+        verify(mOverlayController).setClipDataLegacy(
+                mClipDataCaptor.capture(), mStringCaptor.capture());
+
+        assertEquals(mSampleClipData, mClipDataCaptor.getValue());
+        assertEquals(mSampleSource, mStringCaptor.getValue());
+    }
+
+    @Test
+    public void test_minimizedLayoutFlagOn_usesNew() {
+        mClipboardListener.start();
+        mClipboardListener.onPrimaryClipChanged();
+
+        verify(mOverlayControllerProvider).get();
+
+        verify(mOverlayController).setClipData(
+                mClipDataCaptor.capture(), mStringCaptor.capture());
+
+        assertEquals(mSampleClipData, mClipDataCaptor.getValue());
+        assertEquals(mSampleSource, mStringCaptor.getValue());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardModelTest.kt
new file mode 100644
index 0000000..faef35e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardModelTest.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.clipboardoverlay
+
+import android.content.ClipData
+import android.content.ClipDescription
+import android.content.ContentResolver
+import android.content.Context
+import android.graphics.Bitmap
+import android.net.Uri
+import android.os.PersistableBundle
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.whenever
+import java.io.IOException
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ClipboardModelTest : SysuiTestCase() {
+    @Mock private lateinit var mClipboardUtils: ClipboardOverlayUtils
+    @Mock private lateinit var mMockContext: Context
+    @Mock private lateinit var mMockContentResolver: ContentResolver
+    private lateinit var mSampleClipData: ClipData
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        mSampleClipData = ClipData("Test", arrayOf("text/plain"), ClipData.Item("Test Item"))
+    }
+
+    @Test
+    fun test_nullClipData() {
+        val model = ClipboardModel.fromClipData(mContext, mClipboardUtils, null, "test source")
+        assertNull(model.clipData)
+        assertEquals("test source", model.source)
+        assertEquals(ClipboardModel.Type.OTHER, model.type)
+        assertNull(model.item)
+        assertFalse(model.isSensitive)
+        assertFalse(model.isRemote)
+        assertNull(model.loadThumbnail(mContext))
+    }
+
+    @Test
+    fun test_textClipData() {
+        val source = "test source"
+        val model = ClipboardModel.fromClipData(mContext, mClipboardUtils, mSampleClipData, source)
+        assertEquals(mSampleClipData, model.clipData)
+        assertEquals(source, model.source)
+        assertEquals(ClipboardModel.Type.TEXT, model.type)
+        assertEquals(mSampleClipData.getItemAt(0), model.item)
+        assertFalse(model.isSensitive)
+        assertFalse(model.isRemote)
+        assertNull(model.loadThumbnail(mContext))
+    }
+
+    @Test
+    fun test_sensitiveExtra() {
+        val description = mSampleClipData.description
+        val b = PersistableBundle()
+        b.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true)
+        description.extras = b
+        val data = ClipData(description, mSampleClipData.getItemAt(0))
+        val (_, _, _, _, sensitive) =
+            ClipboardModel.fromClipData(mContext, mClipboardUtils, data, "")
+        assertTrue(sensitive)
+    }
+
+    @Test
+    fun test_remoteExtra() {
+        whenever(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(true)
+        val model = ClipboardModel.fromClipData(mContext, mClipboardUtils, mSampleClipData, "")
+        assertTrue(model.isRemote)
+    }
+
+    @Test
+    @Throws(IOException::class)
+    fun test_imageClipData() {
+        val testBitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888)
+        whenever(mMockContext.contentResolver).thenReturn(mMockContentResolver)
+        whenever(mMockContext.resources).thenReturn(mContext.resources)
+        whenever(mMockContentResolver.loadThumbnail(any(), any(), any())).thenReturn(testBitmap)
+        whenever(mMockContentResolver.getType(any())).thenReturn("image")
+        val imageClipData =
+            ClipData("Test", arrayOf("text/plain"), ClipData.Item(Uri.parse("test")))
+        val model = ClipboardModel.fromClipData(mMockContext, mClipboardUtils, imageClipData, "")
+        assertEquals(ClipboardModel.Type.IMAGE, model.type)
+        assertEquals(testBitmap, model.loadThumbnail(mMockContext))
+    }
+
+    @Test
+    @Throws(IOException::class)
+    fun test_imageClipData_loadFailure() {
+        whenever(mMockContext.contentResolver).thenReturn(mMockContentResolver)
+        whenever(mMockContext.resources).thenReturn(mContext.resources)
+        whenever(mMockContentResolver.loadThumbnail(any(), any(), any())).thenThrow(IOException())
+        whenever(mMockContentResolver.getType(any())).thenReturn("image")
+        val imageClipData =
+            ClipData("Test", arrayOf("text/plain"), ClipData.Item(Uri.parse("test")))
+        val model = ClipboardModel.fromClipData(mMockContext, mClipboardUtils, imageClipData, "")
+        assertEquals(ClipboardModel.Type.IMAGE, model.type)
+        assertNull(model.loadThumbnail(mMockContext))
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
index ca5b7af..0ac2667 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
@@ -16,13 +16,17 @@
 
 package com.android.systemui.clipboardoverlay;
 
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISS_TAPPED;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SHARE_TAPPED;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
+import static com.android.systemui.flags.Flags.CLIPBOARD_MINIMIZED_LAYOUT;
 import static com.android.systemui.flags.Flags.CLIPBOARD_REMOTE_BEHAVIOR;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -35,8 +39,11 @@
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.Context;
+import android.graphics.Insets;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.PersistableBundle;
+import android.view.WindowInsets;
 import android.view.textclassifier.TextLinks;
 
 import androidx.test.filters.SmallTest;
@@ -102,11 +109,14 @@
 
         when(mClipboardOverlayView.getEnterAnimation()).thenReturn(mAnimator);
         when(mClipboardOverlayView.getExitAnimation()).thenReturn(mAnimator);
+        when(mClipboardOverlayWindow.getWindowInsets()).thenReturn(
+                getImeInsets(new Rect(0, 0, 0, 0)));
 
         mSampleClipData = new ClipData("Test", new String[]{"text/plain"},
                 new ClipData.Item("Test Item"));
 
         mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, false);
+        mFeatureFlags.set(CLIPBOARD_MINIMIZED_LAYOUT, true); // turned off for legacy tests
 
         mOverlayController = new ClipboardOverlayController(
                 mContext,
@@ -118,8 +128,7 @@
                 mFeatureFlags,
                 mClipboardUtils,
                 mExecutor,
-                mUiEventLogger,
-                mDisplayTracker);
+                mUiEventLogger);
         verify(mClipboardOverlayView).setCallbacks(mOverlayCallbacksCaptor.capture());
         mCallbacks = mOverlayCallbacksCaptor.getValue();
     }
@@ -130,6 +139,159 @@
     }
 
     @Test
+    public void test_setClipData_nullData_legacy() {
+        ClipData clipData = null;
+        mOverlayController.setClipDataLegacy(clipData, "");
+
+        verify(mClipboardOverlayView, times(1)).showDefaultTextPreview();
+        verify(mClipboardOverlayView, times(0)).showShareChip();
+        verify(mClipboardOverlayView, times(1)).getEnterAnimation();
+    }
+
+    @Test
+    public void test_setClipData_invalidImageData_legacy() {
+        ClipData clipData = new ClipData("", new String[]{"image/png"},
+                new ClipData.Item(Uri.parse("")));
+
+        mOverlayController.setClipDataLegacy(clipData, "");
+
+        verify(mClipboardOverlayView, times(1)).showDefaultTextPreview();
+        verify(mClipboardOverlayView, times(0)).showShareChip();
+        verify(mClipboardOverlayView, times(1)).getEnterAnimation();
+    }
+
+    @Test
+    public void test_setClipData_textData_legacy() {
+        mOverlayController.setClipDataLegacy(mSampleClipData, "");
+
+        verify(mClipboardOverlayView, times(1)).showTextPreview("Test Item", false);
+        verify(mClipboardOverlayView, times(1)).showShareChip();
+        verify(mClipboardOverlayView, times(1)).getEnterAnimation();
+    }
+
+    @Test
+    public void test_setClipData_sensitiveTextData_legacy() {
+        ClipDescription description = mSampleClipData.getDescription();
+        PersistableBundle b = new PersistableBundle();
+        b.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
+        description.setExtras(b);
+        ClipData data = new ClipData(description, mSampleClipData.getItemAt(0));
+        mOverlayController.setClipDataLegacy(data, "");
+
+        verify(mClipboardOverlayView, times(1)).showTextPreview("••••••", true);
+        verify(mClipboardOverlayView, times(1)).showShareChip();
+        verify(mClipboardOverlayView, times(1)).getEnterAnimation();
+    }
+
+    @Test
+    public void test_setClipData_repeatedCalls_legacy() {
+        when(mAnimator.isRunning()).thenReturn(true);
+
+        mOverlayController.setClipDataLegacy(mSampleClipData, "");
+        mOverlayController.setClipDataLegacy(mSampleClipData, "");
+
+        verify(mClipboardOverlayView, times(1)).getEnterAnimation();
+    }
+
+    @Test
+    public void test_viewCallbacks_onShareTapped_legacy() {
+        mOverlayController.setClipDataLegacy(mSampleClipData, "");
+
+        mCallbacks.onShareButtonTapped();
+
+        verify(mUiEventLogger, times(1)).log(CLIPBOARD_OVERLAY_SHARE_TAPPED, 0, "");
+        verify(mClipboardOverlayView, times(1)).getExitAnimation();
+    }
+
+    @Test
+    public void test_viewCallbacks_onDismissTapped_legacy() {
+        mOverlayController.setClipDataLegacy(mSampleClipData, "");
+
+        mCallbacks.onDismissButtonTapped();
+
+        verify(mUiEventLogger, times(1)).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED, 0, "");
+        verify(mClipboardOverlayView, times(1)).getExitAnimation();
+    }
+
+    @Test
+    public void test_multipleDismissals_dismissesOnce_legacy() {
+        mCallbacks.onSwipeDismissInitiated(mAnimator);
+        mCallbacks.onDismissButtonTapped();
+        mCallbacks.onSwipeDismissInitiated(mAnimator);
+        mCallbacks.onDismissButtonTapped();
+
+        verify(mUiEventLogger, times(1)).log(CLIPBOARD_OVERLAY_SWIPE_DISMISSED, 0, null);
+        verify(mUiEventLogger, never()).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED);
+    }
+
+    @Test
+    public void test_remoteCopy_withFlagOn_legacy() {
+        mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true);
+        when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(true);
+
+        mOverlayController.setClipDataLegacy(mSampleClipData, "");
+
+        verify(mTimeoutHandler, never()).resetTimeout();
+    }
+
+    @Test
+    public void test_remoteCopy_withFlagOff_legacy() {
+        when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(true);
+
+        mOverlayController.setClipDataLegacy(mSampleClipData, "");
+
+        verify(mTimeoutHandler).resetTimeout();
+    }
+
+    @Test
+    public void test_nonRemoteCopy_legacy() {
+        mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true);
+        when(mClipboardUtils.isRemoteCopy(any(), any(), any())).thenReturn(false);
+
+        mOverlayController.setClipDataLegacy(mSampleClipData, "");
+
+        verify(mTimeoutHandler).resetTimeout();
+    }
+
+    @Test
+    public void test_logsUseLastClipSource_legacy() {
+        mOverlayController.setClipDataLegacy(mSampleClipData, "first.package");
+        mCallbacks.onDismissButtonTapped();
+        mOverlayController.setClipDataLegacy(mSampleClipData, "second.package");
+        mCallbacks.onDismissButtonTapped();
+
+        verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED, 0, "first.package");
+        verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED, 0, "second.package");
+        verifyNoMoreInteractions(mUiEventLogger);
+    }
+
+    @Test
+    public void test_logOnClipboardActionsShown_legacy() {
+        ClipData.Item item = mSampleClipData.getItemAt(0);
+        item.setTextLinks(Mockito.mock(TextLinks.class));
+        mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true);
+        when(mClipboardUtils.isRemoteCopy(any(Context.class), any(ClipData.class), anyString()))
+                .thenReturn(true);
+        when(mClipboardUtils.getAction(any(ClipData.Item.class), anyString()))
+                .thenReturn(Optional.of(Mockito.mock(RemoteAction.class)));
+        when(mClipboardOverlayView.post(any(Runnable.class))).thenAnswer(new Answer<Object>() {
+            @Override
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                ((Runnable) invocation.getArgument(0)).run();
+                return null;
+            }
+        });
+
+        mOverlayController.setClipDataLegacy(
+                new ClipData(mSampleClipData.getDescription(), item), "actionShownSource");
+        mExecutor.runAllReady();
+
+        verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_ACTION_SHOWN, 0, "actionShownSource");
+        verifyNoMoreInteractions(mUiEventLogger);
+    }
+
+    // start of refactored setClipData tests
+    @Test
     public void test_setClipData_nullData() {
         ClipData clipData = null;
         mOverlayController.setClipData(clipData, "");
@@ -280,4 +442,43 @@
         verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_ACTION_SHOWN, 0, "actionShownSource");
         verifyNoMoreInteractions(mUiEventLogger);
     }
+
+    @Test
+    public void test_noInsets_showsExpanded() {
+        mOverlayController.setClipData(mSampleClipData, "");
+
+        verify(mClipboardOverlayView, never()).setMinimized(true);
+        verify(mClipboardOverlayView).setMinimized(false);
+        verify(mClipboardOverlayView).showTextPreview("Test Item", false);
+    }
+
+    @Test
+    public void test_insets_showsMinimized() {
+        when(mClipboardOverlayWindow.getWindowInsets()).thenReturn(
+                getImeInsets(new Rect(0, 0, 0, 1)));
+        mOverlayController.setClipData(mSampleClipData, "");
+
+        verify(mClipboardOverlayView).setMinimized(true);
+        verify(mClipboardOverlayView, never()).setMinimized(false);
+        verify(mClipboardOverlayView, never()).showTextPreview(any(), anyBoolean());
+
+        mCallbacks.onMinimizedViewTapped();
+
+        verify(mClipboardOverlayView).setMinimized(false);
+        verify(mClipboardOverlayView).showTextPreview("Test Item", false);
+    }
+
+    @Test
+    public void test_insetsChanged_minimizes() {
+        mOverlayController.setClipData(mSampleClipData, "");
+        verify(mClipboardOverlayView, never()).setMinimized(true);
+
+        WindowInsets insetsWithKeyboard = getImeInsets(new Rect(0, 0, 0, 1));
+        mOverlayController.onInsetsChanged(insetsWithKeyboard, ORIENTATION_PORTRAIT);
+        verify(mClipboardOverlayView).setMinimized(true);
+    }
+
+    private static WindowInsets getImeInsets(Rect r) {
+        return new WindowInsets.Builder().setInsets(WindowInsets.Type.ime(), Insets.of(r)).build();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/coroutine/CoroutineResultTest.kt b/packages/SystemUI/tests/src/com/android/systemui/common/coroutine/CoroutineResultTest.kt
new file mode 100644
index 0000000..d552c9d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/coroutine/CoroutineResultTest.kt
@@ -0,0 +1,52 @@
+/*
+ * 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.common.coroutine
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** atest SystemUITests:CoroutineResultTest */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class CoroutineResultTest : SysuiTestCase() {
+
+    @Test
+    fun suspendRunCatching_shouldReturnSuccess() = runTest {
+        val actual = suspendRunCatching { "Placeholder" }
+        assertThat(actual.isSuccess).isTrue()
+        assertThat(actual.getOrNull()).isEqualTo("Placeholder")
+    }
+
+    @Test
+    fun suspendRunCatching_whenExceptionThrow_shouldResumeWithException() = runTest {
+        val actual = suspendRunCatching { throw Exception() }
+        assertThat(actual.isFailure).isTrue()
+        assertThat(actual.exceptionOrNull()).isInstanceOf(Exception::class.java)
+    }
+
+    @Test(expected = CancellationException::class)
+    fun suspendRunCatching_whenCancelled_shouldResumeWithException() = runTest {
+        suspendRunCatching { cancel() }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
new file mode 100644
index 0000000..2ed0346
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.common.ui.view;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link SeekBarWithIconButtonsView}
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
+
+    private ImageView mIconStart;
+    private ImageView mIconEnd;
+    private SeekBar mSeekbar;
+    private SeekBarWithIconButtonsView mIconDiscreteSliderLinearLayout;
+
+    @Before
+    public void setUp() {
+        mIconDiscreteSliderLinearLayout = new SeekBarWithIconButtonsView(mContext);
+        mIconStart = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_start);
+        mIconEnd = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_end);
+        mSeekbar = mIconDiscreteSliderLinearLayout.findViewById(R.id.seekbar);
+    }
+
+    @Test
+    public void setSeekBarProgressZero_startIconAndFrameDisabled() {
+        mIconDiscreteSliderLinearLayout.setProgress(0);
+
+        assertThat(mIconStart.isEnabled()).isFalse();
+        assertThat(mIconEnd.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void setSeekBarProgressMax_endIconAndFrameDisabled() {
+        mIconDiscreteSliderLinearLayout.setProgress(mSeekbar.getMax());
+
+        assertThat(mIconEnd.isEnabled()).isFalse();
+        assertThat(mIconStart.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void setSeekBarProgressMax_allIconsAndFramesEnabled() {
+        // We are using the default value for the max of seekbar.
+        // Therefore, the max value will be DEFAULT_SEEKBAR_MAX = 6.
+        mIconDiscreteSliderLinearLayout.setProgress(1);
+
+        assertThat(mIconStart.isEnabled()).isTrue();
+        assertThat(mIconEnd.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void clickIconEnd_currentProgressIsOneToMax_reachesMax() {
+        mIconDiscreteSliderLinearLayout.setProgress(mSeekbar.getMax() - 1);
+        mIconEnd.performClick();
+
+        assertThat(mSeekbar.getProgress()).isEqualTo(mSeekbar.getMax());
+    }
+
+    @Test
+    public void clickIconStart_currentProgressIsOne_reachesZero() {
+        mIconDiscreteSliderLinearLayout.setProgress(1);
+        mIconStart.performClick();
+
+        assertThat(mSeekbar.getProgress()).isEqualTo(0);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index d54babf..e35b2a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -104,8 +104,6 @@
             ArgumentCaptor<ControlsBindingController.LoadCallback>
 
     @Captor
-    private lateinit var userTrackerCallbackCaptor: ArgumentCaptor<UserTracker.Callback>
-    @Captor
     private lateinit var listingCallbackCaptor:
             ArgumentCaptor<ControlsListingController.ControlsListingCallback>
 
@@ -178,10 +176,6 @@
         )
         controller.auxiliaryPersistenceWrapper = auxiliaryPersistenceWrapper
 
-        verify(userTracker).addCallback(
-            capture(userTrackerCallbackCaptor), any()
-        )
-
         verify(listingController).addCallback(capture(listingCallbackCaptor))
     }
 
@@ -539,7 +533,7 @@
 
         reset(persistenceWrapper)
 
-        userTrackerCallbackCaptor.value.onUserChanged(otherUser, mContext)
+        controller.changeUser(UserHandle.of(otherUser))
 
         verify(persistenceWrapper).changeFileAndBackupManager(any(), any())
         verify(persistenceWrapper).readFavorites()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt
new file mode 100644
index 0000000..7ecaca6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt
@@ -0,0 +1,281 @@
+/*
+ * 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.controls.start
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.ServiceInfo
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.ControlsServiceInfo
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.controls.dagger.ControlsComponent
+import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.ui.SelectedItem
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.time.FakeSystemClock
+import java.util.Optional
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ControlsStartableTest : SysuiTestCase() {
+
+    @Mock private lateinit var controlsController: ControlsController
+    @Mock private lateinit var controlsListingController: ControlsListingController
+    @Mock private lateinit var userTracker: UserTracker
+
+    private lateinit var fakeExecutor: FakeExecutor
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        context.orCreateTestableResources.addOverride(
+            R.array.config_controlsPreferredPackages,
+            arrayOf<String>()
+        )
+
+        fakeExecutor = FakeExecutor(FakeSystemClock())
+    }
+
+    @Test
+    fun testDisabledNothingIsCalled() {
+        createStartable(enabled = false).start()
+
+        verifyZeroInteractions(controlsController, controlsListingController, userTracker)
+    }
+
+    @Test
+    fun testNoPreferredPackagesNoDefaultSelected_noNewSelection() {
+        `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
+        val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController, never()).setPreferredSelection(any())
+    }
+
+    @Test
+    fun testPreferredPackagesNotInstalled_noNewSelection() {
+        context.orCreateTestableResources.addOverride(
+            R.array.config_controlsPreferredPackages,
+            arrayOf(TEST_PACKAGE_PANEL)
+        )
+        `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
+        `when`(controlsListingController.getCurrentServices()).thenReturn(emptyList())
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController, never()).setPreferredSelection(any())
+    }
+
+    @Test
+    fun testPreferredPackageNotPanel_noNewSelection() {
+        context.orCreateTestableResources.addOverride(
+            R.array.config_controlsPreferredPackages,
+            arrayOf(TEST_PACKAGE_PANEL)
+        )
+        `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
+        val listings = listOf(ControlsServiceInfo(TEST_COMPONENT, "not panel", hasPanel = false))
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController, never()).setPreferredSelection(any())
+    }
+
+    @Test
+    fun testExistingSelection_noNewSelection() {
+        context.orCreateTestableResources.addOverride(
+            R.array.config_controlsPreferredPackages,
+            arrayOf(TEST_PACKAGE_PANEL)
+        )
+        `when`(controlsController.getPreferredSelection())
+            .thenReturn(mock<SelectedItem.PanelItem>())
+        val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController, never()).setPreferredSelection(any())
+    }
+
+    @Test
+    fun testPanelAdded() {
+        context.orCreateTestableResources.addOverride(
+            R.array.config_controlsPreferredPackages,
+            arrayOf(TEST_PACKAGE_PANEL)
+        )
+        `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
+        val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController).setPreferredSelection(listings[0].toPanelItem())
+    }
+
+    @Test
+    fun testMultiplePreferredOnlyOnePanel_panelAdded() {
+        context.orCreateTestableResources.addOverride(
+            R.array.config_controlsPreferredPackages,
+            arrayOf("other_package", TEST_PACKAGE_PANEL)
+        )
+        `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
+        val listings =
+            listOf(
+                ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true),
+                ControlsServiceInfo(ComponentName("other_package", "cls"), "non panel", false)
+            )
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController).setPreferredSelection(listings[0].toPanelItem())
+    }
+
+    @Test
+    fun testMultiplePreferredMultiplePanels_firstPreferredAdded() {
+        context.orCreateTestableResources.addOverride(
+            R.array.config_controlsPreferredPackages,
+            arrayOf(TEST_PACKAGE_PANEL, "other_package")
+        )
+        `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
+        val listings =
+            listOf(
+                ControlsServiceInfo(ComponentName("other_package", "cls"), "panel", true),
+                ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true)
+            )
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController).setPreferredSelection(listings[1].toPanelItem())
+    }
+
+    @Test
+    fun testPreferredSelectionIsPanel_bindOnStart() {
+        val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        `when`(controlsController.getPreferredSelection()).thenReturn(listings[0].toPanelItem())
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController).bindComponentForPanel(TEST_COMPONENT_PANEL)
+    }
+
+    @Test
+    fun testPreferredSelectionPanel_listingNoPanel_notBind() {
+        val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false))
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        `when`(controlsController.getPreferredSelection())
+            .thenReturn(SelectedItem.PanelItem("panel", TEST_COMPONENT_PANEL))
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController, never()).bindComponentForPanel(any())
+    }
+
+    @Test
+    fun testNotPanelSelection_noBind() {
+        val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false))
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController, never()).bindComponentForPanel(any())
+    }
+
+    private fun createStartable(enabled: Boolean): ControlsStartable {
+        val component: ControlsComponent =
+            mock() {
+                `when`(isEnabled()).thenReturn(enabled)
+                if (enabled) {
+                    `when`(getControlsController()).thenReturn(Optional.of(controlsController))
+                    `when`(getControlsListingController())
+                        .thenReturn(Optional.of(controlsListingController))
+                } else {
+                    `when`(getControlsController()).thenReturn(Optional.empty())
+                    `when`(getControlsListingController()).thenReturn(Optional.empty())
+                }
+            }
+        return ControlsStartable(context.resources, fakeExecutor, component, userTracker)
+    }
+
+    private fun ControlsServiceInfo(
+        componentName: ComponentName,
+        label: CharSequence,
+        hasPanel: Boolean
+    ): ControlsServiceInfo {
+        val serviceInfo =
+            ServiceInfo().apply {
+                applicationInfo = ApplicationInfo()
+                packageName = componentName.packageName
+                name = componentName.className
+            }
+        return FakeControlsServiceInfo(context, serviceInfo, label, hasPanel)
+    }
+
+    private class FakeControlsServiceInfo(
+        context: Context,
+        serviceInfo: ServiceInfo,
+        private val label: CharSequence,
+        hasPanel: Boolean
+    ) : ControlsServiceInfo(context, serviceInfo) {
+
+        init {
+            if (hasPanel) {
+                panelActivity = serviceInfo.componentName
+            }
+        }
+
+        override fun loadLabel(): CharSequence {
+            return label
+        }
+    }
+
+    companion object {
+        private fun ControlsServiceInfo.toPanelItem(): SelectedItem.PanelItem {
+            if (panelActivity == null) {
+                throw IllegalArgumentException("$this is not a panel")
+            }
+            return SelectedItem.PanelItem(loadLabel(), componentName)
+        }
+
+        private const val TEST_PACKAGE = "pkg"
+        private val TEST_COMPONENT = ComponentName(TEST_PACKAGE, "service")
+        private const val TEST_PACKAGE_PANEL = "pkg.panel"
+        private val TEST_COMPONENT_PANEL = ComponentName(TEST_PACKAGE_PANEL, "service")
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/coroutines/FlowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/coroutines/FlowTest.kt
new file mode 100644
index 0000000..1e4753e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/coroutines/FlowTest.kt
@@ -0,0 +1,24 @@
+package com.android.systemui.coroutines
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class FlowTest : SysuiTestCase() {
+
+    @Test
+    fun collectLastValue() = runTest {
+        val flow = flowOf(0, 1, 2)
+        val lastValue by collectLastValue(flow)
+        assertThat(lastValue).isEqualTo(2)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
index b7d0f29..0f25764 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
@@ -289,4 +289,36 @@
         verify(mCallback, times(1)).onStateChanged();
         assertThat(stateController.areEntryAnimationsFinished()).isTrue();
     }
+
+    @Test
+    public void testNotifyDreamOverlayStatusBarVisibleChanged() {
+        final DreamOverlayStateController stateController =
+                new DreamOverlayStateController(mExecutor, true);
+
+        stateController.addCallback(mCallback);
+        mExecutor.runAllReady();
+        assertThat(stateController.isDreamOverlayStatusBarVisible()).isFalse();
+
+        stateController.setDreamOverlayStatusBarVisible(true);
+        mExecutor.runAllReady();
+
+        verify(mCallback, times(1)).onStateChanged();
+        assertThat(stateController.isDreamOverlayStatusBarVisible()).isTrue();
+    }
+
+    @Test
+    public void testNotifyHasAssistantAttentionChanged() {
+        final DreamOverlayStateController stateController =
+                new DreamOverlayStateController(mExecutor, true);
+
+        stateController.addCallback(mCallback);
+        mExecutor.runAllReady();
+        assertThat(stateController.hasAssistantAttention()).isFalse();
+
+        stateController.setHasAssistantAttention(true);
+        mExecutor.runAllReady();
+
+        verify(mCallback, times(1)).onStateChanged();
+        assertThat(stateController.hasAssistantAttention()).isTrue();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
index 596b903..d16b757 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -468,6 +468,21 @@
     }
 
     @Test
+    public void testAssistantAttentionIconShownWhenAttentionGained() {
+        mController.onViewAttached();
+
+        when(mDreamOverlayStateController.hasAssistantAttention()).thenReturn(true);
+
+        final ArgumentCaptor<DreamOverlayStateController.Callback> callbackCapture =
+                ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class);
+        verify(mDreamOverlayStateController).addCallback(callbackCapture.capture());
+        callbackCapture.getValue().onStateChanged();
+
+        verify(mView).showIcon(
+                DreamOverlayStatusBarView.STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE, true, null);
+    }
+
+    @Test
     public void testStatusBarHiddenWhenSystemStatusBarShown() {
         mController.onViewAttached();
 
@@ -572,6 +587,13 @@
         assertThat(mView.getVisibility()).isEqualTo(View.VISIBLE);
     }
 
+    @Test
+    public void testDreamOverlayStatusBarVisibleSetToFalseOnDetach() {
+        mController.onViewAttached();
+        mController.onViewDetached();
+        verify(mDreamOverlayStateController).setDreamOverlayStatusBarVisible(false);
+    }
+
     private StatusBarWindowStateListener updateStatusBarWindowState(boolean show) {
         when(mStatusBarWindowStateController.windowIsShowing()).thenReturn(show);
         final ArgumentCaptor<StatusBarWindowStateListener>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
new file mode 100644
index 0000000..ef1061f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.dreams.conditions;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.RemoteException;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.app.AssistUtils;
+import com.android.internal.app.IVisualQueryDetectionAttentionListener;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.shared.condition.Condition;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class AssistantAttentionConditionTest extends SysuiTestCase {
+    @Mock
+    Condition.Callback mCallback;
+    @Mock
+    AssistUtils mAssistUtils;
+    @Mock
+    DreamOverlayStateController mDreamOverlayStateController;
+
+    private AssistantAttentionCondition mAssistantAttentionCondition;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        mAssistantAttentionCondition =
+                new AssistantAttentionCondition(mDreamOverlayStateController, mAssistUtils);
+        // Adding a callback also starts the condition.
+        mAssistantAttentionCondition.addCallback(mCallback);
+    }
+
+    @Test
+    public void testEnableVisualQueryDetection() {
+        final ArgumentCaptor<DreamOverlayStateController.Callback> argumentCaptor =
+                ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class);
+        verify(mDreamOverlayStateController).addCallback(argumentCaptor.capture());
+
+        when(mDreamOverlayStateController.isDreamOverlayStatusBarVisible()).thenReturn(true);
+        argumentCaptor.getValue().onStateChanged();
+
+        verify(mAssistUtils).enableVisualQueryDetection(any());
+    }
+
+    @Test
+    public void testDisableVisualQueryDetection() {
+        final ArgumentCaptor<DreamOverlayStateController.Callback> argumentCaptor =
+                ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class);
+        verify(mDreamOverlayStateController).addCallback(argumentCaptor.capture());
+
+        when(mDreamOverlayStateController.isDreamOverlayStatusBarVisible()).thenReturn(true);
+        argumentCaptor.getValue().onStateChanged();
+        when(mDreamOverlayStateController.isDreamOverlayStatusBarVisible()).thenReturn(false);
+        argumentCaptor.getValue().onStateChanged();
+
+        verify(mAssistUtils).disableVisualQueryDetection();
+    }
+
+    @Test
+    public void testAttentionChangedTriggersCondition() throws RemoteException {
+        final ArgumentCaptor<DreamOverlayStateController.Callback> callbackCaptor =
+                ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class);
+        verify(mDreamOverlayStateController).addCallback(callbackCaptor.capture());
+
+        when(mDreamOverlayStateController.isDreamOverlayStatusBarVisible()).thenReturn(true);
+        callbackCaptor.getValue().onStateChanged();
+
+        final ArgumentCaptor<IVisualQueryDetectionAttentionListener> listenerCaptor =
+                ArgumentCaptor.forClass(IVisualQueryDetectionAttentionListener.class);
+        verify(mAssistUtils).enableVisualQueryDetection(listenerCaptor.capture());
+
+        listenerCaptor.getValue().onAttentionGained();
+        assertThat(mAssistantAttentionCondition.isConditionMet()).isTrue();
+
+        listenerCaptor.getValue().onAttentionLost();
+        assertThat(mAssistantAttentionCondition.isConditionMet()).isFalse();
+
+        verify(mCallback, times(2)).onConditionChanged(eq(mAssistantAttentionCondition));
+    }
+}
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 fb54d6d..4415033 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -157,25 +157,28 @@
                 dumpManager = mock(),
                 userHandle = UserHandle.SYSTEM,
             )
+        val featureFlags =
+            FakeFeatureFlags().apply {
+                set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true)
+                set(Flags.LOCKSCREEN_CUSTOM_CLOCKS, true)
+                set(Flags.REVAMPED_WALLPAPER_UI, true)
+                set(Flags.WALLPAPER_FULLSCREEN_PREVIEW, true)
+                set(Flags.FACE_AUTH_REFACTOR, true)
+            }
         underTest.interactor =
             KeyguardQuickAffordanceInteractor(
                 keyguardInteractor =
                     KeyguardInteractor(
                         repository = FakeKeyguardRepository(),
                         commandQueue = commandQueue,
+                        featureFlags = featureFlags,
                     ),
                 registry = mock(),
                 lockPatternUtils = lockPatternUtils,
                 keyguardStateController = keyguardStateController,
                 userTracker = userTracker,
                 activityStarter = activityStarter,
-                featureFlags =
-                    FakeFeatureFlags().apply {
-                        set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true)
-                        set(Flags.LOCKSCREEN_CUSTOM_CLOCKS, true)
-                        set(Flags.REVAMPED_WALLPAPER_UI, true)
-                        set(Flags.WALLPAPER_FULLSCREEN_PREVIEW, true)
-                    },
+                featureFlags = featureFlags,
                 repository = { quickAffordanceRepository },
                 launchAnimator = launchAnimator,
             )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
index 2290676..c3b0e5226 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
@@ -38,6 +38,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.keyguard.logging.KeyguardLogger;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
@@ -66,6 +67,8 @@
     private KeyguardIndicationTextView mView;
     @Mock
     private StatusBarStateController mStatusBarStateController;
+    @Mock
+    private KeyguardLogger mLogger;
     @Captor
     private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
 
@@ -77,7 +80,7 @@
         MockitoAnnotations.initMocks(this);
         when(mView.getTextColors()).thenReturn(ColorStateList.valueOf(Color.WHITE));
         mController = new KeyguardIndicationRotateTextViewController(mView, mExecutor,
-                mStatusBarStateController);
+                mStatusBarStateController, mLogger);
         mController.onViewAttached();
 
         verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
new file mode 100644
index 0000000..925c06f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.content.Context
+import android.media.AudioManager
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.RingerModeTracker
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.whenever
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class MuteQuickAffordanceConfigTest : SysuiTestCase() {
+
+    private lateinit var underTest: MuteQuickAffordanceConfig
+    @Mock
+    private lateinit var ringerModeTracker: RingerModeTracker
+    @Mock
+    private lateinit var audioManager: AudioManager
+    @Mock
+    private lateinit var userTracker: UserTracker
+    @Mock
+    private lateinit var userFileManager: UserFileManager
+
+    private lateinit var testDispatcher: TestDispatcher
+    private lateinit var testScope: TestScope
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        testDispatcher = StandardTestDispatcher()
+        testScope = TestScope(testDispatcher)
+
+        whenever(userTracker.userContext).thenReturn(context)
+        whenever(userFileManager.getSharedPreferences(any(), any(), any()))
+                .thenReturn(context.getSharedPreferences("mutequickaffordancetest", Context.MODE_PRIVATE))
+
+        underTest = MuteQuickAffordanceConfig(
+                context,
+                userTracker,
+                userFileManager,
+                ringerModeTracker,
+                audioManager,
+                testScope.backgroundScope,
+                testDispatcher,
+                testDispatcher,
+        )
+    }
+
+    @Test
+    fun `picker state - volume fixed - not available`() = testScope.runTest {
+        //given
+        whenever(audioManager.isVolumeFixed).thenReturn(true)
+
+        //when
+        val result = underTest.getPickerScreenState()
+
+        //then
+        assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice, result)
+    }
+
+    @Test
+    fun `picker state - volume not fixed - available`() = testScope.runTest {
+        //given
+        whenever(audioManager.isVolumeFixed).thenReturn(false)
+
+        //when
+        val result = underTest.getPickerScreenState()
+
+        //then
+        assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.Default(), result)
+    }
+
+    @Test
+    fun `triggered - state was previously NORMAL - currently SILENT - move to previous state`() = testScope.runTest {
+        //given
+        val ringerModeCapture = argumentCaptor<Int>()
+        whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)
+        underTest.onTriggered(null)
+        whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_SILENT)
+
+        //when
+        val result = underTest.onTriggered(null)
+        runCurrent()
+        verify(audioManager, times(2)).ringerModeInternal = ringerModeCapture.capture()
+
+        //then
+        assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+        assertEquals(AudioManager.RINGER_MODE_NORMAL, ringerModeCapture.value)
+    }
+
+    @Test
+    fun `triggered - state is not SILENT - move to SILENT ringer`() = testScope.runTest {
+        //given
+        val ringerModeCapture = argumentCaptor<Int>()
+        whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)
+
+        //when
+        val result = underTest.onTriggered(null)
+        runCurrent()
+        verify(audioManager).ringerModeInternal = ringerModeCapture.capture()
+
+        //then
+        assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+        assertEquals(AudioManager.RINGER_MODE_SILENT, ringerModeCapture.value)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
new file mode 100644
index 0000000..34f3ed8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.content.Context
+import android.media.AudioManager
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.Observer
+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.keyguard.data.repository.KeyguardQuickAffordanceRepository
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.RingerModeTracker
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertEquals
+
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class MuteQuickAffordanceCoreStartableTest : SysuiTestCase()  {
+
+    @Mock
+    private lateinit var featureFlags: FeatureFlags
+    @Mock
+    private lateinit var userTracker: UserTracker
+    @Mock
+    private lateinit var ringerModeTracker: RingerModeTracker
+    @Mock
+    private lateinit var userFileManager: UserFileManager
+    @Mock
+    private lateinit var keyguardQuickAffordanceRepository: KeyguardQuickAffordanceRepository
+
+    private lateinit var testDispatcher: TestDispatcher
+    private lateinit var testScope: TestScope
+
+    private lateinit var underTest: MuteQuickAffordanceCoreStartable
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        whenever(featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES)).thenReturn(true)
+
+        val config: KeyguardQuickAffordanceConfig = mock()
+        whenever(config.key).thenReturn(BuiltInKeyguardQuickAffordanceKeys.MUTE)
+
+        val emission = MutableStateFlow(mapOf("testQuickAffordanceKey" to listOf(config)))
+        whenever(keyguardQuickAffordanceRepository.selections).thenReturn(emission)
+
+        testDispatcher = StandardTestDispatcher()
+        testScope = TestScope(testDispatcher)
+
+        underTest = MuteQuickAffordanceCoreStartable(
+            featureFlags,
+            userTracker,
+            ringerModeTracker,
+            userFileManager,
+            keyguardQuickAffordanceRepository,
+            testScope.backgroundScope,
+            testDispatcher,
+        )
+    }
+
+    @Test
+    fun `feature flag is OFF - do nothing with keyguardQuickAffordanceRepository`() = testScope.runTest {
+        //given
+        whenever(featureFlags.isEnabled(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES)).thenReturn(false)
+
+        //when
+        underTest.start()
+
+        //then
+        verifyZeroInteractions(keyguardQuickAffordanceRepository)
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun `feature flag is ON - call to keyguardQuickAffordanceRepository`() = testScope.runTest {
+        //given
+        val ringerModeInternal = mock<MutableLiveData<Int>>()
+        whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
+
+        //when
+        underTest.start()
+        runCurrent()
+
+        //then
+        verify(keyguardQuickAffordanceRepository).selections
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun `ringer mode is changed to SILENT - do not save to shared preferences`() = testScope.runTest {
+        //given
+        val ringerModeInternal = mock<MutableLiveData<Int>>()
+        val observerCaptor = argumentCaptor<Observer<Int>>()
+        whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
+
+        //when
+        underTest.start()
+        runCurrent()
+        verify(ringerModeInternal).observeForever(observerCaptor.capture())
+        observerCaptor.value.onChanged(AudioManager.RINGER_MODE_SILENT)
+
+        //then
+        verifyZeroInteractions(userFileManager)
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun `ringerModeInternal changes to something not SILENT - is set in sharedpreferences`() = testScope.runTest {
+        //given
+        val newRingerMode = 99
+        val observerCaptor = argumentCaptor<Observer<Int>>()
+        val ringerModeInternal = mock<MutableLiveData<Int>>()
+        val sharedPrefs = context.getSharedPreferences("quick_affordance_mute_ringer_mode_cache_test", Context.MODE_PRIVATE)
+        whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
+        whenever(
+            userFileManager.getSharedPreferences(eq("quick_affordance_mute_ringer_mode_cache"), any(), any())
+        ).thenReturn(sharedPrefs)
+
+        //when
+        underTest.start()
+        runCurrent()
+        verify(ringerModeInternal).observeForever(observerCaptor.capture())
+        observerCaptor.value.onChanged(newRingerMode)
+        runCurrent()
+        val result = sharedPrefs.getInt("key_last_non_silent_ringer_mode", -1)
+
+        //then
+        assertEquals(newRingerMode, result)
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun `MUTE is in selections - observe ringerModeInternal`() = testScope.runTest {
+        //given
+        val ringerModeInternal = mock<MutableLiveData<Int>>()
+        whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
+
+        //when
+        underTest.start()
+        runCurrent()
+
+        //then
+        verify(ringerModeInternal).observeForever(any())
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun `MUTE is in selections 2x - observe ringerModeInternal`() = testScope.runTest {
+        //given
+        val config: KeyguardQuickAffordanceConfig = mock()
+        whenever(config.key).thenReturn(BuiltInKeyguardQuickAffordanceKeys.MUTE)
+        val emission = MutableStateFlow(mapOf("testKey" to listOf(config), "testkey2" to listOf(config)))
+        whenever(keyguardQuickAffordanceRepository.selections).thenReturn(emission)
+        val ringerModeInternal = mock<MutableLiveData<Int>>()
+        whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
+
+        //when
+        underTest.start()
+        runCurrent()
+
+        //then
+        verify(ringerModeInternal).observeForever(any())
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun `MUTE is not in selections - stop observing ringerModeInternal`() = testScope.runTest {
+        //given
+        val config: KeyguardQuickAffordanceConfig = mock()
+        whenever(config.key).thenReturn("notmutequickaffordance")
+        val emission = MutableStateFlow(mapOf("testKey" to listOf(config)))
+        whenever(keyguardQuickAffordanceRepository.selections).thenReturn(emission)
+        val ringerModeInternal = mock<MutableLiveData<Int>>()
+        whenever(ringerModeTracker.ringerModeInternal).thenReturn(ringerModeInternal)
+
+        //when
+        underTest.start()
+        runCurrent()
+
+        //then
+        verify(ringerModeInternal).removeObserver(any())
+        coroutineContext.cancelChildren()
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricRepositoryTest.kt
deleted file mode 100644
index 4aac7d0..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricRepositoryTest.kt
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.keyguard.data.repository
-
-import android.app.admin.DevicePolicyManager
-import android.content.Intent
-import android.content.pm.UserInfo
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.internal.widget.LockPatternUtils
-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.biometrics.AuthController
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.user.data.repository.FakeUserRepository
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestDispatcher
-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.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@RunWith(AndroidTestingRunner::class)
-class BiometricRepositoryTest : SysuiTestCase() {
-    private lateinit var underTest: BiometricRepository
-
-    @Mock private lateinit var authController: AuthController
-    @Mock private lateinit var lockPatternUtils: LockPatternUtils
-    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
-    private lateinit var userRepository: FakeUserRepository
-
-    private lateinit var testDispatcher: TestDispatcher
-    private lateinit var testScope: TestScope
-    private var testableLooper: TestableLooper? = null
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        testableLooper = TestableLooper.get(this)
-        testDispatcher = StandardTestDispatcher()
-        testScope = TestScope(testDispatcher)
-        userRepository = FakeUserRepository()
-    }
-
-    private suspend fun createBiometricRepository() {
-        userRepository.setUserInfos(listOf(PRIMARY_USER))
-        userRepository.setSelectedUserInfo(PRIMARY_USER)
-        underTest =
-            BiometricRepositoryImpl(
-                context = context,
-                lockPatternUtils = lockPatternUtils,
-                broadcastDispatcher = fakeBroadcastDispatcher,
-                authController = authController,
-                userRepository = userRepository,
-                devicePolicyManager = devicePolicyManager,
-                scope = testScope.backgroundScope,
-                backgroundDispatcher = testDispatcher,
-                looper = testableLooper!!.looper,
-            )
-    }
-
-    @Test
-    fun fingerprintEnrollmentChange() =
-        testScope.runTest {
-            createBiometricRepository()
-            val fingerprintEnabledByDevicePolicy = collectLastValue(underTest.isFingerprintEnrolled)
-            runCurrent()
-
-            val captor = argumentCaptor<AuthController.Callback>()
-            verify(authController).addCallback(captor.capture())
-            whenever(authController.isFingerprintEnrolled(anyInt())).thenReturn(true)
-            captor.value.onEnrollmentsChanged(
-                BiometricType.UNDER_DISPLAY_FINGERPRINT,
-                PRIMARY_USER_ID,
-                true
-            )
-            assertThat(fingerprintEnabledByDevicePolicy()).isTrue()
-
-            whenever(authController.isFingerprintEnrolled(anyInt())).thenReturn(false)
-            captor.value.onEnrollmentsChanged(
-                BiometricType.UNDER_DISPLAY_FINGERPRINT,
-                PRIMARY_USER_ID,
-                false
-            )
-            assertThat(fingerprintEnabledByDevicePolicy()).isFalse()
-        }
-
-    @Test
-    fun strongBiometricAllowedChange() =
-        testScope.runTest {
-            createBiometricRepository()
-            val strongBiometricAllowed = collectLastValue(underTest.isStrongBiometricAllowed)
-            runCurrent()
-
-            val captor = argumentCaptor<LockPatternUtils.StrongAuthTracker>()
-            verify(lockPatternUtils).registerStrongAuthTracker(captor.capture())
-
-            captor.value
-                .getStub()
-                .onStrongAuthRequiredChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
-            testableLooper?.processAllMessages() // StrongAuthTracker uses the TestableLooper
-            assertThat(strongBiometricAllowed()).isTrue()
-
-            captor.value
-                .getStub()
-                .onStrongAuthRequiredChanged(STRONG_AUTH_REQUIRED_AFTER_BOOT, PRIMARY_USER_ID)
-            testableLooper?.processAllMessages() // StrongAuthTracker uses the TestableLooper
-            assertThat(strongBiometricAllowed()).isFalse()
-        }
-
-    @Test
-    fun fingerprintDisabledByDpmChange() =
-        testScope.runTest {
-            createBiometricRepository()
-            val fingerprintEnabledByDevicePolicy =
-                collectLastValue(underTest.isFingerprintEnabledByDevicePolicy)
-            runCurrent()
-
-            whenever(devicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt()))
-                .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT)
-            broadcastDPMStateChange()
-            assertThat(fingerprintEnabledByDevicePolicy()).isFalse()
-
-            whenever(devicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt())).thenReturn(0)
-            broadcastDPMStateChange()
-            assertThat(fingerprintEnabledByDevicePolicy()).isTrue()
-        }
-
-    private fun broadcastDPMStateChange() {
-        fakeBroadcastDispatcher.registeredReceivers.forEach { receiver ->
-            receiver.onReceive(
-                context,
-                Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED)
-            )
-        }
-    }
-
-    companion object {
-        private const val PRIMARY_USER_ID = 0
-        private val PRIMARY_USER =
-            UserInfo(
-                /* id= */ PRIMARY_USER_ID,
-                /* name= */ "primary user",
-                /* flags= */ UserInfo.FLAG_PRIMARY
-            )
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
new file mode 100644
index 0000000..21ad5e2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.repository
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT
+import android.content.Intent
+import android.content.pm.UserInfo
+import android.hardware.biometrics.BiometricManager
+import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.widget.LockPatternUtils
+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.biometrics.AuthController
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.data.repository.BiometricType.FACE
+import com.android.systemui.keyguard.data.repository.BiometricType.REAR_FINGERPRINT
+import com.android.systemui.keyguard.data.repository.BiometricType.SIDE_FINGERPRINT
+import com.android.systemui.keyguard.data.repository.BiometricType.UNDER_DISPLAY_FINGERPRINT
+import com.android.systemui.user.data.repository.FakeUserRepository
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestDispatcher
+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.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.isNull
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidTestingRunner::class)
+class BiometricSettingsRepositoryTest : SysuiTestCase() {
+    private lateinit var underTest: BiometricSettingsRepository
+
+    @Mock private lateinit var authController: AuthController
+    @Mock private lateinit var lockPatternUtils: LockPatternUtils
+    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+    @Mock private lateinit var dumpManager: DumpManager
+    @Mock private lateinit var biometricManager: BiometricManager
+    @Captor private lateinit var authControllerCallback: ArgumentCaptor<AuthController.Callback>
+    @Captor
+    private lateinit var biometricManagerCallback:
+        ArgumentCaptor<IBiometricEnabledOnKeyguardCallback.Stub>
+    private lateinit var userRepository: FakeUserRepository
+
+    private lateinit var testDispatcher: TestDispatcher
+    private lateinit var testScope: TestScope
+    private var testableLooper: TestableLooper? = null
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        testableLooper = TestableLooper.get(this)
+        testDispatcher = StandardTestDispatcher()
+        testScope = TestScope(testDispatcher)
+        userRepository = FakeUserRepository()
+    }
+
+    private suspend fun createBiometricSettingsRepository() {
+        userRepository.setUserInfos(listOf(PRIMARY_USER, ANOTHER_USER))
+        userRepository.setSelectedUserInfo(PRIMARY_USER)
+        underTest =
+            BiometricSettingsRepositoryImpl(
+                context = context,
+                lockPatternUtils = lockPatternUtils,
+                broadcastDispatcher = fakeBroadcastDispatcher,
+                authController = authController,
+                userRepository = userRepository,
+                devicePolicyManager = devicePolicyManager,
+                scope = testScope.backgroundScope,
+                backgroundDispatcher = testDispatcher,
+                looper = testableLooper!!.looper,
+                dumpManager = dumpManager,
+                biometricManager = biometricManager,
+            )
+        testScope.runCurrent()
+    }
+
+    @Test
+    fun fingerprintEnrollmentChange() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+            val fingerprintEnrolled = collectLastValue(underTest.isFingerprintEnrolled)
+            runCurrent()
+
+            verify(authController).addCallback(authControllerCallback.capture())
+            whenever(authController.isFingerprintEnrolled(anyInt())).thenReturn(true)
+            enrollmentChange(UNDER_DISPLAY_FINGERPRINT, PRIMARY_USER_ID, true)
+            assertThat(fingerprintEnrolled()).isTrue()
+
+            whenever(authController.isFingerprintEnrolled(anyInt())).thenReturn(false)
+            enrollmentChange(UNDER_DISPLAY_FINGERPRINT, ANOTHER_USER_ID, false)
+            assertThat(fingerprintEnrolled()).isTrue()
+
+            enrollmentChange(UNDER_DISPLAY_FINGERPRINT, PRIMARY_USER_ID, false)
+            assertThat(fingerprintEnrolled()).isFalse()
+        }
+
+    @Test
+    fun strongBiometricAllowedChange() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+            val strongBiometricAllowed = collectLastValue(underTest.isStrongBiometricAllowed)
+            runCurrent()
+
+            val captor = argumentCaptor<LockPatternUtils.StrongAuthTracker>()
+            verify(lockPatternUtils).registerStrongAuthTracker(captor.capture())
+
+            captor.value.stub.onStrongAuthRequiredChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
+            testableLooper?.processAllMessages() // StrongAuthTracker uses the TestableLooper
+            assertThat(strongBiometricAllowed()).isTrue()
+
+            captor.value.stub.onStrongAuthRequiredChanged(
+                STRONG_AUTH_REQUIRED_AFTER_BOOT,
+                PRIMARY_USER_ID
+            )
+            testableLooper?.processAllMessages() // StrongAuthTracker uses the TestableLooper
+            assertThat(strongBiometricAllowed()).isFalse()
+        }
+
+    @Test
+    fun fingerprintDisabledByDpmChange() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+            val fingerprintEnabledByDevicePolicy =
+                collectLastValue(underTest.isFingerprintEnabledByDevicePolicy)
+            runCurrent()
+
+            whenever(devicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt()))
+                .thenReturn(KEYGUARD_DISABLE_FINGERPRINT)
+            broadcastDPMStateChange()
+            assertThat(fingerprintEnabledByDevicePolicy()).isFalse()
+
+            whenever(devicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt())).thenReturn(0)
+            broadcastDPMStateChange()
+            assertThat(fingerprintEnabledByDevicePolicy()).isTrue()
+        }
+
+    @Test
+    fun faceEnrollmentChangeIsPropagatedForTheCurrentUser() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+            runCurrent()
+            clearInvocations(authController)
+
+            whenever(authController.isFaceAuthEnrolled(PRIMARY_USER_ID)).thenReturn(false)
+            val faceEnrolled = collectLastValue(underTest.isFaceEnrolled)
+
+            assertThat(faceEnrolled()).isFalse()
+            verify(authController).addCallback(authControllerCallback.capture())
+            enrollmentChange(REAR_FINGERPRINT, PRIMARY_USER_ID, true)
+
+            assertThat(faceEnrolled()).isFalse()
+
+            enrollmentChange(SIDE_FINGERPRINT, PRIMARY_USER_ID, true)
+
+            assertThat(faceEnrolled()).isFalse()
+
+            enrollmentChange(UNDER_DISPLAY_FINGERPRINT, PRIMARY_USER_ID, true)
+
+            assertThat(faceEnrolled()).isFalse()
+
+            enrollmentChange(FACE, ANOTHER_USER_ID, true)
+
+            assertThat(faceEnrolled()).isFalse()
+
+            enrollmentChange(FACE, PRIMARY_USER_ID, true)
+
+            assertThat(faceEnrolled()).isTrue()
+        }
+
+    @Test
+    fun faceEnrollmentStatusOfNewUserUponUserSwitch() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+            runCurrent()
+            clearInvocations(authController)
+
+            whenever(authController.isFaceAuthEnrolled(PRIMARY_USER_ID)).thenReturn(false)
+            whenever(authController.isFaceAuthEnrolled(ANOTHER_USER_ID)).thenReturn(true)
+            val faceEnrolled = collectLastValue(underTest.isFaceEnrolled)
+
+            assertThat(faceEnrolled()).isFalse()
+        }
+
+    @Test
+    fun faceEnrollmentChangesArePropagatedAfterUserSwitch() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+
+            userRepository.setSelectedUserInfo(ANOTHER_USER)
+            runCurrent()
+            clearInvocations(authController)
+
+            val faceEnrolled = collectLastValue(underTest.isFaceEnrolled)
+            runCurrent()
+
+            verify(authController).addCallback(authControllerCallback.capture())
+
+            enrollmentChange(FACE, ANOTHER_USER_ID, true)
+
+            assertThat(faceEnrolled()).isTrue()
+        }
+
+    @Test
+    fun devicePolicyControlsFaceAuthenticationEnabledState() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+            verify(biometricManager)
+                .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture())
+
+            whenever(devicePolicyManager.getKeyguardDisabledFeatures(isNull(), eq(PRIMARY_USER_ID)))
+                .thenReturn(KEYGUARD_DISABLE_FINGERPRINT or KEYGUARD_DISABLE_FACE)
+
+            val isFaceAuthEnabled = collectLastValue(underTest.isFaceAuthenticationEnabled)
+            runCurrent()
+
+            broadcastDPMStateChange()
+
+            assertThat(isFaceAuthEnabled()).isFalse()
+
+            biometricManagerCallback.value.onChanged(true, PRIMARY_USER_ID)
+            runCurrent()
+            assertThat(isFaceAuthEnabled()).isFalse()
+
+            whenever(devicePolicyManager.getKeyguardDisabledFeatures(isNull(), eq(PRIMARY_USER_ID)))
+                .thenReturn(KEYGUARD_DISABLE_FINGERPRINT)
+            broadcastDPMStateChange()
+
+            assertThat(isFaceAuthEnabled()).isTrue()
+        }
+
+    @Test
+    fun biometricManagerControlsFaceAuthenticationEnabledStatus() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+            verify(biometricManager)
+                .registerEnabledOnKeyguardCallback(biometricManagerCallback.capture())
+
+            whenever(devicePolicyManager.getKeyguardDisabledFeatures(isNull(), eq(PRIMARY_USER_ID)))
+                .thenReturn(0)
+            broadcastDPMStateChange()
+
+            biometricManagerCallback.value.onChanged(true, PRIMARY_USER_ID)
+            val isFaceAuthEnabled = collectLastValue(underTest.isFaceAuthenticationEnabled)
+
+            assertThat(isFaceAuthEnabled()).isTrue()
+
+            biometricManagerCallback.value.onChanged(false, PRIMARY_USER_ID)
+
+            assertThat(isFaceAuthEnabled()).isFalse()
+        }
+
+    @Test
+    fun biometricManagerCallbackIsRegisteredOnlyOnce() =
+        testScope.runTest {
+            createBiometricSettingsRepository()
+
+            collectLastValue(underTest.isFaceAuthenticationEnabled)()
+            collectLastValue(underTest.isFaceAuthenticationEnabled)()
+            collectLastValue(underTest.isFaceAuthenticationEnabled)()
+
+            verify(biometricManager, times(1)).registerEnabledOnKeyguardCallback(any())
+        }
+
+    private fun enrollmentChange(biometricType: BiometricType, userId: Int, enabled: Boolean) {
+        authControllerCallback.value.onEnrollmentsChanged(biometricType, userId, enabled)
+    }
+
+    private fun broadcastDPMStateChange() {
+        fakeBroadcastDispatcher.registeredReceivers.forEach { receiver ->
+            receiver.onReceive(
+                context,
+                Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED)
+            )
+        }
+    }
+
+    companion object {
+        private const val PRIMARY_USER_ID = 0
+        private val PRIMARY_USER =
+            UserInfo(
+                /* id= */ PRIMARY_USER_ID,
+                /* name= */ "primary user",
+                /* flags= */ UserInfo.FLAG_PRIMARY
+            )
+
+        private const val ANOTHER_USER_ID = 1
+        private val ANOTHER_USER =
+            UserInfo(
+                /* id= */ ANOTHER_USER_ID,
+                /* name= */ "another user",
+                /* flags= */ UserInfo.FLAG_PRIMARY
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
index 9203f05..0519a44 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
@@ -22,6 +22,7 @@
 import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.dump.DumpManager
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -44,6 +45,7 @@
 @RunWith(JUnit4::class)
 class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
     @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    @Mock private lateinit var dumpManager: DumpManager
     @Captor private lateinit var callbackCaptor: ArgumentCaptor<KeyguardUpdateMonitorCallback>
 
     private lateinit var testScope: TestScope
@@ -59,6 +61,7 @@
             DeviceEntryFingerprintAuthRepositoryImpl(
                 keyguardUpdateMonitor,
                 testScope.backgroundScope,
+                dumpManager,
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
index 2bc2ea1..03cb1db 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
@@ -47,7 +47,7 @@
         MockitoAnnotations.initMocks(this)
         val testCoroutineScope = TestCoroutineScope()
         underTest =
-            KeyguardBouncerRepository(
+            KeyguardBouncerRepositoryImpl(
                 viewMediatorCallback,
                 systemClock,
                 testCoroutineScope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
index b071a02..6099f01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
@@ -275,10 +275,10 @@
         expected: Map<String, List<KeyguardQuickAffordanceConfig>>,
     ) {
         assertThat(observed).isEqualTo(expected)
-        assertThat(underTest.getSelections())
+        assertThat(underTest.getCurrentSelections())
             .isEqualTo(expected.mapValues { (_, configs) -> configs.map { it.key } })
         expected.forEach { (slotId, configs) ->
-            assertThat(underTest.getSelections(slotId)).isEqualTo(configs)
+            assertThat(underTest.getCurrentSelections(slotId)).isEqualTo(configs)
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
index 68fff26..8caf60f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
@@ -22,9 +22,10 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeBiometricRepository
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
+import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.util.time.FakeSystemClock
 import com.android.systemui.util.time.SystemClock
@@ -46,7 +47,7 @@
 class AlternateBouncerInteractorTest : SysuiTestCase() {
     private lateinit var underTest: AlternateBouncerInteractor
     private lateinit var bouncerRepository: KeyguardBouncerRepository
-    private lateinit var biometricRepository: FakeBiometricRepository
+    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
     private lateinit var deviceEntryFingerprintAuthRepository:
         FakeDeviceEntryFingerprintAuthRepository
     @Mock private lateinit var systemClock: SystemClock
@@ -58,19 +59,19 @@
     fun setup() {
         MockitoAnnotations.initMocks(this)
         bouncerRepository =
-            KeyguardBouncerRepository(
+            KeyguardBouncerRepositoryImpl(
                 mock(ViewMediatorCallback::class.java),
                 FakeSystemClock(),
                 TestCoroutineScope(),
                 bouncerLogger,
             )
-        biometricRepository = FakeBiometricRepository()
+        biometricSettingsRepository = FakeBiometricSettingsRepository()
         deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
         featureFlags = FakeFeatureFlags().apply { this.set(Flags.MODERN_ALTERNATE_BOUNCER, true) }
         underTest =
             AlternateBouncerInteractor(
                 bouncerRepository,
-                biometricRepository,
+                biometricSettingsRepository,
                 deviceEntryFingerprintAuthRepository,
                 systemClock,
                 keyguardUpdateMonitor,
@@ -95,7 +96,7 @@
     @Test
     fun canShowAlternateBouncerForFingerprint_noFingerprintsEnrolled() {
         givenCanShowAlternateBouncer()
-        biometricRepository.setFingerprintEnrolled(false)
+        biometricSettingsRepository.setFingerprintEnrolled(false)
 
         assertFalse(underTest.canShowAlternateBouncerForFingerprint())
     }
@@ -103,7 +104,7 @@
     @Test
     fun canShowAlternateBouncerForFingerprint_strongBiometricNotAllowed() {
         givenCanShowAlternateBouncer()
-        biometricRepository.setStrongBiometricAllowed(false)
+        biometricSettingsRepository.setStrongBiometricAllowed(false)
 
         assertFalse(underTest.canShowAlternateBouncerForFingerprint())
     }
@@ -111,7 +112,7 @@
     @Test
     fun canShowAlternateBouncerForFingerprint_devicePolicyDoesNotAllowFingerprint() {
         givenCanShowAlternateBouncer()
-        biometricRepository.setFingerprintEnabledByDevicePolicy(false)
+        biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(false)
 
         assertFalse(underTest.canShowAlternateBouncerForFingerprint())
     }
@@ -158,13 +159,13 @@
 
     private fun givenCanShowAlternateBouncer() {
         bouncerRepository.setAlternateBouncerUIAvailable(true)
-        biometricRepository.setFingerprintEnrolled(true)
-        biometricRepository.setStrongBiometricAllowed(true)
-        biometricRepository.setFingerprintEnabledByDevicePolicy(true)
+        biometricSettingsRepository.setFingerprintEnrolled(true)
+        biometricSettingsRepository.setStrongBiometricAllowed(true)
+        biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true)
         deviceEntryFingerprintAuthRepository.setLockedOut(false)
     }
 
     private fun givenCannotShowAlternateBouncer() {
-        biometricRepository.setFingerprintEnrolled(false)
+        biometricSettingsRepository.setFingerprintEnrolled(false)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 68d13d3..d938243 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -18,30 +18,34 @@
 package com.android.systemui.keyguard.domain.interactor
 
 import android.app.StatusBarManager
+import android.content.Context
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
+import com.android.systemui.settings.DisplayTracker
 import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.statusbar.CommandQueue.Callbacks
-import com.android.systemui.util.mockito.argumentCaptor
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.onCompletion
+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.junit.runners.JUnit4
-import org.mockito.Mock
-import org.mockito.Mockito.verify
+import org.mockito.Mockito.mock
 import org.mockito.MockitoAnnotations
 
 @SmallTest
 @RunWith(JUnit4::class)
 class KeyguardInteractorTest : SysuiTestCase() {
-    @Mock private lateinit var commandQueue: CommandQueue
+    private lateinit var commandQueue: FakeCommandQueue
+    private lateinit var featureFlags: FakeFeatureFlags
+    private lateinit var testScope: TestScope
 
     private lateinit var underTest: KeyguardInteractor
     private lateinit var repository: FakeKeyguardRepository
@@ -49,38 +53,134 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-
+        featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
+        commandQueue = FakeCommandQueue(mock(Context::class.java), mock(DisplayTracker::class.java))
+        testScope = TestScope()
         repository = FakeKeyguardRepository()
-        underTest = KeyguardInteractor(repository, commandQueue)
+        underTest = KeyguardInteractor(repository, commandQueue, featureFlags)
     }
 
     @Test
-    fun onCameraLaunchDetected() = runTest {
-        val flow = underTest.onCameraLaunchDetected
-        var cameraLaunchSource = collectLastValue(flow)
-        runCurrent()
+    fun onCameraLaunchDetected() =
+        testScope.runTest {
+            val flow = underTest.onCameraLaunchDetected
+            var cameraLaunchSource = collectLastValue(flow)
+            runCurrent()
 
-        val captor = argumentCaptor<CommandQueue.Callbacks>()
-        verify(commandQueue).addCallback(captor.capture())
+            commandQueue.doForEachCallback {
+                it.onCameraLaunchGestureDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE)
+            }
+            assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.WIGGLE)
 
-        captor.value.onCameraLaunchGestureDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE)
-        assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.WIGGLE)
+            commandQueue.doForEachCallback {
+                it.onCameraLaunchGestureDetected(
+                    StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP
+                )
+            }
+            assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.POWER_DOUBLE_TAP)
 
-        captor.value.onCameraLaunchGestureDetected(
-            StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP
-        )
-        assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.POWER_DOUBLE_TAP)
+            commandQueue.doForEachCallback {
+                it.onCameraLaunchGestureDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER)
+            }
+            assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.LIFT_TRIGGER)
 
-        captor.value.onCameraLaunchGestureDetected(
-            StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER
-        )
-        assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.LIFT_TRIGGER)
+            commandQueue.doForEachCallback {
+                it.onCameraLaunchGestureDetected(
+                    StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE
+                )
+            }
+            assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.QUICK_AFFORDANCE)
 
-        captor.value.onCameraLaunchGestureDetected(
-            StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE
-        )
-        assertThat(cameraLaunchSource()).isEqualTo(CameraLaunchSourceModel.QUICK_AFFORDANCE)
+            flow.onCompletion { assertThat(commandQueue.callbackCount()).isEqualTo(0) }
+        }
 
-        flow.onCompletion { verify(commandQueue).removeCallback(captor.value) }
+    @Test
+    fun testKeyguardGuardVisibilityStopsSecureCamera() =
+        testScope.runTest {
+            val secureCameraActive = collectLastValue(underTest.isSecureCameraActive)
+            runCurrent()
+
+            commandQueue.doForEachCallback {
+                it.onCameraLaunchGestureDetected(
+                    StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP
+                )
+            }
+
+            assertThat(secureCameraActive()).isTrue()
+
+            // Keyguard is showing but occluded
+            repository.setKeyguardShowing(true)
+            repository.setKeyguardOccluded(true)
+            assertThat(secureCameraActive()).isTrue()
+
+            // Keyguard is showing and not occluded
+            repository.setKeyguardOccluded(false)
+            assertThat(secureCameraActive()).isFalse()
+        }
+
+    @Test
+    fun testBouncerShowingResetsSecureCameraState() =
+        testScope.runTest {
+            val secureCameraActive = collectLastValue(underTest.isSecureCameraActive)
+            runCurrent()
+
+            commandQueue.doForEachCallback {
+                it.onCameraLaunchGestureDetected(
+                    StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP
+                )
+            }
+            assertThat(secureCameraActive()).isTrue()
+
+            // Keyguard is showing and not occluded
+            repository.setKeyguardShowing(true)
+            repository.setKeyguardOccluded(true)
+            assertThat(secureCameraActive()).isTrue()
+
+            repository.setBouncerShowing(true)
+            assertThat(secureCameraActive()).isFalse()
+        }
+
+    @Test
+    fun keyguardVisibilityIsDefinedAsKeyguardShowingButNotOccluded() = runTest {
+        var isVisible = collectLastValue(underTest.isKeyguardVisible)
+        repository.setKeyguardShowing(true)
+        repository.setKeyguardOccluded(false)
+
+        assertThat(isVisible()).isTrue()
+
+        repository.setKeyguardOccluded(true)
+        assertThat(isVisible()).isFalse()
+
+        repository.setKeyguardShowing(false)
+        repository.setKeyguardOccluded(true)
+        assertThat(isVisible()).isFalse()
     }
+
+    @Test
+    fun secureCameraIsNotActiveWhenNoCameraLaunchEventHasBeenFiredYet() =
+        testScope.runTest {
+            val secureCameraActive = collectLastValue(underTest.isSecureCameraActive)
+            runCurrent()
+
+            assertThat(secureCameraActive()).isFalse()
+        }
+}
+
+class FakeCommandQueue(val context: Context, val displayTracker: DisplayTracker) :
+    CommandQueue(context, displayTracker) {
+    private val callbacks = mutableListOf<Callbacks>()
+
+    override fun addCallback(callback: Callbacks) {
+        callbacks.add(callback)
+    }
+
+    override fun removeCallback(callback: Callbacks) {
+        callbacks.remove(callback)
+    }
+
+    fun doForEachCallback(func: (callback: Callbacks) -> Unit) {
+        callbacks.forEach { func(it) }
+    }
+
+    fun callbackCount(): Int = callbacks.size
 }
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 43287b0..240af7b 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
@@ -286,12 +286,18 @@
                 dumpManager = mock(),
                 userHandle = UserHandle.SYSTEM,
             )
+        val featureFlags =
+            FakeFeatureFlags().apply {
+                set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false)
+                set(Flags.FACE_AUTH_REFACTOR, true)
+            }
         underTest =
             KeyguardQuickAffordanceInteractor(
                 keyguardInteractor =
                     KeyguardInteractor(
                         repository = FakeKeyguardRepository(),
-                        commandQueue = commandQueue
+                        commandQueue = commandQueue,
+                        featureFlags = featureFlags,
                     ),
                 registry =
                     FakeKeyguardQuickAffordanceRegistry(
@@ -311,10 +317,7 @@
                 keyguardStateController = keyguardStateController,
                 userTracker = userTracker,
                 activityStarter = activityStarter,
-                featureFlags =
-                    FakeFeatureFlags().apply {
-                        set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false)
-                    },
+                featureFlags = featureFlags,
                 repository = { quickAffordanceRepository },
                 launchAnimator = launchAnimator,
             )
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 b75a15d..8cff0ae 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
@@ -150,12 +150,17 @@
         featureFlags =
             FakeFeatureFlags().apply {
                 set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false)
+                set(Flags.FACE_AUTH_REFACTOR, true)
             }
 
         underTest =
             KeyguardQuickAffordanceInteractor(
                 keyguardInteractor =
-                    KeyguardInteractor(repository = repository, commandQueue = commandQueue),
+                    KeyguardInteractor(
+                        repository = repository,
+                        commandQueue = commandQueue,
+                        featureFlags = featureFlags
+                    ),
                 registry =
                     FakeKeyguardQuickAffordanceRegistry(
                         mapOf(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 3a871b4..46e4679 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -21,9 +21,12 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.Interpolators
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositoryImpl
+import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
 import com.android.systemui.keyguard.shared.model.DozeStateModel
 import com.android.systemui.keyguard.shared.model.DozeTransitionModel
 import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -91,10 +94,12 @@
         transitionRepository = KeyguardTransitionRepositoryImpl()
         runner = KeyguardTransitionRunner(transitionRepository)
 
+        val featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
         fromLockscreenTransitionInteractor =
             FromLockscreenTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+                keyguardInteractor =
+                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
                 shadeRepository = shadeRepository,
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
@@ -104,7 +109,8 @@
         fromDreamingTransitionInteractor =
             FromDreamingTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+                keyguardInteractor =
+                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
@@ -113,7 +119,8 @@
         fromAodTransitionInteractor =
             FromAodTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+                keyguardInteractor =
+                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
@@ -122,7 +129,8 @@
         fromGoneTransitionInteractor =
             FromGoneTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+                keyguardInteractor =
+                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
@@ -131,7 +139,8 @@
         fromDozingTransitionInteractor =
             FromDozingTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+                keyguardInteractor =
+                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
@@ -140,7 +149,8 @@
         fromOccludedTransitionInteractor =
             FromOccludedTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor = KeyguardInteractor(keyguardRepository, commandQueue),
+                keyguardInteractor =
+                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
@@ -148,7 +158,7 @@
     }
 
     @Test
-    fun `DREAMING to LOCKSCREEN`() =
+    fun `DREAMING to LOCKSCREEN - dreaming state changes first`() =
         testScope.runTest {
             // GIVEN a device is dreaming and occluded
             keyguardRepository.setDreamingWithOverlay(true)
@@ -178,9 +188,59 @@
             )
             // AND dreaming has stopped
             keyguardRepository.setDreamingWithOverlay(false)
+            advanceUntilIdle()
+            // AND then occluded has stopped
+            keyguardRepository.setKeyguardOccluded(false)
+            advanceUntilIdle()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture())
+                }
+            // THEN a transition to BOUNCER should occur
+            assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.DREAMING)
+            assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
+    fun `DREAMING to LOCKSCREEN - occluded state changes first`() =
+        testScope.runTest {
+            // GIVEN a device is dreaming and occluded
+            keyguardRepository.setDreamingWithOverlay(true)
+            keyguardRepository.setKeyguardOccluded(true)
+            runCurrent()
+
+            // GIVEN a prior transition has run to DREAMING
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.DREAMING,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // WHEN doze is complete
+            keyguardRepository.setDozeTransitionModel(
+                DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
+            )
             // AND occluded has stopped
             keyguardRepository.setKeyguardOccluded(false)
             advanceUntilIdle()
+            // AND then dreaming has stopped
+            keyguardRepository.setDreamingWithOverlay(false)
+            advanceUntilIdle()
 
             val info =
                 withArgCaptor<TransitionInfo> {
@@ -437,6 +497,43 @@
         }
 
     @Test
+    fun `DOZING to GONE`() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to DOZING
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.DOZING,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // WHEN biometrics succeeds with wake and unlock mode
+            keyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+            runCurrent()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture())
+                }
+            // THEN a transition to DOZING should occur
+            assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.DOZING)
+            assertThat(info.to).isEqualTo(KeyguardState.GONE)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
     fun `GONE to DOZING`() =
         testScope.runTest {
             // GIVEN a device with AOD not available
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
index 7f48ea1..c5e0252 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -68,13 +68,13 @@
     @Mock private lateinit var keyguardBypassController: KeyguardBypassController
     @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
     private val mainHandler = FakeHandler(Looper.getMainLooper())
-    private lateinit var mPrimaryBouncerInteractor: PrimaryBouncerInteractor
+    private lateinit var underTest: PrimaryBouncerInteractor
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         DejankUtils.setImmediate(true)
-        mPrimaryBouncerInteractor =
+        underTest =
             PrimaryBouncerInteractor(
                 repository,
                 bouncerView,
@@ -94,7 +94,7 @@
 
     @Test
     fun testShow_isScrimmed() {
-        mPrimaryBouncerInteractor.show(true)
+        underTest.show(true)
         verify(repository).setOnScreenTurnedOff(false)
         verify(repository).setKeyguardAuthenticated(null)
         verify(repository).setPrimaryHide(false)
@@ -124,7 +124,7 @@
 
     @Test
     fun testHide() {
-        mPrimaryBouncerInteractor.hide()
+        underTest.hide()
         verify(falsingCollector).onBouncerHidden()
         verify(keyguardStateController).notifyBouncerShowing(false)
         verify(repository).setPrimaryShowingSoon(false)
@@ -137,7 +137,7 @@
     @Test
     fun testExpansion() {
         `when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
-        mPrimaryBouncerInteractor.setPanelExpansion(0.6f)
+        underTest.setPanelExpansion(0.6f)
         verify(repository).setPanelExpansion(0.6f)
         verify(mPrimaryBouncerCallbackInteractor).dispatchExpansionChanged(0.6f)
     }
@@ -146,7 +146,7 @@
     fun testExpansion_fullyShown() {
         `when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
         `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        mPrimaryBouncerInteractor.setPanelExpansion(EXPANSION_VISIBLE)
+        underTest.setPanelExpansion(EXPANSION_VISIBLE)
         verify(falsingCollector).onBouncerShown()
         verify(mPrimaryBouncerCallbackInteractor).dispatchFullyShown()
     }
@@ -155,7 +155,7 @@
     fun testExpansion_fullyHidden() {
         `when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
         `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        mPrimaryBouncerInteractor.setPanelExpansion(EXPANSION_HIDDEN)
+        underTest.setPanelExpansion(EXPANSION_HIDDEN)
         verify(repository).setPrimaryVisible(false)
         verify(repository).setPrimaryShow(null)
         verify(repository).setPrimaryHide(true)
@@ -167,7 +167,7 @@
     @Test
     fun testExpansion_startingToHide() {
         `when`(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
-        mPrimaryBouncerInteractor.setPanelExpansion(0.1f)
+        underTest.setPanelExpansion(0.1f)
         verify(repository).setPrimaryStartingToHide(true)
         verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToHide()
     }
@@ -175,7 +175,7 @@
     @Test
     fun testShowMessage() {
         val argCaptor = ArgumentCaptor.forClass(BouncerShowMessageModel::class.java)
-        mPrimaryBouncerInteractor.showMessage("abc", null)
+        underTest.showMessage("abc", null)
         verify(repository).setShowMessage(argCaptor.capture())
         assertThat(argCaptor.value.message).isEqualTo("abc")
     }
@@ -184,62 +184,62 @@
     fun testDismissAction() {
         val onDismissAction = mock(ActivityStarter.OnDismissAction::class.java)
         val cancelAction = mock(Runnable::class.java)
-        mPrimaryBouncerInteractor.setDismissAction(onDismissAction, cancelAction)
+        underTest.setDismissAction(onDismissAction, cancelAction)
         verify(bouncerViewDelegate).setDismissAction(onDismissAction, cancelAction)
     }
 
     @Test
     fun testUpdateResources() {
-        mPrimaryBouncerInteractor.updateResources()
+        underTest.updateResources()
         verify(repository).setResourceUpdateRequests(true)
     }
 
     @Test
     fun testNotifyKeyguardAuthenticated() {
-        mPrimaryBouncerInteractor.notifyKeyguardAuthenticated(true)
+        underTest.notifyKeyguardAuthenticated(true)
         verify(repository).setKeyguardAuthenticated(true)
     }
 
     @Test
     fun testNotifyShowedMessage() {
-        mPrimaryBouncerInteractor.onMessageShown()
+        underTest.onMessageShown()
         verify(repository).setShowMessage(null)
     }
 
     @Test
     fun testOnScreenTurnedOff() {
-        mPrimaryBouncerInteractor.onScreenTurnedOff()
+        underTest.onScreenTurnedOff()
         verify(repository).setOnScreenTurnedOff(true)
     }
 
     @Test
     fun testSetKeyguardPosition() {
-        mPrimaryBouncerInteractor.setKeyguardPosition(0f)
+        underTest.setKeyguardPosition(0f)
         verify(repository).setKeyguardPosition(0f)
     }
 
     @Test
     fun testNotifyKeyguardAuthenticatedHandled() {
-        mPrimaryBouncerInteractor.notifyKeyguardAuthenticatedHandled()
+        underTest.notifyKeyguardAuthenticatedHandled()
         verify(repository).setKeyguardAuthenticated(null)
     }
 
     @Test
     fun testNotifyUpdatedResources() {
-        mPrimaryBouncerInteractor.notifyUpdatedResources()
+        underTest.notifyUpdatedResources()
         verify(repository).setResourceUpdateRequests(false)
     }
 
     @Test
     fun testSetBackButtonEnabled() {
-        mPrimaryBouncerInteractor.setBackButtonEnabled(true)
+        underTest.setBackButtonEnabled(true)
         verify(repository).setIsBackButtonEnabled(true)
     }
 
     @Test
     fun testStartDisappearAnimation() {
         val runnable = mock(Runnable::class.java)
-        mPrimaryBouncerInteractor.startDisappearAnimation(runnable)
+        underTest.startDisappearAnimation(runnable)
         verify(repository).setPrimaryStartDisappearAnimation(any(Runnable::class.java))
     }
 
@@ -248,42 +248,42 @@
         `when`(repository.primaryBouncerVisible.value).thenReturn(true)
         `when`(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
         `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        assertThat(mPrimaryBouncerInteractor.isFullyShowing()).isTrue()
+        assertThat(underTest.isFullyShowing()).isTrue()
         `when`(repository.primaryBouncerVisible.value).thenReturn(false)
-        assertThat(mPrimaryBouncerInteractor.isFullyShowing()).isFalse()
+        assertThat(underTest.isFullyShowing()).isFalse()
     }
 
     @Test
     fun testIsScrimmed() {
         `when`(repository.primaryBouncerScrimmed.value).thenReturn(true)
-        assertThat(mPrimaryBouncerInteractor.isScrimmed()).isTrue()
+        assertThat(underTest.isScrimmed()).isTrue()
         `when`(repository.primaryBouncerScrimmed.value).thenReturn(false)
-        assertThat(mPrimaryBouncerInteractor.isScrimmed()).isFalse()
+        assertThat(underTest.isScrimmed()).isFalse()
     }
 
     @Test
     fun testIsInTransit() {
         `when`(repository.primaryBouncerShowingSoon.value).thenReturn(true)
-        assertThat(mPrimaryBouncerInteractor.isInTransit()).isTrue()
+        assertThat(underTest.isInTransit()).isTrue()
         `when`(repository.primaryBouncerShowingSoon.value).thenReturn(false)
-        assertThat(mPrimaryBouncerInteractor.isInTransit()).isFalse()
+        assertThat(underTest.isInTransit()).isFalse()
         `when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
-        assertThat(mPrimaryBouncerInteractor.isInTransit()).isTrue()
+        assertThat(underTest.isInTransit()).isTrue()
     }
 
     @Test
     fun testIsAnimatingAway() {
         `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(Runnable {})
-        assertThat(mPrimaryBouncerInteractor.isAnimatingAway()).isTrue()
+        assertThat(underTest.isAnimatingAway()).isTrue()
         `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        assertThat(mPrimaryBouncerInteractor.isAnimatingAway()).isFalse()
+        assertThat(underTest.isAnimatingAway()).isFalse()
     }
 
     @Test
     fun testWillDismissWithAction() {
         `when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(true)
-        assertThat(mPrimaryBouncerInteractor.willDismissWithAction()).isTrue()
+        assertThat(underTest.willDismissWithAction()).isTrue()
         `when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(false)
-        assertThat(mPrimaryBouncerInteractor.willDismissWithAction()).isFalse()
+        assertThat(underTest.willDismissWithAction()).isFalse()
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
new file mode 100644
index 0000000..ea7bc91
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import android.os.Looper
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.keyguard.data.BouncerView
+import com.android.systemui.keyguard.data.BouncerViewDelegate
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.utils.os.FakeHandler
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
+    private lateinit var repository: FakeKeyguardBouncerRepository
+    @Mock private lateinit var bouncerView: BouncerView
+    @Mock private lateinit var bouncerViewDelegate: BouncerViewDelegate
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
+    @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
+    @Mock private lateinit var falsingCollector: FalsingCollector
+    @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
+    @Mock private lateinit var keyguardBypassController: KeyguardBypassController
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    private val mainHandler = FakeHandler(Looper.getMainLooper())
+    private lateinit var underTest: PrimaryBouncerInteractor
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        repository = FakeKeyguardBouncerRepository()
+        underTest =
+            PrimaryBouncerInteractor(
+                repository,
+                bouncerView,
+                mainHandler,
+                keyguardStateController,
+                keyguardSecurityModel,
+                primaryBouncerCallbackInteractor,
+                falsingCollector,
+                dismissCallbackRegistry,
+                keyguardBypassController,
+                keyguardUpdateMonitor,
+            )
+    }
+
+    @Test
+    fun notInteractableWhenExpansionIsBelow90Percent() = runTest {
+        val isInteractable = collectLastValue(underTest.isInteractable)
+
+        repository.setPrimaryVisible(true)
+        repository.setPanelExpansion(0.15f)
+
+        assertThat(isInteractable()).isFalse()
+    }
+
+    @Test
+    fun notInteractableWhenExpansionAbove90PercentButNotVisible() = runTest {
+        val isInteractable = collectLastValue(underTest.isInteractable)
+
+        repository.setPrimaryVisible(false)
+        repository.setPanelExpansion(0.05f)
+
+        assertThat(isInteractable()).isFalse()
+    }
+
+    @Test
+    fun isInteractableWhenExpansionAbove90PercentAndVisible() = runTest {
+        var isInteractable = collectLastValue(underTest.isInteractable)
+
+        repository.setPrimaryVisible(true)
+        repository.setPanelExpansion(0.09f)
+
+        assertThat(isInteractable()).isTrue()
+
+        repository.setPanelExpansion(0.12f)
+        assertThat(isInteractable()).isFalse()
+
+        repository.setPanelExpansion(0f)
+        assertThat(isInteractable()).isTrue()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
new file mode 100644
index 0000000..a5b78b74
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyguardTransitionAnimationFlowTest : SysuiTestCase() {
+    private lateinit var underTest: KeyguardTransitionAnimationFlow
+    private lateinit var repository: FakeKeyguardTransitionRepository
+
+    @Before
+    fun setUp() {
+        repository = FakeKeyguardTransitionRepository()
+        underTest =
+            KeyguardTransitionAnimationFlow(
+                1000.milliseconds,
+                repository.transitions,
+            )
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun zeroDurationThrowsException() = runTest {
+        val flow = underTest.createFlow(duration = 0.milliseconds, onStep = { it })
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun startTimePlusDurationGreaterThanTransitionDurationThrowsException() = runTest {
+        val flow =
+            underTest.createFlow(
+                startTime = 300.milliseconds,
+                duration = 800.milliseconds,
+                onStep = { it }
+            )
+    }
+
+    @Test
+    fun onFinishRunsWhenSpecified() = runTest {
+        val flow =
+            underTest.createFlow(
+                duration = 100.milliseconds,
+                onStep = { it },
+                onFinish = { 10f },
+            )
+        var animationValues = collectLastValue(flow)
+        repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
+        assertThat(animationValues()).isEqualTo(10f)
+    }
+
+    @Test
+    fun onCancelRunsWhenSpecified() = runTest {
+        val flow =
+            underTest.createFlow(
+                duration = 100.milliseconds,
+                onStep = { it },
+                onCancel = { 100f },
+            )
+        var animationValues = collectLastValue(flow)
+        repository.sendTransitionStep(step(0.5f, TransitionState.CANCELED))
+        assertThat(animationValues()).isEqualTo(100f)
+    }
+
+    @Test
+    fun usesStartTime() = runTest {
+        val flow =
+            underTest.createFlow(
+                startTime = 500.milliseconds,
+                duration = 500.milliseconds,
+                onStep = { it },
+            )
+        var animationValues = collectLastValue(flow)
+        repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+        assertThat(animationValues()).isEqualTo(0f)
+
+        // Should not emit a value
+        repository.sendTransitionStep(step(0.1f, TransitionState.RUNNING))
+
+        repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
+        assertFloat(animationValues(), 0f)
+        repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+        assertFloat(animationValues(), 0.2f)
+        repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+        assertFloat(animationValues(), 0.6f)
+        repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+        assertFloat(animationValues(), 1f)
+    }
+
+    @Test
+    fun usesInterpolator() = runTest {
+        val flow =
+            underTest.createFlow(
+                duration = 1000.milliseconds,
+                interpolator = EMPHASIZED_ACCELERATE,
+                onStep = { it },
+            )
+        var animationValues = collectLastValue(flow)
+        repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+        assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0f))
+        repository.sendTransitionStep(step(0.5f, TransitionState.RUNNING))
+        assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.5f))
+        repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+        assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.6f))
+        repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+        assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(0.8f))
+        repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+        assertFloat(animationValues(), EMPHASIZED_ACCELERATE.getInterpolation(1f))
+    }
+
+    @Test
+    fun usesOnStepToDoubleValue() = runTest {
+        val flow =
+            underTest.createFlow(
+                duration = 1000.milliseconds,
+                onStep = { it * 2 },
+            )
+        var animationValues = collectLastValue(flow)
+        repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+        assertFloat(animationValues(), 0f)
+        repository.sendTransitionStep(step(0.3f, TransitionState.RUNNING))
+        assertFloat(animationValues(), 0.6f)
+        repository.sendTransitionStep(step(0.6f, TransitionState.RUNNING))
+        assertFloat(animationValues(), 1.2f)
+        repository.sendTransitionStep(step(0.8f, TransitionState.RUNNING))
+        assertFloat(animationValues(), 1.6f)
+        repository.sendTransitionStep(step(1f, TransitionState.RUNNING))
+        assertFloat(animationValues(), 2f)
+    }
+
+    private fun assertFloat(actual: Float?, expected: Float) {
+        assertThat(actual!!).isWithin(0.01f).of(expected)
+    }
+
+    private fun step(
+        value: Float,
+        state: TransitionState = TransitionState.RUNNING
+    ): TransitionStep {
+        return TransitionStep(
+            from = KeyguardState.GONE,
+            to = KeyguardState.DREAMING,
+            value = value,
+            transitionState = state,
+            ownerName = "GoneToDreamingTransitionViewModelTest"
+        )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
index 5571663..06e397d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
@@ -18,19 +18,13 @@
 
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
-import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel.Companion.DREAM_OVERLAY_ALPHA
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel.Companion.DREAM_OVERLAY_TRANSLATION_Y
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel.Companion.LOCKSCREEN_ALPHA
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel.Companion.LOCKSCREEN_TRANSLATION_Y
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.google.common.collect.Range
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
@@ -46,6 +40,7 @@
 class DreamingToLockscreenTransitionViewModelTest : SysuiTestCase() {
     private lateinit var underTest: DreamingToLockscreenTransitionViewModel
     private lateinit var repository: FakeKeyguardTransitionRepository
+    private lateinit var transitionAnimation: KeyguardTransitionAnimationFlow
 
     @Before
     fun setUp() {
@@ -63,32 +58,18 @@
             val job =
                 underTest.dreamOverlayTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
+            // Should start running here...
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.5f))
+            repository.sendTransitionStep(step(0.6f))
+            // ...up to here
+            repository.sendTransitionStep(step(0.8f))
             repository.sendTransitionStep(step(1f))
 
-            // Only 3 values should be present, since the dream overlay runs for a small fraction
-            // of the overall animation time
-            assertThat(values.size).isEqualTo(3)
-            assertThat(values[0])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0f, DREAM_OVERLAY_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[1])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0.3f, DREAM_OVERLAY_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[2])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0.5f, DREAM_OVERLAY_TRANSLATION_Y)
-                    ) * pixels
-                )
+            assertThat(values.size).isEqualTo(5)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
 
             job.cancel()
         }
@@ -100,16 +81,18 @@
 
             val job = underTest.dreamOverlayAlpha.onEach { values.add(it) }.launchIn(this)
 
+            // Should start running here...
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.1f))
             repository.sendTransitionStep(step(0.5f))
+            // ...up to here
             repository.sendTransitionStep(step(1f))
 
             // Only two values should be present, since the dream overlay runs for a small fraction
             // of the overall animation time
-            assertThat(values.size).isEqualTo(2)
-            assertThat(values[0]).isEqualTo(1f - animValue(0f, DREAM_OVERLAY_ALPHA))
-            assertThat(values[1]).isEqualTo(1f - animValue(0.1f, DREAM_OVERLAY_ALPHA))
+            assertThat(values.size).isEqualTo(4)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
 
             job.cancel()
         }
@@ -121,19 +104,15 @@
 
             val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
 
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.1f))
-            // Should start running here...
             repository.sendTransitionStep(step(0.2f))
             repository.sendTransitionStep(step(0.3f))
-            // ...up to here
             repository.sendTransitionStep(step(1f))
 
-            // Only two values should be present, since the dream overlay runs for a small fraction
-            // of the overall animation time
-            assertThat(values.size).isEqualTo(2)
-            assertThat(values[0]).isEqualTo(animValue(0.2f, LOCKSCREEN_ALPHA))
-            assertThat(values[1]).isEqualTo(animValue(0.3f, LOCKSCREEN_ALPHA))
+            assertThat(values.size).isEqualTo(4)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
 
             job.cancel()
         }
@@ -147,58 +126,27 @@
             val job =
                 underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.5f))
             repository.sendTransitionStep(step(1f))
 
-            assertThat(values.size).isEqualTo(4)
-            assertThat(values[0])
-                .isEqualTo(
-                    -pixels +
-                        EMPHASIZED_DECELERATE.getInterpolation(
-                            animValue(0f, LOCKSCREEN_TRANSLATION_Y)
-                        ) * pixels
-                )
-            assertThat(values[1])
-                .isEqualTo(
-                    -pixels +
-                        EMPHASIZED_DECELERATE.getInterpolation(
-                            animValue(0.3f, LOCKSCREEN_TRANSLATION_Y)
-                        ) * pixels
-                )
-            assertThat(values[2])
-                .isEqualTo(
-                    -pixels +
-                        EMPHASIZED_DECELERATE.getInterpolation(
-                            animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
-                        ) * pixels
-                )
-            assertThat(values[3])
-                .isEqualTo(
-                    -pixels +
-                        EMPHASIZED_DECELERATE.getInterpolation(
-                            animValue(1f, LOCKSCREEN_TRANSLATION_Y)
-                        ) * pixels
-                )
+            assertThat(values.size).isEqualTo(5)
+            values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) }
 
             job.cancel()
         }
 
-    private fun animValue(stepValue: Float, params: AnimationParams): Float {
-        val totalDuration = TO_LOCKSCREEN_DURATION
-        val startValue = (params.startTime / totalDuration).toFloat()
-
-        val multiplier = (totalDuration / params.duration).toFloat()
-        return (stepValue - startValue) * multiplier
-    }
-
-    private fun step(value: Float): TransitionStep {
+    private fun step(
+        value: Float,
+        state: TransitionState = TransitionState.RUNNING
+    ): TransitionStep {
         return TransitionStep(
             from = KeyguardState.DREAMING,
             to = KeyguardState.LOCKSCREEN,
             value = value,
-            transitionState = TransitionState.RUNNING,
+            transitionState = state,
             ownerName = "DreamingToLockscreenTransitionViewModelTest"
         )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
index 7fa204b..14c3b50 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
@@ -18,16 +18,12 @@
 
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.FromGoneTransitionInteractor.Companion.TO_DREAMING_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel.Companion.LOCKSCREEN_ALPHA
-import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel.Companion.LOCKSCREEN_TRANSLATION_Y
+import com.google.common.collect.Range
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
@@ -59,20 +55,18 @@
             val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
 
             // Should start running here...
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.1f))
             repository.sendTransitionStep(step(0.2f))
-            // ...up to here
             repository.sendTransitionStep(step(0.3f))
+            // ...up to here
             repository.sendTransitionStep(step(1f))
 
             // Only three values should be present, since the dream overlay runs for a small
-            // fraction
-            // of the overall animation time
-            assertThat(values.size).isEqualTo(3)
-            assertThat(values[0]).isEqualTo(1f - animValue(0f, LOCKSCREEN_ALPHA))
-            assertThat(values[1]).isEqualTo(1f - animValue(0.1f, LOCKSCREEN_ALPHA))
-            assertThat(values[2]).isEqualTo(1f - animValue(0.2f, LOCKSCREEN_ALPHA))
+            // fraction of the overall animation time
+            assertThat(values.size).isEqualTo(5)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
 
             job.cancel()
         }
@@ -87,45 +81,19 @@
                 underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
             // Should start running here...
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.5f))
-            // ...up to here
-            repository.sendTransitionStep(step(1f))
             // And a final reset event on CANCEL
             repository.sendTransitionStep(step(0.8f, TransitionState.CANCELED))
 
-            assertThat(values.size).isEqualTo(4)
-            assertThat(values[0])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[1])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0.3f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[2])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[3]).isEqualTo(0f)
+            assertThat(values.size).isEqualTo(5)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
+
             job.cancel()
         }
 
-    private fun animValue(stepValue: Float, params: AnimationParams): Float {
-        val totalDuration = TO_DREAMING_DURATION
-        val startValue = (params.startTime / totalDuration).toFloat()
-
-        val multiplier = (totalDuration / params.duration).toFloat()
-        return (stepValue - startValue) * multiplier
-    }
-
     private fun step(
         value: Float,
         state: TransitionState = TransitionState.RUNNING
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 4b04b7b..03a347e 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
@@ -125,9 +125,18 @@
                 ),
             )
         repository = FakeKeyguardRepository()
+        val featureFlags =
+            FakeFeatureFlags().apply {
+                set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false)
+                set(Flags.FACE_AUTH_REFACTOR, true)
+            }
 
         val keyguardInteractor =
-            KeyguardInteractor(repository = repository, commandQueue = commandQueue)
+            KeyguardInteractor(
+                repository = repository,
+                commandQueue = commandQueue,
+                featureFlags = featureFlags,
+            )
         whenever(userTracker.userHandle).thenReturn(mock())
         whenever(lockPatternUtils.getStrongAuthForUser(anyInt()))
             .thenReturn(LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED)
@@ -191,10 +200,7 @@
                         keyguardStateController = keyguardStateController,
                         userTracker = userTracker,
                         activityStarter = activityStarter,
-                        featureFlags =
-                            FakeFeatureFlags().apply {
-                                set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false)
-                            },
+                        featureFlags = featureFlags,
                         repository = { quickAffordanceRepository },
                         launchAnimator = launchAnimator,
                     ),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
index 539fc2c..ed31dc3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
@@ -18,16 +18,12 @@
 
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_DREAMING_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.Companion.LOCKSCREEN_ALPHA
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.Companion.LOCKSCREEN_TRANSLATION_Y
+import com.google.common.collect.Range
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
@@ -59,19 +55,18 @@
             val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
 
             // Should start running here...
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.1f))
             repository.sendTransitionStep(step(0.2f))
-            // ...up to here
             repository.sendTransitionStep(step(0.3f))
+            // ...up to here
             repository.sendTransitionStep(step(1f))
 
             // Only three values should be present, since the dream overlay runs for a small
             // fraction of the overall animation time
-            assertThat(values.size).isEqualTo(3)
-            assertThat(values[0]).isEqualTo(1f - animValue(0f, LOCKSCREEN_ALPHA))
-            assertThat(values[1]).isEqualTo(1f - animValue(0.1f, LOCKSCREEN_ALPHA))
-            assertThat(values[2]).isEqualTo(1f - animValue(0.2f, LOCKSCREEN_ALPHA))
+            assertThat(values.size).isEqualTo(5)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
 
             job.cancel()
         }
@@ -85,47 +80,22 @@
             val job =
                 underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
-            // Should start running here...
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.5f))
-            // ...up to here
             repository.sendTransitionStep(step(1f))
             // And a final reset event on FINISHED
             repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
 
-            assertThat(values.size).isEqualTo(4)
-            assertThat(values[0])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[1])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0.3f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[2])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[3]).isEqualTo(0f)
+            assertThat(values.size).isEqualTo(6)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
+            // Validate finished value
+            assertThat(values[5]).isEqualTo(0f)
 
             job.cancel()
         }
 
-    private fun animValue(stepValue: Float, params: AnimationParams): Float {
-        val totalDuration = TO_DREAMING_DURATION
-        val startValue = (params.startTime / totalDuration).toFloat()
-
-        val multiplier = (totalDuration / params.duration).toFloat()
-        return (stepValue - startValue) * multiplier
-    }
-
     private fun step(
         value: Float,
         state: TransitionState = TransitionState.RUNNING
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
index 759345f..458b315 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
@@ -18,16 +18,12 @@
 
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_OCCLUDED_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel.Companion.LOCKSCREEN_ALPHA
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel.Companion.LOCKSCREEN_TRANSLATION_Y
+import com.google.common.collect.Range
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
@@ -59,19 +55,18 @@
             val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
 
             // Should start running here...
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.1f))
             repository.sendTransitionStep(step(0.4f))
-            // ...up to here
             repository.sendTransitionStep(step(0.7f))
+            // ...up to here
             repository.sendTransitionStep(step(1f))
 
             // Only 3 values should be present, since the dream overlay runs for a small fraction
             // of the overall animation time
-            assertThat(values.size).isEqualTo(3)
-            assertThat(values[0]).isEqualTo(1f - animValue(0f, LOCKSCREEN_ALPHA))
-            assertThat(values[1]).isEqualTo(1f - animValue(0.1f, LOCKSCREEN_ALPHA))
-            assertThat(values[2]).isEqualTo(1f - animValue(0.4f, LOCKSCREEN_ALPHA))
+            assertThat(values.size).isEqualTo(5)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
 
             job.cancel()
         }
@@ -86,54 +81,51 @@
                 underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
             // Should start running here...
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.5f))
             repository.sendTransitionStep(step(1f))
             // ...up to here
 
-            assertThat(values.size).isEqualTo(4)
-            assertThat(values[0])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[1])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0.3f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[2])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
-            assertThat(values[3])
-                .isEqualTo(
-                    EMPHASIZED_ACCELERATE.getInterpolation(
-                        animValue(1f, LOCKSCREEN_TRANSLATION_Y)
-                    ) * pixels
-                )
+            assertThat(values.size).isEqualTo(5)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
+
             job.cancel()
         }
 
-    private fun animValue(stepValue: Float, params: AnimationParams): Float {
-        val totalDuration = TO_OCCLUDED_DURATION
-        val startValue = (params.startTime / totalDuration).toFloat()
+    @Test
+    fun lockscreenTranslationYIsCanceled() =
+        runTest(UnconfinedTestDispatcher()) {
+            val values = mutableListOf<Float>()
 
-        val multiplier = (totalDuration / params.duration).toFloat()
-        return (stepValue - startValue) * multiplier
-    }
+            val pixels = 100
+            val job =
+                underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
-    private fun step(value: Float): TransitionStep {
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0f))
+            repository.sendTransitionStep(step(0.3f))
+            repository.sendTransitionStep(step(0.3f, TransitionState.CANCELED))
+
+            assertThat(values.size).isEqualTo(4)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
+
+            // Cancel will reset the translation
+            assertThat(values[3]).isEqualTo(0)
+
+            job.cancel()
+        }
+
+    private fun step(
+        value: Float,
+        state: TransitionState = TransitionState.RUNNING,
+    ): TransitionStep {
         return TransitionStep(
             from = KeyguardState.LOCKSCREEN,
             to = KeyguardState.OCCLUDED,
             value = value,
-            transitionState = TransitionState.RUNNING,
+            transitionState = state,
             ownerName = "LockscreenToOccludedTransitionViewModelTest"
         )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
index 98d292d..a36214e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
@@ -18,16 +18,12 @@
 
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.AnimationParams
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel.Companion.LOCKSCREEN_ALPHA
-import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel.Companion.LOCKSCREEN_TRANSLATION_Y
+import com.google.common.collect.Range
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
@@ -58,21 +54,19 @@
 
             val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
 
-            repository.sendTransitionStep(step(0f))
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0.1f))
             // Should start running here...
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.4f))
             repository.sendTransitionStep(step(0.5f))
-            // ...up to here
             repository.sendTransitionStep(step(0.6f))
+            // ...up to here
+            repository.sendTransitionStep(step(0.8f))
             repository.sendTransitionStep(step(1f))
 
-            // Only two values should be present, since the dream overlay runs for a small fraction
-            // of the overall animation time
-            assertThat(values.size).isEqualTo(3)
-            assertThat(values[0]).isEqualTo(animValue(0.3f, LOCKSCREEN_ALPHA))
-            assertThat(values[1]).isEqualTo(animValue(0.4f, LOCKSCREEN_ALPHA))
-            assertThat(values[2]).isEqualTo(animValue(0.5f, LOCKSCREEN_ALPHA))
+            assertThat(values.size).isEqualTo(5)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
 
             job.cancel()
         }
@@ -86,58 +80,27 @@
             val job =
                 underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.5f))
             repository.sendTransitionStep(step(1f))
 
-            assertThat(values.size).isEqualTo(4)
-            assertThat(values[0])
-                .isEqualTo(
-                    -pixels +
-                        EMPHASIZED_DECELERATE.getInterpolation(
-                            animValue(0f, LOCKSCREEN_TRANSLATION_Y)
-                        ) * pixels
-                )
-            assertThat(values[1])
-                .isEqualTo(
-                    -pixels +
-                        EMPHASIZED_DECELERATE.getInterpolation(
-                            animValue(0.3f, LOCKSCREEN_TRANSLATION_Y)
-                        ) * pixels
-                )
-            assertThat(values[2])
-                .isEqualTo(
-                    -pixels +
-                        EMPHASIZED_DECELERATE.getInterpolation(
-                            animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
-                        ) * pixels
-                )
-            assertThat(values[3])
-                .isEqualTo(
-                    -pixels +
-                        EMPHASIZED_DECELERATE.getInterpolation(
-                            animValue(1f, LOCKSCREEN_TRANSLATION_Y)
-                        ) * pixels
-                )
+            assertThat(values.size).isEqualTo(5)
+            values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) }
 
             job.cancel()
         }
 
-    private fun animValue(stepValue: Float, params: AnimationParams): Float {
-        val totalDuration = TO_LOCKSCREEN_DURATION
-        val startValue = (params.startTime / totalDuration).toFloat()
-
-        val multiplier = (totalDuration / params.duration).toFloat()
-        return (stepValue - startValue) * multiplier
-    }
-
-    private fun step(value: Float): TransitionStep {
+    private fun step(
+        value: Float,
+        state: TransitionState = TransitionState.RUNNING
+    ): TransitionStep {
         return TransitionStep(
             from = KeyguardState.OCCLUDED,
             to = KeyguardState.LOCKSCREEN,
             value = value,
-            transitionState = TransitionState.RUNNING,
+            transitionState = state,
             ownerName = "OccludedToLockscreenTransitionViewModelTest"
         )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
index 3b5e6b9..d1744c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
@@ -276,6 +276,52 @@
         }
 
     @Test
+    fun intNullable_logsNull() =
+        testScope.runTest {
+            systemClock.setCurrentTimeMillis(100L)
+            val flow = flow {
+                for (int in listOf(null, 6, null, 8)) {
+                    systemClock.advanceTime(100L)
+                    emit(int)
+                }
+            }
+
+            val flowWithLogging =
+                flow.logDiffsForTable(
+                    tableLogBuffer,
+                    COLUMN_PREFIX,
+                    COLUMN_NAME,
+                    initialValue = 1234,
+                )
+
+            val job = launch { flowWithLogging.collect() }
+
+            val logs = dumpLog()
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(100L) + SEPARATOR + FULL_NAME + SEPARATOR + "1234"
+                )
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(200L) + SEPARATOR + FULL_NAME + SEPARATOR + "null"
+                )
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(300L) + SEPARATOR + FULL_NAME + SEPARATOR + "6"
+                )
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(400L) + SEPARATOR + FULL_NAME + SEPARATOR + "null"
+                )
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(500L) + SEPARATOR + FULL_NAME + SEPARATOR + "8"
+                )
+
+            job.cancel()
+        }
+
+    @Test
     fun int_logsUpdates() =
         testScope.runTest {
             systemClock.setCurrentTimeMillis(100L)
@@ -1030,6 +1076,246 @@
             job.cancel()
         }
 
+    // ---- Flow<List<T>> tests ----
+
+    @Test
+    fun list_doesNotLogWhenNotCollected() {
+        val flow = flowOf(listOf(5), listOf(6), listOf(7))
+
+        flow.logDiffsForTable(
+            tableLogBuffer,
+            COLUMN_PREFIX,
+            COLUMN_NAME,
+            initialValue = listOf(1234),
+        )
+
+        val logs = dumpLog()
+        assertThat(logs).doesNotContain(COLUMN_PREFIX)
+        assertThat(logs).doesNotContain(COLUMN_NAME)
+        assertThat(logs).doesNotContain("1234")
+    }
+
+    @Test
+    fun list_logsInitialWhenCollected() =
+        testScope.runTest {
+            val flow = flowOf(listOf(5), listOf(6), listOf(7))
+
+            val flowWithLogging =
+                flow.logDiffsForTable(
+                    tableLogBuffer,
+                    COLUMN_PREFIX,
+                    COLUMN_NAME,
+                    initialValue = listOf(1234),
+                )
+
+            systemClock.setCurrentTimeMillis(3000L)
+            val job = launch { flowWithLogging.collect() }
+
+            val logs = dumpLog()
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(3000L) +
+                        SEPARATOR +
+                        FULL_NAME +
+                        SEPARATOR +
+                        listOf(1234).toString()
+                )
+
+            job.cancel()
+        }
+
+    @Test
+    fun list_logsUpdates() =
+        testScope.runTest {
+            systemClock.setCurrentTimeMillis(100L)
+
+            val listItems =
+                listOf(listOf("val1", "val2"), listOf("val3"), listOf("val4", "val5", "val6"))
+            val flow = flow {
+                for (list in listItems) {
+                    systemClock.advanceTime(100L)
+                    emit(list)
+                }
+            }
+
+            val flowWithLogging =
+                flow.logDiffsForTable(
+                    tableLogBuffer,
+                    COLUMN_PREFIX,
+                    COLUMN_NAME,
+                    initialValue = listOf("val0", "val00"),
+                )
+
+            val job = launch { flowWithLogging.collect() }
+
+            val logs = dumpLog()
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(100L) +
+                        SEPARATOR +
+                        FULL_NAME +
+                        SEPARATOR +
+                        listOf("val0", "val00").toString()
+                )
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(200L) +
+                        SEPARATOR +
+                        FULL_NAME +
+                        SEPARATOR +
+                        listOf("val1", "val2").toString()
+                )
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(300L) +
+                        SEPARATOR +
+                        FULL_NAME +
+                        SEPARATOR +
+                        listOf("val3").toString()
+                )
+            assertThat(logs)
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(400L) +
+                        SEPARATOR +
+                        FULL_NAME +
+                        SEPARATOR +
+                        listOf("val4", "val5", "val6").toString()
+                )
+
+            job.cancel()
+        }
+
+    @Test
+    fun list_doesNotLogIfSameValue() =
+        testScope.runTest {
+            systemClock.setCurrentTimeMillis(100L)
+
+            val listItems =
+                listOf(
+                    listOf("val0", "val00"),
+                    listOf("val1"),
+                    listOf("val1"),
+                    listOf("val1", "val2"),
+                )
+            val flow = flow {
+                for (bool in listItems) {
+                    systemClock.advanceTime(100L)
+                    emit(bool)
+                }
+            }
+
+            val flowWithLogging =
+                flow.logDiffsForTable(
+                    tableLogBuffer,
+                    COLUMN_PREFIX,
+                    COLUMN_NAME,
+                    initialValue = listOf("val0", "val00"),
+                )
+
+            val job = launch { flowWithLogging.collect() }
+
+            val logs = dumpLog()
+
+            val expected1 =
+                TABLE_LOG_DATE_FORMAT.format(100L) +
+                    SEPARATOR +
+                    FULL_NAME +
+                    SEPARATOR +
+                    listOf("val0", "val00").toString()
+            val expected3 =
+                TABLE_LOG_DATE_FORMAT.format(300L) +
+                    SEPARATOR +
+                    FULL_NAME +
+                    SEPARATOR +
+                    listOf("val1").toString()
+            val expected5 =
+                TABLE_LOG_DATE_FORMAT.format(500L) +
+                    SEPARATOR +
+                    FULL_NAME +
+                    SEPARATOR +
+                    listOf("val1", "val2").toString()
+            assertThat(logs).contains(expected1)
+            assertThat(logs).contains(expected3)
+            assertThat(logs).contains(expected5)
+
+            val unexpected2 =
+                TABLE_LOG_DATE_FORMAT.format(200L) +
+                    SEPARATOR +
+                    FULL_NAME +
+                    SEPARATOR +
+                    listOf("val0", "val00")
+            val unexpected4 =
+                TABLE_LOG_DATE_FORMAT.format(400L) +
+                    SEPARATOR +
+                    FULL_NAME +
+                    SEPARATOR +
+                    listOf("val1")
+            assertThat(logs).doesNotContain(unexpected2)
+            assertThat(logs).doesNotContain(unexpected4)
+            job.cancel()
+        }
+
+    @Test
+    fun list_worksForStateFlows() =
+        testScope.runTest {
+            val flow = MutableStateFlow(listOf(1111))
+
+            val flowWithLogging =
+                flow.logDiffsForTable(
+                    tableLogBuffer,
+                    COLUMN_PREFIX,
+                    COLUMN_NAME,
+                    initialValue = listOf(1111),
+                )
+
+            systemClock.setCurrentTimeMillis(50L)
+            val job = launch { flowWithLogging.collect() }
+            assertThat(dumpLog())
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(50L) +
+                        SEPARATOR +
+                        FULL_NAME +
+                        SEPARATOR +
+                        listOf(1111).toString()
+                )
+
+            systemClock.setCurrentTimeMillis(100L)
+            flow.emit(listOf(2222, 3333))
+            assertThat(dumpLog())
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(100L) +
+                        SEPARATOR +
+                        FULL_NAME +
+                        SEPARATOR +
+                        listOf(2222, 3333).toString()
+                )
+
+            systemClock.setCurrentTimeMillis(200L)
+            flow.emit(listOf(3333, 4444))
+            assertThat(dumpLog())
+                .contains(
+                    TABLE_LOG_DATE_FORMAT.format(200L) +
+                        SEPARATOR +
+                        FULL_NAME +
+                        SEPARATOR +
+                        listOf(3333, 4444).toString()
+                )
+
+            // Doesn't log duplicates
+            systemClock.setCurrentTimeMillis(300L)
+            flow.emit(listOf(3333, 4444))
+            assertThat(dumpLog())
+                .doesNotContain(
+                    TABLE_LOG_DATE_FORMAT.format(300L) +
+                        SEPARATOR +
+                        FULL_NAME +
+                        SEPARATOR +
+                        listOf(3333, 4444).toString()
+                )
+
+            job.cancel()
+        }
+
     private fun dumpLog(): String {
         val outputWriter = StringWriter()
         tableLogBuffer.dump(PrintWriter(outputWriter), arrayOf())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
index 432764a..c7f3fa0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
@@ -36,6 +36,17 @@
     }
 
     @Test
+    fun setString_null() {
+        val underTest = TableChange()
+
+        underTest.reset(timestamp = 100, columnPrefix = "", columnName = "fakeName")
+        underTest.set(null as String?)
+
+        assertThat(underTest.hasData()).isTrue()
+        assertThat(underTest.getVal()).isEqualTo("null")
+    }
+
+    @Test
     fun setBoolean_isBoolean() {
         val underTest = TableChange()
 
@@ -58,6 +69,17 @@
     }
 
     @Test
+    fun setInt_null() {
+        val underTest = TableChange()
+
+        underTest.reset(timestamp = 100, columnPrefix = "", columnName = "fakeName")
+        underTest.set(null as Int?)
+
+        assertThat(underTest.hasData()).isTrue()
+        assertThat(underTest.getVal()).isEqualTo("null")
+    }
+
+    @Test
     fun setThenReset_isEmpty() {
         val underTest = TableChange()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaDataTest.kt
index 1d6e980..670f117 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaDataTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaDataTest.kt
@@ -113,5 +113,6 @@
         recommendations = emptyList(),
         dismissIntent = null,
         headphoneConnectionTimeMillis = 0,
-        instanceId = InstanceId.fakeInstanceId(-1)
+        instanceId = InstanceId.fakeInstanceId(-1),
+        expiryTimeMs = 0,
     )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataCombineLatestTest.java
index c0639f3..0a5b124 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataCombineLatestTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataCombineLatestTest.java
@@ -79,7 +79,7 @@
                 USER_ID, true, APP, null, ARTIST, TITLE, null,
                 new ArrayList<>(), new ArrayList<>(), null, PACKAGE, null, null, null, true, null,
                 MediaData.PLAYBACK_LOCAL, false, KEY, false, false, false, 0L,
-                InstanceId.fakeInstanceId(-1), -1, false);
+                InstanceId.fakeInstanceId(-1), -1, false, null);
         mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME, null, false);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
index 9d33e6f..eb6235c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
@@ -27,11 +27,13 @@
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
 import com.android.systemui.media.controls.ui.MediaPlayerData
+import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.media.controls.util.MediaUiEventLogger
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import java.util.concurrent.Executor
@@ -40,11 +42,11 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyLong
 import org.mockito.Mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
 
 private const val KEY = "TEST_KEY"
@@ -72,6 +74,7 @@
     @Mock private lateinit var smartspaceData: SmartspaceMediaData
     @Mock private lateinit var smartspaceMediaRecommendationItem: SmartspaceAction
     @Mock private lateinit var logger: MediaUiEventLogger
+    @Mock private lateinit var mediaFlags: MediaFlags
 
     private lateinit var mediaDataFilter: MediaDataFilter
     private lateinit var dataMain: MediaData
@@ -82,6 +85,7 @@
     fun setup() {
         MockitoAnnotations.initMocks(this)
         MediaPlayerData.clear()
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
         mediaDataFilter =
             MediaDataFilter(
                 context,
@@ -90,7 +94,8 @@
                 lockscreenUserManager,
                 executor,
                 clock,
-                logger
+                logger,
+                mediaFlags
             )
         mediaDataFilter.mediaDataManager = mediaDataManager
         mediaDataFilter.addListener(listener)
@@ -108,19 +113,20 @@
             )
         dataGuest = dataMain.copy(userId = USER_GUEST)
 
-        `when`(smartspaceData.targetId).thenReturn(SMARTSPACE_KEY)
-        `when`(smartspaceData.isActive).thenReturn(true)
-        `when`(smartspaceData.isValid()).thenReturn(true)
-        `when`(smartspaceData.packageName).thenReturn(SMARTSPACE_PACKAGE)
-        `when`(smartspaceData.recommendations).thenReturn(listOf(smartspaceMediaRecommendationItem))
-        `when`(smartspaceData.headphoneConnectionTimeMillis)
+        whenever(smartspaceData.targetId).thenReturn(SMARTSPACE_KEY)
+        whenever(smartspaceData.isActive).thenReturn(true)
+        whenever(smartspaceData.isValid()).thenReturn(true)
+        whenever(smartspaceData.packageName).thenReturn(SMARTSPACE_PACKAGE)
+        whenever(smartspaceData.recommendations)
+            .thenReturn(listOf(smartspaceMediaRecommendationItem))
+        whenever(smartspaceData.headphoneConnectionTimeMillis)
             .thenReturn(clock.currentTimeMillis() - 100)
-        `when`(smartspaceData.instanceId).thenReturn(SMARTSPACE_INSTANCE_ID)
+        whenever(smartspaceData.instanceId).thenReturn(SMARTSPACE_INSTANCE_ID)
     }
 
     private fun setUser(id: Int) {
-        `when`(lockscreenUserManager.isCurrentProfile(anyInt())).thenReturn(false)
-        `when`(lockscreenUserManager.isCurrentProfile(eq(id))).thenReturn(true)
+        whenever(lockscreenUserManager.isCurrentProfile(anyInt())).thenReturn(false)
+        whenever(lockscreenUserManager.isCurrentProfile(eq(id))).thenReturn(true)
         mediaDataFilter.handleUserSwitched(id)
     }
 
@@ -277,7 +283,7 @@
 
     @Test
     fun hasActiveMediaOrRecommendation_inactiveRecommendationSet_returnsFalse() {
-        `when`(smartspaceData.isActive).thenReturn(false)
+        whenever(smartspaceData.isActive).thenReturn(false)
         mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
         assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
@@ -285,7 +291,7 @@
 
     @Test
     fun hasActiveMediaOrRecommendation_invalidRecommendationSet_returnsFalse() {
-        `when`(smartspaceData.isValid()).thenReturn(false)
+        whenever(smartspaceData.isValid()).thenReturn(false)
         mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
         assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
@@ -293,8 +299,8 @@
 
     @Test
     fun hasActiveMediaOrRecommendation_activeAndValidRecommendationSet_returnsTrue() {
-        `when`(smartspaceData.isActive).thenReturn(true)
-        `when`(smartspaceData.isValid()).thenReturn(true)
+        whenever(smartspaceData.isActive).thenReturn(true)
+        whenever(smartspaceData.isValid()).thenReturn(true)
         mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
         assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
@@ -349,7 +355,7 @@
 
     @Test
     fun testOnSmartspaceMediaDataLoaded_noMedia_inactiveRec_showsNothing() {
-        `when`(smartspaceData.isActive).thenReturn(false)
+        whenever(smartspaceData.isActive).thenReturn(false)
 
         mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
 
@@ -379,7 +385,7 @@
 
     @Test
     fun testOnSmartspaceMediaDataLoaded_noRecentMedia_inactiveRec_showsNothing() {
-        `when`(smartspaceData.isActive).thenReturn(false)
+        whenever(smartspaceData.isActive).thenReturn(false)
 
         val dataOld = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
         mediaDataFilter.onMediaDataLoaded(KEY, null, dataOld)
@@ -395,7 +401,7 @@
 
     @Test
     fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_inactiveRec_showsNothing() {
-        `when`(smartspaceData.isActive).thenReturn(false)
+        whenever(smartspaceData.isActive).thenReturn(false)
 
         // WHEN we have media that was recently played, but not currently active
         val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
@@ -418,7 +424,7 @@
 
     @Test
     fun testOnSmartspaceMediaDataLoaded_hasRecentMedia_activeInvalidRec_usesMedia() {
-        `when`(smartspaceData.isValid()).thenReturn(false)
+        whenever(smartspaceData.isValid()).thenReturn(false)
 
         // WHEN we have media that was recently played, but not currently active
         val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
@@ -513,4 +519,59 @@
         assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
         assertThat(mediaDataFilter.hasActiveMedia()).isFalse()
     }
+
+    @Test
+    fun testOnSmartspaceLoaded_persistentEnabled_isInactive_notifiesListeners() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+        whenever(smartspaceData.isActive).thenReturn(false)
+
+        mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+
+        verify(listener)
+            .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+        assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
+        assertThat(mediaDataFilter.hasAnyMediaOrRecommendation()).isTrue()
+    }
+
+    @Test
+    fun testOnSmartspaceLoaded_persistentEnabled_inactive_hasRecentMedia_staysInactive() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+        whenever(smartspaceData.isActive).thenReturn(false)
+
+        // If there is media that was recently played but inactive
+        val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+        mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+        verify(listener)
+            .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
+
+        // And an inactive recommendation is loaded
+        mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+
+        // Smartspace is loaded but the media stays inactive
+        verify(listener)
+            .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+        verify(listener, never())
+            .onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt(), anyBoolean())
+        assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse()
+        assertThat(mediaDataFilter.hasAnyMediaOrRecommendation()).isTrue()
+    }
+
+    @Test
+    fun testOnSwipeToDismiss_persistentEnabled_recommendationSetInactive() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+
+        val data =
+            EMPTY_SMARTSPACE_MEDIA_DATA.copy(
+                targetId = SMARTSPACE_KEY,
+                isActive = true,
+                packageName = SMARTSPACE_PACKAGE,
+                recommendations = listOf(smartspaceMediaRecommendationItem),
+            )
+        mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, data)
+        mediaDataFilter.onSwipeToDismiss()
+
+        verify(mediaDataManager).setRecommendationInactive(eq(SMARTSPACE_KEY))
+        verify(mediaDataManager, never())
+            .dismissSmartspaceRecommendation(eq(SMARTSPACE_KEY), anyLong())
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
index 1ac6695..6f1b42b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
@@ -40,15 +40,19 @@
 import androidx.media.utils.MediaConstants
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.InstanceId
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.InstanceIdSequenceFake
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.media.controls.models.player.MediaData
+import com.android.systemui.media.controls.models.recommendation.EXTRA_KEY_TRIGGER_SOURCE
+import com.android.systemui.media.controls.models.recommendation.EXTRA_VALUE_TRIGGER_PERIODIC
 import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
 import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaDataProvider
 import com.android.systemui.media.controls.resume.MediaResumeListener
+import com.android.systemui.media.controls.resume.ResumeMediaBrowser
 import com.android.systemui.media.controls.util.MediaControllerFactory
 import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.media.controls.util.MediaUiEventLogger
@@ -82,6 +86,8 @@
 private const val KEY = "KEY"
 private const val KEY_2 = "KEY_2"
 private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
+private const val SMARTSPACE_CREATION_TIME = 1234L
+private const val SMARTSPACE_EXPIRY_TIME = 5678L
 private const val PACKAGE_NAME = "com.example.app"
 private const val SYSTEM_PACKAGE_NAME = "com.android.systemui"
 private const val APP_NAME = "SystemUI"
@@ -121,6 +127,7 @@
     @Mock lateinit var pendingIntent: PendingIntent
     @Mock lateinit var activityStarter: ActivityStarter
     @Mock lateinit var smartspaceManager: SmartspaceManager
+    @Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
     lateinit var smartspaceMediaDataProvider: SmartspaceMediaDataProvider
     @Mock lateinit var mediaSmartspaceTarget: SmartspaceTarget
     @Mock private lateinit var mediaRecommendationItem: SmartspaceAction
@@ -182,6 +189,7 @@
                 mediaFlags = mediaFlags,
                 logger = logger,
                 smartspaceManager = smartspaceManager,
+                keyguardUpdateMonitor = keyguardUpdateMonitor
             )
         verify(tunerService)
             .addTunable(capture(tunableCaptor), eq(Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION))
@@ -230,11 +238,14 @@
         whenever(mediaSmartspaceTarget.smartspaceTargetId).thenReturn(KEY_MEDIA_SMARTSPACE)
         whenever(mediaSmartspaceTarget.featureType).thenReturn(SmartspaceTarget.FEATURE_MEDIA)
         whenever(mediaSmartspaceTarget.iconGrid).thenReturn(validRecommendationList)
-        whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(1234L)
+        whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(SMARTSPACE_CREATION_TIME)
+        whenever(mediaSmartspaceTarget.expiryTimeMillis).thenReturn(SMARTSPACE_EXPIRY_TIME)
         whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(false)
         whenever(mediaFlags.isExplicitIndicatorEnabled()).thenReturn(true)
         whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(false)
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
         whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
+        whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false)
     }
 
     @After
@@ -636,6 +647,59 @@
     }
 
     @Test
+    fun testOnNotificationRemoved_withResumption_tooManyPlayers() {
+        // Given the maximum number of resume controls already
+        val desc =
+            MediaDescription.Builder().run {
+                setTitle(SESSION_TITLE)
+                build()
+            }
+        for (i in 0..ResumeMediaBrowser.MAX_RESUMPTION_CONTROLS) {
+            addResumeControlAndLoad(desc, "$i:$PACKAGE_NAME")
+            clock.advanceTime(1000)
+        }
+
+        // And an active, resumable notification
+        whenever(controller.metadata).thenReturn(metadataBuilder.build())
+        addNotificationAndLoad()
+        val data = mediaDataCaptor.value
+        assertThat(data.resumption).isFalse()
+        mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
+
+        // When the notification is removed
+        mediaDataManager.onNotificationRemoved(KEY)
+
+        // Then it is converted to resumption
+        verify(listener)
+            .onMediaDataLoaded(
+                eq(PACKAGE_NAME),
+                eq(KEY),
+                capture(mediaDataCaptor),
+                eq(true),
+                eq(0),
+                eq(false)
+            )
+        assertThat(mediaDataCaptor.value.resumption).isTrue()
+        assertThat(mediaDataCaptor.value.isPlaying).isFalse()
+
+        // And the oldest resume control was removed
+        verify(listener).onMediaDataRemoved(eq("0:$PACKAGE_NAME"))
+    }
+
+    fun testOnNotificationRemoved_lockDownMode() {
+        whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(true)
+
+        addNotificationAndLoad()
+        val data = mediaDataCaptor.value
+        mediaDataManager.onNotificationRemoved(KEY)
+
+        verify(listener, never()).onMediaDataRemoved(eq(KEY))
+        verify(logger, never())
+            .logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId))
+        verify(logger).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId))
+    }
+
+    @Test
     fun testAddResumptionControls() {
         // WHEN resumption controls are added
         val desc =
@@ -644,27 +708,8 @@
                 build()
             }
         val currentTime = clock.elapsedRealtime()
-        mediaDataManager.addResumptionControls(
-            USER_ID,
-            desc,
-            Runnable {},
-            session.sessionToken,
-            APP_NAME,
-            pendingIntent,
-            PACKAGE_NAME
-        )
-        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
-        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
-        // THEN the media data indicates that it is for resumption
-        verify(listener)
-            .onMediaDataLoaded(
-                eq(PACKAGE_NAME),
-                eq(null),
-                capture(mediaDataCaptor),
-                eq(true),
-                eq(0),
-                eq(false)
-            )
+        addResumeControlAndLoad(desc)
+
         val data = mediaDataCaptor.value
         assertThat(data.resumption).isTrue()
         assertThat(data.song).isEqualTo(SESSION_TITLE)
@@ -690,27 +735,8 @@
                 build()
             }
         val currentTime = clock.elapsedRealtime()
-        mediaDataManager.addResumptionControls(
-            USER_ID,
-            desc,
-            Runnable {},
-            session.sessionToken,
-            APP_NAME,
-            pendingIntent,
-            PACKAGE_NAME
-        )
-        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
-        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
-        // THEN the media data indicates that it is for resumption
-        verify(listener)
-            .onMediaDataLoaded(
-                eq(PACKAGE_NAME),
-                eq(null),
-                capture(mediaDataCaptor),
-                eq(true),
-                eq(0),
-                eq(false)
-            )
+        addResumeControlAndLoad(desc)
+
         val data = mediaDataCaptor.value
         assertThat(data.resumption).isTrue()
         assertThat(data.song).isEqualTo(SESSION_TITLE)
@@ -723,6 +749,84 @@
     }
 
     @Test
+    fun testAddResumptionControls_hasPartialProgress() {
+        whenever(mediaFlags.isResumeProgressEnabled()).thenReturn(true)
+
+        // WHEN resumption controls are added with partial progress
+        val progress = 0.5
+        val extras =
+            Bundle().apply {
+                putInt(
+                    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS,
+                    MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED
+                )
+                putDouble(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, progress)
+            }
+        val desc =
+            MediaDescription.Builder().run {
+                setTitle(SESSION_TITLE)
+                setExtras(extras)
+                build()
+            }
+        addResumeControlAndLoad(desc)
+
+        val data = mediaDataCaptor.value
+        assertThat(data.resumption).isTrue()
+        assertThat(data.resumeProgress).isEqualTo(progress)
+    }
+
+    @Test
+    fun testAddResumptionControls_hasNotPlayedProgress() {
+        whenever(mediaFlags.isResumeProgressEnabled()).thenReturn(true)
+
+        // WHEN resumption controls are added that have not been played
+        val extras =
+            Bundle().apply {
+                putInt(
+                    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS,
+                    MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED
+                )
+            }
+        val desc =
+            MediaDescription.Builder().run {
+                setTitle(SESSION_TITLE)
+                setExtras(extras)
+                build()
+            }
+        addResumeControlAndLoad(desc)
+
+        val data = mediaDataCaptor.value
+        assertThat(data.resumption).isTrue()
+        assertThat(data.resumeProgress).isEqualTo(0)
+    }
+
+    @Test
+    fun testAddResumptionControls_hasFullProgress() {
+        whenever(mediaFlags.isResumeProgressEnabled()).thenReturn(true)
+
+        // WHEN resumption controls are added with progress info
+        val extras =
+            Bundle().apply {
+                putInt(
+                    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS,
+                    MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED
+                )
+            }
+        val desc =
+            MediaDescription.Builder().run {
+                setTitle(SESSION_TITLE)
+                setExtras(extras)
+                build()
+            }
+        addResumeControlAndLoad(desc)
+
+        // THEN the media data includes the progress
+        val data = mediaDataCaptor.value
+        assertThat(data.resumption).isTrue()
+        assertThat(data.resumeProgress).isEqualTo(1)
+    }
+
+    @Test
     fun testResumptionDisabled_dismissesResumeControls() {
         // WHEN there are resume controls and resumption is switched off
         val desc =
@@ -730,26 +834,8 @@
                 setTitle(SESSION_TITLE)
                 build()
             }
-        mediaDataManager.addResumptionControls(
-            USER_ID,
-            desc,
-            Runnable {},
-            session.sessionToken,
-            APP_NAME,
-            pendingIntent,
-            PACKAGE_NAME
-        )
-        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
-        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
-        verify(listener)
-            .onMediaDataLoaded(
-                eq(PACKAGE_NAME),
-                eq(null),
-                capture(mediaDataCaptor),
-                eq(true),
-                eq(0),
-                eq(false)
-            )
+        addResumeControlAndLoad(desc)
+
         val data = mediaDataCaptor.value
         mediaDataManager.setMediaResumptionEnabled(false)
 
@@ -825,8 +911,9 @@
                         cardAction = mediaSmartspaceBaseAction,
                         recommendations = validRecommendationList,
                         dismissIntent = DISMISS_INTENT,
-                        headphoneConnectionTimeMillis = 1234L,
-                        instanceId = InstanceId.fakeInstanceId(instanceId)
+                        headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
+                        instanceId = InstanceId.fakeInstanceId(instanceId),
+                        expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
                     )
                 ),
                 eq(false)
@@ -848,8 +935,9 @@
                         targetId = KEY_MEDIA_SMARTSPACE,
                         isActive = true,
                         dismissIntent = DISMISS_INTENT,
-                        headphoneConnectionTimeMillis = 1234L,
-                        instanceId = InstanceId.fakeInstanceId(instanceId)
+                        headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
+                        instanceId = InstanceId.fakeInstanceId(instanceId),
+                        expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
                     )
                 ),
                 eq(false)
@@ -879,8 +967,9 @@
                         targetId = KEY_MEDIA_SMARTSPACE,
                         isActive = true,
                         dismissIntent = null,
-                        headphoneConnectionTimeMillis = 1234L,
-                        instanceId = InstanceId.fakeInstanceId(instanceId)
+                        headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
+                        instanceId = InstanceId.fakeInstanceId(instanceId),
+                        expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
                     )
                 ),
                 eq(false)
@@ -909,6 +998,129 @@
     }
 
     @Test
+    fun testOnSmartspaceMediaDataLoaded_persistentEnabled_headphoneTrigger_isActive() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+        smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
+        val instanceId = instanceIdSequence.lastInstanceId
+
+        verify(listener)
+            .onSmartspaceMediaDataLoaded(
+                eq(KEY_MEDIA_SMARTSPACE),
+                eq(
+                    SmartspaceMediaData(
+                        targetId = KEY_MEDIA_SMARTSPACE,
+                        isActive = true,
+                        packageName = PACKAGE_NAME,
+                        cardAction = mediaSmartspaceBaseAction,
+                        recommendations = validRecommendationList,
+                        dismissIntent = DISMISS_INTENT,
+                        headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
+                        instanceId = InstanceId.fakeInstanceId(instanceId),
+                        expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
+                    )
+                ),
+                eq(false)
+            )
+    }
+
+    @Test
+    fun testOnSmartspaceMediaDataLoaded_persistentEnabled_periodicTrigger_notActive() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+        val extras =
+            Bundle().apply {
+                putString("package_name", PACKAGE_NAME)
+                putParcelable("dismiss_intent", DISMISS_INTENT)
+                putString(EXTRA_KEY_TRIGGER_SOURCE, EXTRA_VALUE_TRIGGER_PERIODIC)
+            }
+        whenever(mediaSmartspaceBaseAction.extras).thenReturn(extras)
+
+        smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
+        val instanceId = instanceIdSequence.lastInstanceId
+
+        verify(listener)
+            .onSmartspaceMediaDataLoaded(
+                eq(KEY_MEDIA_SMARTSPACE),
+                eq(
+                    SmartspaceMediaData(
+                        targetId = KEY_MEDIA_SMARTSPACE,
+                        isActive = false,
+                        packageName = PACKAGE_NAME,
+                        cardAction = mediaSmartspaceBaseAction,
+                        recommendations = validRecommendationList,
+                        dismissIntent = DISMISS_INTENT,
+                        headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
+                        instanceId = InstanceId.fakeInstanceId(instanceId),
+                        expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
+                    )
+                ),
+                eq(false)
+            )
+    }
+
+    @Test
+    fun testOnSmartspaceMediaDataLoaded_persistentEnabled_noTargets_inactive() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+
+        smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
+        val instanceId = instanceIdSequence.lastInstanceId
+
+        smartspaceMediaDataProvider.onTargetsAvailable(listOf())
+        uiExecutor.advanceClockToLast()
+        uiExecutor.runAllReady()
+
+        verify(listener)
+            .onSmartspaceMediaDataLoaded(
+                eq(KEY_MEDIA_SMARTSPACE),
+                eq(
+                    SmartspaceMediaData(
+                        targetId = KEY_MEDIA_SMARTSPACE,
+                        isActive = false,
+                        packageName = PACKAGE_NAME,
+                        cardAction = mediaSmartspaceBaseAction,
+                        recommendations = validRecommendationList,
+                        dismissIntent = DISMISS_INTENT,
+                        headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
+                        instanceId = InstanceId.fakeInstanceId(instanceId),
+                        expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
+                    )
+                ),
+                eq(false)
+            )
+        verify(listener, never()).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false))
+    }
+
+    @Test
+    fun testSetRecommendationInactive_notifiesListeners() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+
+        smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget))
+        val instanceId = instanceIdSequence.lastInstanceId
+
+        mediaDataManager.setRecommendationInactive(KEY_MEDIA_SMARTSPACE)
+        uiExecutor.advanceClockToLast()
+        uiExecutor.runAllReady()
+
+        verify(listener)
+            .onSmartspaceMediaDataLoaded(
+                eq(KEY_MEDIA_SMARTSPACE),
+                eq(
+                    SmartspaceMediaData(
+                        targetId = KEY_MEDIA_SMARTSPACE,
+                        isActive = false,
+                        packageName = PACKAGE_NAME,
+                        cardAction = mediaSmartspaceBaseAction,
+                        recommendations = validRecommendationList,
+                        dismissIntent = DISMISS_INTENT,
+                        headphoneConnectionTimeMillis = SMARTSPACE_CREATION_TIME,
+                        instanceId = InstanceId.fakeInstanceId(instanceId),
+                        expiryTimeMs = SMARTSPACE_EXPIRY_TIME,
+                    )
+                ),
+                eq(false)
+            )
+    }
+
+    @Test
     fun testOnSmartspaceMediaDataLoaded_settingDisabled_doesNothing() {
         // WHEN media recommendation setting is off
         Settings.Secure.putInt(
@@ -1690,4 +1902,32 @@
         stateBuilder.setState(PlaybackState.STATE_PAUSED, 0, 1.0f)
         whenever(controller.playbackState).thenReturn(stateBuilder.build())
     }
+
+    /** Helper function to add a resumption control and capture the resulting MediaData */
+    private fun addResumeControlAndLoad(
+        desc: MediaDescription,
+        packageName: String = PACKAGE_NAME
+    ) {
+        mediaDataManager.addResumptionControls(
+            USER_ID,
+            desc,
+            Runnable {},
+            session.sessionToken,
+            APP_NAME,
+            pendingIntent,
+            packageName
+        )
+        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
+
+        verify(listener)
+            .onMediaDataLoaded(
+                eq(packageName),
+                eq(null),
+                capture(mediaDataCaptor),
+                eq(true),
+                eq(0),
+                eq(false)
+            )
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListenerTest.kt
index 92bf84c..8baa06a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListenerTest.kt
@@ -25,13 +25,16 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.media.controls.MediaTestUtils
 import com.android.systemui.media.controls.models.player.MediaData
+import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
 import com.android.systemui.media.controls.util.MediaControllerFactory
+import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -48,7 +51,6 @@
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
 import org.mockito.junit.MockitoJUnit
 
 private const val KEY = "KEY"
@@ -56,6 +58,7 @@
 private const val SESSION_KEY = "SESSION_KEY"
 private const val SESSION_ARTIST = "SESSION_ARTIST"
 private const val SESSION_TITLE = "SESSION_TITLE"
+private const val SMARTSPACE_KEY = "SMARTSPACE_KEY"
 
 private fun <T> anyObject(): T {
     return Mockito.anyObject<T>()
@@ -85,10 +88,13 @@
     private lateinit var resumeData: MediaData
     private lateinit var mediaTimeoutListener: MediaTimeoutListener
     private var clock = FakeSystemClock()
+    @Mock private lateinit var mediaFlags: MediaFlags
+    @Mock private lateinit var smartspaceData: SmartspaceMediaData
 
     @Before
     fun setup() {
-        `when`(mediaControllerFactory.create(any())).thenReturn(mediaController)
+        whenever(mediaControllerFactory.create(any())).thenReturn(mediaController)
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
         executor = FakeExecutor(clock)
         mediaTimeoutListener =
             MediaTimeoutListener(
@@ -96,7 +102,8 @@
                 executor,
                 logger,
                 statusBarStateController,
-                clock
+                clock,
+                mediaFlags,
             )
         mediaTimeoutListener.timeoutCallback = timeoutCallback
         mediaTimeoutListener.stateCallback = stateCallback
@@ -133,9 +140,9 @@
     @Test
     fun testOnMediaDataLoaded_registersPlaybackListener() {
         val playingState = mock(android.media.session.PlaybackState::class.java)
-        `when`(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
+        whenever(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
 
-        `when`(mediaController.playbackState).thenReturn(playingState)
+        whenever(mediaController.playbackState).thenReturn(playingState)
         mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
         verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
         verify(logger).logPlaybackState(eq(KEY), eq(playingState))
@@ -188,8 +195,8 @@
 
         // To playing
         val playingState = mock(android.media.session.PlaybackState::class.java)
-        `when`(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
-        `when`(mediaController.playbackState).thenReturn(playingState)
+        whenever(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
+        whenever(mediaController.playbackState).thenReturn(playingState)
         mediaTimeoutListener.onMediaDataLoaded(newKey, KEY, mediaData)
         verify(mediaController).unregisterCallback(anyObject())
         verify(mediaController).registerCallback(anyObject())
@@ -208,8 +215,8 @@
 
         // Migrate, still not playing
         val playingState = mock(android.media.session.PlaybackState::class.java)
-        `when`(playingState.state).thenReturn(PlaybackState.STATE_PAUSED)
-        `when`(mediaController.playbackState).thenReturn(playingState)
+        whenever(playingState.state).thenReturn(PlaybackState.STATE_PAUSED)
+        whenever(mediaController.playbackState).thenReturn(playingState)
         mediaTimeoutListener.onMediaDataLoaded(newKey, KEY, mediaData)
 
         // The number of queued timeout tasks remains the same. The timeout task isn't cancelled nor
@@ -296,8 +303,8 @@
 
         // WHEN we get an update with media playing
         val playingState = mock(android.media.session.PlaybackState::class.java)
-        `when`(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
-        `when`(mediaController.playbackState).thenReturn(playingState)
+        whenever(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
+        whenever(mediaController.playbackState).thenReturn(playingState)
         val mediaPlaying = mediaData.copy(isPlaying = true)
         mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaPlaying)
 
@@ -347,7 +354,7 @@
         // WHEN regular media is paused
         val pausedState =
             PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()
-        `when`(mediaController.playbackState).thenReturn(pausedState)
+        whenever(mediaController.playbackState).thenReturn(pausedState)
         mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
         assertThat(executor.numPending()).isEqualTo(1)
 
@@ -379,7 +386,7 @@
         // AND that media is resumed
         val playingState =
             PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()
-        `when`(mediaController.playbackState).thenReturn(playingState)
+        whenever(mediaController.playbackState).thenReturn(playingState)
         mediaTimeoutListener.onMediaDataLoaded(KEY, PACKAGE, mediaData)
 
         // THEN the timeout length is changed to a regular media control
@@ -593,8 +600,91 @@
         assertThat(executor.numPending()).isEqualTo(1)
     }
 
+    @Test
+    fun testSmartspaceDataLoaded_schedulesTimeout() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+        val duration = 60_000
+        val createTime = 1234L
+        val expireTime = createTime + duration
+        whenever(smartspaceData.headphoneConnectionTimeMillis).thenReturn(createTime)
+        whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
+
+        mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(executor.advanceClockToNext()).isEqualTo(duration)
+    }
+
+    @Test
+    fun testSmartspaceMediaData_timesOut_invokesCallback() {
+        // Given a pending timeout
+        testSmartspaceDataLoaded_schedulesTimeout()
+
+        executor.runAllReady()
+        verify(timeoutCallback).invoke(eq(SMARTSPACE_KEY), eq(true))
+    }
+
+    @Test
+    fun testSmartspaceDataLoaded_alreadyExists_updatesTimeout() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+        val duration = 100
+        val createTime = 1234L
+        val expireTime = createTime + duration
+        whenever(smartspaceData.headphoneConnectionTimeMillis).thenReturn(createTime)
+        whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
+
+        mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+        assertThat(executor.numPending()).isEqualTo(1)
+
+        val expiryLonger = expireTime + duration
+        whenever(smartspaceData.expiryTimeMs).thenReturn(expiryLonger)
+        mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+
+        assertThat(executor.numPending()).isEqualTo(1)
+        assertThat(executor.advanceClockToNext()).isEqualTo(duration * 2)
+    }
+
+    @Test
+    fun testSmartspaceDataRemoved_cancelTimeout() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+
+        mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+        assertThat(executor.numPending()).isEqualTo(1)
+
+        mediaTimeoutListener.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
+        assertThat(executor.numPending()).isEqualTo(0)
+    }
+
+    @Test
+    fun testSmartspaceData_dozedPastTimeout_invokedOnWakeup() {
+        // Given a pending timeout
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+        verify(statusBarStateController).addCallback(capture(dozingCallbackCaptor))
+        val duration = 60_000
+        val createTime = 1234L
+        val expireTime = createTime + duration
+        whenever(smartspaceData.headphoneConnectionTimeMillis).thenReturn(createTime)
+        whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
+
+        mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+        assertThat(executor.numPending()).isEqualTo(1)
+
+        // And we doze past the scheduled timeout
+        val time = clock.currentTimeMillis()
+        clock.setElapsedRealtime(time + duration * 2)
+        assertThat(executor.numPending()).isEqualTo(1)
+
+        // Then when no longer dozing, the timeout runs immediately
+        dozingCallbackCaptor.value.onDozingChanged(false)
+        verify(timeoutCallback).invoke(eq(SMARTSPACE_KEY), eq(true))
+        verify(logger).logTimeout(eq(SMARTSPACE_KEY))
+
+        // and cancel any later scheduled timeout
+        assertThat(executor.numPending()).isEqualTo(0)
+    }
+
     private fun loadMediaDataWithPlaybackState(state: PlaybackState) {
-        `when`(mediaController.playbackState).thenReturn(state)
+        whenever(mediaController.playbackState).thenReturn(state)
         mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
         verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
index 5e5dc8b..997198e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
@@ -21,12 +21,20 @@
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.util.MathUtils.abs
+import android.view.View
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.InstanceId
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.media.controls.MediaTestUtils
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
@@ -47,7 +55,11 @@
 import com.android.systemui.util.time.FakeSystemClock
 import javax.inject.Provider
 import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertTrue
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Ignore
 import org.junit.Test
@@ -89,11 +101,15 @@
     @Mock lateinit var mediaCarousel: MediaScrollView
     @Mock lateinit var pageIndicator: PageIndicator
     @Mock lateinit var mediaFlags: MediaFlags
+    @Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    @Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+    private lateinit var transitionRepository: FakeKeyguardTransitionRepository
     @Captor lateinit var listener: ArgumentCaptor<MediaDataManager.Listener>
     @Captor
     lateinit var configListener: ArgumentCaptor<ConfigurationController.ConfigurationListener>
     @Captor lateinit var newConfig: ArgumentCaptor<Configuration>
     @Captor lateinit var visualStabilityCallback: ArgumentCaptor<OnReorderingAllowedListener>
+    @Captor lateinit var keyguardCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
 
     private val clock = FakeSystemClock()
     private lateinit var mediaCarouselController: MediaCarouselController
@@ -101,6 +117,7 @@
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
+        transitionRepository = FakeKeyguardTransitionRepository()
         mediaCarouselController =
             MediaCarouselController(
                 context,
@@ -118,14 +135,18 @@
                 logger,
                 debugLogger,
                 mediaFlags,
+                keyguardUpdateMonitor,
+                KeyguardTransitionInteractor(repository = transitionRepository),
             )
         verify(configurationController).addCallback(capture(configListener))
         verify(mediaDataManager).addListener(capture(listener))
         verify(visualStabilityProvider)
             .addPersistentReorderingAllowedListener(capture(visualStabilityCallback))
+        verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCallback))
         whenever(mediaControlPanelFactory.get()).thenReturn(panel)
         whenever(panel.mediaViewController).thenReturn(mediaViewController)
         whenever(mediaDataManager.smartspaceMediaData).thenReturn(smartspaceMediaData)
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
         MediaPlayerData.clear()
     }
 
@@ -703,4 +724,76 @@
             mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
         )
     }
+
+    @Test
+    fun testRecommendation_persistentEnabled_newSmartspaceLoaded_updatesSort() {
+        testRecommendation_persistentEnabled_inactiveSmartspaceDataLoaded_isAdded()
+
+        // When an update to existing smartspace data is loaded
+        listener.value.onSmartspaceMediaDataLoaded(
+            SMARTSPACE_KEY,
+            EMPTY_SMARTSPACE_MEDIA_DATA.copy(isActive = true),
+            true
+        )
+
+        // Then the carousel is updated
+        assertTrue(MediaPlayerData.playerKeys().elementAt(0).data.active)
+        assertTrue(MediaPlayerData.visiblePlayerKeys().elementAt(0).data.active)
+    }
+
+    @Test
+    fun testRecommendation_persistentEnabled_inactiveSmartspaceDataLoaded_isAdded() {
+        whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
+
+        // When inactive smartspace data is loaded
+        listener.value.onSmartspaceMediaDataLoaded(
+            SMARTSPACE_KEY,
+            EMPTY_SMARTSPACE_MEDIA_DATA,
+            false
+        )
+
+        // Then it is added to the carousel with correct state
+        assertTrue(MediaPlayerData.playerKeys().elementAt(0).isSsMediaRec)
+        assertFalse(MediaPlayerData.playerKeys().elementAt(0).data.active)
+
+        assertTrue(MediaPlayerData.visiblePlayerKeys().elementAt(0).isSsMediaRec)
+        assertFalse(MediaPlayerData.visiblePlayerKeys().elementAt(0).data.active)
+    }
+
+    @Test
+    fun testOnLockDownMode_hideMediaCarousel() {
+        whenever(keyguardUpdateMonitor.isUserInLockdown(context.userId)).thenReturn(true)
+        mediaCarouselController.mediaCarousel = mediaCarousel
+
+        keyguardCallback.value.onStrongAuthStateChanged(context.userId)
+
+        verify(mediaCarousel).visibility = View.GONE
+    }
+
+    @Test
+    fun testLockDownModeOff_showMediaCarousel() {
+        whenever(keyguardUpdateMonitor.isUserInLockdown(context.userId)).thenReturn(false)
+        whenever(keyguardUpdateMonitor.isUserUnlocked(context.userId)).thenReturn(true)
+        mediaCarouselController.mediaCarousel = mediaCarousel
+
+        keyguardCallback.value.onStrongAuthStateChanged(context.userId)
+
+        verify(mediaCarousel).visibility = View.VISIBLE
+    }
+
+    @ExperimentalCoroutinesApi
+    @Test
+    fun testKeyguardGone_showMediaCarousel() =
+        runTest(UnconfinedTestDispatcher()) {
+            mediaCarouselController.mediaCarousel = mediaCarousel
+
+            val job = mediaCarouselController.listenForAnyStateToGoneKeyguardTransition(this)
+            transitionRepository.sendTransitionStep(
+                TransitionStep(to = KeyguardState.GONE, transitionState = TransitionState.FINISHED)
+            )
+
+            verify(mediaCarousel).visibility = View.VISIBLE
+
+            job.cancel()
+        }
 }
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 ce22b19..55a33b6 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
@@ -52,6 +52,7 @@
 import androidx.constraintlayout.widget.Barrier
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.lifecycle.LiveData
+import androidx.media.utils.MediaConstants
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.InstanceId
 import com.android.internal.widget.CachingIconView
@@ -206,6 +207,12 @@
     @Mock private lateinit var coverContainer3: ViewGroup
     @Mock private lateinit var recAppIconItem: CachingIconView
     @Mock private lateinit var recCardTitle: TextView
+    @Mock private lateinit var recProgressBar1: SeekBar
+    @Mock private lateinit var recProgressBar2: SeekBar
+    @Mock private lateinit var recProgressBar3: SeekBar
+    @Mock private lateinit var recSubtitleMock1: TextView
+    @Mock private lateinit var recSubtitleMock2: TextView
+    @Mock private lateinit var recSubtitleMock3: TextView
     @Mock private lateinit var coverItem: ImageView
     private lateinit var coverItem1: ImageView
     private lateinit var coverItem2: ImageView
@@ -906,6 +913,17 @@
     }
 
     @Test
+    fun bind_resumeState_withProgress() {
+        val progress = 0.5
+        val state = mediaData.copy(resumption = true, resumeProgress = progress)
+
+        player.attachPlayer(viewHolder)
+        player.bindPlayer(state, PACKAGE)
+
+        verify(seekBarViewModel).updateStaticProgress(progress)
+    }
+
+    @Test
     fun bindNotificationActions() {
         val icon = context.getDrawable(android.R.drawable.ic_media_play)
         val bg = context.getDrawable(R.drawable.qs_media_round_button_background)
@@ -2070,6 +2088,10 @@
         whenever(recommendationViewHolder.cardTitle).thenReturn(recCardTitle)
         whenever(recommendationViewHolder.mediaCoverItems)
             .thenReturn(listOf(coverItem, coverItem, coverItem))
+        whenever(recommendationViewHolder.mediaProgressBars)
+            .thenReturn(listOf(recProgressBar1, recProgressBar2, recProgressBar3))
+        whenever(recommendationViewHolder.mediaSubtitles)
+            .thenReturn(listOf(recSubtitleMock1, recSubtitleMock2, recSubtitleMock3))
 
         val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
         val canvas = Canvas(bmp)
@@ -2108,6 +2130,65 @@
     }
 
     @Test
+    fun bindRecommendationWithProgressBars() {
+        fakeFeatureFlag.set(Flags.MEDIA_RECOMMENDATION_CARD_UPDATE, true)
+        whenever(recommendationViewHolder.mediaAppIcons)
+            .thenReturn(listOf(recAppIconItem, recAppIconItem, recAppIconItem))
+        whenever(recommendationViewHolder.cardTitle).thenReturn(recCardTitle)
+        whenever(recommendationViewHolder.mediaCoverItems)
+            .thenReturn(listOf(coverItem, coverItem, coverItem))
+        whenever(recommendationViewHolder.mediaProgressBars)
+            .thenReturn(listOf(recProgressBar1, recProgressBar2, recProgressBar3))
+        whenever(recommendationViewHolder.mediaSubtitles)
+            .thenReturn(listOf(recSubtitleMock1, recSubtitleMock2, recSubtitleMock3))
+
+        val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+        val canvas = Canvas(bmp)
+        canvas.drawColor(Color.RED)
+        val albumArt = Icon.createWithBitmap(bmp)
+        val bundle =
+            Bundle().apply {
+                putInt(
+                    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS,
+                    MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED
+                )
+                putDouble(MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.5)
+            }
+        val data =
+            smartspaceData.copy(
+                recommendations =
+                    listOf(
+                        SmartspaceAction.Builder("id1", "title1")
+                            .setSubtitle("subtitle1")
+                            .setIcon(albumArt)
+                            .setExtras(bundle)
+                            .build(),
+                        SmartspaceAction.Builder("id2", "title2")
+                            .setSubtitle("subtitle1")
+                            .setIcon(albumArt)
+                            .setExtras(Bundle.EMPTY)
+                            .build(),
+                        SmartspaceAction.Builder("id3", "title3")
+                            .setSubtitle("subtitle1")
+                            .setIcon(albumArt)
+                            .setExtras(Bundle.EMPTY)
+                            .build()
+                    )
+            )
+
+        player.attachRecommendation(recommendationViewHolder)
+        player.bindRecommendation(data)
+
+        verify(recProgressBar1).setProgress(50)
+        verify(recProgressBar1).visibility = View.VISIBLE
+        verify(recProgressBar2).visibility = View.GONE
+        verify(recProgressBar3).visibility = View.GONE
+        verify(recSubtitleMock1).visibility = View.GONE
+        verify(recSubtitleMock2).visibility = View.VISIBLE
+        verify(recSubtitleMock3).visibility = View.VISIBLE
+    }
+
+    @Test
     fun onButtonClick_touchRippleFlagEnabled_playsTouchRipple() {
         fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
         val semanticActions =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 5564774..56e060d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -16,7 +16,11 @@
 
 package com.android.systemui.media.dialog;
 
-import static android.media.RouteListingPreference.Item.DISABLE_REASON_SUBSCRIPTION_REQUIRED;
+import static android.media.RouteListingPreference.Item.SELECTION_BEHAVIOR_GO_TO_APP;
+import static android.media.RouteListingPreference.Item.SELECTION_BEHAVIOR_NONE;
+import static android.media.RouteListingPreference.Item.SUBTEXT_AD_ROUTING_DISALLOWED;
+import static android.media.RouteListingPreference.Item.SUBTEXT_CUSTOM;
+import static android.media.RouteListingPreference.Item.SUBTEXT_SUBSCRIPTION_REQUIRED;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -62,6 +66,7 @@
     private static final String TEST_DEVICE_ID_1 = "test_device_id_1";
     private static final String TEST_DEVICE_ID_2 = "test_device_id_2";
     private static final String TEST_SESSION_NAME = "test_session_name";
+    private static final String TEST_CUSTOM_SUBTEXT = "custom subtext";
 
     private static final int TEST_MAX_VOLUME = 20;
     private static final int TEST_CURRENT_VOLUME = 10;
@@ -431,12 +436,46 @@
     }
 
     @Test
-    public void subStatusSupported_onBindViewHolder_bindFailedStateDevice_verifyView() {
+    public void subStatusSupported_onBindViewHolder_bindHostDeviceWithOngoingSession_verifyView() {
+        when(mMediaOutputController.isSubStatusSupported()).thenReturn(true);
+        when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
+        when(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(true);
+        when(mMediaDevice1.isHostForOngoingSession()).thenReturn(true);
+        when(mMediaDevice1.hasSubtext()).thenReturn(true);
+        when(mMediaDevice1.getSubtext()).thenReturn(SUBTEXT_CUSTOM);
+        when(mMediaDevice1.getSubtextString()).thenReturn(TEST_CUSTOM_SUBTEXT);
+        when(mMediaDevice1.hasOngoingSession()).thenReturn(true);
+        when(mMediaDevice1.getSelectionBehavior()).thenReturn(SELECTION_BEHAVIOR_GO_TO_APP);
+        mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
+                .onCreateViewHolder(new LinearLayout(mContext), 0);
+        mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mEndClickIcon.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(TEST_CUSTOM_SUBTEXT);
+        assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
+                TEST_DEVICE_NAME_1);
+        assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isFalse();
+    }
+
+    @Test
+    public void subStatusSupported_onBindViewHolder_bindDeviceRequirePremium_verifyView() {
         String deviceStatus = (String) mContext.getText(
                 R.string.media_output_status_require_premium);
         when(mMediaOutputController.isSubStatusSupported()).thenReturn(true);
-        when(mMediaDevice2.hasDisabledReason()).thenReturn(true);
-        when(mMediaDevice2.getDisableReason()).thenReturn(DISABLE_REASON_SUBSCRIPTION_REQUIRED);
+        when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
+        when(mMediaDevice2.hasSubtext()).thenReturn(true);
+        when(mMediaDevice2.getSubtext()).thenReturn(SUBTEXT_SUBSCRIPTION_REQUIRED);
+        when(mMediaDevice2.getSubtextString()).thenReturn(deviceStatus);
+        when(mMediaDevice2.getSelectionBehavior()).thenReturn(SELECTION_BEHAVIOR_GO_TO_APP);
+        mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
+                .onCreateViewHolder(new LinearLayout(mContext), 0);
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
 
         assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
@@ -444,9 +483,64 @@
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(deviceStatus);
         assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2);
+        assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isTrue();
+    }
+
+    @Test
+    public void subStatusSupported_onBindViewHolder_bindDeviceWithAdPlaying_verifyView() {
+        String deviceStatus = (String) mContext.getText(
+                R.string.media_output_status_try_after_ad);
+        when(mMediaOutputController.isSubStatusSupported()).thenReturn(true);
+        when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
+        when(mMediaDevice2.hasSubtext()).thenReturn(true);
+        when(mMediaDevice2.getSubtext()).thenReturn(SUBTEXT_AD_ROUTING_DISALLOWED);
+        when(mMediaDevice2.getSubtextString()).thenReturn(deviceStatus);
+        when(mMediaDevice2.getSelectionBehavior()).thenReturn(SELECTION_BEHAVIOR_NONE);
+        mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
+                .onCreateViewHolder(new LinearLayout(mContext), 0);
+        mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
+
+        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(deviceStatus);
+        assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
+                TEST_DEVICE_NAME_2);
+        assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isFalse();
+    }
+
+    @Test
+    public void subStatusSupported_onBindViewHolder_bindDeviceWithOngoingSession_verifyView() {
+        when(mMediaOutputController.isSubStatusSupported()).thenReturn(true);
+        when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(true);
+        when(mMediaDevice1.hasSubtext()).thenReturn(true);
+        when(mMediaDevice1.getSubtext()).thenReturn(SUBTEXT_CUSTOM);
+        when(mMediaDevice1.getSubtextString()).thenReturn(TEST_CUSTOM_SUBTEXT);
+        when(mMediaDevice1.hasOngoingSession()).thenReturn(true);
+        when(mMediaDevice1.getSelectionBehavior()).thenReturn(SELECTION_BEHAVIOR_GO_TO_APP);
+        mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
+                .onCreateViewHolder(new LinearLayout(mContext), 0);
+        mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(TEST_CUSTOM_SUBTEXT);
+        assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
+                TEST_DEVICE_NAME_1);
+        assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isTrue();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 7c36e46..0bdcaf4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -240,7 +240,6 @@
         verify(mMediaController, never()).unregisterCallback(any());
     }
 
-
     @Test
     public void stop_nearbyMediaDevicesManagerNotNull_unregistersNearbyDevicesCallback() {
         mMediaOutputController.start(mCb);
@@ -253,7 +252,7 @@
 
     @Test
     public void tryToLaunchMediaApplication_nullIntent_skip() {
-        mMediaOutputController.tryToLaunchMediaApplication();
+        mMediaOutputController.tryToLaunchMediaApplication(mDialogLaunchView);
 
         verify(mCb, never()).dismissDialog();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index 31866a8..9ecc63c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -36,6 +36,7 @@
 import android.os.PowerExemptionManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.util.FeatureFlagUtils;
 import android.view.View;
 
 import androidx.test.filters.SmallTest;
@@ -171,6 +172,8 @@
                 mLocalBluetoothLeBroadcast);
         when(mLocalBluetoothLeBroadcast.isEnabled(any())).thenReturn(false);
         when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_PLAYING);
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
         when(mMediaDevice.isBLEDevice()).thenReturn(false);
 
         assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.GONE);
@@ -184,6 +187,62 @@
     }
 
     @Test
+    public void isBroadcastSupported_flagOnAndConnectBleDevice_returnsTrue() {
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+        when(mLocalBluetoothLeBroadcast.isEnabled(any())).thenReturn(false);
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
+        when(mMediaDevice.isBLEDevice()).thenReturn(true);
+
+        assertThat(mMediaOutputDialog.isBroadcastSupported()).isTrue();
+    }
+
+    @Test
+    public void isBroadcastSupported_flagOnAndNoBleDevice_returnsFalse() {
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+        when(mLocalBluetoothLeBroadcast.isEnabled(any())).thenReturn(false);
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
+        when(mMediaDevice.isBLEDevice()).thenReturn(false);
+
+        assertThat(mMediaOutputDialog.isBroadcastSupported()).isFalse();
+    }
+
+    @Test
+    public void isBroadcastSupported_notSupportBroadcastAndflagOn_returnsFalse() {
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, true);
+
+        assertThat(mMediaOutputDialog.isBroadcastSupported()).isFalse();
+    }
+
+    @Test
+    public void isBroadcastSupported_flagOffAndConnectToBleDevice_returnsTrue() {
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+        when(mLocalBluetoothLeBroadcast.isEnabled(any())).thenReturn(false);
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, false);
+        when(mMediaDevice.isBLEDevice()).thenReturn(true);
+
+        assertThat(mMediaOutputDialog.isBroadcastSupported()).isTrue();
+    }
+
+    @Test
+    public void isBroadcastSupported_flagOffAndNoBleDevice_returnsTrue() {
+        when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
+                mLocalBluetoothLeBroadcast);
+        when(mLocalBluetoothLeBroadcast.isEnabled(any())).thenReturn(false);
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_NEED_CONNECTED_BLE_DEVICE_FOR_BROADCAST, false);
+        when(mMediaDevice.isBLEDevice()).thenReturn(false);
+
+        assertThat(mMediaOutputDialog.isBroadcastSupported()).isTrue();
+    }
+
+    @Test
     public void getBroadcastIconVisibility_isBroadcasting_returnVisible() {
         when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(
                 mLocalBluetoothLeBroadcast);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
index 8055b98..4fc9ca7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
@@ -65,7 +65,13 @@
 
     @Test
     fun getIconInfoFromPackageName_nullPackageName_returnsDefault() {
-        val iconInfo = MediaTttUtils.getIconInfoFromPackageName(context, appPackageName = null) {}
+        val iconInfo =
+            MediaTttUtils.getIconInfoFromPackageName(
+                context,
+                appPackageName = null,
+                isReceiver = false,
+            ) {
+            }
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -74,10 +80,32 @@
     }
 
     @Test
+    fun getIconInfoFromPackageName_nullPackageName_isReceiver_returnsDefault() {
+        val iconInfo =
+            MediaTttUtils.getIconInfoFromPackageName(
+                context,
+                appPackageName = null,
+                isReceiver = true,
+            ) {
+            }
+
+        assertThat(iconInfo.isAppIcon).isFalse()
+        assertThat(iconInfo.contentDescription.loadContentDescription(context))
+            .isEqualTo(
+                context.getString(R.string.media_transfer_receiver_content_description_unknown_app)
+            )
+        assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Resource(R.drawable.ic_cast))
+    }
+
+    @Test
     fun getIconInfoFromPackageName_nullPackageName_exceptionFnNotTriggered() {
         var exceptionTriggered = false
 
-        MediaTttUtils.getIconInfoFromPackageName(context, appPackageName = null) {
+        MediaTttUtils.getIconInfoFromPackageName(
+            context,
+            appPackageName = null,
+            isReceiver = false,
+        ) {
             exceptionTriggered = true
         }
 
@@ -86,7 +114,13 @@
 
     @Test
     fun getIconInfoFromPackageName_invalidPackageName_returnsDefault() {
-        val iconInfo = MediaTttUtils.getIconInfoFromPackageName(context, "fakePackageName") {}
+        val iconInfo =
+            MediaTttUtils.getIconInfoFromPackageName(
+                context,
+                appPackageName = "fakePackageName",
+                isReceiver = false,
+            ) {
+            }
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -95,19 +129,58 @@
     }
 
     @Test
+    fun getIconInfoFromPackageName_invalidPackageName_isReceiver_returnsDefault() {
+        val iconInfo =
+            MediaTttUtils.getIconInfoFromPackageName(
+                context,
+                appPackageName = "fakePackageName",
+                isReceiver = true,
+            ) {
+            }
+
+        assertThat(iconInfo.isAppIcon).isFalse()
+        assertThat(iconInfo.contentDescription.loadContentDescription(context))
+            .isEqualTo(
+                context.getString(R.string.media_transfer_receiver_content_description_unknown_app)
+            )
+        assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Resource(R.drawable.ic_cast))
+    }
+
+    @Test
     fun getIconInfoFromPackageName_invalidPackageName_exceptionFnTriggered() {
         var exceptionTriggered = false
 
-        MediaTttUtils.getIconInfoFromPackageName(context, appPackageName = "fakePackageName") {
-            exceptionTriggered = true
-        }
+        MediaTttUtils.getIconInfoFromPackageName(
+            context,
+            appPackageName = "fakePackageName",
+            isReceiver = false
+        ) { exceptionTriggered = true }
+
+        assertThat(exceptionTriggered).isTrue()
+    }
+
+    @Test
+    fun getIconInfoFromPackageName_invalidPackageName_isReceiver_exceptionFnTriggered() {
+        var exceptionTriggered = false
+
+        MediaTttUtils.getIconInfoFromPackageName(
+            context,
+            appPackageName = "fakePackageName",
+            isReceiver = true
+        ) { exceptionTriggered = true }
 
         assertThat(exceptionTriggered).isTrue()
     }
 
     @Test
     fun getIconInfoFromPackageName_validPackageName_returnsAppInfo() {
-        val iconInfo = MediaTttUtils.getIconInfoFromPackageName(context, PACKAGE_NAME) {}
+        val iconInfo =
+            MediaTttUtils.getIconInfoFromPackageName(
+                context,
+                PACKAGE_NAME,
+                isReceiver = false,
+            ) {
+            }
 
         assertThat(iconInfo.isAppIcon).isTrue()
         assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
@@ -115,10 +188,42 @@
     }
 
     @Test
+    fun getIconInfoFromPackageName_validPackageName_isReceiver_returnsAppInfo() {
+        val iconInfo =
+            MediaTttUtils.getIconInfoFromPackageName(
+                context,
+                PACKAGE_NAME,
+                isReceiver = true,
+            ) {
+            }
+
+        assertThat(iconInfo.isAppIcon).isTrue()
+        assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
+        assertThat(iconInfo.contentDescription.loadContentDescription(context))
+            .isEqualTo(
+                context.getString(
+                    R.string.media_transfer_receiver_content_description_with_app_name,
+                    APP_NAME
+                )
+            )
+    }
+
+    @Test
     fun getIconInfoFromPackageName_validPackageName_exceptionFnNotTriggered() {
         var exceptionTriggered = false
 
-        MediaTttUtils.getIconInfoFromPackageName(context, PACKAGE_NAME) {
+        MediaTttUtils.getIconInfoFromPackageName(context, PACKAGE_NAME, isReceiver = false) {
+            exceptionTriggered = true
+        }
+
+        assertThat(exceptionTriggered).isFalse()
+    }
+
+    @Test
+    fun getIconInfoFromPackageName_validPackageName_isReceiver_exceptionFnNotTriggered() {
+        var exceptionTriggered = false
+
+        MediaTttUtils.getIconInfoFromPackageName(context, PACKAGE_NAME, isReceiver = true) {
             exceptionTriggered = true
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
index dba2da7..19dd2f0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
@@ -354,7 +354,11 @@
 
         val view = getChipView()
         assertThat(view.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable)
-        assertThat(view.getAppIconView().contentDescription).isEqualTo(APP_NAME)
+        assertThat(view.getAppIconView().contentDescription)
+            .isEqualTo(context.getString(
+                R.string.media_transfer_receiver_content_description_with_app_name,
+                APP_NAME,
+            ))
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
index c63ca3d..db890f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
@@ -45,6 +45,7 @@
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.temporarydisplay.TemporaryViewDisplayController
+import com.android.systemui.temporarydisplay.chipbar.ChipbarAnimator
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
 import com.android.systemui.temporarydisplay.chipbar.ChipbarLogger
 import com.android.systemui.temporarydisplay.chipbar.SwipeChipbarAwayGestureHandler
@@ -145,6 +146,7 @@
                 configurationController,
                 dumpManager,
                 powerManager,
+                ChipbarAnimator(),
                 falsingManager,
                 falsingCollector,
                 swipeHandler,
@@ -622,7 +624,7 @@
     }
 
     @Test
-    fun commandQueueCallback_receiverSucceededThenReceiverTriggered_invalidTransitionLogged() {
+    fun commandQueueCallback_receiverSucceededThenThisDeviceSucceeded_invalidTransitionLogged() {
         displayReceiverTriggered()
         commandQueueCallback.updateMediaTapToTransferSenderDisplay(
             StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
@@ -632,7 +634,7 @@
         reset(windowManager)
 
         commandQueueCallback.updateMediaTapToTransferSenderDisplay(
-            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
+            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
             routeInfo,
             null
         )
@@ -642,7 +644,7 @@
     }
 
     @Test
-    fun commandQueueCallback_thisDeviceSucceededThenThisDeviceTriggered_invalidTransitionLogged() {
+    fun commandQueueCallback_thisDeviceSucceededThenReceiverSucceeded_invalidTransitionLogged() {
         displayThisDeviceTriggered()
         commandQueueCallback.updateMediaTapToTransferSenderDisplay(
             StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
@@ -652,7 +654,7 @@
         reset(windowManager)
 
         commandQueueCallback.updateMediaTapToTransferSenderDisplay(
-            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
+            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
             routeInfo,
             null
         )
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 1042ea7..4977775 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
@@ -24,6 +24,8 @@
     private val taskListProvider = TestRecentTaskListProvider()
     private val scope = CoroutineScope(Dispatchers.Unconfined)
     private val appSelectorComponentName = ComponentName("com.test", "AppSelector")
+    private val callerPackageName = "com.test.caller"
+    private val callerComponentName = ComponentName(callerPackageName, "Caller")
 
     private val hostUserHandle = UserHandle.of(123)
     private val otherUserHandle = UserHandle.of(456)
@@ -31,14 +33,16 @@
     private val view: MediaProjectionAppSelectorView = mock()
     private val featureFlags: FeatureFlags = mock()
 
-    private val controller = MediaProjectionAppSelectorController(
-        taskListProvider,
-        view,
-        featureFlags,
-        hostUserHandle,
-        scope,
-        appSelectorComponentName
-    )
+    private val controller =
+        MediaProjectionAppSelectorController(
+            taskListProvider,
+            view,
+            featureFlags,
+            hostUserHandle,
+            scope,
+            appSelectorComponentName,
+            callerPackageName
+        )
 
     @Test
     fun initNoRecentTasks_bindsEmptyList() {
@@ -51,104 +55,87 @@
 
     @Test
     fun initOneRecentTask_bindsList() {
-        taskListProvider.tasks = listOf(
-            createRecentTask(taskId = 1)
-        )
+        taskListProvider.tasks = listOf(createRecentTask(taskId = 1))
 
         controller.init()
 
-        verify(view).bind(
-            listOf(
-                createRecentTask(taskId = 1)
-            )
-        )
+        verify(view).bind(listOf(createRecentTask(taskId = 1)))
     }
 
     @Test
     fun initMultipleRecentTasksWithoutAppSelectorTask_bindsListInTheSameOrder() {
-        val tasks = listOf(
-            createRecentTask(taskId = 1),
-            createRecentTask(taskId = 2),
-            createRecentTask(taskId = 3),
-        )
-        taskListProvider.tasks = tasks
-
-        controller.init()
-
-        verify(view).bind(
+        val tasks =
             listOf(
                 createRecentTask(taskId = 1),
                 createRecentTask(taskId = 2),
                 createRecentTask(taskId = 3),
             )
-        )
-    }
-
-    @Test
-    fun initRecentTasksWithAppSelectorTasks_bindsAppSelectorTasksAtTheEnd() {
-        val tasks = listOf(
-            createRecentTask(taskId = 1),
-            createRecentTask(taskId = 2, topActivityComponent = appSelectorComponentName),
-            createRecentTask(taskId = 3),
-            createRecentTask(taskId = 4, topActivityComponent = appSelectorComponentName),
-            createRecentTask(taskId = 5),
-        )
         taskListProvider.tasks = tasks
 
         controller.init()
 
-        verify(view).bind(
+        verify(view)
+            .bind(
+                listOf(
+                    createRecentTask(taskId = 1),
+                    createRecentTask(taskId = 2),
+                    createRecentTask(taskId = 3),
+                )
+            )
+    }
+
+    @Test
+    fun initRecentTasksWithAppSelectorTasks_removeAppSelector() {
+        val tasks =
             listOf(
                 createRecentTask(taskId = 1),
-                createRecentTask(taskId = 3),
-                createRecentTask(taskId = 5),
                 createRecentTask(taskId = 2, topActivityComponent = appSelectorComponentName),
-                createRecentTask(taskId = 4, topActivityComponent = appSelectorComponentName),
+                createRecentTask(taskId = 3),
+                createRecentTask(taskId = 4),
             )
-        )
+        taskListProvider.tasks = tasks
+
+        controller.init()
+
+        verify(view)
+            .bind(
+                listOf(
+                    createRecentTask(taskId = 1),
+                    createRecentTask(taskId = 3),
+                    createRecentTask(taskId = 4),
+                )
+            )
+    }
+
+    @Test
+    fun initRecentTasksWithAppSelectorTasks_bindsCallerTasksAtTheEnd() {
+        val tasks =
+            listOf(
+                createRecentTask(taskId = 1),
+                createRecentTask(taskId = 2, topActivityComponent = callerComponentName),
+                createRecentTask(taskId = 3),
+                createRecentTask(taskId = 4),
+            )
+        taskListProvider.tasks = tasks
+
+        controller.init()
+
+        verify(view)
+            .bind(
+                listOf(
+                    createRecentTask(taskId = 1),
+                    createRecentTask(taskId = 3),
+                    createRecentTask(taskId = 4),
+                    createRecentTask(taskId = 2, topActivityComponent = callerComponentName),
+                )
+            )
     }
 
     @Test
     fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesDisabled_bindsOnlyTasksWithHostProfile() {
         givenEnterprisePoliciesFeatureFlag(enabled = false)
 
-        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),
-        )
-        taskListProvider.tasks = tasks
-
-        controller.init()
-
-        verify(view).bind(
-            listOf(
-                createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
-                createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
-                createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
-            )
-        )
-    }
-
-    @Test
-    fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesEnabled_bindsAllTasks() {
-        givenEnterprisePoliciesFeatureFlag(enabled = true)
-
-        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),
-        )
-        taskListProvider.tasks = tasks
-
-        controller.init()
-
-        // TODO(b/233348916) should filter depending on the policies
-        verify(view).bind(
+        val tasks =
             listOf(
                 createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
                 createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
@@ -156,7 +143,47 @@
                 createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
                 createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
             )
-        )
+        taskListProvider.tasks = tasks
+
+        controller.init()
+
+        verify(view)
+            .bind(
+                listOf(
+                    createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
+                    createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
+                    createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
+                )
+            )
+    }
+
+    @Test
+    fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesEnabled_bindsAllTasks() {
+        givenEnterprisePoliciesFeatureFlag(enabled = true)
+
+        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),
+            )
+        taskListProvider.tasks = tasks
+
+        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),
+                )
+            )
     }
 
     private fun givenEnterprisePoliciesFeatureFlag(enabled: Boolean) {
@@ -183,6 +210,5 @@
         var tasks: List<RecentTask> = emptyList()
 
         override suspend fun loadRecentTasks(): List<RecentTask> = tasks
-
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/BlendTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/BlendTest.java
new file mode 100644
index 0000000..5b3419d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/BlendTest.java
@@ -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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.blend.Blend;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class BlendTest extends SysuiTestCase {
+    private static final int RED = 0xffff0000;
+    private static final int BLUE = 0xff0000ff;
+    private static final int GREEN = 0xff00ff00;
+    private static final int YELLOW = 0xffffff00;
+
+    @Test
+    public void harmonize_redToBlue() {
+        int blended = Blend.harmonize(RED, BLUE);
+        assertThat(blended).isSameColorAs(0xffFB0057);
+    }
+
+    @Test
+    public void harmonize_redToGreen() {
+        int answer = Blend.harmonize(RED, GREEN);
+        assertThat(answer).isSameColorAs(0xffD85600);
+    }
+
+    @Test
+    public void harmonize_redToYellow() {
+        int answer = Blend.harmonize(RED, YELLOW);
+        assertThat(answer).isSameColorAs(0xffD85600);
+    }
+
+    @Test
+    public void harmonize_blueToGreen() {
+        int answer = Blend.harmonize(BLUE, GREEN);
+        assertThat(answer).isSameColorAs(0xff0047A3);
+    }
+
+    @Test
+    public void harmonize_blueToRed() {
+        int answer = Blend.harmonize(BLUE, RED);
+        assertThat(answer).isSameColorAs(0xff5700DC);
+    }
+
+    @Test
+    public void harmonize_blueToYellow() {
+        int answer = Blend.harmonize(BLUE, YELLOW);
+        assertThat(answer).isSameColorAs(0xff0047A3);
+    }
+
+    @Test
+    public void harmonize_greenToBlue() {
+        int answer = Blend.harmonize(GREEN, BLUE);
+        assertThat(answer).isSameColorAs(0xff00FC94);
+    }
+
+    @Test
+    public void harmonize_greenToRed() {
+        int answer = Blend.harmonize(GREEN, RED);
+        assertThat(answer).isSameColorAs(0xffB1F000);
+    }
+
+    @Test
+    public void harmonize_greenToYellow() {
+        int answer = Blend.harmonize(GREEN, YELLOW);
+        assertThat(answer).isSameColorAs(0xffB1F000);
+    }
+
+    @Test
+    public void harmonize_yellowToBlue() {
+        int answer = Blend.harmonize(YELLOW, BLUE);
+        assertThat(answer).isSameColorAs(0xffEBFFBA);
+    }
+
+    @Test
+    public void harmonize_yellowToGreen() {
+        int answer = Blend.harmonize(YELLOW, GREEN);
+        assertThat(answer).isSameColorAs(0xffEBFFBA);
+    }
+
+    @Test
+    public void harmonize_yellowToRed() {
+        int answer = Blend.harmonize(YELLOW, RED);
+        assertThat(answer).isSameColorAs(0xffFFF6E3);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorUtilsTest.java
new file mode 100644
index 0000000..6a7f104
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorUtilsTest.java
@@ -0,0 +1,207 @@
+/*
+ * 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.monet;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.utils.ColorUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class ColorUtilsTest extends SysuiTestCase {
+
+    @Test
+    public void argbFromLab() {
+        assertThat(ColorUtils.argbFromLab(0.0, 0.0, 0.0)).isEqualTo(0xff000000);
+        assertThat(ColorUtils.argbFromLab(0.25, 0.0, 0.0)).isEqualTo(0xff010101);
+        assertThat(ColorUtils.argbFromLab(0.5, 0.0, 0.0)).isEqualTo(0xff020202);
+        assertThat(ColorUtils.argbFromLab(0.75, 0.0, 0.0)).isEqualTo(0xff030303);
+        assertThat(ColorUtils.argbFromLab(1.0, 0.0, 0.0)).isEqualTo(0xff040404);
+        assertThat(ColorUtils.argbFromLab(1.5, 0.0, 0.0)).isEqualTo(0xff050505);
+        assertThat(ColorUtils.argbFromLab(2.0, 0.0, 0.0)).isEqualTo(0xff070707);
+        assertThat(ColorUtils.argbFromLab(3.0, 0.0, 0.0)).isEqualTo(0xff0b0b0b);
+        assertThat(ColorUtils.argbFromLab(4.0, 0.0, 0.0)).isEqualTo(0xff0e0e0e);
+        assertThat(ColorUtils.argbFromLab(5.0, 0.0, 0.0)).isEqualTo(0xff111111);
+        assertThat(ColorUtils.argbFromLab(6.0, 0.0, 0.0)).isEqualTo(0xff131313);
+        assertThat(ColorUtils.argbFromLab(7.0, 0.0, 0.0)).isEqualTo(0xff151515);
+        assertThat(ColorUtils.argbFromLab(8.0, 0.0, 0.0)).isEqualTo(0xff181818);
+        assertThat(ColorUtils.argbFromLab(9.0, 0.0, 0.0)).isEqualTo(0xff191919);
+        assertThat(ColorUtils.argbFromLab(10.0, 0.0, 0.0)).isEqualTo(0xff1b1b1b);
+        assertThat(ColorUtils.argbFromLab(20.0, 0.0, 0.0)).isEqualTo(0xff303030);
+        assertThat(ColorUtils.argbFromLab(30.0, 0.0, 0.0)).isEqualTo(0xff474747);
+        assertThat(ColorUtils.argbFromLab(40.0, 0.0, 0.0)).isEqualTo(0xff5e5e5e);
+        assertThat(ColorUtils.argbFromLab(50.0, 0.0, 0.0)).isEqualTo(0xff777777);
+        assertThat(ColorUtils.argbFromLab(60.0, 0.0, 0.0)).isEqualTo(0xff919191);
+        assertThat(ColorUtils.argbFromLab(70.0, 0.0, 0.0)).isEqualTo(0xffababab);
+        assertThat(ColorUtils.argbFromLab(80.0, 0.0, 0.0)).isEqualTo(0xffc6c6c6);
+        assertThat(ColorUtils.argbFromLab(90.0, 0.0, 0.0)).isEqualTo(0xffe2e2e2);
+        assertThat(ColorUtils.argbFromLab(100.0, 0.0, 0.0)).isEqualTo(0xffffffff);
+    }
+
+    @Test
+    public void labFromArgb() {
+        assertThat(ColorUtils.labFromArgb(0xff000000)[0]).isWithin(0.001).of(0.0);
+        assertThat(ColorUtils.labFromArgb(0xff010101)[0]).isWithin(0.001).of(0.2741748000656514);
+        assertThat(ColorUtils.labFromArgb(0xff020202)[0]).isWithin(0.001).of(0.5483496001313029);
+        assertThat(ColorUtils.labFromArgb(0xff030303)[0]).isWithin(0.001).of(0.8225244001969543);
+        assertThat(ColorUtils.labFromArgb(0xff040404)[0]).isWithin(0.001).of(1.0966992002626057);
+        assertThat(ColorUtils.labFromArgb(0xff050505)[0]).isWithin(0.001).of(1.3708740003282571);
+        assertThat(ColorUtils.labFromArgb(0xff060606)[0]).isWithin(0.001).of(1.645048800393912);
+        assertThat(ColorUtils.labFromArgb(0xff070707)[0]).isWithin(0.001).of(1.9192236004595635);
+        assertThat(ColorUtils.labFromArgb(0xff080808)[0]).isWithin(0.001).of(2.193398400525215);
+        assertThat(ColorUtils.labFromArgb(0xff0c0c0c)[0]).isWithin(0.001).of(3.3209754491182544);
+        assertThat(ColorUtils.labFromArgb(0xff101010)[0]).isWithin(0.001).of(4.680444846419661);
+        assertThat(ColorUtils.labFromArgb(0xff181818)[0]).isWithin(0.001).of(8.248186036170349);
+        assertThat(ColorUtils.labFromArgb(0xff202020)[0]).isWithin(0.001).of(12.250030101522828);
+        assertThat(ColorUtils.labFromArgb(0xff404040)[0]).isWithin(0.001).of(27.093413739449055);
+        assertThat(ColorUtils.labFromArgb(0xff808080)[0]).isWithin(0.001).of(53.585013452169036);
+        assertThat(ColorUtils.labFromArgb(0xffffffff)[0]).isWithin(0.001).of(100.0);
+    }
+
+    @Test
+    public void argbFromLstar() {
+        assertThat(ColorUtils.argbFromLstar(0.0)).isEqualTo(0xff000000);
+        assertThat(ColorUtils.argbFromLstar(0.25)).isEqualTo(0xff010101);
+        assertThat(ColorUtils.argbFromLstar(0.5)).isEqualTo(0xff020202);
+        assertThat(ColorUtils.argbFromLstar(0.75)).isEqualTo(0xff030303);
+        assertThat(ColorUtils.argbFromLstar(1.0)).isEqualTo(0xff040404);
+        assertThat(ColorUtils.argbFromLstar(1.5)).isEqualTo(0xff050505);
+        assertThat(ColorUtils.argbFromLstar(2.0)).isEqualTo(0xff070707);
+        assertThat(ColorUtils.argbFromLstar(3.0)).isEqualTo(0xff0b0b0b);
+        assertThat(ColorUtils.argbFromLstar(4.0)).isEqualTo(0xff0e0e0e);
+        assertThat(ColorUtils.argbFromLstar(5.0)).isEqualTo(0xff111111);
+        assertThat(ColorUtils.argbFromLstar(6.0)).isEqualTo(0xff131313);
+        assertThat(ColorUtils.argbFromLstar(7.0)).isEqualTo(0xff151515);
+        assertThat(ColorUtils.argbFromLstar(8.0)).isEqualTo(0xff181818);
+        assertThat(ColorUtils.argbFromLstar(9.0)).isEqualTo(0xff191919);
+        assertThat(ColorUtils.argbFromLstar(10.0)).isEqualTo(0xff1b1b1b);
+        assertThat(ColorUtils.argbFromLstar(20.0)).isEqualTo(0xff303030);
+        assertThat(ColorUtils.argbFromLstar(30.0)).isEqualTo(0xff474747);
+        assertThat(ColorUtils.argbFromLstar(40.0)).isEqualTo(0xff5e5e5e);
+        assertThat(ColorUtils.argbFromLstar(50.0)).isEqualTo(0xff777777);
+        assertThat(ColorUtils.argbFromLstar(60.0)).isEqualTo(0xff919191);
+        assertThat(ColorUtils.argbFromLstar(70.0)).isEqualTo(0xffababab);
+        assertThat(ColorUtils.argbFromLstar(80.0)).isEqualTo(0xffc6c6c6);
+        assertThat(ColorUtils.argbFromLstar(90.0)).isEqualTo(0xffe2e2e2);
+        assertThat(ColorUtils.argbFromLstar(100.0)).isEqualTo(0xffffffff);
+    }
+
+    @Test
+    public void lstarFromArgb() {
+        assertThat(ColorUtils.lstarFromArgb(0xff000000)).isWithin(0.001).of(0.0);
+        assertThat(ColorUtils.lstarFromArgb(0xff010101)).isWithin(0.001).of(0.2741748000656518);
+        assertThat(ColorUtils.lstarFromArgb(0xff020202)).isWithin(0.001).of(0.5483496001313036);
+        assertThat(ColorUtils.lstarFromArgb(0xff030303)).isWithin(0.001).of(0.8225244001969553);
+        assertThat(ColorUtils.lstarFromArgb(0xff040404)).isWithin(0.001).of(1.0966992002626073);
+        assertThat(ColorUtils.lstarFromArgb(0xff050505)).isWithin(0.001).of(1.3708740003282587);
+        assertThat(ColorUtils.lstarFromArgb(0xff060606)).isWithin(0.001).of(1.6450488003939105);
+        assertThat(ColorUtils.lstarFromArgb(0xff070707)).isWithin(0.001).of(1.9192236004595624);
+        assertThat(ColorUtils.lstarFromArgb(0xff080808)).isWithin(0.001).of(2.1933984005252145);
+        assertThat(ColorUtils.lstarFromArgb(0xff0c0c0c)).isWithin(0.001).of(3.3209754491182557);
+        assertThat(ColorUtils.lstarFromArgb(0xff101010)).isWithin(0.001).of(4.680444846419663);
+        assertThat(ColorUtils.lstarFromArgb(0xff181818)).isWithin(0.001).of(8.248186036170349);
+        assertThat(ColorUtils.lstarFromArgb(0xff202020)).isWithin(0.001).of(12.250030101522828);
+        assertThat(ColorUtils.lstarFromArgb(0xff404040)).isWithin(0.001).of(27.093413739449055);
+        assertThat(ColorUtils.lstarFromArgb(0xff808080)).isWithin(0.001).of(53.585013452169036);
+        assertThat(ColorUtils.lstarFromArgb(0xffffffff)).isWithin(0.001).of(100.0);
+    }
+
+    @Test
+    public void yFromLstar() {
+        assertThat(ColorUtils.yFromLstar(0.0)).isWithin(1e-5).of(0.0);
+        assertThat(ColorUtils.yFromLstar(0.1)).isWithin(1e-5).of(0.0110705);
+        assertThat(ColorUtils.yFromLstar(0.2)).isWithin(1e-5).of(0.0221411);
+        assertThat(ColorUtils.yFromLstar(0.3)).isWithin(1e-5).of(0.0332116);
+        assertThat(ColorUtils.yFromLstar(0.4)).isWithin(1e-5).of(0.0442822);
+        assertThat(ColorUtils.yFromLstar(0.5)).isWithin(1e-5).of(0.0553528);
+        assertThat(ColorUtils.yFromLstar(1.0)).isWithin(1e-5).of(0.1107056);
+        assertThat(ColorUtils.yFromLstar(2.0)).isWithin(1e-5).of(0.2214112);
+        assertThat(ColorUtils.yFromLstar(3.0)).isWithin(1e-5).of(0.3321169);
+        assertThat(ColorUtils.yFromLstar(4.0)).isWithin(1e-5).of(0.4428225);
+        assertThat(ColorUtils.yFromLstar(5.0)).isWithin(1e-5).of(0.5535282);
+        assertThat(ColorUtils.yFromLstar(8.0)).isWithin(1e-5).of(0.8856451);
+        assertThat(ColorUtils.yFromLstar(10.0)).isWithin(1e-5).of(1.1260199);
+        assertThat(ColorUtils.yFromLstar(15.0)).isWithin(1e-5).of(1.9085832);
+        assertThat(ColorUtils.yFromLstar(20.0)).isWithin(1e-5).of(2.9890524);
+        assertThat(ColorUtils.yFromLstar(25.0)).isWithin(1e-5).of(4.4154767);
+        assertThat(ColorUtils.yFromLstar(30.0)).isWithin(1e-5).of(6.2359055);
+        assertThat(ColorUtils.yFromLstar(40.0)).isWithin(1e-5).of(11.2509737);
+        assertThat(ColorUtils.yFromLstar(50.0)).isWithin(1e-5).of(18.4186518);
+        assertThat(ColorUtils.yFromLstar(60.0)).isWithin(1e-5).of(28.1233342);
+        assertThat(ColorUtils.yFromLstar(70.0)).isWithin(1e-5).of(40.7494157);
+        assertThat(ColorUtils.yFromLstar(80.0)).isWithin(1e-5).of(56.6812907);
+        assertThat(ColorUtils.yFromLstar(90.0)).isWithin(1e-5).of(76.3033539);
+        assertThat(ColorUtils.yFromLstar(95.0)).isWithin(1e-5).of(87.6183294);
+        assertThat(ColorUtils.yFromLstar(99.0)).isWithin(1e-5).of(97.4360239);
+        assertThat(ColorUtils.yFromLstar(100.0)).isWithin(1e-5).of(100.0);
+    }
+
+    @Test
+    public void lstarFromY() {
+        assertThat(ColorUtils.lstarFromY(0.0)).isWithin(1e-5).of(0.0);
+        assertThat(ColorUtils.lstarFromY(0.1)).isWithin(1e-5).of(0.9032962);
+        assertThat(ColorUtils.lstarFromY(0.2)).isWithin(1e-5).of(1.8065925);
+        assertThat(ColorUtils.lstarFromY(0.3)).isWithin(1e-5).of(2.7098888);
+        assertThat(ColorUtils.lstarFromY(0.4)).isWithin(1e-5).of(3.6131851);
+        assertThat(ColorUtils.lstarFromY(0.5)).isWithin(1e-5).of(4.5164814);
+        assertThat(ColorUtils.lstarFromY(0.8856451)).isWithin(1e-5).of(8.0);
+        assertThat(ColorUtils.lstarFromY(1.0)).isWithin(1e-5).of(8.9914424);
+        assertThat(ColorUtils.lstarFromY(2.0)).isWithin(1e-5).of(15.4872443);
+        assertThat(ColorUtils.lstarFromY(3.0)).isWithin(1e-5).of(20.0438970);
+        assertThat(ColorUtils.lstarFromY(4.0)).isWithin(1e-5).of(23.6714419);
+        assertThat(ColorUtils.lstarFromY(5.0)).isWithin(1e-5).of(26.7347653);
+        assertThat(ColorUtils.lstarFromY(10.0)).isWithin(1e-5).of(37.8424304);
+        assertThat(ColorUtils.lstarFromY(15.0)).isWithin(1e-5).of(45.6341970);
+        assertThat(ColorUtils.lstarFromY(20.0)).isWithin(1e-5).of(51.8372115);
+        assertThat(ColorUtils.lstarFromY(25.0)).isWithin(1e-5).of(57.0754208);
+        assertThat(ColorUtils.lstarFromY(30.0)).isWithin(1e-5).of(61.6542222);
+        assertThat(ColorUtils.lstarFromY(40.0)).isWithin(1e-5).of(69.4695307);
+        assertThat(ColorUtils.lstarFromY(50.0)).isWithin(1e-5).of(76.0692610);
+        assertThat(ColorUtils.lstarFromY(60.0)).isWithin(1e-5).of(81.8381891);
+        assertThat(ColorUtils.lstarFromY(70.0)).isWithin(1e-5).of(86.9968642);
+        assertThat(ColorUtils.lstarFromY(80.0)).isWithin(1e-5).of(91.6848609);
+        assertThat(ColorUtils.lstarFromY(90.0)).isWithin(1e-5).of(95.9967686);
+        assertThat(ColorUtils.lstarFromY(95.0)).isWithin(1e-5).of(98.0335184);
+        assertThat(ColorUtils.lstarFromY(99.0)).isWithin(1e-5).of(99.6120372);
+        assertThat(ColorUtils.lstarFromY(100.0)).isWithin(1e-5).of(100.0);
+    }
+
+    @Test
+    public void yToLstarToY() {
+        for (double y = 0.0; y <= 100.0; y += 0.1) {
+            double lstar = ColorUtils.lstarFromY(y);
+            double reconstructedY = ColorUtils.yFromLstar(lstar);
+            assertThat(reconstructedY).isWithin(1e-8).of(y);
+        }
+    }
+
+    @Test
+    public void lstarToYToLstar() {
+        for (double lstar = 0.0; lstar <= 100.0; lstar += 0.1) {
+            double y = ColorUtils.yFromLstar(lstar);
+            double reconstructedLstar = ColorUtils.lstarFromY(y);
+            assertThat(reconstructedLstar).isWithin(1e-8).of(lstar);
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/ContrastTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/ContrastTest.java
new file mode 100644
index 0000000..8d3e401
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/ContrastTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.monet;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.contrast.Contrast;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class ContrastTest extends SysuiTestCase {
+
+    @Test
+    public void lighter_impossibleRatioErrors() {
+        assertEquals(-1.0, Contrast.lighter(90.0, 10.0), 0.001);
+    }
+
+    @Test
+    public void lighter_outOfBoundsInputAboveErrors() {
+        assertEquals(-1.0, Contrast.lighter(110.0, 2.0), 0.001);
+    }
+
+    @Test
+    public void lighter_outOfBoundsInputBelowErrors() {
+        assertEquals(-1.0, Contrast.lighter(-10.0, 2.0), 0.001);
+    }
+
+    @Test
+    public void lighterUnsafe_returnsMaxTone() {
+        assertEquals(100, Contrast.lighterUnsafe(100.0, 2.0), 0.001);
+    }
+
+    @Test
+    public void darker_impossibleRatioErrors() {
+        assertEquals(-1.0, Contrast.darker(10.0, 20.0), 0.001);
+    }
+
+    @Test
+    public void darker_outOfBoundsInputAboveErrors() {
+        assertEquals(-1.0, Contrast.darker(110.0, 2.0), 0.001);
+    }
+
+    @Test
+    public void darker_outOfBoundsInputBelowErrors() {
+        assertEquals(-1.0, Contrast.darker(-10.0, 2.0), 0.001);
+    }
+
+    @Test
+    public void darkerUnsafe_returnsMinTone() {
+        assertEquals(0.0, Contrast.darkerUnsafe(0.0, 2.0), 0.001);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/DislikeTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/DislikeTest.java
new file mode 100644
index 0000000..bda7fcc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/DislikeTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.monet;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dislike.DislikeAnalyzer;
+import com.android.systemui.monet.hct.Hct;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class DislikeTest extends SysuiTestCase {
+
+    @Test
+    public void monkSkinToneScaleColorsLiked() {
+        // From https://skintone.google#/get-started
+        int[] monkSkinToneScaleColors =
+                new int[]{
+                        0xfff6ede4,
+                        0xfff3e7db,
+                        0xfff7ead0,
+                        0xffeadaba,
+                        0xffd7bd96,
+                        0xffa07e56,
+                        0xff825c43,
+                        0xff604134,
+                        0xff3a312a,
+                        0xff292420,
+                };
+        for (int color : monkSkinToneScaleColors) {
+            assertFalse(DislikeAnalyzer.isDisliked(Hct.fromInt(color)));
+        }
+    }
+
+    @Test
+    public void bileColorsDisliked() {
+        int[] unlikable =
+                new int[]{
+                        0xff95884B, 0xff716B40, 0xffB08E00, 0xff4C4308, 0xff464521,
+                };
+        for (int color : unlikable) {
+            assertTrue(DislikeAnalyzer.isDisliked(Hct.fromInt(color)));
+        }
+    }
+
+    @Test
+    public void bileColorsBecameLikable() {
+        int[] unlikable =
+                new int[]{
+                        0xff95884B, 0xff716B40, 0xffB08E00, 0xff4C4308, 0xff464521,
+                };
+        for (int color : unlikable) {
+            Hct hct = Hct.fromInt(color);
+            assertTrue(DislikeAnalyzer.isDisliked(hct));
+            Hct likable = DislikeAnalyzer.fixIfDisliked(hct);
+            assertFalse(DislikeAnalyzer.isDisliked(likable));
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
new file mode 100644
index 0000000..41ac3213
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.DynamicColor;
+import com.android.systemui.monet.dynamiccolor.ToneDeltaConstraint;
+import com.android.systemui.monet.dynamiccolor.TonePolarity;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeTonalSpot;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class DynamicColorTest extends SysuiTestCase {
+
+    @Test
+    public void fromArgbNoBackground_doesntChangeForContrast() {
+        final int blueArgb = 0xff0000ff;
+        final DynamicColor dynamicColor = DynamicColor.fromArgb(blueArgb);
+
+        final SchemeTonalSpot standardContrast = new SchemeTonalSpot(Hct.fromInt(blueArgb), false,
+                0.0);
+        assertThat(dynamicColor.getArgb(standardContrast)).isSameColorAs(blueArgb);
+
+        final SchemeTonalSpot minContrast = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, -1.0);
+        assertThat(dynamicColor.getArgb(minContrast)).isSameColorAs(blueArgb);
+
+        final SchemeTonalSpot maxContrast = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, 1.0);
+        assertThat(dynamicColor.getArgb(maxContrast)).isSameColorAs(blueArgb);
+    }
+
+    @Test
+    public void toneDeltaConstraintNoPreference_evaluatesCorrectly() {
+        final int blueArgb = 0xff0000ff;
+        final int redArgb = 0xffff0000;
+        final DynamicColor otherDynamicColor = DynamicColor.fromArgb(redArgb);
+        final DynamicColor dynamicColor =
+                DynamicColor.fromArgb(
+                        blueArgb,
+                        (s) -> 30.0,
+                        null,
+                        (s) -> new ToneDeltaConstraint(30, otherDynamicColor,
+                                TonePolarity.NO_PREFERENCE));
+        final SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, 0.0);
+        assertThat(dynamicColor.getArgb(scheme)).isSameColorAs(0xff0000ef);
+    }
+
+    @Test
+    public void dynamicColor_withOpacity() {
+        final DynamicColor dynamicColor =
+                new DynamicColor(
+                        s -> 0.0,
+                        s -> 0.0,
+                        s -> s.isDark ? 100.0 : 0.0,
+                        s -> s.isDark ? 0.20 : 0.12,
+                        null,
+                        scheme ->
+                                DynamicColor.toneMinContrastDefault(
+                                        (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
+                        scheme ->
+                                DynamicColor.toneMaxContrastDefault(
+                                        (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
+                        null);
+        final SchemeTonalSpot lightScheme = new SchemeTonalSpot(Hct.fromInt(0xff4285f4), false,
+                0.0);
+        assertThat(dynamicColor.getArgb(lightScheme)).isSameColorAs(0x1f000000);
+
+        final SchemeTonalSpot darkScheme = new SchemeTonalSpot(Hct.fromInt(0xff4285f4), true, 0.0);
+        assertThat(dynamicColor.getArgb(darkScheme)).isSameColorAs(0x33ffffff);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/HctTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/HctTest.java
new file mode 100644
index 0000000..e9ca8a6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/HctTest.java
@@ -0,0 +1,320 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.hct.Cam16;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.hct.ViewingConditions;
+import com.android.systemui.monet.utils.ColorUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class HctTest extends SysuiTestCase {
+    private static final int RED = 0xffff0000;
+    private static final int GREEN = 0xff00ff00;
+    private static final int BLUE = 0xff0000ff;
+    private static final int WHITE = 0xffffffff;
+    private static final int BLACK = 0xff000000;
+    private static final int MIDGRAY = 0xff777777;
+
+    public static final ViewingConditions VIEWING_CONDITIONS_WHITE_BACKGROUND =
+            ViewingConditions.make(
+                    new double[]{
+                            ColorUtils.whitePointD65()[0],
+                            ColorUtils.whitePointD65()[1],
+                            ColorUtils.whitePointD65()[2]
+                    },
+                    (200.0 / Math.PI * ColorUtils.yFromLstar(50.0) / 100.f),
+                    100.0,
+                    2.0,
+                    false);
+
+    public static final ViewingConditions VIEWING_CONDITIONS_BLACK_BACKGROUND =
+            ViewingConditions.make(
+                    new double[]{
+                            ColorUtils.whitePointD65()[0],
+                            ColorUtils.whitePointD65()[1],
+                            ColorUtils.whitePointD65()[2]
+                    },
+                    (200.0 / Math.PI * ColorUtils.yFromLstar(50.0) / 100.f),
+                    0.0,
+                    2.0,
+                    false);
+
+    @Test
+    public void camFromArgb_red() {
+        Cam16 cam = Cam16.fromInt(RED);
+
+        assertEquals(27.408, cam.getHue(), 0.001);
+        assertEquals(113.357, cam.getChroma(), 0.001);
+        assertEquals(46.445, cam.getJ(), 0.001);
+        assertEquals(89.494, cam.getM(), 0.001);
+        assertEquals(91.889, cam.getS(), 0.001);
+        assertEquals(105.988, cam.getQ(), 0.001);
+    }
+
+    @Test
+    public void camFromArgb_green() {
+        Cam16 cam = Cam16.fromInt(GREEN);
+
+        assertEquals(142.139, cam.getHue(), 0.001);
+        assertEquals(108.410, cam.getChroma(), 0.001);
+        assertEquals(79.331, cam.getJ(), 0.001);
+        assertEquals(85.587, cam.getM(), 0.001);
+        assertEquals(78.604, cam.getS(), 0.001);
+        assertEquals(138.520, cam.getQ(), 0.001);
+    }
+
+    @Test
+    public void camFromArgb_blue() {
+        Cam16 cam = Cam16.fromInt(BLUE);
+
+        assertEquals(282.788, cam.getHue(), 0.001);
+        assertEquals(87.230, cam.getChroma(), 0.001);
+        assertEquals(25.465, cam.getJ(), 0.001);
+        assertEquals(68.867, cam.getM(), 0.001);
+        assertEquals(93.674, cam.getS(), 0.001);
+        assertEquals(78.481, cam.getQ(), 0.001);
+    }
+
+    @Test
+    public void camFromArgb_white() {
+        Cam16 cam = Cam16.fromInt(WHITE);
+
+        assertEquals(209.492, cam.getHue(), 0.001);
+        assertEquals(2.869, cam.getChroma(), 0.001);
+        assertEquals(100.0, cam.getJ(), 0.001);
+        assertEquals(2.265, cam.getM(), 0.001);
+        assertEquals(12.068, cam.getS(), 0.001);
+        assertEquals(155.521, cam.getQ(), 0.001);
+    }
+
+    @Test
+    public void camFromArgb_black() {
+        Cam16 cam = Cam16.fromInt(BLACK);
+
+        assertEquals(0.0, cam.getHue(), 0.001);
+        assertEquals(0.0, cam.getChroma(), 0.001);
+        assertEquals(0.0, cam.getJ(), 0.001);
+        assertEquals(0.0, cam.getM(), 0.001);
+        assertEquals(0.0, cam.getS(), 0.001);
+        assertEquals(0.0, cam.getQ(), 0.001);
+    }
+
+    @Test
+    public void camToArgbToCam_red() {
+        Cam16 cam = Cam16.fromInt(RED);
+        int argb = cam.toInt();
+        assertEquals(RED, argb);
+    }
+
+    @Test
+    public void camToArgbToCam_green() {
+        Cam16 cam = Cam16.fromInt(GREEN);
+        int argb = cam.toInt();
+        assertEquals(GREEN, argb);
+    }
+
+    @Test
+    public void camToArgbToCam_blue() {
+        Cam16 cam = Cam16.fromInt(BLUE);
+        int argb = cam.toInt();
+        assertEquals(BLUE, argb);
+    }
+
+    @Test
+    public void viewingConditions_default() {
+        ViewingConditions vc = ViewingConditions.DEFAULT;
+
+        assertEquals(0.184, vc.getN(), 0.001);
+        assertEquals(29.981, vc.getAw(), 0.001);
+        assertEquals(1.016, vc.getNbb(), 0.001);
+        assertEquals(1.021, vc.getRgbD()[0], 0.001);
+        assertEquals(0.986, vc.getRgbD()[1], 0.001);
+        assertEquals(0.933, vc.getRgbD()[2], 0.001);
+        assertEquals(0.789, vc.getFlRoot(), 0.001);
+    }
+
+    private boolean colorIsOnBoundary(int argb) {
+        return ColorUtils.redFromArgb(argb) == 0
+                || ColorUtils.redFromArgb(argb) == 255
+                || ColorUtils.greenFromArgb(argb) == 0
+                || ColorUtils.greenFromArgb(argb) == 255
+                || ColorUtils.blueFromArgb(argb) == 0
+                || ColorUtils.blueFromArgb(argb) == 255;
+    }
+
+    @Test
+    public void correctness() {
+        for (int hue = 15; hue < 360; hue += 30) {
+            for (int chroma = 0; chroma <= 100; chroma += 10) {
+                for (int tone = 20; tone <= 80; tone += 10) {
+                    Hct hctColor = Hct.from((double) hue, (double) chroma, (double) tone);
+
+                    if (chroma > 0) {
+                        assertEquals(
+                                "Incorrect hue for H" + hue + " C" + chroma + " T" + tone,
+                                hue,
+                                hctColor.getHue(),
+                                4.0);
+                    }
+
+                    assertTrue(
+                            "Negative chroma for H" + hue + " C" + chroma + " T" + tone,
+                            hctColor.getChroma() >= 0.0);
+
+                    assertTrue(
+                            "Chroma too high for H" + hue + " C" + chroma + " T" + tone,
+                            hctColor.getChroma() <= chroma + 2.5);
+
+                    if (hctColor.getChroma() < chroma - 2.5) {
+                        assertTrue(
+                                "Color not on boundary for non-sRGB color for H"
+                                        + hue
+                                        + " C"
+                                        + chroma
+                                        + " T"
+                                        + tone,
+                                colorIsOnBoundary(hctColor.toInt()));
+                    }
+
+                    assertEquals(tone, hctColor.getTone(), 0.5);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void relativity_redInBlack() {
+        final int colorToTest = RED;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xff9F5C51)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_BLACK_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_redInWhite() {
+        final int colorToTest = RED;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xffFF5D48)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_WHITE_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_greenInBlack() {
+        final int colorToTest = GREEN;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xffACD69D)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_BLACK_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_greenInWhite() {
+        final int colorToTest = GREEN;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xff8EFF77)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_WHITE_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_blueInBlack() {
+        final int colorToTest = BLUE;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xff343654)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_BLACK_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_blueInWhite() {
+        final int colorToTest = BLUE;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xff3F49FF)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_WHITE_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_whiteInBlack() {
+        final int colorToTest = WHITE;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xffFFFFFF)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_BLACK_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_whiteInWhite() {
+        final int colorToTest = WHITE;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xffFFFFFF)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_WHITE_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_midgrayInBlack() {
+        final int colorToTest = MIDGRAY;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xff605F5F)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_BLACK_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_midgrayInWhite() {
+        final int colorToTest = MIDGRAY;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xff8E8E8E)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_WHITE_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_blackInBlack() {
+        final int colorToTest = BLACK;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xff000000)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_BLACK_BACKGROUND).toInt());
+    }
+
+    @Test
+    public void relativity_blackInWhite() {
+        final int colorToTest = BLACK;
+        final Hct hct = Hct.fromInt(colorToTest);
+        assertThat(0xff000000)
+                .isSameColorAs(
+                        hct.inViewingConditions(VIEWING_CONDITIONS_WHITE_BACKGROUND).toInt());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/MathUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/MathUtilsTest.java
new file mode 100644
index 0000000..6b8437a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/MathUtilsTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.monet;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.utils.MathUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class MathUtilsTest extends SysuiTestCase {
+
+    @Test
+    public void signum() {
+        assertThat(MathUtils.signum(1.5)).isEqualTo(1);
+        assertThat(MathUtils.signum(0)).isEqualTo(0);
+        assertThat(MathUtils.signum(-3.0)).isEqualTo(-1);
+    }
+
+    @Test
+    public void sanitizeDegreesInt() {
+        assertThat(MathUtils.sanitizeDegreesInt(0)).isEqualTo(0);
+        assertThat(MathUtils.sanitizeDegreesInt(30)).isEqualTo(30);
+        assertThat(MathUtils.sanitizeDegreesInt(150)).isEqualTo(150);
+        assertThat(MathUtils.sanitizeDegreesInt(360)).isEqualTo(0);
+        assertThat(MathUtils.sanitizeDegreesInt(450)).isEqualTo(90);
+        assertThat(MathUtils.sanitizeDegreesInt(1000000)).isEqualTo(280);
+        assertThat(MathUtils.sanitizeDegreesInt(-10)).isEqualTo(350);
+        assertThat(MathUtils.sanitizeDegreesInt(-90)).isEqualTo(270);
+        assertThat(MathUtils.sanitizeDegreesInt(-1000000)).isEqualTo(80);
+    }
+
+    @Test
+    public void sanitizeDegreesDouble() {
+        assertThat(MathUtils.sanitizeDegreesDouble(0.0)).isWithin(0.001).of(0.0);
+        assertThat(MathUtils.sanitizeDegreesDouble(30.0)).isWithin(0.001).of(30.0);
+        assertThat(MathUtils.sanitizeDegreesDouble(150.0)).isWithin(0.001).of(150.0);
+        assertThat(MathUtils.sanitizeDegreesDouble(360.0)).isWithin(0.001).of(0.0);
+        assertThat(MathUtils.sanitizeDegreesDouble(450.0)).isWithin(0.001).of(90.0);
+        assertThat(MathUtils.sanitizeDegreesDouble(1000000.0)).isWithin(0.001).of(280.0);
+        assertThat(MathUtils.sanitizeDegreesDouble(-10.0)).isWithin(0.001).of(350.0);
+        assertThat(MathUtils.sanitizeDegreesDouble(-90.0)).isWithin(0.001).of(270.0);
+        assertThat(MathUtils.sanitizeDegreesDouble(-1000000.0)).isWithin(0.001).of(80.0);
+        assertThat(MathUtils.sanitizeDegreesDouble(100.375)).isWithin(0.001).of(100.375);
+        assertThat(MathUtils.sanitizeDegreesDouble(123456.789)).isWithin(0.001).of(336.789);
+        assertThat(MathUtils.sanitizeDegreesDouble(-200.625)).isWithin(0.001).of(159.375);
+        assertThat(MathUtils.sanitizeDegreesDouble(-123456.789)).isWithin(0.001).of(23.211);
+    }
+
+    @Test
+    public void rotationDirection() {
+        for (double from = 0.0; from < 360.0; from += 15.0) {
+            for (double to = 7.5; to < 360.0; to += 15.0) {
+                double expectedAnswer = originalRotationDirection(from, to);
+                double actualAnswer = MathUtils.rotationDirection(from, to);
+                assertThat(actualAnswer).isEqualTo(expectedAnswer);
+                assertThat(Math.abs(actualAnswer)).isEqualTo(1.0);
+            }
+        }
+    }
+
+    // Original implementation for MathUtils.rotationDirection.
+    // Included here to test equivalence with new implementation.
+    private static double originalRotationDirection(double from, double to) {
+        double a = to - from;
+        double b = to - from + 360.0;
+        double c = to - from - 360.0;
+        double aAbs = Math.abs(a);
+        double bAbs = Math.abs(b);
+        double cAbs = Math.abs(c);
+        if (aAbs <= bAbs && aAbs <= cAbs) {
+            return a >= 0.0 ? 1.0 : -1.0;
+        } else if (bAbs <= aAbs && bAbs <= cAbs) {
+            return b >= 0.0 ? 1.0 : -1.0;
+        } else {
+            return c >= 0.0 ? 1.0 : -1.0;
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/PalettesTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/PalettesTest.java
new file mode 100644
index 0000000..0b65fdf
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/PalettesTest.java
@@ -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.systemui.monet;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.hct.Cam16;
+import com.android.systemui.monet.palettes.CorePalette;
+import com.android.systemui.monet.palettes.TonalPalette;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class PalettesTest extends SysuiTestCase {
+
+    @Test
+    public void tones_ofBlue() {
+        int color = 0xff0000ff;
+        Cam16 cam = Cam16.fromInt(color);
+        TonalPalette tones = TonalPalette.fromHueAndChroma(cam.getHue(), cam.getChroma());
+        assertThat(tones.tone(100)).isEqualTo(0xFFFFFFFF);
+        assertThat(tones.tone(95)).isEqualTo(0xfff1efff);
+        assertThat(tones.tone(90)).isEqualTo(0xffe0e0ff);
+        assertThat(tones.tone(80)).isEqualTo(0xffbec2ff);
+        assertThat(tones.tone(70)).isEqualTo(0xff9da3ff);
+        assertThat(tones.tone(60)).isEqualTo(0xff7c84ff);
+        assertThat(tones.tone(50)).isEqualTo(0xff5a64ff);
+        assertThat(tones.tone(40)).isEqualTo(0xff343dff);
+        assertThat(tones.tone(30)).isEqualTo(0xff0000ef);
+        assertThat(tones.tone(20)).isEqualTo(0xff0001ac);
+        assertThat(tones.tone(10)).isEqualTo(0xff00006e);
+        assertThat(tones.tone(0)).isEqualTo(0xff000000);
+    }
+
+    @Test
+    public void keyTones_ofBlue() {
+        CorePalette core = CorePalette.of(0xff0000ff);
+
+        assertThat(core.a1.tone(100)).isEqualTo(0xFFFFFFFF);
+        assertThat(core.a1.tone(95)).isEqualTo(0xfff1efff);
+        assertThat(core.a1.tone(90)).isEqualTo(0xffe0e0ff);
+        assertThat(core.a1.tone(80)).isEqualTo(0xffbec2ff);
+        assertThat(core.a1.tone(70)).isEqualTo(0xff9da3ff);
+        assertThat(core.a1.tone(60)).isEqualTo(0xff7c84ff);
+        assertThat(core.a1.tone(50)).isEqualTo(0xff5a64ff);
+        assertThat(core.a1.tone(40)).isEqualTo(0xff343dff);
+        assertThat(core.a1.tone(30)).isEqualTo(0xff0000ef);
+        assertThat(core.a1.tone(20)).isEqualTo(0xff0001ac);
+        assertThat(core.a1.tone(10)).isEqualTo(0xff00006e);
+        assertThat(core.a1.tone(0)).isEqualTo(0xff000000);
+
+        assertThat(core.a2.tone(100)).isEqualTo(0xffffffff);
+        assertThat(core.a2.tone(95)).isEqualTo(0xfff1efff);
+        assertThat(core.a2.tone(90)).isEqualTo(0xffe1e0f9);
+        assertThat(core.a2.tone(80)).isEqualTo(0xffc5c4dd);
+        assertThat(core.a2.tone(70)).isEqualTo(0xffa9a9c1);
+        assertThat(core.a2.tone(60)).isEqualTo(0xff8f8fa6);
+        assertThat(core.a2.tone(50)).isEqualTo(0xff75758b);
+        assertThat(core.a2.tone(40)).isEqualTo(0xff5c5d72);
+        assertThat(core.a2.tone(30)).isEqualTo(0xff444559);
+        assertThat(core.a2.tone(20)).isEqualTo(0xff2e2f42);
+        assertThat(core.a2.tone(10)).isEqualTo(0xff191a2c);
+        assertThat(core.a2.tone(0)).isEqualTo(0xff000000);
+    }
+
+    @Test
+    public void keyTones_contentOfBlue() {
+        CorePalette core = CorePalette.contentOf(0xff0000ff);
+
+        assertThat(core.a1.tone(100)).isEqualTo(0xffffffff);
+        assertThat(core.a1.tone(95)).isEqualTo(0xfff1efff);
+        assertThat(core.a1.tone(90)).isEqualTo(0xffe0e0ff);
+        assertThat(core.a1.tone(80)).isEqualTo(0xffbec2ff);
+        assertThat(core.a1.tone(70)).isEqualTo(0xff9da3ff);
+        assertThat(core.a1.tone(60)).isEqualTo(0xff7c84ff);
+        assertThat(core.a1.tone(50)).isEqualTo(0xff5a64ff);
+        assertThat(core.a1.tone(40)).isEqualTo(0xff343dff);
+        assertThat(core.a1.tone(30)).isEqualTo(0xff0000ef);
+        assertThat(core.a1.tone(20)).isEqualTo(0xff0001ac);
+        assertThat(core.a1.tone(10)).isEqualTo(0xff00006e);
+        assertThat(core.a1.tone(0)).isEqualTo(0xff000000);
+
+        assertThat(core.a2.tone(100)).isEqualTo(0xffffffff);
+        assertThat(core.a2.tone(95)).isEqualTo(0xfff1efff);
+        assertThat(core.a2.tone(90)).isEqualTo(0xffe0e0ff);
+        assertThat(core.a2.tone(80)).isEqualTo(0xffc1c3f4);
+        assertThat(core.a2.tone(70)).isEqualTo(0xffa5a7d7);
+        assertThat(core.a2.tone(60)).isEqualTo(0xff8b8dbb);
+        assertThat(core.a2.tone(50)).isEqualTo(0xff7173a0);
+        assertThat(core.a2.tone(40)).isEqualTo(0xff585b86);
+        assertThat(core.a2.tone(30)).isEqualTo(0xff40436d);
+        assertThat(core.a2.tone(20)).isEqualTo(0xff2a2d55);
+        assertThat(core.a2.tone(10)).isEqualTo(0xff14173f);
+        assertThat(core.a2.tone(0)).isEqualTo(0xff000000);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/QuantizerMapTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/QuantizerMapTest.java
new file mode 100644
index 0000000..6a282a1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/QuantizerMapTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.monet;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.quantize.QuantizerMap;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Map;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class QuantizerMapTest extends SysuiTestCase {
+    private static final int RED = 0xffff0000;
+    private static final int GREEN = 0xff00ff00;
+    private static final int BLUE = 0xff0000ff;
+    private static final QuantizerMap quantizer = new QuantizerMap();
+
+    @Test
+    public void quantize_1R() {
+        Map<Integer, Integer> answer = quantizer.quantize(new int[]{RED}, 128).colorToCount;
+
+        assertThat(answer).hasSize(1);
+        assertThat(answer).containsEntry(RED, 1);
+    }
+
+    @Test
+    public void quantize_1G() {
+        Map<Integer, Integer> answer = quantizer.quantize(new int[]{GREEN}, 128).colorToCount;
+
+        assertThat(answer).hasSize(1);
+        assertThat(answer).containsEntry(GREEN, 1);
+    }
+
+    @Test
+    public void quantize_1B() {
+        Map<Integer, Integer> answer = quantizer.quantize(new int[]{BLUE}, 128).colorToCount;
+
+        assertThat(answer).hasSize(1);
+        assertThat(answer).containsEntry(BLUE, 1);
+    }
+
+    @Test
+    public void quantize_5B() {
+        Map<Integer, Integer> answer =
+                quantizer.quantize(new int[]{BLUE, BLUE, BLUE, BLUE, BLUE}, 128).colorToCount;
+
+        assertThat(answer).hasSize(1);
+        assertThat(answer).containsEntry(BLUE, 5);
+    }
+
+    @Test
+    public void quantize_2R3G() {
+        Map<Integer, Integer> answer =
+                quantizer.quantize(new int[]{RED, RED, GREEN, GREEN, GREEN}, 128).colorToCount;
+
+        assertThat(answer).hasSize(2);
+        assertThat(answer).containsEntry(RED, 2);
+        assertThat(answer).containsEntry(GREEN, 3);
+    }
+
+    @Test
+    public void quantize_1R1G1B() {
+        Map<Integer, Integer> answer =
+                quantizer.quantize(new int[]{RED, GREEN, BLUE}, 128).colorToCount;
+
+        assertThat(answer).hasSize(3);
+        assertThat(answer).containsEntry(RED, 1);
+        assertThat(answer).containsEntry(GREEN, 1);
+        assertThat(answer).containsEntry(BLUE, 1);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/README.md b/packages/SystemUI/tests/src/com/android/systemui/monet/README.md
new file mode 100644
index 0000000..a3e0257
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/README.md
@@ -0,0 +1,4 @@
+The tests in this folder are imported from Google's internal source repository.
+
+For instructions on importing, see:
+  frameworks/base/packages/SystemUI/tests/src/com/android/systemui/monet/README
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeContentTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeContentTest.java
new file mode 100644
index 0000000..1ddfc4d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeContentTest.java
@@ -0,0 +1,270 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeContent;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeContentTest extends SysuiTestCase {
+
+    @Test
+    public void testKeyColors() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xff0000ff), false, 0.0);
+
+        assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff080CFF);
+        assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff656DD3);
+        assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff81009F);
+        assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff767684);
+        assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff757589);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primary() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF1218FF);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primary() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF0001C3);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primary() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF000181);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF5660FF);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF2D36FF);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF0000E3);
+    }
+
+    @Test
+    public void lightTheme_minContrast_tertiaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFB042CC);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_tertiaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF9221AF);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_tertiaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF73008E);
+    }
+
+    @Test
+    public void lightTheme_minContrast_objectionableTertiaryContainerLightens() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF850096), false, -1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFD03A71);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_objectionableTertiaryContainerLightens() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF850096), false, 0.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFAC1B57);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_objectionableTertiaryContainerDarkens() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF850096), false, 1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF870040);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onPrimaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFCBCDFF);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onPrimaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFCECFFF);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onPrimaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFD6D6FF);
+    }
+
+    @Test
+    public void lightTheme_minContrast_surface() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFFFBF8FF);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_surface() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFFFBF8FF);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_surface() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFFFBF8FF);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primary() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF5660FF);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primary() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFFBEC2FF);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primary() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFFF6F4FF);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF0000E6);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF0000E6);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFC4C6FF);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onPrimaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF7A83FF);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onPrimaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFA4AAFF);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onPrimaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF0001C6);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onTertiaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFCF60EA);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onTertiaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFFEB8CFF);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onTertiaryContainer() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF63007B);
+    }
+
+    @Test
+    public void darkTheme_minContrast_surface() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFF12121D);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_surface() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFF12121D);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_surface() {
+        SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFF12121D);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeExpressiveTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeExpressiveTest.java
new file mode 100644
index 0000000..31e8711
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeExpressiveTest.java
@@ -0,0 +1,207 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeExpressive;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeExpressiveTest extends SysuiTestCase {
+
+    @Test
+    public void testKeyColors() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
+
+        assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff35855F);
+        assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff8C6D8C);
+        assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff806EA1);
+        assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff79757F);
+        assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff7A7585);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primary() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff32835D);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primary() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff146C48);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primary() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff002818);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffA2F4C6);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffA2F4C6);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff004D31);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onPrimaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff1e724e);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onPrimaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff002112);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onPrimaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff9aebbe);
+    }
+
+    @Test
+    public void lightTheme_minContrast_surface() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffdf7ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_surface() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffdf7ff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_surface() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffdf7ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primary() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff32835d);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primary() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff87d7ab);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primary() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffd5ffe4);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff005234);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff005234);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff8bdbaf);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onPrimaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff76c59b);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onPrimaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffa2f4c6);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onPrimaryContainer() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff004229);
+    }
+
+    @Test
+    public void darkTheme_minContrast_surface() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff14121a);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_surface() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff14121a);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_surface() {
+        SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff14121a);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFidelityTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFidelityTest.java
new file mode 100644
index 0000000..511f83b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFidelityTest.java
@@ -0,0 +1,269 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeFidelity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeFidelityTest extends SysuiTestCase {
+    @Test
+    public void testKeyColors() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
+
+        assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff080CFF);
+        assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff656DD3);
+        assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff9D0002);
+        assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff767684);
+        assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff757589);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primary() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff1218ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primary() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff0001c3);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primary() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff000181);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff5660ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff2d36ff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff0000e3);
+    }
+
+    @Test
+    public void lightTheme_minContrast_tertiaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffd93628);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_tertiaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffb31910);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_tertiaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff8c0002);
+    }
+
+    @Test
+    public void lightTheme_minContrast_objectionableTertiaryContainerLightens() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff850096), false, -1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffbcac5a);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_objectionableTertiaryContainerLightens() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff850096), false, 0.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffbcac5a);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_objectionableTertiaryContainerDarkens() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff850096), false, 1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff4d4300);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onPrimaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffcbcdff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onPrimaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffcecfff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onPrimaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffd6d6ff);
+    }
+
+    @Test
+    public void lightTheme_minContrast_surface() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_surface() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_surface() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primary() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5660ff);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primary() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffbec2ff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primary() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff0000e6);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff0000e6);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffc4c6ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onPrimaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff7a83ff);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onPrimaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffa4aaff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onPrimaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff0001c6);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onTertiaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xfffe513e);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onTertiaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffFF9181);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onTertiaryContainer() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff790001);
+    }
+
+    @Test
+    public void darkTheme_minContrast_surface() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12121d);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_surface() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12121d);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_surface() {
+        SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12121d);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFruitSaladTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFruitSaladTest.java
new file mode 100644
index 0000000..4cf14d5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFruitSaladTest.java
@@ -0,0 +1,250 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeFruitSalad;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeFruitSaladTest extends SysuiTestCase {
+
+    @Test
+    public void testKeyColors() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
+
+        assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff0091C0);
+        assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff3A7E9E);
+        assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff6E72AC);
+        assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff777682);
+        assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff75758B);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primary() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff007ea7);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primary() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff006688);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primary() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff002635);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffC2E8FF);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffC2E8FF);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff004862);
+    }
+
+    @Test
+    public void lightTheme_minContrast_tertiaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffE0E0FF);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_tertiaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffE0E0FF);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_tertiaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF3A3E74);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onPrimaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff006C90);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onPrimaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff001E2B);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onPrimaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffACE1FF);
+    }
+
+    @Test
+    public void lightTheme_minContrast_surface() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_surface() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_surface() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primary() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff007EA7);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primary() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF76D1FF);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primary() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFFECF7FF);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF004D67);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF004D67);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xFF83D5FF);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onPrimaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff55C0F2);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onPrimaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffC2E8FF);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onPrimaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff003E54);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onTertiaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffADB0EF);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onTertiaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe0e0ff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onTertiaryContainer() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff30346A);
+    }
+
+    @Test
+    public void darkTheme_minContrast_surface() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131c);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_surface() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131c);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_surface() {
+        SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131c);
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeMonochromeTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeMonochromeTest.java
new file mode 100644
index 0000000..3eca4dc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeMonochromeTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeMonochrome;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeMonochromeTest extends SysuiTestCase {
+
+    @Test
+    public void testKeyColors() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
+
+        assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff070707);
+        assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff070707);
+        assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff070707);
+        assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff070707);
+        assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff070707);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primary() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff747474);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primary() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5e5e5e);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primary() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff222222);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe2e2e2);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe2e2e2);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff434343);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onPrimaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff646464);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onPrimaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff1b1b1b);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onPrimaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffdadada);
+    }
+
+    @Test
+    public void lightTheme_minContrast_surface() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_surface() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_surface() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primary() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff747474);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primary() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffc6c6c6);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primary() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff5f5f5);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff474747);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff474747);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffcbcbcb);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onPrimaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffb5b5b5);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onPrimaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe2e2e2);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onPrimaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff393939);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onTertiaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffb5b5b5);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onTertiaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe2e2e2);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onTertiaryContainer() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff393939);
+    }
+
+    @Test
+    public void darkTheme_minContrast_surface() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_surface() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_surface() {
+        SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeNeutralTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeNeutralTest.java
new file mode 100644
index 0000000..71e9f4d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeNeutralTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeNeutral;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeNeutralTest extends SysuiTestCase {
+
+    @Test
+    public void testKeyColors() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
+
+        assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff767685);
+        assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff777680);
+        assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff75758B);
+        assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff787678);
+        assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff787678);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primary() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff737383);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primary() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5d5d6c);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primary() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff21212e);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe2e1f3);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe2e1f3);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff414250);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onPrimaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff636372);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onPrimaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff1a1b27);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onPrimaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffd9d8ea);
+    }
+
+    @Test
+    public void lightTheme_minContrast_surface() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffcf8fa);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_surface() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffcf8fa);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_surface() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffcf8fa);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primary() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff737383);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primary() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffc6c5d6);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primary() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff454654);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff454654);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffcac9da);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onPrimaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffb5b3c4);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onPrimaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe2e1f3);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onPrimaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff373846);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onTertiaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffb3b3cb);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onTertiaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe1e0f9);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onTertiaryContainer() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff37374b);
+    }
+
+    @Test
+    public void darkTheme_minContrast_surface() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131315);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_surface() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131315);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_surface() {
+        SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131315);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeRainbowTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeRainbowTest.java
new file mode 100644
index 0000000..cc6f044
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeRainbowTest.java
@@ -0,0 +1,249 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeRainbow;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeRainbowTest extends SysuiTestCase {
+
+    @Test
+    public void testKeyColors() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
+
+        assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff696FC4);
+        assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff75758B);
+        assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff936B84);
+        assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff070707);
+        assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff070707);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primary() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff676DC1);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primary() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5056A9);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primary() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff0F136A);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffE0E0FF);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffE0E0FF);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff34398B);
+    }
+
+    @Test
+    public void lightTheme_minContrast_tertiaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffffd8ee);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_tertiaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffffd8ee);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_tertiaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff5A384E);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onPrimaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff565CB0);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onPrimaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff050865);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onPrimaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffd6d6ff);
+    }
+
+    @Test
+    public void lightTheme_minContrast_surface() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_surface() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_surface() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primary() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff676DC1);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primary() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffbec2ff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primary() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff383E8F);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff383E8F);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffc4c6ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onPrimaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffa9afff);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onPrimaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe0e0ff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onPrimaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff292f81);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onTertiaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffd5a8c3);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onTertiaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffffd8ee);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onTertiaryContainer() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff4f2e44);
+    }
+
+    @Test
+    public void darkTheme_minContrast_surface() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_surface() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_surface() {
+        SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTest.java
new file mode 100644
index 0000000..859b65b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTest.java
@@ -0,0 +1,201 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.scheme.Scheme;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeTest extends SysuiTestCase {
+
+    @Test
+    public void lightScheme_ofBlue() {
+        Scheme scheme = Scheme.light(0xff0000ff);
+        assertThat(scheme.getPrimary()).isSameColorAs(0xff343DFF);
+    }
+
+    @Test
+    public void darkScheme_ofBlue() {
+        Scheme scheme = Scheme.dark(0xff0000ff);
+        assertThat(scheme.getPrimary()).isSameColorAs(0xffBEC2FF);
+    }
+
+    @Test
+    public void thirdPartyScheme_light() {
+        Scheme scheme = Scheme.light(0xff6750A4);
+        assertThat(scheme.getPrimary()).isSameColorAs(0xff6750A4);
+        assertThat(scheme.getSecondary()).isSameColorAs(0xff625B71);
+        assertThat(scheme.getTertiary()).isSameColorAs(0xff7e5260);
+        assertThat(scheme.getSurface()).isSameColorAs(0xfffffbff);
+        assertThat(scheme.getOnSurface()).isSameColorAs(0xff1c1b1e);
+    }
+
+    @Test
+    public void thirdPartyScheme_dark() {
+        Scheme scheme = Scheme.dark(0xff6750A4);
+        assertThat(scheme.getPrimary()).isSameColorAs(0xffcfbcff);
+        assertThat(scheme.getSecondary()).isSameColorAs(0xffcbc2db);
+        assertThat(scheme.getTertiary()).isSameColorAs(0xffefb8c8);
+        assertThat(scheme.getSurface()).isSameColorAs(0xff1c1b1e);
+        assertThat(scheme.getOnSurface()).isSameColorAs(0xffe6e1e6);
+    }
+
+    @Test
+    public void lightSchemeFromHighChromaColor() {
+        Scheme scheme = Scheme.light(0xfffa2bec);
+        assertThat(scheme.getPrimary()).isSameColorAs(0xffab00a2);
+        assertThat(scheme.getOnPrimary()).isSameColorAs(0xffffffff);
+        assertThat(scheme.getPrimaryContainer()).isSameColorAs(0xffffd7f3);
+        assertThat(scheme.getOnPrimaryContainer()).isSameColorAs(0xff390035);
+        assertThat(scheme.getSecondary()).isSameColorAs(0xff6e5868);
+        assertThat(scheme.getOnSecondary()).isSameColorAs(0xffffffff);
+        assertThat(scheme.getSecondaryContainer()).isSameColorAs(0xfff8daee);
+        assertThat(scheme.getOnSecondaryContainer()).isSameColorAs(0xff271624);
+        assertThat(scheme.getTertiary()).isSameColorAs(0xff815343);
+        assertThat(scheme.getOnTertiary()).isSameColorAs(0xffffffff);
+        assertThat(scheme.getTertiaryContainer()).isSameColorAs(0xffffdbd0);
+        assertThat(scheme.getOnTertiaryContainer()).isSameColorAs(0xff321207);
+        assertThat(scheme.getError()).isSameColorAs(0xffba1a1a);
+        assertThat(scheme.getOnError()).isSameColorAs(0xffffffff);
+        assertThat(scheme.getErrorContainer()).isSameColorAs(0xffffdad6);
+        assertThat(scheme.getOnErrorContainer()).isSameColorAs(0xff410002);
+        assertThat(scheme.getBackground()).isSameColorAs(0xfffffbff);
+        assertThat(scheme.getOnBackground()).isSameColorAs(0xff1f1a1d);
+        assertThat(scheme.getSurface()).isSameColorAs(0xfffffbff);
+        assertThat(scheme.getOnSurface()).isSameColorAs(0xff1f1a1d);
+        assertThat(scheme.getSurfaceVariant()).isSameColorAs(0xffeedee7);
+        assertThat(scheme.getOnSurfaceVariant()).isSameColorAs(0xff4e444b);
+        assertThat(scheme.getOutline()).isSameColorAs(0xff80747b);
+        assertThat(scheme.getOutlineVariant()).isSameColorAs(0xffd2c2cb);
+        assertThat(scheme.getShadow()).isSameColorAs(0xff000000);
+        assertThat(scheme.getScrim()).isSameColorAs(0xff000000);
+        assertThat(scheme.getInverseSurface()).isSameColorAs(0xff342f32);
+        assertThat(scheme.getInverseOnSurface()).isSameColorAs(0xfff8eef2);
+        assertThat(scheme.getInversePrimary()).isSameColorAs(0xffffabee);
+    }
+
+    @Test
+    public void darkSchemeFromHighChromaColor() {
+        Scheme scheme = Scheme.dark(0xfffa2bec);
+        assertThat(scheme.getPrimary()).isSameColorAs(0xffffabee);
+        assertThat(scheme.getOnPrimary()).isSameColorAs(0xff5c0057);
+        assertThat(scheme.getPrimaryContainer()).isSameColorAs(0xff83007b);
+        assertThat(scheme.getOnPrimaryContainer()).isSameColorAs(0xffffd7f3);
+        assertThat(scheme.getSecondary()).isSameColorAs(0xffdbbed1);
+        assertThat(scheme.getOnSecondary()).isSameColorAs(0xff3e2a39);
+        assertThat(scheme.getSecondaryContainer()).isSameColorAs(0xff554050);
+        assertThat(scheme.getOnSecondaryContainer()).isSameColorAs(0xfff8daee);
+        assertThat(scheme.getTertiary()).isSameColorAs(0xfff5b9a5);
+        assertThat(scheme.getOnTertiary()).isSameColorAs(0xff4c2619);
+        assertThat(scheme.getTertiaryContainer()).isSameColorAs(0xff663c2d);
+        assertThat(scheme.getOnTertiaryContainer()).isSameColorAs(0xffffdbd0);
+        assertThat(scheme.getError()).isSameColorAs(0xffffb4ab);
+        assertThat(scheme.getOnError()).isSameColorAs(0xff690005);
+        assertThat(scheme.getErrorContainer()).isSameColorAs(0xff93000a);
+        assertThat(scheme.getOnErrorContainer()).isSameColorAs(0xffffb4ab);
+        assertThat(scheme.getBackground()).isSameColorAs(0xff1f1a1d);
+        assertThat(scheme.getOnBackground()).isSameColorAs(0xffeae0e4);
+        assertThat(scheme.getSurface()).isSameColorAs(0xff1f1a1d);
+        assertThat(scheme.getOnSurface()).isSameColorAs(0xffeae0e4);
+        assertThat(scheme.getSurfaceVariant()).isSameColorAs(0xff4e444b);
+        assertThat(scheme.getOnSurfaceVariant()).isSameColorAs(0xffd2c2cb);
+        assertThat(scheme.getOutline()).isSameColorAs(0xff9a8d95);
+        assertThat(scheme.getOutlineVariant()).isSameColorAs(0xff4e444b);
+        assertThat(scheme.getShadow()).isSameColorAs(0xff000000);
+        assertThat(scheme.getScrim()).isSameColorAs(0xff000000);
+        assertThat(scheme.getInverseSurface()).isSameColorAs(0xffeae0e4);
+        assertThat(scheme.getInverseOnSurface()).isSameColorAs(0xff342f32);
+        assertThat(scheme.getInversePrimary()).isSameColorAs(0xffab00a2);
+    }
+
+    @Test
+    public void lightContentSchemeFromHighChromaColor() {
+        Scheme scheme = Scheme.lightContent(0xfffa2bec);
+        assertThat(scheme.getPrimary()).isSameColorAs(0xffab00a2);
+        assertThat(scheme.getOnPrimary()).isSameColorAs(0xffffffff);
+        assertThat(scheme.getPrimaryContainer()).isSameColorAs(0xffffd7f3);
+        assertThat(scheme.getOnPrimaryContainer()).isSameColorAs(0xff390035);
+        assertThat(scheme.getSecondary()).isSameColorAs(0xff7f4e75);
+        assertThat(scheme.getOnSecondary()).isSameColorAs(0xffffffff);
+        assertThat(scheme.getSecondaryContainer()).isSameColorAs(0xffffd7f3);
+        assertThat(scheme.getOnSecondaryContainer()).isSameColorAs(0xff330b2f);
+        assertThat(scheme.getTertiary()).isSameColorAs(0xff9c4323);
+        assertThat(scheme.getOnTertiary()).isSameColorAs(0xffffffff);
+        assertThat(scheme.getTertiaryContainer()).isSameColorAs(0xffffdbd0);
+        assertThat(scheme.getOnTertiaryContainer()).isSameColorAs(0xff390c00);
+        assertThat(scheme.getError()).isSameColorAs(0xffba1a1a);
+        assertThat(scheme.getOnError()).isSameColorAs(0xffffffff);
+        assertThat(scheme.getErrorContainer()).isSameColorAs(0xffffdad6);
+        assertThat(scheme.getOnErrorContainer()).isSameColorAs(0xff410002);
+        assertThat(scheme.getBackground()).isSameColorAs(0xfffffbff);
+        assertThat(scheme.getOnBackground()).isSameColorAs(0xff1f1a1d);
+        assertThat(scheme.getSurface()).isSameColorAs(0xfffffbff);
+        assertThat(scheme.getOnSurface()).isSameColorAs(0xff1f1a1d);
+        assertThat(scheme.getSurfaceVariant()).isSameColorAs(0xffeedee7);
+        assertThat(scheme.getOnSurfaceVariant()).isSameColorAs(0xff4e444b);
+        assertThat(scheme.getOutline()).isSameColorAs(0xff80747b);
+        assertThat(scheme.getOutlineVariant()).isSameColorAs(0xffd2c2cb);
+        assertThat(scheme.getShadow()).isSameColorAs(0xff000000);
+        assertThat(scheme.getScrim()).isSameColorAs(0xff000000);
+        assertThat(scheme.getInverseSurface()).isSameColorAs(0xff342f32);
+        assertThat(scheme.getInverseOnSurface()).isSameColorAs(0xfff8eef2);
+        assertThat(scheme.getInversePrimary()).isSameColorAs(0xffffabee);
+    }
+
+    @Test
+    public void darkContentSchemeFromHighChromaColor() {
+        Scheme scheme = Scheme.darkContent(0xfffa2bec);
+        assertThat(scheme.getPrimary()).isSameColorAs(0xffffabee);
+        assertThat(scheme.getOnPrimary()).isSameColorAs(0xff5c0057);
+        assertThat(scheme.getPrimaryContainer()).isSameColorAs(0xff83007b);
+        assertThat(scheme.getOnPrimaryContainer()).isSameColorAs(0xffffd7f3);
+        assertThat(scheme.getSecondary()).isSameColorAs(0xfff0b4e1);
+        assertThat(scheme.getOnSecondary()).isSameColorAs(0xff4b2145);
+        assertThat(scheme.getSecondaryContainer()).isSameColorAs(0xff64375c);
+        assertThat(scheme.getOnSecondaryContainer()).isSameColorAs(0xffffd7f3);
+        assertThat(scheme.getTertiary()).isSameColorAs(0xffffb59c);
+        assertThat(scheme.getOnTertiary()).isSameColorAs(0xff5c1900);
+        assertThat(scheme.getTertiaryContainer()).isSameColorAs(0xff7d2c0d);
+        assertThat(scheme.getOnTertiaryContainer()).isSameColorAs(0xffffdbd0);
+        assertThat(scheme.getError()).isSameColorAs(0xffffb4ab);
+        assertThat(scheme.getOnError()).isSameColorAs(0xff690005);
+        assertThat(scheme.getErrorContainer()).isSameColorAs(0xff93000a);
+        assertThat(scheme.getOnErrorContainer()).isSameColorAs(0xffffb4ab);
+        assertThat(scheme.getBackground()).isSameColorAs(0xff1f1a1d);
+        assertThat(scheme.getOnBackground()).isSameColorAs(0xffeae0e4);
+        assertThat(scheme.getSurface()).isSameColorAs(0xff1f1a1d);
+        assertThat(scheme.getOnSurface()).isSameColorAs(0xffeae0e4);
+        assertThat(scheme.getSurfaceVariant()).isSameColorAs(0xff4e444b);
+        assertThat(scheme.getOnSurfaceVariant()).isSameColorAs(0xffd2c2cb);
+        assertThat(scheme.getOutline()).isSameColorAs(0xff9a8d95);
+        assertThat(scheme.getOutlineVariant()).isSameColorAs(0xff4e444b);
+        assertThat(scheme.getShadow()).isSameColorAs(0xff000000);
+        assertThat(scheme.getScrim()).isSameColorAs(0xff000000);
+        assertThat(scheme.getInverseSurface()).isSameColorAs(0xffeae0e4);
+        assertThat(scheme.getInverseOnSurface()).isSameColorAs(0xff342f32);
+        assertThat(scheme.getInversePrimary()).isSameColorAs(0xffab00a2);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTonalSpotTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTonalSpotTest.java
new file mode 100644
index 0000000..e4880d9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTonalSpotTest.java
@@ -0,0 +1,372 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeTonalSpot;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeTonalSpotTest extends SysuiTestCase {
+
+    @Test
+    public void testKeyColors() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
+
+        assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff6E72AC);
+        assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff75758B);
+        assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff936B84);
+        assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff78767A);
+        assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff777680);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff6c70aa);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff555992);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff181c51);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe0e0ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe0e0ff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff3a3e74);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onPrimaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff5C5F98);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onPrimaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff11144B);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onPrimaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffd6d6ff);
+    }
+
+    @Test
+    public void lightTheme_minContrast_surface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xffFCF8FD);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_surface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xffFCF8FD);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_surface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xffFCF8FD);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onSurface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xff605E62);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onSurface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xff1B1B1F);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onSurface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xff1B1A1E);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onSecondary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xffcfcfe7);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onSecondary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xffffffff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onSecondary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xffababc3);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onTertiary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xfff3c3df);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onTertiary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xffffffff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onTertiary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xffcda0bb);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onError() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xffffc2bb);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onError() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xffffffff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onError() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xffff8d80);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff6C70AA);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffbec2ff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff3E4278);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff3E4278);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffc4c6ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onPrimaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffadb0ef);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onPrimaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe0e0ff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onPrimaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff30346A);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onTertiaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffd5a8c3);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onTertiaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffffd8ee);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onTertiaryContainer() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff4f2e44);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onSecondary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xfffffbff);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onSecondary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xff2e2f42);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onSecondary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xff505165);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onTertiary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xfffffbff);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onTertiary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xff46263b);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onTertiary() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xff6b485f);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onError() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xfffffbff);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onError() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xff690005);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onError() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xffa80710);
+    }
+
+    @Test
+    public void darkTheme_minContrast_surface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131316);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_surface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131316);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_surface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131316);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onSurface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xffa4a2a6);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onSurface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xffe5e1e6);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onSurface() {
+        SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xffe6e2e7);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeVibrantTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeVibrantTest.java
new file mode 100644
index 0000000..e5963a2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeVibrantTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.SchemeVibrant;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class SchemeVibrantTest extends SysuiTestCase {
+
+    @Test
+    public void testKeyColors() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
+
+        assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff080CFF);
+        assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff7B7296);
+        assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff886C9D);
+        assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff777682);
+        assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+                .isSameColorAs(0xff767685);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primary() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5660ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primary() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff343dff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primary() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff000181);
+    }
+
+    @Test
+    public void lightTheme_minContrast_primaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe0e0ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_primaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe0e0ff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_primaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff0000e3);
+    }
+
+    @Test
+    public void lightTheme_minContrast_onPrimaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff3e47ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_onPrimaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff00006e);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_onPrimaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffd6d6ff);
+    }
+
+    @Test
+    public void lightTheme_minContrast_surface() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+    }
+
+    @Test
+    public void lightTheme_standardContrast_surface() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+    }
+
+    @Test
+    public void lightTheme_maxContrast_surface() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primary() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5660ff);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primary() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffbec2ff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primary() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_primaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff0000ef);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_primaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff0000ef);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_primaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffc4c6ff);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onPrimaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffa9afff);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onPrimaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffe0e0ff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onPrimaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff0001c6);
+    }
+
+    @Test
+    public void darkTheme_minContrast_onTertiaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xffc9a9df);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_onTertiaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xfff2daff);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_onTertiaryContainer() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+                0xff472e5b);
+    }
+
+    @Test
+    public void darkTheme_minContrast_surface() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131C);
+    }
+
+    @Test
+    public void darkTheme_standardContrast_surface() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131C);
+    }
+
+    @Test
+    public void darkTheme_maxContrast_surface() {
+        SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
+        assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131C);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/ScoreTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/ScoreTest.java
new file mode 100644
index 0000000..47ad43c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/ScoreTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.monet;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.score.Score;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class ScoreTest extends SysuiTestCase {
+
+    @Test
+    public void score_picksMostChromatic() {
+        Map<Integer, Integer> colorsToPopulation = new HashMap<>();
+        colorsToPopulation.put(0xFF0000FF, 1);
+        colorsToPopulation.put(0xFFFF0000, 1);
+        colorsToPopulation.put(0xFF00FF00, 1);
+
+        List<Integer> scores = Score.score(colorsToPopulation);
+
+        assertThat(scores.get(0)).isEqualTo(0xffff0000);
+        assertThat(scores.get(1)).isEqualTo(0xff00ff00);
+        assertThat(scores.get(2)).isEqualTo(0xff0000ff);
+    }
+
+    @Test
+    public void score_usesGblueFallback() {
+        Map<Integer, Integer> colorsToPopulation = new HashMap<>();
+        colorsToPopulation.put(0xFF000000, 1);
+
+        List<Integer> scores = Score.score(colorsToPopulation);
+
+        assertThat(scores).containsExactly(0xff4285f4);
+    }
+
+    @Test
+    public void score_dedupesNearbyHues() {
+        Map<Integer, Integer> colorsToPopulation = new HashMap<>();
+        colorsToPopulation.put(0xff008772, 1);
+        colorsToPopulation.put(0xff318477, 1);
+
+        List<Integer> scores = Score.score(colorsToPopulation);
+
+        assertThat(scores).containsExactly(0xff008772);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/TemperatureCacheTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/TemperatureCacheTest.java
new file mode 100644
index 0000000..c304e92e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/TemperatureCacheTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.monet;
+
+import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.temperature.TemperatureCache;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public final class TemperatureCacheTest extends SysuiTestCase {
+
+    @Test
+    public void testRawTemperature() {
+        final Hct blueHct = Hct.fromInt(0xff0000ff);
+        final double blueTemp = TemperatureCache.rawTemperature(blueHct);
+        assertEquals(-1.393, blueTemp, 0.001);
+
+        final Hct redHct = Hct.fromInt(0xffff0000);
+        final double redTemp = TemperatureCache.rawTemperature(redHct);
+        assertEquals(2.351, redTemp, 0.001);
+
+        final Hct greenHct = Hct.fromInt(0xff00ff00);
+        final double greenTemp = TemperatureCache.rawTemperature(greenHct);
+        assertEquals(-0.267, greenTemp, 0.001);
+
+        final Hct whiteHct = Hct.fromInt(0xffffffff);
+        final double whiteTemp = TemperatureCache.rawTemperature(whiteHct);
+        assertEquals(-0.5, whiteTemp, 0.001);
+
+        final Hct blackHct = Hct.fromInt(0xff000000);
+        final double blackTemp = TemperatureCache.rawTemperature(blackHct);
+        assertEquals(-0.5, blackTemp, 0.001);
+    }
+
+    @Test
+    public void testComplement() {
+        final int blueComplement =
+                new TemperatureCache(Hct.fromInt(0xff0000ff)).getComplement().toInt();
+        assertThat(0xff9D0002).isSameColorAs(blueComplement);
+
+        final int redComplement = new TemperatureCache(
+                Hct.fromInt(0xffff0000)).getComplement().toInt();
+        assertThat(0xff007BFC).isSameColorAs(redComplement);
+
+        final int greenComplement =
+                new TemperatureCache(Hct.fromInt(0xff00ff00)).getComplement().toInt();
+        assertThat(0xffFFD2C9).isSameColorAs(greenComplement);
+
+        final int whiteComplement =
+                new TemperatureCache(Hct.fromInt(0xffffffff)).getComplement().toInt();
+        assertThat(0xffffffff).isSameColorAs(whiteComplement);
+
+        final int blackComplement =
+                new TemperatureCache(Hct.fromInt(0xff000000)).getComplement().toInt();
+        assertThat(0xff000000).isSameColorAs(blackComplement);
+    }
+
+    @Test
+    public void testAnalogous() {
+        final List<Hct> blueAnalogous =
+                new TemperatureCache(Hct.fromInt(0xff0000ff)).getAnalogousColors();
+        assertThat(0xff00590C).isSameColorAs(blueAnalogous.get(0).toInt());
+        assertThat(0xff00564E).isSameColorAs(blueAnalogous.get(1).toInt());
+        assertThat(0xff0000ff).isSameColorAs(blueAnalogous.get(2).toInt());
+        assertThat(0xff6700CC).isSameColorAs(blueAnalogous.get(3).toInt());
+        assertThat(0xff81009F).isSameColorAs(blueAnalogous.get(4).toInt());
+
+        final List<Hct> redAnalogous =
+                new TemperatureCache(Hct.fromInt(0xffff0000)).getAnalogousColors();
+        assertThat(0xffF60082).isSameColorAs(redAnalogous.get(0).toInt());
+        assertThat(0xffFC004C).isSameColorAs(redAnalogous.get(1).toInt());
+        assertThat(0xffff0000).isSameColorAs(redAnalogous.get(2).toInt());
+        assertThat(0xffD95500).isSameColorAs(redAnalogous.get(3).toInt());
+        assertThat(0xffAF7200).isSameColorAs(redAnalogous.get(4).toInt());
+
+        final List<Hct> greenAnalogous =
+                new TemperatureCache(Hct.fromInt(0xff00ff00)).getAnalogousColors();
+        assertThat(0xffCEE900).isSameColorAs(greenAnalogous.get(0).toInt());
+        assertThat(0xff92F500).isSameColorAs(greenAnalogous.get(1).toInt());
+        assertThat(0xff00ff00).isSameColorAs(greenAnalogous.get(2).toInt());
+        assertThat(0xff00FD6F).isSameColorAs(greenAnalogous.get(3).toInt());
+        assertThat(0xff00FAB3).isSameColorAs(greenAnalogous.get(4).toInt());
+
+        final List<Hct> blackAnalogous =
+                new TemperatureCache(Hct.fromInt(0xff000000)).getAnalogousColors();
+        assertThat(0xff000000).isSameColorAs(blackAnalogous.get(0).toInt());
+        assertThat(0xff000000).isSameColorAs(blackAnalogous.get(1).toInt());
+        assertThat(0xff000000).isSameColorAs(blackAnalogous.get(2).toInt());
+        assertThat(0xff000000).isSameColorAs(blackAnalogous.get(3).toInt());
+        assertThat(0xff000000).isSameColorAs(blackAnalogous.get(4).toInt());
+
+        final List<Hct> whiteAnalogous =
+                new TemperatureCache(Hct.fromInt(0xffffffff)).getAnalogousColors();
+        assertThat(0xffffffff).isSameColorAs(whiteAnalogous.get(0).toInt());
+        assertThat(0xffffffff).isSameColorAs(whiteAnalogous.get(1).toInt());
+        assertThat(0xffffffff).isSameColorAs(whiteAnalogous.get(2).toInt());
+        assertThat(0xffffffff).isSameColorAs(whiteAnalogous.get(3).toInt());
+        assertThat(0xffffffff).isSameColorAs(whiteAnalogous.get(4).toInt());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/utils/ArgbSubject.java b/packages/SystemUI/tests/src/com/android/systemui/monet/utils/ArgbSubject.java
new file mode 100644
index 0000000..f3040c8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/utils/ArgbSubject.java
@@ -0,0 +1,59 @@
+/*
+ * 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.monet.utils;
+
+import static com.google.common.truth.Truth.assertAbout;
+
+import com.google.common.truth.FailureMetadata;
+import com.google.common.truth.Subject;
+
+/** Enables assertions involving colors as integers to log as hex codes instead of raw integers. */
+public final class ArgbSubject extends Subject {
+
+    public static ArgbSubject assertThat(int argb) {
+        return assertAbout(ArgbSubject::new).that(argb);
+    }
+
+    private final int actual;
+
+    private ArgbSubject(FailureMetadata failureMetadata, int subject) {
+        super(failureMetadata, subject);
+        this.actual = subject;
+    }
+
+    @Override
+    protected String actualCustomStringRepresentation() {
+        return userFriendlyHexCode(actual);
+    }
+
+    public void isSameColorAs(int otherArgb) {
+        if (otherArgb != actual) {
+            failWithActual("color", userFriendlyHexCode(otherArgb));
+        }
+    }
+
+    private static String userFriendlyHexCode(int integer) {
+        String hexString = Integer.toHexString(integer);
+        if (hexString.length() > 6) {
+            return String.format("#%s", hexString.substring(hexString.length() - 6));
+        } else if (hexString.length() == 6) {
+            return String.format("#%s", hexString);
+        } else {
+            return String.format("??? #%s", hexString);
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
new file mode 100644
index 0000000..bc31a0e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.navigationbar.gestural
+
+import android.os.Handler
+import android.os.Looper
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.ACTION_UP
+import android.view.ViewConfiguration
+import android.view.WindowManager
+import androidx.test.filters.SmallTest
+import com.android.internal.util.LatencyTracker
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.NavigationEdgeBackPlugin
+import com.android.systemui.statusbar.VibratorHelper
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class BackPanelControllerTest : SysuiTestCase() {
+    companion object {
+        private const val START_X: Float = 0f
+    }
+    private lateinit var mBackPanelController: BackPanelController
+    private lateinit var testableLooper: TestableLooper
+    private var triggerThreshold: Float = 0.0f
+    private val touchSlop = ViewConfiguration.get(context).scaledEdgeSlop
+    @Mock private lateinit var vibratorHelper: VibratorHelper
+    @Mock private lateinit var windowManager: WindowManager
+    @Mock private lateinit var configurationController: ConfigurationController
+    @Mock private lateinit var latencyTracker: LatencyTracker
+    @Mock private lateinit var layoutParams: WindowManager.LayoutParams
+    @Mock private lateinit var backCallback: NavigationEdgeBackPlugin.BackCallback
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        mBackPanelController =
+            BackPanelController(
+                context,
+                windowManager,
+                ViewConfiguration.get(context),
+                Handler.createAsync(Looper.myLooper()),
+                vibratorHelper,
+                configurationController,
+                latencyTracker
+            )
+        mBackPanelController.setLayoutParams(layoutParams)
+        mBackPanelController.setBackCallback(backCallback)
+        mBackPanelController.setIsLeftPanel(true)
+        testableLooper = TestableLooper.get(this)
+        triggerThreshold = mBackPanelController.params.staticTriggerThreshold
+    }
+
+    @Test
+    fun handlesActionDown() {
+        startTouch()
+
+        assertThat(mBackPanelController.currentState)
+            .isEqualTo(BackPanelController.GestureState.GONE)
+    }
+
+    @Test
+    fun staysHiddenBeforeSlopCrossed() {
+        startTouch()
+        // Move just enough to not cross the touch slop
+        continueTouch(START_X + touchSlop - 1)
+
+        assertThat(mBackPanelController.currentState)
+            .isEqualTo(BackPanelController.GestureState.GONE)
+    }
+
+    @Test
+    fun handlesBackCommitted() {
+        startTouch()
+        // Move once to cross the touch slop
+        continueTouch(START_X + touchSlop.toFloat() + 1)
+        // Move again to cross the back trigger threshold
+        continueTouch(START_X + touchSlop + triggerThreshold + 1)
+
+        assertThat(mBackPanelController.currentState)
+            .isEqualTo(BackPanelController.GestureState.ACTIVE)
+        verify(backCallback).setTriggerBack(true)
+        testableLooper.moveTimeForward(100)
+        testableLooper.processAllMessages()
+        verify(vibratorHelper).vibrate(VIBRATE_ACTIVATED_EFFECT)
+
+        finishTouchActionUp(START_X + touchSlop + triggerThreshold + 1)
+        assertThat(mBackPanelController.currentState)
+            .isEqualTo(BackPanelController.GestureState.FLUNG)
+        verify(backCallback).triggerBack()
+    }
+
+    @Test
+    fun handlesBackCancelled() {
+        startTouch()
+        continueTouch(START_X + touchSlop.toFloat() + 1)
+        continueTouch(
+            START_X + touchSlop + triggerThreshold -
+                mBackPanelController.params.deactivationSwipeTriggerThreshold
+        )
+        clearInvocations(backCallback)
+        Thread.sleep(MIN_DURATION_ACTIVE_ANIMATION)
+        // Move in the opposite direction to cross the deactivation threshold and cancel back
+        continueTouch(START_X)
+
+        assertThat(mBackPanelController.currentState)
+            .isEqualTo(BackPanelController.GestureState.INACTIVE)
+        verify(backCallback).setTriggerBack(false)
+        verify(vibratorHelper).vibrate(VIBRATE_DEACTIVATED_EFFECT)
+
+        finishTouchActionUp(START_X)
+        verify(backCallback).cancelBack()
+    }
+
+    private fun startTouch() {
+        mBackPanelController.onMotionEvent(createMotionEvent(ACTION_DOWN, START_X, 0f))
+    }
+
+    private fun continueTouch(x: Float) {
+        mBackPanelController.onMotionEvent(createMotionEvent(ACTION_MOVE, x, 0f))
+    }
+
+    private fun finishTouchActionUp(x: Float) {
+        mBackPanelController.onMotionEvent(createMotionEvent(ACTION_UP, x, 0f))
+    }
+
+    private fun createMotionEvent(action: Int, x: Float, y: Float): MotionEvent {
+        return MotionEvent.obtain(0L, 0L, action, x, y, 0)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/MotionEventsHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/MotionEventsHandlerTest.java
index 509d5f0..70ba306 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/MotionEventsHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/MotionEventsHandlerTest.java
@@ -16,10 +16,10 @@
 
 package com.android.systemui.navigationbar.gestural;
 
-import static android.view.InputDevice.SOURCE_TOUCHPAD;
-import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
+import static android.view.InputDevice.SOURCE_MOUSE;
 import static android.view.MotionEvent.AXIS_GESTURE_X_OFFSET;
 import static android.view.MotionEvent.AXIS_GESTURE_Y_OFFSET;
+import static android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -57,14 +57,9 @@
     @Test
     public void onTouchEvent_touchScreen_hasCorrectDisplacements() {
         MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 100, 100, 0);
-        // TODO: change to use classification after gesture library is ported.
-        down.setSource(SOURCE_TOUCHSCREEN);
         MotionEvent move1 = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 150, 125, 0);
-        move1.setSource(SOURCE_TOUCHSCREEN);
         MotionEvent move2 = MotionEvent.obtain(0, 2, MotionEvent.ACTION_MOVE, 200, 150, 0);
-        move2.setSource(SOURCE_TOUCHSCREEN);
         MotionEvent up = MotionEvent.obtain(0, 3, MotionEvent.ACTION_UP, 250, 175, 0);
-        up.setSource(SOURCE_TOUCHSCREEN);
 
         mMotionEventsHandler.onMotionEvent(down);
         mMotionEventsHandler.onMotionEvent(move1);
@@ -90,8 +85,8 @@
         downPointerProperties[0].id = 1;
         downPointerProperties[0].toolType = MotionEvent.TOOL_TYPE_FINGER;
         MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 1,
-                downPointerProperties, downPointerCoords, 0, 0, 1.0f, 1.0f, 0, 0,
-                SOURCE_TOUCHPAD, 0);
+                downPointerProperties, downPointerCoords, 0, 0, 1.0f, 1.0f, 0, 0, SOURCE_MOUSE,
+                0, 0, CLASSIFICATION_MULTI_FINGER_SWIPE);
 
         MotionEvent.PointerCoords[] movePointerCoords1 = new MotionEvent.PointerCoords[1];
         movePointerCoords1[0] = new MotionEvent.PointerCoords();
@@ -103,8 +98,8 @@
         movePointerProperties1[0].id = 1;
         movePointerProperties1[0].toolType = MotionEvent.TOOL_TYPE_FINGER;
         MotionEvent move1 = MotionEvent.obtain(0, 1, MotionEvent.ACTION_MOVE, 1,
-                movePointerProperties1, movePointerCoords1, 0, 0, 1.0f, 1.0f, 0, 0, SOURCE_TOUCHPAD,
-                0);
+                movePointerProperties1, movePointerCoords1, 0, 0, 1.0f, 1.0f, 0, 0, SOURCE_MOUSE,
+                0, 0, CLASSIFICATION_MULTI_FINGER_SWIPE);
 
         MotionEvent.PointerCoords[] movePointerCoords2 = new MotionEvent.PointerCoords[1];
         movePointerCoords2[0] = new MotionEvent.PointerCoords();
@@ -116,8 +111,8 @@
         movePointerProperties2[0].id = 1;
         movePointerProperties2[0].toolType = MotionEvent.TOOL_TYPE_FINGER;
         MotionEvent move2 = MotionEvent.obtain(0, 2, MotionEvent.ACTION_MOVE, 1,
-                movePointerProperties2, movePointerCoords2, 0, 0, 1.0f, 1.0f, 0, 0, SOURCE_TOUCHPAD,
-                0);
+                movePointerProperties2, movePointerCoords2, 0, 0, 1.0f, 1.0f, 0, 0, SOURCE_MOUSE,
+                0, 0, CLASSIFICATION_MULTI_FINGER_SWIPE);
 
         MotionEvent.PointerCoords[] upPointerCoords = new MotionEvent.PointerCoords[1];
         upPointerCoords[0] = new MotionEvent.PointerCoords();
@@ -129,7 +124,8 @@
         upPointerProperties2[0].id = 1;
         upPointerProperties2[0].toolType = MotionEvent.TOOL_TYPE_FINGER;
         MotionEvent up = MotionEvent.obtain(0, 2, MotionEvent.ACTION_UP, 1,
-                upPointerProperties2, upPointerCoords, 0, 0, 1.0f, 1.0f, 0, 0, SOURCE_TOUCHPAD, 0);
+                upPointerProperties2, upPointerCoords, 0, 0, 1.0f, 1.0f, 0, 0, SOURCE_MOUSE,
+                0, 0, CLASSIFICATION_MULTI_FINGER_SWIPE);
 
         mMotionEventsHandler.onMotionEvent(down);
         mMotionEventsHandler.onMotionEvent(move1);
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 8440455..39c4e06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -23,10 +23,14 @@
 import android.os.UserManager
 import android.test.suitebuilder.annotation.SmallTest
 import androidx.test.runner.AndroidJUnit4
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.ACTION_CREATE_NOTE
+import com.android.systemui.notetask.NoteTaskController.Companion.INTENT_EXTRA_USE_STYLUS_MODE
+import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
+import com.android.systemui.notetask.NoteTaskInfoResolver.NoteTaskInfo
 import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
 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.whenever
 import com.android.wm.shell.bubbles.Bubbles
@@ -36,8 +40,8 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
-import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
 import org.mockito.MockitoAnnotations
 
 /**
@@ -50,24 +54,23 @@
 @RunWith(AndroidJUnit4::class)
 internal class NoteTaskControllerTest : SysuiTestCase() {
 
-    private val notesIntent = Intent(ACTION_CREATE_NOTE)
-
     @Mock lateinit var context: Context
     @Mock lateinit var packageManager: PackageManager
-    @Mock lateinit var noteTaskIntentResolver: NoteTaskIntentResolver
+    @Mock lateinit var resolver: NoteTaskInfoResolver
     @Mock lateinit var bubbles: Bubbles
     @Mock lateinit var optionalBubbles: Optional<Bubbles>
     @Mock lateinit var keyguardManager: KeyguardManager
     @Mock lateinit var optionalKeyguardManager: Optional<KeyguardManager>
     @Mock lateinit var optionalUserManager: Optional<UserManager>
     @Mock lateinit var userManager: UserManager
+    @Mock lateinit var uiEventLogger: UiEventLogger
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
         whenever(context.packageManager).thenReturn(packageManager)
-        whenever(noteTaskIntentResolver.resolveIntent()).thenReturn(notesIntent)
+        whenever(resolver.resolveInfo()).thenReturn(NoteTaskInfo(NOTES_PACKAGE_NAME, NOTES_UID))
         whenever(optionalBubbles.orElse(null)).thenReturn(bubbles)
         whenever(optionalKeyguardManager.orElse(null)).thenReturn(keyguardManager)
         whenever(optionalUserManager.orElse(null)).thenReturn(userManager)
@@ -77,101 +80,182 @@
     private fun createNoteTaskController(isEnabled: Boolean = true): NoteTaskController {
         return NoteTaskController(
             context = context,
-            intentResolver = noteTaskIntentResolver,
+            resolver = resolver,
             optionalBubbles = optionalBubbles,
             optionalKeyguardManager = optionalKeyguardManager,
             optionalUserManager = optionalUserManager,
             isEnabled = isEnabled,
+            uiEventLogger = uiEventLogger,
         )
     }
 
     // region showNoteTask
     @Test
-    fun showNoteTask_keyguardIsLocked_shouldStartActivity() {
+    fun showNoteTask_keyguardIsLocked_shouldStartActivityAndLogUiEvent() {
         whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
 
-        createNoteTaskController().showNoteTask(isInMultiWindowMode = false)
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE,
+            )
 
-        verify(context).startActivity(notesIntent)
-        verify(bubbles, never()).showOrHideAppBubble(notesIntent)
+        val intentCaptor = argumentCaptor<Intent>()
+        verify(context).startActivity(capture(intentCaptor))
+        intentCaptor.value.let { intent ->
+            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+            assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+        }
+        verifyZeroInteractions(bubbles)
+        verify(uiEventLogger)
+            .log(
+                ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE,
+                NOTES_UID,
+                NOTES_PACKAGE_NAME
+            )
     }
 
     @Test
-    fun showNoteTask_keyguardIsUnlocked_shouldStartBubbles() {
+    fun showNoteTask_keyguardIsUnlocked_shouldStartBubblesAndLogUiEvent() {
         whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
 
-        createNoteTaskController().showNoteTask(isInMultiWindowMode = false)
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
+            )
 
-        verify(bubbles).showOrHideAppBubble(notesIntent)
-        verify(context, never()).startActivity(notesIntent)
+        verifyZeroInteractions(context)
+        val intentCaptor = argumentCaptor<Intent>()
+        verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+        intentCaptor.value.let { intent ->
+            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+            assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+        }
+        verify(uiEventLogger)
+            .log(
+                ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
+                NOTES_UID,
+                NOTES_PACKAGE_NAME
+            )
     }
 
     @Test
-    fun showNoteTask_isInMultiWindowMode_shouldStartActivity() {
+    fun showNoteTask_keyguardIsUnlocked_uiEventIsNull_shouldStartBubblesWithoutLoggingUiEvent() {
         whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
 
-        createNoteTaskController().showNoteTask(isInMultiWindowMode = true)
+        createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
 
-        verify(context).startActivity(notesIntent)
-        verify(bubbles, never()).showOrHideAppBubble(notesIntent)
+        verifyZeroInteractions(context)
+        val intentCaptor = argumentCaptor<Intent>()
+        verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+        intentCaptor.value.let { intent ->
+            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+            assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+        }
+        verifyZeroInteractions(uiEventLogger)
+    }
+
+    @Test
+    fun showNoteTask_isInMultiWindowMode_shouldStartActivityAndLogUiEvent() {
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = true,
+                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT,
+            )
+
+        val intentCaptor = argumentCaptor<Intent>()
+        verify(context).startActivity(capture(intentCaptor))
+        intentCaptor.value.let { intent ->
+            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+            assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+        }
+        verifyZeroInteractions(bubbles)
+        verify(uiEventLogger)
+            .log(ShowNoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT, NOTES_UID, NOTES_PACKAGE_NAME)
     }
 
     @Test
     fun showNoteTask_bubblesIsNull_shouldDoNothing() {
         whenever(optionalBubbles.orElse(null)).thenReturn(null)
 
-        createNoteTaskController().showNoteTask(isInMultiWindowMode = false)
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+            )
 
-        verify(context, never()).startActivity(notesIntent)
-        verify(bubbles, never()).showOrHideAppBubble(notesIntent)
+        verifyZeroInteractions(context, bubbles, uiEventLogger)
     }
 
     @Test
     fun showNoteTask_keyguardManagerIsNull_shouldDoNothing() {
         whenever(optionalKeyguardManager.orElse(null)).thenReturn(null)
 
-        createNoteTaskController().showNoteTask(isInMultiWindowMode = false)
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
+            )
 
-        verify(context, never()).startActivity(notesIntent)
-        verify(bubbles, never()).showOrHideAppBubble(notesIntent)
+        verifyZeroInteractions(context, bubbles, uiEventLogger)
     }
 
     @Test
     fun showNoteTask_userManagerIsNull_shouldDoNothing() {
         whenever(optionalUserManager.orElse(null)).thenReturn(null)
 
-        createNoteTaskController().showNoteTask(isInMultiWindowMode = false)
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
+            )
 
-        verify(context, never()).startActivity(notesIntent)
-        verify(bubbles, never()).showOrHideAppBubble(notesIntent)
+        verifyZeroInteractions(context, bubbles, uiEventLogger)
     }
 
     @Test
     fun showNoteTask_intentResolverReturnsNull_shouldDoNothing() {
-        whenever(noteTaskIntentResolver.resolveIntent()).thenReturn(null)
+        whenever(resolver.resolveInfo()).thenReturn(null)
 
-        createNoteTaskController().showNoteTask(isInMultiWindowMode = false)
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
+            )
 
-        verify(context, never()).startActivity(notesIntent)
-        verify(bubbles, never()).showOrHideAppBubble(notesIntent)
+        verifyZeroInteractions(context, bubbles, uiEventLogger)
     }
 
     @Test
     fun showNoteTask_flagDisabled_shouldDoNothing() {
-        createNoteTaskController(isEnabled = false).showNoteTask()
+        createNoteTaskController(isEnabled = false)
+            .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON)
 
-        verify(context, never()).startActivity(notesIntent)
-        verify(bubbles, never()).showOrHideAppBubble(notesIntent)
+        verifyZeroInteractions(context, bubbles, uiEventLogger)
     }
 
     @Test
     fun showNoteTask_userIsLocked_shouldDoNothing() {
         whenever(userManager.isUserUnlocked).thenReturn(false)
 
-        createNoteTaskController().showNoteTask(isInMultiWindowMode = false)
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
+            )
 
-        verify(context, never()).startActivity(notesIntent)
-        verify(bubbles, never()).showOrHideAppBubble(notesIntent)
+        verifyZeroInteractions(context, bubbles, uiEventLogger)
     }
     // endregion
 
@@ -206,4 +290,9 @@
         assertThat(argument.value.flattenToString()).isEqualTo(expected.flattenToString())
     }
     // endregion
+
+    private companion object {
+        const val NOTES_PACKAGE_NAME = "com.android.note.app"
+        const val NOTES_UID = 123456
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
new file mode 100644
index 0000000..d6495d8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
@@ -0,0 +1,108 @@
+/*
+ * 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.notetask
+
+import android.app.role.RoleManager
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
+import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.eq
+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.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.MockitoAnnotations
+
+/**
+ * Tests for [NoteTaskInfoResolver].
+ *
+ * Build/Install/Run:
+ * - atest SystemUITests:NoteTaskInfoResolverTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+internal class NoteTaskInfoResolverTest : SysuiTestCase() {
+
+    @Mock lateinit var packageManager: PackageManager
+    @Mock lateinit var roleManager: RoleManager
+
+    private lateinit var underTest: NoteTaskInfoResolver
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        underTest = NoteTaskInfoResolver(context, roleManager, packageManager)
+    }
+
+    @Test
+    fun resolveInfo_shouldReturnInfo() {
+        val packageName = "com.android.note.app"
+        val uid = 123456
+        whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
+            .then { listOf(packageName) }
+        whenever(
+                packageManager.getApplicationInfoAsUser(
+                    eq(packageName),
+                    any<PackageManager.ApplicationInfoFlags>(),
+                    eq(context.user)
+                )
+            )
+            .thenReturn(ApplicationInfo().apply { this.uid = uid })
+
+        val actual = underTest.resolveInfo()
+
+        requireNotNull(actual) { "Note task info must not be null" }
+        assertThat(actual.packageName).isEqualTo(packageName)
+        assertThat(actual.uid).isEqualTo(uid)
+    }
+
+    @Test
+    fun resolveInfo_packageManagerThrowsException_shouldReturnInfoWithZeroUid() {
+        val packageName = "com.android.note.app"
+        whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
+            .then { listOf(packageName) }
+        whenever(
+                packageManager.getApplicationInfoAsUser(
+                    eq(packageName),
+                    any<PackageManager.ApplicationInfoFlags>(),
+                    eq(context.user)
+                )
+            )
+            .thenThrow(PackageManager.NameNotFoundException(packageName))
+
+        val actual = underTest.resolveInfo()
+
+        requireNotNull(actual) { "Note task info must not be null" }
+        assertThat(actual.packageName).isEqualTo(packageName)
+        assertThat(actual.uid).isEqualTo(0)
+    }
+
+    @Test
+    fun resolveInfo_noRoleHolderIsSet_shouldReturnNull() {
+        whenever(roleManager.getRoleHoldersAsUser(eq(NoteTaskInfoResolver.ROLE_NOTES), any()))
+            .then { listOf<String>() }
+
+        val actual = underTest.resolveInfo()
+
+        assertThat(actual).isNull()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
index 010ac5b..53720ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
@@ -15,11 +15,14 @@
  */
 package com.android.systemui.notetask
 
+import android.app.KeyguardManager
 import android.test.suitebuilder.annotation.SmallTest
 import android.view.KeyEvent
 import androidx.test.runner.AndroidJUnit4
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
 import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.android.wm.shell.bubbles.Bubbles
 import java.util.Optional
@@ -30,6 +33,7 @@
 import org.mockito.Mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
 import org.mockito.MockitoAnnotations
 
 /**
@@ -55,12 +59,16 @@
         whenever(optionalBubbles.orElse(null)).thenReturn(bubbles)
     }
 
-    private fun createNoteTaskInitializer(isEnabled: Boolean = true): NoteTaskInitializer {
+    private fun createNoteTaskInitializer(
+        isEnabled: Boolean = true,
+        optionalKeyguardManager: Optional<KeyguardManager> = Optional.empty(),
+    ): NoteTaskInitializer {
         return NoteTaskInitializer(
             optionalBubbles = optionalBubbles,
             noteTaskController = noteTaskController,
             commandQueue = commandQueue,
             isEnabled = isEnabled,
+            optionalKeyguardManager = optionalKeyguardManager,
         )
     }
 
@@ -105,19 +113,44 @@
 
     // region handleSystemKey
     @Test
-    fun handleSystemKey_receiveValidSystemKey_shouldShowNoteTask() {
-        createNoteTaskInitializer()
+    fun handleSystemKey_receiveValidSystemKey_keyguardNotLocked_shouldShowNoteTaskWithUnlocked() {
+        val keyguardManager =
+            mock<KeyguardManager>() { whenever(isKeyguardLocked).thenReturn(false) }
+        createNoteTaskInitializer(optionalKeyguardManager = Optional.of(keyguardManager))
             .callbacks
             .handleSystemKey(NoteTaskController.NOTE_TASK_KEY_EVENT)
 
-        verify(noteTaskController).showNoteTask()
+        verify(noteTaskController)
+            .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON)
+    }
+
+    @Test
+    fun handleSystemKey_receiveValidSystemKey_keyguardLocked_shouldShowNoteTaskWithLocked() {
+        val keyguardManager =
+            mock<KeyguardManager>() { whenever(isKeyguardLocked).thenReturn(true) }
+        createNoteTaskInitializer(optionalKeyguardManager = Optional.of(keyguardManager))
+            .callbacks
+            .handleSystemKey(NoteTaskController.NOTE_TASK_KEY_EVENT)
+
+        verify(noteTaskController)
+            .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED)
+    }
+
+    @Test
+    fun handleSystemKey_receiveValidSystemKey_nullKeyguardManager_shouldShowNoteTaskWithUnlocked() {
+        createNoteTaskInitializer(optionalKeyguardManager = Optional.empty())
+            .callbacks
+            .handleSystemKey(NoteTaskController.NOTE_TASK_KEY_EVENT)
+
+        verify(noteTaskController)
+            .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON)
     }
 
     @Test
     fun handleSystemKey_receiveInvalidSystemKey_shouldDoNothing() {
         createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent.KEYCODE_UNKNOWN)
 
-        verify(noteTaskController, never()).showNoteTask()
+        verifyZeroInteractions(noteTaskController)
     }
     // endregion
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt
deleted file mode 100644
index 18be92b..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.notetask
-
-import android.app.role.RoleManager
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.test.suitebuilder.annotation.SmallTest
-import androidx.test.runner.AndroidJUnit4
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.ACTION_CREATE_NOTE
-import com.android.systemui.util.mockito.eq
-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.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.MockitoAnnotations
-
-/**
- * Tests for [NoteTaskIntentResolver].
- *
- * Build/Install/Run:
- * - atest SystemUITests:NoteTaskIntentResolverTest
- */
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-internal class NoteTaskIntentResolverTest : SysuiTestCase() {
-
-    @Mock lateinit var packageManager: PackageManager
-    @Mock lateinit var roleManager: RoleManager
-
-    private lateinit var underTest: NoteTaskIntentResolver
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        underTest = NoteTaskIntentResolver(context, roleManager)
-    }
-
-    @Test
-    fun resolveIntent_shouldReturnIntentInStylusMode() {
-        val packageName = "com.android.note.app"
-        whenever(roleManager.getRoleHoldersAsUser(NoteTaskIntentResolver.ROLE_NOTES, context.user))
-            .then { listOf(packageName) }
-
-        val actual = underTest.resolveIntent()
-
-        requireNotNull(actual) { "Intent must not be null" }
-        assertThat(actual.action).isEqualTo(ACTION_CREATE_NOTE)
-        assertThat(actual.`package`).isEqualTo(packageName)
-        val expectedExtra = actual.getExtra(NoteTaskIntentResolver.INTENT_EXTRA_USE_STYLUS_MODE)
-        assertThat(expectedExtra).isEqualTo(true)
-        val expectedFlag = actual.flags and Intent.FLAG_ACTIVITY_NEW_TASK
-        assertThat(expectedFlag).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
-    }
-
-    @Test
-    fun resolveIntent_noRoleHolderIsSet_shouldReturnNull() {
-        whenever(roleManager.getRoleHoldersAsUser(eq(NoteTaskIntentResolver.ROLE_NOTES), any()))
-            .then { listOf<String>() }
-
-        val actual = underTest.resolveIntent()
-
-        assertThat(actual).isNull()
-    }
-}
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 a1d42a0..cdc683f 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
@@ -27,7 +27,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState
 import com.android.systemui.notetask.NoteTaskController
-import com.android.systemui.util.mockito.whenever
+import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
@@ -53,7 +53,6 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        whenever(noteTaskController.showNoteTask()).then {}
     }
 
     private fun createUnderTest(isEnabled: Boolean) =
@@ -96,6 +95,7 @@
 
         underTest.onTriggered(expandable = null)
 
-        verify(noteTaskController).showNoteTask()
+        verify(noteTaskController)
+            .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index 3da7a22..8019fb5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -42,7 +42,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -158,16 +157,6 @@
     }
 
     @Test
-    public void testDisableLowBatteryReminder_noNotification() {
-        mGlobalSettings.putInt(Settings.Global.LOW_POWER_MODE_REMINDER_ENABLED, 0);
-
-        mPowerNotificationWarnings.showLowBatteryWarning(false);
-
-        verify(mMockNotificationManager, times(0))
-                .notifyAsUser(anyString(), eq(SystemMessage.NOTE_POWER_LOW), any(), any());
-    }
-
-    @Test
     public void testShowLowBatteryNotification_NotifyAsUser() {
         mPowerNotificationWarnings.showLowBatteryWarning(false);
         verify(mMockNotificationManager, times(1))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/process/condition/UserProcessConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/process/condition/UserProcessConditionTest.java
new file mode 100644
index 0000000..2293fc5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/process/condition/UserProcessConditionTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.process.condition;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.process.ProcessWrapper;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shared.condition.Condition;
+import com.android.systemui.shared.condition.Monitor;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class UserProcessConditionTest extends SysuiTestCase {
+    @Mock
+    UserTracker mUserTracker;
+
+    @Mock
+    ProcessWrapper mProcessWrapper;
+
+    @Mock
+    Monitor.Callback mCallback;
+
+    private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    /**
+     * Verifies condition reports false when tracker reports a different user id than the
+     * identifier from the process handle.
+     */
+    @Test
+    public void testConditionFailsWithDifferentIds() {
+
+        final Condition condition = new UserProcessCondition(mProcessWrapper, mUserTracker);
+        when(mProcessWrapper.getUserHandleIdentifier()).thenReturn(0);
+        when(mUserTracker.getUserId()).thenReturn(1);
+
+        final Monitor monitor = new Monitor(mExecutor);
+
+        monitor.addSubscription(new Monitor.Subscription.Builder(mCallback)
+                .addCondition(condition)
+                .build());
+
+        mExecutor.runAllReady();
+
+        verify(mCallback).onConditionsChanged(false);
+    }
+
+    /**
+     * Verifies condition reports false when tracker reports a different user id than the
+     * identifier from the process handle.
+     */
+    @Test
+    public void testConditionSucceedsWithSameIds() {
+
+        final Condition condition = new UserProcessCondition(mProcessWrapper, mUserTracker);
+        when(mProcessWrapper.getUserHandleIdentifier()).thenReturn(0);
+        when(mUserTracker.getUserId()).thenReturn(0);
+
+        final Monitor monitor = new Monitor(mExecutor);
+
+        monitor.addSubscription(new Monitor.Subscription.Builder(mCallback)
+                .addCondition(condition)
+                .build());
+
+        mExecutor.runAllReady();
+
+        verify(mCallback).onConditionsChanged(true);
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
index a13bece..15545a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
@@ -29,9 +29,9 @@
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.pm.UserInfo;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.dreams.IDreamManager;
 import android.service.quicksettings.Tile;
@@ -123,7 +123,7 @@
 
         // Should not be available if component is not set
         mSecureSettings.putInt(Settings.Secure.SCREENSAVER_ENABLED, 1);
-        when(mDreamManager.getDreamComponents()).thenReturn(null);
+        when(mDreamManager.getDreamComponentsForUser(mUserTracker.getUserId())).thenReturn(null);
 
         mTestableLooper.processAllMessages();
         assertEquals(Tile.STATE_UNAVAILABLE, mTile.getState().state);
@@ -134,9 +134,8 @@
     public void testInactiveWhenDreaming() throws RemoteException {
         setScreensaverEnabled(true);
 
-        when(mDreamManager.getDreamComponents()).thenReturn(new ComponentName[]{
-                COLORS_DREAM_COMPONENT_NAME
-        });
+        when(mDreamManager.getDreamComponentsForUser(mUserTracker.getUserId()))
+             .thenReturn(new ComponentName[]{COLORS_DREAM_COMPONENT_NAME});
         when(mDreamManager.isDreaming()).thenReturn(false);
 
         mTile.refreshState();
@@ -148,9 +147,8 @@
     public void testActive() throws RemoteException {
         setScreensaverEnabled(true);
 
-        when(mDreamManager.getDreamComponents()).thenReturn(new ComponentName[]{
-                COLORS_DREAM_COMPONENT_NAME
-        });
+        when(mDreamManager.getDreamComponentsForUser(mUserTracker.getUserId()))
+             .thenReturn(new ComponentName[]{COLORS_DREAM_COMPONENT_NAME});
         when(mDreamManager.isDreaming()).thenReturn(true);
 
         mTile.refreshState();
@@ -162,9 +160,8 @@
     public void testClick() throws RemoteException {
         // Set the AOSP dream enabled as the base setup.
         setScreensaverEnabled(true);
-        when(mDreamManager.getDreamComponents()).thenReturn(new ComponentName[]{
-                COLORS_DREAM_COMPONENT_NAME
-        });
+        when(mDreamManager.getDreamComponentsForUser(mUserTracker.getUserId()))
+             .thenReturn(new ComponentName[]{COLORS_DREAM_COMPONENT_NAME});
         when(mDreamManager.isDreaming()).thenReturn(false);
 
         mTile.refreshState();
@@ -203,21 +200,21 @@
 
         DreamTile supportedTileAllUsers = constructTileForTest(true, false);
 
-        UserHandle systemUserHandle = mock(UserHandle.class);
-        when(systemUserHandle.isSystem()).thenReturn(true);
+        UserInfo mainUserInfo = mock(UserInfo.class);
+        when(mainUserInfo.isMain()).thenReturn(true);
 
-        UserHandle nonSystemUserHandle = mock(UserHandle.class);
-        when(nonSystemUserHandle.isSystem()).thenReturn(false);
+        UserInfo nonMainUserInfo = mock(UserInfo.class);
+        when(nonMainUserInfo.isMain()).thenReturn(false);
 
-        when(mUserTracker.getUserHandle()).thenReturn(systemUserHandle);
+        when(mUserTracker.getUserInfo()).thenReturn(mainUserInfo);
         assertTrue(supportedTileAllUsers.isAvailable());
-        when(mUserTracker.getUserHandle()).thenReturn(nonSystemUserHandle);
+        when(mUserTracker.getUserInfo()).thenReturn(nonMainUserInfo);
         assertTrue(supportedTileAllUsers.isAvailable());
 
         DreamTile supportedTileOnlySystemUser = constructTileForTest(true, true);
-        when(mUserTracker.getUserHandle()).thenReturn(systemUserHandle);
+        when(mUserTracker.getUserInfo()).thenReturn(mainUserInfo);
         assertTrue(supportedTileOnlySystemUser.isAvailable());
-        when(mUserTracker.getUserHandle()).thenReturn(nonSystemUserHandle);
+        when(mUserTracker.getUserInfo()).thenReturn(nonMainUserInfo);
         assertFalse(supportedTileOnlySystemUser.isAvailable());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
index 80c39cf..addca9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
@@ -37,10 +37,12 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
 import com.android.systemui.statusbar.connectivity.AccessPointController;
 import com.android.systemui.statusbar.connectivity.IconState;
 import com.android.systemui.statusbar.connectivity.NetworkController;
+import com.android.systemui.statusbar.connectivity.WifiIndicators;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -135,4 +137,24 @@
         assertThat(mTile.getState().secondaryLabel)
             .isNotEqualTo(mContext.getString(R.string.status_bar_airplane));
     }
+
+    @Test
+    public void setIsAirplaneMode_APM_enabled_after_wifi_disconnected() {
+        WifiIndicators wifiIndicators = new WifiIndicators(
+            /* enabled= */ true,
+            /* statusIcon= */ null,
+            /* qsIcon= */ null,
+            /* activityIn= */ false,
+            /* activityOut= */ false,
+            /* description= */ null,
+            /* isTransient= */ false,
+            /* statusLabel= */ null
+        );
+        mTile.mSignalCallback.setWifiIndicators(wifiIndicators);
+        IconState state = new IconState(true, 0, "");
+        mTile.mSignalCallback.setIsAirplaneMode(state);
+        mTestableLooper.processAllMessages();
+        assertThat(mTile.getState().icon).isEqualTo(
+                QSTileImpl.ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index 62404cb..84cc977 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -941,6 +941,26 @@
         }
     }
 
+    @Test
+    public void getMobileNetworkSummary_withCarrierNetworkChange() {
+        Resources res = mock(Resources.class);
+        doReturn("Carrier network changing").when(res).getString(anyInt());
+        when(SubscriptionManager.getResourcesForSubId(any(), eq(SUB_ID))).thenReturn(res);
+        InternetDialogController spyController = spy(mInternetDialogController);
+        Map<Integer, TelephonyDisplayInfo> mSubIdTelephonyDisplayInfoMap =
+                spyController.mSubIdTelephonyDisplayInfoMap;
+        TelephonyDisplayInfo info = new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
+
+        mSubIdTelephonyDisplayInfoMap.put(SUB_ID, info);
+        doReturn(true).when(spyController).isMobileDataEnabled();
+        doReturn(true).when(spyController).activeNetworkIsCellular();
+        spyController.mCarrierNetworkChangeMode = true;
+        String dds = spyController.getMobileNetworkSummary(SUB_ID);
+
+        assertThat(dds).contains(mContext.getString(R.string.carrier_network_change_mode));
+    }
+
     private String getResourcesString(String name) {
         return mContext.getResources().getString(getResourcesId(name));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
index 8127ccc..6e6833d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
@@ -16,13 +16,15 @@
 
 package com.android.systemui.screenrecord;
 
+import static com.google.common.truth.Truth.assertThat;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
+import android.app.Dialog;
 import android.app.PendingIntent;
 import android.content.Intent;
 import android.os.Looper;
@@ -31,7 +33,13 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver;
+import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.settings.UserContextProvider;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.concurrency.FakeExecutor;
@@ -61,8 +69,15 @@
     @Mock
     private UserContextProvider mUserContextProvider;
     @Mock
+    private ScreenCaptureDevicePolicyResolver mDevicePolicyResolver;
+    @Mock
+    private DialogLaunchAnimator mDialogLaunchAnimator;
+    @Mock
+    private ActivityStarter mActivityStarter;
+    @Mock
     private UserTracker mUserTracker;
 
+    private FakeFeatureFlags mFeatureFlags;
     private RecordingController mController;
 
     private static final int USER_ID = 10;
@@ -70,8 +85,9 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mController = new RecordingController(mMainExecutor, mBroadcastDispatcher,
-                mUserContextProvider, mUserTracker);
+        mFeatureFlags = new FakeFeatureFlags();
+        mController = new RecordingController(mMainExecutor, mBroadcastDispatcher, mContext,
+                mFeatureFlags, mUserContextProvider, () -> mDevicePolicyResolver, mUserTracker);
         mController.addCallback(mCallback);
     }
 
@@ -190,4 +206,67 @@
         verify(mCallback).onRecordingEnd();
         assertFalse(mController.isRecording());
     }
+
+    @Test
+    public void testPoliciesFlagDisabled_screenCapturingNotAllowed_returnsNullDevicePolicyDialog() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING, true);
+        mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES, false);
+        when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(true);
+
+        Dialog dialog = mController.createScreenRecordDialog(mContext, mFeatureFlags,
+                mDialogLaunchAnimator, mActivityStarter, /* onStartRecordingClicked= */ null);
+
+        assertThat(dialog).isInstanceOf(ScreenRecordPermissionDialog.class);
+    }
+
+    @Test
+    public void testPartialScreenSharingDisabled_returnsLegacyDialog() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING, false);
+        mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES, false);
+
+        Dialog dialog = mController.createScreenRecordDialog(mContext, mFeatureFlags,
+                mDialogLaunchAnimator, mActivityStarter, /* onStartRecordingClicked= */ null);
+
+        assertThat(dialog).isInstanceOf(ScreenRecordDialog.class);
+    }
+
+    @Test
+    public void testPoliciesFlagEnabled_screenCapturingNotAllowed_returnsDevicePolicyDialog() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING, true);
+        mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES, true);
+        when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(true);
+
+        Dialog dialog = mController.createScreenRecordDialog(mContext, mFeatureFlags,
+                mDialogLaunchAnimator, mActivityStarter, /* onStartRecordingClicked= */ null);
+
+        assertThat(dialog).isInstanceOf(ScreenCaptureDisabledDialog.class);
+    }
+
+    @Test
+    public void testPoliciesFlagEnabled_screenCapturingAllowed_returnsNullDevicePolicyDialog() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING, true);
+        mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES, true);
+        when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(false);
+
+        Dialog dialog = mController.createScreenRecordDialog(mContext, mFeatureFlags,
+                mDialogLaunchAnimator, mActivityStarter, /* onStartRecordingClicked= */ null);
+
+        assertThat(dialog).isInstanceOf(ScreenRecordPermissionDialog.class);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt
index 0aa3621..5b094c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.screenrecord
 
+import android.os.UserHandle
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.View
@@ -59,6 +60,7 @@
         dialog =
             ScreenRecordPermissionDialog(
                 context,
+                UserHandle.of(0),
                 controller,
                 starter,
                 dialogLaunchAnimator,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt
new file mode 100644
index 0000000..9f0a803
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt
@@ -0,0 +1,143 @@
+package com.android.systemui.screenshot
+
+import android.graphics.drawable.Drawable
+import android.os.UserHandle
+import android.testing.AndroidTestingRunner
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.Guideline
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import junit.framework.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class MessageContainerControllerTest : SysuiTestCase() {
+    lateinit var messageContainer: MessageContainerController
+
+    @Mock lateinit var workProfileMessageController: WorkProfileMessageController
+
+    @Mock lateinit var screenshotDetectionController: ScreenshotDetectionController
+
+    @Mock lateinit var icon: Drawable
+
+    lateinit var workProfileFirstRunView: ViewGroup
+    lateinit var detectionNoticeView: ViewGroup
+    lateinit var container: FrameLayout
+
+    var featureFlags = FakeFeatureFlags()
+    lateinit var screenshotView: ViewGroup
+
+    val userHandle = UserHandle.of(5)
+    val screenshotData = ScreenshotData.forTesting()
+
+    val appName = "app name"
+    lateinit var workProfileData: WorkProfileMessageController.WorkProfileFirstRunData
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        messageContainer =
+            MessageContainerController(
+                workProfileMessageController,
+                screenshotDetectionController,
+                featureFlags
+            )
+        screenshotView = ConstraintLayout(mContext)
+        workProfileData = WorkProfileMessageController.WorkProfileFirstRunData(appName, icon)
+
+        val guideline = Guideline(mContext)
+        guideline.id = com.android.systemui.R.id.guideline
+        screenshotView.addView(guideline)
+
+        container = FrameLayout(mContext)
+        container.id = com.android.systemui.R.id.screenshot_message_container
+        screenshotView.addView(container)
+
+        workProfileFirstRunView = FrameLayout(mContext)
+        workProfileFirstRunView.id = com.android.systemui.R.id.work_profile_first_run
+        container.addView(workProfileFirstRunView)
+
+        detectionNoticeView = FrameLayout(mContext)
+        detectionNoticeView.id = com.android.systemui.R.id.screenshot_detection_notice
+        container.addView(detectionNoticeView)
+
+        messageContainer.setView(screenshotView)
+
+        screenshotData.userHandle = userHandle
+    }
+
+    @Test
+    fun testOnScreenshotTakenUserHandle_noWorkProfileFirstRun() {
+        featureFlags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, true)
+        // (just being explicit here)
+        whenever(workProfileMessageController.onScreenshotTaken(eq(userHandle))).thenReturn(null)
+
+        messageContainer.onScreenshotTaken(userHandle)
+
+        verify(workProfileMessageController, never()).populateView(any(), any(), any())
+    }
+
+    @Test
+    fun testOnScreenshotTakenUserHandle_noWorkProfileFlag() {
+        featureFlags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
+
+        messageContainer.onScreenshotTaken(userHandle)
+
+        verify(workProfileMessageController, never()).onScreenshotTaken(any())
+        verify(workProfileMessageController, never()).populateView(any(), any(), any())
+    }
+
+    @Test
+    fun testOnScreenshotTakenUserHandle_withWorkProfileFirstRun() {
+        featureFlags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, true)
+        whenever(workProfileMessageController.onScreenshotTaken(eq(userHandle)))
+            .thenReturn(workProfileData)
+        messageContainer.onScreenshotTaken(userHandle)
+
+        verify(workProfileMessageController)
+            .populateView(eq(workProfileFirstRunView), eq(workProfileData), any())
+        assertEquals(View.VISIBLE, workProfileFirstRunView.visibility)
+        assertEquals(View.GONE, detectionNoticeView.visibility)
+    }
+
+    @Test
+    fun testOnScreenshotTakenScreenshotData_flagsOff() {
+        featureFlags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
+        featureFlags.set(Flags.SCREENSHOT_DETECTION, false)
+
+        messageContainer.onScreenshotTaken(screenshotData)
+
+        verify(workProfileMessageController, never()).onScreenshotTaken(any())
+        verify(screenshotDetectionController, never()).maybeNotifyOfScreenshot(any())
+
+        assertEquals(View.GONE, container.visibility)
+    }
+
+    @Test
+    fun testOnScreenshotTakenScreenshotData_nothingToShow() {
+        featureFlags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, true)
+        featureFlags.set(Flags.SCREENSHOT_DETECTION, true)
+
+        messageContainer.onScreenshotTaken(screenshotData)
+
+        verify(workProfileMessageController, never()).populateView(any(), any(), any())
+        verify(screenshotDetectionController, never()).populateView(any(), any())
+
+        assertEquals(View.GONE, container.visibility)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
index 541d6c2..2e73c0b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
@@ -23,7 +23,7 @@
 import android.graphics.Rect
 import android.hardware.HardwareBuffer
 import android.os.UserHandle
-import android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD
+import android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER
 import android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER
 import android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN
 import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
@@ -35,6 +35,7 @@
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
+import org.junit.Assert
 import org.junit.Test
 
 private const val USER_ID = 1
@@ -55,7 +56,7 @@
         flags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
 
         val request =
-            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD).build()
+            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER).build()
         val processor = RequestProcessor(imageCapture, policy, flags, scope)
 
         var result: ScreenshotRequest? = null
@@ -78,8 +79,10 @@
     fun testProcessAsync_ScreenshotData() {
         flags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
 
-        val request = ScreenshotData.fromRequest(
-            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD).build())
+        val request =
+            ScreenshotData.fromRequest(
+                ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER).build()
+            )
         val processor = RequestProcessor(imageCapture, policy, flags, scope)
 
         var result: ScreenshotData? = null
@@ -102,7 +105,7 @@
         flags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
 
         val request =
-            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD).build()
+            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER).build()
         val processor = RequestProcessor(imageCapture, policy, flags, scope)
 
         val processedRequest = processor.process(request)
@@ -162,7 +165,7 @@
         )
 
         val request =
-            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD).build()
+            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER).build()
         val processor = RequestProcessor(imageCapture, policy, flags, scope)
 
         val processedRequest = processor.process(request)
@@ -191,6 +194,32 @@
     }
 
     @Test
+    fun testFullScreenshot_managedProfile_nullBitmap() {
+        flags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, true)
+
+        // Provide a null task bitmap when asked
+        imageCapture.image = null
+
+        // Indicate that the primary content belongs to a manged profile
+        policy.setManagedProfile(USER_ID, true)
+        policy.setDisplayContentInfo(
+            policy.getDefaultDisplayId(),
+            DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID)
+        )
+
+        val request =
+            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER).build()
+        val processor = RequestProcessor(imageCapture, policy, flags, scope)
+
+        Assert.assertThrows(IllegalStateException::class.java) {
+            runBlocking { processor.process(request) }
+        }
+        Assert.assertThrows(IllegalStateException::class.java) {
+            runBlocking { processor.process(ScreenshotData.fromRequest(request)) }
+        }
+    }
+
+    @Test
     fun testProvidedImageScreenshot_workProfilePolicyDisabled() = runBlocking {
         flags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt
new file mode 100644
index 0000000..1f18d91
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotDetectionControllerTest.kt
@@ -0,0 +1,161 @@
+/*
+ * 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.content.ComponentName
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
+import android.testing.AndroidTestingRunner
+import android.view.Display
+import android.view.IWindowManager
+import android.view.WindowManager
+import androidx.test.filters.SmallTest
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ScreenshotDetectionControllerTest {
+
+    @Mock lateinit var windowManager: IWindowManager
+
+    @Mock lateinit var packageManager: PackageManager
+
+    lateinit var controller: ScreenshotDetectionController
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+
+        controller = ScreenshotDetectionController(windowManager, packageManager)
+    }
+
+    @Test
+    fun testMaybeNotifyOfScreenshot_ignoresOverview() {
+        val data = ScreenshotData.forTesting()
+        data.source = WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW
+
+        val list = controller.maybeNotifyOfScreenshot(data)
+
+        assertTrue(list.isEmpty())
+        verify(windowManager, never()).notifyScreenshotListeners(any())
+    }
+
+    @Test
+    fun testMaybeNotifyOfScreenshot_emptySet() {
+        val data = ScreenshotData.forTesting()
+        data.source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD
+
+        whenever(windowManager.notifyScreenshotListeners(eq(Display.DEFAULT_DISPLAY)))
+            .thenReturn(listOf())
+
+        val list = controller.maybeNotifyOfScreenshot(data)
+
+        assertTrue(list.isEmpty())
+    }
+
+    @Test
+    fun testMaybeNotifyOfScreenshot_oneApp() {
+        val data = ScreenshotData.forTesting()
+        data.source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD
+
+        val component = ComponentName("package1", "class1")
+        val appName = "app name"
+        val activityInfo = mock(ActivityInfo::class.java)
+
+        whenever(
+                packageManager.getActivityInfo(
+                    eq(component),
+                    any(PackageManager.ComponentInfoFlags::class.java)
+                )
+            )
+            .thenReturn(activityInfo)
+        whenever(activityInfo.loadLabel(eq(packageManager))).thenReturn(appName)
+
+        whenever(windowManager.notifyScreenshotListeners(eq(Display.DEFAULT_DISPLAY)))
+            .thenReturn(listOf(component))
+
+        val list = controller.maybeNotifyOfScreenshot(data)
+
+        assertEquals(1, list.size)
+        assertEquals(appName, list[0])
+    }
+
+    @Test
+    fun testMaybeNotifyOfScreenshot_multipleApps() {
+        val data = ScreenshotData.forTesting()
+        data.source = WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD
+
+        val component1 = ComponentName("package1", "class1")
+        val component2 = ComponentName("package2", "class2")
+        val component3 = ComponentName("package3", "class3")
+        val appName1 = "app name 1"
+        val appName2 = "app name 2"
+        val appName3 = "app name 3"
+
+        val activityInfo1 = mock(ActivityInfo::class.java)
+        val activityInfo2 = mock(ActivityInfo::class.java)
+        val activityInfo3 = mock(ActivityInfo::class.java)
+
+        whenever(
+                packageManager.getActivityInfo(
+                    eq(component1),
+                    any(PackageManager.ComponentInfoFlags::class.java)
+                )
+            )
+            .thenReturn(activityInfo1)
+        whenever(
+                packageManager.getActivityInfo(
+                    eq(component2),
+                    any(PackageManager.ComponentInfoFlags::class.java)
+                )
+            )
+            .thenReturn(activityInfo2)
+        whenever(
+                packageManager.getActivityInfo(
+                    eq(component3),
+                    any(PackageManager.ComponentInfoFlags::class.java)
+                )
+            )
+            .thenReturn(activityInfo3)
+
+        whenever(activityInfo1.loadLabel(eq(packageManager))).thenReturn(appName1)
+        whenever(activityInfo2.loadLabel(eq(packageManager))).thenReturn(appName2)
+        whenever(activityInfo3.loadLabel(eq(packageManager))).thenReturn(appName3)
+
+        whenever(windowManager.notifyScreenshotListeners(eq(Display.DEFAULT_DISPLAY)))
+            .thenReturn(listOf(component1, component2, component3))
+
+        val list = controller.maybeNotifyOfScreenshot(data)
+
+        assertEquals(3, list.size)
+        assertEquals(appName1, list[0])
+        assertEquals(appName2, list[1])
+        assertEquals(appName3, list[2])
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
index 74969d0..1fa2ace 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
@@ -38,8 +38,9 @@
 import com.android.internal.util.ScreenshotRequest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags.SCREENSHOT_WORK_PROFILE_POLICY
 import com.android.systemui.flags.Flags.SCREENSHOT_METADATA
+import com.android.systemui.flags.Flags.SCREENSHOT_WORK_PROFILE_POLICY
+import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_CAPTURE_FAILED
 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_REQUESTED_KEY_OTHER
 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_REQUESTED_OVERVIEW
 import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback
@@ -47,6 +48,7 @@
 import com.android.systemui.util.mockito.argThat
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
 import java.util.function.Consumer
 import org.junit.Assert.assertEquals
 import org.junit.Before
@@ -55,10 +57,10 @@
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.isNull
 import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.doThrow
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
 
 private const val USER_ID = 1
 private const val TASK_ID = 11
@@ -107,18 +109,20 @@
 
         // Stub request processor as a synchronous no-op for tests with the flag enabled
         doAnswer {
-            val request: ScreenshotRequest = it.getArgument(0) as ScreenshotRequest
-            val consumer: Consumer<ScreenshotRequest> = it.getArgument(1)
-            consumer.accept(request)
-        }.`when`(requestProcessor).processAsync(
-            /* request= */ any(ScreenshotRequest::class.java), /* callback= */ any())
+                val request: ScreenshotRequest = it.getArgument(0) as ScreenshotRequest
+                val consumer: Consumer<ScreenshotRequest> = it.getArgument(1)
+                consumer.accept(request)
+            }
+            .whenever(requestProcessor)
+            .processAsync(/* request= */ any(ScreenshotRequest::class.java), /* callback= */ any())
 
         doAnswer {
-            val request: ScreenshotData = it.getArgument(0) as ScreenshotData
-            val consumer: Consumer<ScreenshotData> = it.getArgument(1)
-            consumer.accept(request)
-        }.`when`(requestProcessor).processAsync(
-            /* screenshot= */ any(ScreenshotData::class.java), /* callback= */ any())
+                val request: ScreenshotData = it.getArgument(0) as ScreenshotData
+                val consumer: Consumer<ScreenshotData> = it.getArgument(1)
+                consumer.accept(request)
+            }
+            .whenever(requestProcessor)
+            .processAsync(/* screenshot= */ any(ScreenshotData::class.java), /* callback= */ any())
 
         // Flipped in selected test cases
         flags.set(SCREENSHOT_WORK_PROFILE_POLICY, false)
@@ -162,37 +166,52 @@
                 /* requestCallback = */ any()
             )
 
-        assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
+        assertEquals("Expected one UiEvent", 1, eventLogger.numLogs())
         val logEvent = eventLogger.get(0)
 
-        assertEquals("Expected SCREENSHOT_REQUESTED UiEvent",
-            logEvent.eventId, SCREENSHOT_REQUESTED_KEY_OTHER.id)
-        assertEquals("Expected supplied package name",
-            topComponent.packageName, eventLogger.get(0).packageName)
+        assertEquals(
+            "Expected SCREENSHOT_REQUESTED UiEvent",
+            logEvent.eventId,
+            SCREENSHOT_REQUESTED_KEY_OTHER.id
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            eventLogger.get(0).packageName
+        )
     }
 
     @Test
     fun takeScreenshotFullscreen_screenshotDataEnabled() {
         flags.set(SCREENSHOT_METADATA, true)
 
-        val request = ScreenshotRequest.Builder(
-            TAKE_SCREENSHOT_FULLSCREEN,
-            SCREENSHOT_KEY_OTHER).setTopComponent(topComponent).build()
+        val request =
+            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER)
+                .setTopComponent(topComponent)
+                .build()
 
-        service.handleRequest(request, { /* onSaved */ }, callback)
+        service.handleRequest(request, { /* onSaved */}, callback)
 
-        verify(controller, times(1)).handleScreenshot(
-            eq(ScreenshotData.fromRequest(request)),
-            /* onSavedListener = */ any(),
-            /* requestCallback = */ any())
+        verify(controller, times(1))
+            .handleScreenshot(
+                eq(ScreenshotData.fromRequest(request)),
+                /* onSavedListener = */ any(),
+                /* requestCallback = */ any()
+            )
 
         assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
         val logEvent = eventLogger.get(0)
 
-        assertEquals("Expected SCREENSHOT_REQUESTED UiEvent",
-            logEvent.eventId, SCREENSHOT_REQUESTED_KEY_OTHER.id)
-        assertEquals("Expected supplied package name",
-            topComponent.packageName, eventLogger.get(0).packageName)
+        assertEquals(
+            "Expected SCREENSHOT_REQUESTED UiEvent",
+            logEvent.eventId,
+            SCREENSHOT_REQUESTED_KEY_OTHER.id
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            eventLogger.get(0).packageName
+        )
     }
 
     @Test
@@ -224,7 +243,7 @@
                 /* requestCallback = */ any()
             )
 
-        assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
+        assertEquals("Expected one UiEvent", 1, eventLogger.numLogs())
         val logEvent = eventLogger.get(0)
 
         assertEquals(
@@ -241,6 +260,8 @@
 
     @Test
     fun takeScreenshotFullscreen_userLocked() {
+        flags.set(SCREENSHOT_METADATA, true)
+
         whenever(userManager.isUserUnlocked).thenReturn(false)
 
         val request =
@@ -253,10 +274,36 @@
         verify(notificationsController, times(1)).notifyScreenshotError(anyInt())
         verify(callback, times(1)).reportError()
         verifyZeroInteractions(controller)
+
+        assertEquals("Expected two UiEvents", 2, eventLogger.numLogs())
+        val requestEvent = eventLogger.get(0)
+        assertEquals(
+            "Expected SCREENSHOT_REQUESTED_* UiEvent",
+            SCREENSHOT_REQUESTED_KEY_OTHER.id,
+            requestEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            requestEvent.packageName
+        )
+        val failureEvent = eventLogger.get(1)
+        assertEquals(
+            "Expected SCREENSHOT_CAPTURE_FAILED UiEvent",
+            SCREENSHOT_CAPTURE_FAILED.id,
+            failureEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            failureEvent.packageName
+        )
     }
 
     @Test
     fun takeScreenshotFullscreen_screenCaptureDisabled_allUsers() {
+        flags.set(SCREENSHOT_METADATA, true)
+
         whenever(devicePolicyManager.getScreenCaptureDisabled(isNull(), eq(UserHandle.USER_ALL)))
             .thenReturn(true)
 
@@ -279,6 +326,206 @@
         // error shown: Toast.makeText(...).show(), untestable
         verify(callback, times(1)).reportError()
         verifyZeroInteractions(controller)
+        assertEquals("Expected two UiEvents", 2, eventLogger.numLogs())
+        val requestEvent = eventLogger.get(0)
+        assertEquals(
+            "Expected SCREENSHOT_REQUESTED_* UiEvent",
+            SCREENSHOT_REQUESTED_KEY_OTHER.id,
+            requestEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            requestEvent.packageName
+        )
+        val failureEvent = eventLogger.get(1)
+        assertEquals(
+            "Expected SCREENSHOT_CAPTURE_FAILED UiEvent",
+            SCREENSHOT_CAPTURE_FAILED.id,
+            failureEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            failureEvent.packageName
+        )
+    }
+
+    @Test
+    fun takeScreenshotFullscreen_userLocked_metadataDisabled() {
+        flags.set(SCREENSHOT_METADATA, false)
+        whenever(userManager.isUserUnlocked).thenReturn(false)
+
+        val request =
+            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER)
+                .setTopComponent(topComponent)
+                .build()
+
+        service.handleRequest(request, { /* onSaved */}, callback)
+
+        verify(notificationsController, times(1)).notifyScreenshotError(anyInt())
+        verify(callback, times(1)).reportError()
+        verifyZeroInteractions(controller)
+
+        assertEquals("Expected two UiEvents", 2, eventLogger.numLogs())
+        val requestEvent = eventLogger.get(0)
+        assertEquals(
+            "Expected SCREENSHOT_REQUESTED_* UiEvent",
+            SCREENSHOT_REQUESTED_KEY_OTHER.id,
+            requestEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            requestEvent.packageName
+        )
+        val failureEvent = eventLogger.get(1)
+        assertEquals(
+            "Expected SCREENSHOT_CAPTURE_FAILED UiEvent",
+            SCREENSHOT_CAPTURE_FAILED.id,
+            failureEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            failureEvent.packageName
+        )
+    }
+
+    @Test
+    fun takeScreenshotFullscreen_screenCaptureDisabled_allUsers_metadataDisabled() {
+        flags.set(SCREENSHOT_METADATA, false)
+
+        whenever(devicePolicyManager.getScreenCaptureDisabled(isNull(), eq(UserHandle.USER_ALL)))
+            .thenReturn(true)
+
+        whenever(
+                devicePolicyResourcesManager.getString(
+                    eq(SCREENSHOT_BLOCKED_BY_ADMIN),
+                    /* Supplier<String> */
+                    any(),
+                )
+            )
+            .thenReturn("SCREENSHOT_BLOCKED_BY_ADMIN")
+
+        val request =
+            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER)
+                .setTopComponent(topComponent)
+                .build()
+
+        service.handleRequest(request, { /* onSaved */}, callback)
+
+        // error shown: Toast.makeText(...).show(), untestable
+        verify(callback, times(1)).reportError()
+        verifyZeroInteractions(controller)
+        assertEquals("Expected two UiEvents", 2, eventLogger.numLogs())
+        val requestEvent = eventLogger.get(0)
+        assertEquals(
+            "Expected SCREENSHOT_REQUESTED_* UiEvent",
+            SCREENSHOT_REQUESTED_KEY_OTHER.id,
+            requestEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            requestEvent.packageName
+        )
+        val failureEvent = eventLogger.get(1)
+        assertEquals(
+            "Expected SCREENSHOT_CAPTURE_FAILED UiEvent",
+            SCREENSHOT_CAPTURE_FAILED.id,
+            failureEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            failureEvent.packageName
+        )
+    }
+
+    @Test
+    fun takeScreenshot_workProfile_nullBitmap_metadataDisabled() {
+        flags.set(SCREENSHOT_METADATA, false)
+
+        val request =
+            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER)
+                .setTopComponent(topComponent)
+                .build()
+
+        doThrow(IllegalStateException::class.java)
+            .whenever(requestProcessor)
+            .processAsync(any(ScreenshotRequest::class.java), any())
+
+        service.handleRequest(request, { /* onSaved */}, callback)
+
+        verify(callback, times(1)).reportError()
+        verify(notificationsController, times(1)).notifyScreenshotError(anyInt())
+        verifyZeroInteractions(controller)
+        assertEquals("Expected two UiEvents", 2, eventLogger.numLogs())
+        val requestEvent = eventLogger.get(0)
+        assertEquals(
+            "Expected SCREENSHOT_REQUESTED_* UiEvent",
+            SCREENSHOT_REQUESTED_KEY_OTHER.id,
+            requestEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            requestEvent.packageName
+        )
+        val failureEvent = eventLogger.get(1)
+        assertEquals(
+            "Expected SCREENSHOT_CAPTURE_FAILED UiEvent",
+            SCREENSHOT_CAPTURE_FAILED.id,
+            failureEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            failureEvent.packageName
+        )
+    }
+    @Test
+    fun takeScreenshot_workProfile_nullBitmap() {
+        flags.set(SCREENSHOT_METADATA, true)
+
+        val request =
+            ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER)
+                .setTopComponent(topComponent)
+                .build()
+
+        doThrow(IllegalStateException::class.java)
+            .whenever(requestProcessor)
+            .processAsync(any(ScreenshotData::class.java), any())
+
+        service.handleRequest(request, { /* onSaved */}, callback)
+
+        verify(callback, times(1)).reportError()
+        verify(notificationsController, times(1)).notifyScreenshotError(anyInt())
+        verifyZeroInteractions(controller)
+        assertEquals("Expected two UiEvents", 2, eventLogger.numLogs())
+        val requestEvent = eventLogger.get(0)
+        assertEquals(
+            "Expected SCREENSHOT_REQUESTED_* UiEvent",
+            SCREENSHOT_REQUESTED_KEY_OTHER.id,
+            requestEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            requestEvent.packageName
+        )
+        val failureEvent = eventLogger.get(1)
+        assertEquals(
+            "Expected SCREENSHOT_CAPTURE_FAILED UiEvent",
+            SCREENSHOT_CAPTURE_FAILED.id,
+            failureEvent.eventId
+        )
+        assertEquals(
+            "Expected supplied package name",
+            topComponent.packageName,
+            failureEvent.packageName
+        )
     }
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
index e8905ab..3440f91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
@@ -16,13 +16,11 @@
 
 package com.android.systemui.screenshot;
 
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.ComponentName;
@@ -33,28 +31,35 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.testing.AndroidTestingRunner;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.FakeSharedPreferences;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatchers;
-import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import kotlin.Unit;
+
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
-public class WorkProfileMessageControllerTest {
+public class WorkProfileMessageControllerTest extends SysuiTestCase {
     private static final String DEFAULT_LABEL = "default label";
-    private static final String BADGED_DEFAULT_LABEL = "badged default label";
     private static final String APP_LABEL = "app label";
-    private static final String BADGED_APP_LABEL = "badged app label";
     private static final UserHandle NON_WORK_USER = UserHandle.of(0);
     private static final UserHandle WORK_USER = UserHandle.of(10);
 
@@ -63,17 +68,13 @@
     @Mock
     private PackageManager mPackageManager;
     @Mock
-    private Context mContext;
-    @Mock
-    private MessageContainerController mMessageDisplay;
+    private Context mMockContext;
     @Mock
     private Drawable mActivityIcon;
     @Mock
     private Drawable mBadgedActivityIcon;
     @Mock
     private ActivityInfo mActivityInfo;
-    @Captor
-    private ArgumentCaptor<Runnable> mRunnableArgumentCaptor;
 
     private FakeSharedPreferences mSharedPreferences = new FakeSharedPreferences();
 
@@ -84,14 +85,10 @@
         MockitoAnnotations.initMocks(this);
 
         when(mUserManager.isManagedProfile(eq(WORK_USER.getIdentifier()))).thenReturn(true);
-        when(mContext.getSharedPreferences(
+        when(mMockContext.getSharedPreferences(
                 eq(WorkProfileMessageController.SHARED_PREFERENCES_NAME),
                 eq(Context.MODE_PRIVATE))).thenReturn(mSharedPreferences);
-        when(mContext.getString(ArgumentMatchers.anyInt())).thenReturn(DEFAULT_LABEL);
-        when(mPackageManager.getUserBadgedLabel(eq(DEFAULT_LABEL), any()))
-                .thenReturn(BADGED_DEFAULT_LABEL);
-        when(mPackageManager.getUserBadgedLabel(eq(APP_LABEL), any()))
-                .thenReturn(BADGED_APP_LABEL);
+        when(mMockContext.getString(ArgumentMatchers.anyInt())).thenReturn(DEFAULT_LABEL);
         when(mPackageManager.getActivityIcon(any(ComponentName.class)))
                 .thenReturn(mActivityIcon);
         when(mPackageManager.getUserBadgedIcon(
@@ -103,16 +100,13 @@
         mSharedPreferences.edit().putBoolean(
                 WorkProfileMessageController.PREFERENCE_KEY, false).apply();
 
-        mMessageController = new WorkProfileMessageController(mContext, mUserManager,
+        mMessageController = new WorkProfileMessageController(mMockContext, mUserManager,
                 mPackageManager);
     }
 
     @Test
     public void testOnScreenshotTaken_notManaged() {
-        mMessageController.onScreenshotTaken(NON_WORK_USER, mMessageDisplay);
-
-        verify(mMessageDisplay, never())
-                .showWorkProfileMessage(any(), nullable(Drawable.class), any());
+        assertNull(mMessageController.onScreenshotTaken(NON_WORK_USER));
     }
 
     @Test
@@ -120,10 +114,7 @@
         mSharedPreferences.edit().putBoolean(
                 WorkProfileMessageController.PREFERENCE_KEY, true).apply();
 
-        mMessageController.onScreenshotTaken(WORK_USER, mMessageDisplay);
-
-        verify(mMessageDisplay, never())
-                .showWorkProfileMessage(any(), nullable(Drawable.class), any());
+        assertNull(mMessageController.onScreenshotTaken(WORK_USER));
     }
 
     @Test
@@ -133,28 +124,45 @@
                 any(PackageManager.ComponentInfoFlags.class))).thenThrow(
                 new PackageManager.NameNotFoundException());
 
-        mMessageController.onScreenshotTaken(WORK_USER, mMessageDisplay);
+        WorkProfileMessageController.WorkProfileFirstRunData data =
+                mMessageController.onScreenshotTaken(WORK_USER);
 
-        verify(mMessageDisplay).showWorkProfileMessage(
-                eq(BADGED_DEFAULT_LABEL), eq(null), any());
+        assertEquals(DEFAULT_LABEL, data.getAppName());
+        assertNull(data.getIcon());
     }
 
     @Test
     public void testOnScreenshotTaken() {
-        mMessageController.onScreenshotTaken(WORK_USER, mMessageDisplay);
+        WorkProfileMessageController.WorkProfileFirstRunData data =
+                mMessageController.onScreenshotTaken(WORK_USER);
 
-        verify(mMessageDisplay).showWorkProfileMessage(
-                eq(BADGED_APP_LABEL), eq(mBadgedActivityIcon), mRunnableArgumentCaptor.capture());
+        assertEquals(APP_LABEL, data.getAppName());
+        assertEquals(mBadgedActivityIcon, data.getIcon());
+    }
 
-        // Dismiss hasn't been tapped, preference untouched.
-        assertFalse(
-                mSharedPreferences.getBoolean(WorkProfileMessageController.PREFERENCE_KEY, false));
+    @Test
+    public void testPopulateView() throws InterruptedException {
+        ViewGroup layout = (ViewGroup) LayoutInflater.from(mContext).inflate(
+                R.layout.screenshot_work_profile_first_run, null);
+        WorkProfileMessageController.WorkProfileFirstRunData data =
+                new WorkProfileMessageController.WorkProfileFirstRunData(APP_LABEL,
+                        mBadgedActivityIcon);
+        final CountDownLatch countdown = new CountDownLatch(1);
+        mMessageController.populateView(layout, data, () -> {
+            countdown.countDown();
+            return Unit.INSTANCE;
+        });
 
-        mRunnableArgumentCaptor.getValue().run();
+        ImageView image = layout.findViewById(R.id.screenshot_message_icon);
+        assertEquals(mBadgedActivityIcon, image.getDrawable());
+        TextView text = layout.findViewById(R.id.screenshot_message_content);
+        // The app name is used in a template, but at least validate that it was inserted.
+        assertTrue(text.getText().toString().contains(APP_LABEL));
 
-        // After dismiss has been tapped, the setting should be updated.
-        assertTrue(
-                mSharedPreferences.getBoolean(WorkProfileMessageController.PREFERENCE_KEY, false));
+        // Validate that clicking the dismiss button calls back properly.
+        assertEquals(1, countdown.getCount());
+        layout.findViewById(R.id.message_dismiss_button).callOnClick();
+        countdown.await(1000, TimeUnit.MILLISECONDS);
     }
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java
new file mode 100644
index 0000000..6e8f5fe
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.appclips;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Intent;
+import android.graphics.ColorSpace;
+import android.hardware.HardwareBuffer;
+import android.os.RemoteException;
+import android.view.Display;
+import android.window.ScreenCapture.ScreenshotHardwareBuffer;
+import android.window.ScreenCapture.ScreenshotSync;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.wm.shell.bubbles.Bubbles;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+@RunWith(AndroidJUnit4.class)
+public final class AppClipsScreenshotHelperServiceTest extends SysuiTestCase {
+
+    private static final Intent FAKE_INTENT = new Intent();
+    private static final int DEFAULT_DISPLAY = Display.DEFAULT_DISPLAY;
+    private static final HardwareBuffer FAKE_HARDWARE_BUFFER =
+            HardwareBuffer.create(1, 1, HardwareBuffer.RGBA_8888, 1,
+                    HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
+    private static final ColorSpace FAKE_COLOR_SPACE = ColorSpace.get(ColorSpace.Named.SRGB);
+    private static final ScreenshotHardwareBufferInternal EXPECTED_SCREENSHOT_BUFFER =
+            new ScreenshotHardwareBufferInternal(
+                    new ScreenshotHardwareBuffer(FAKE_HARDWARE_BUFFER, FAKE_COLOR_SPACE, false,
+                            false));
+
+    @Mock private Optional<Bubbles> mBubblesOptional;
+    @Mock private Bubbles mBubbles;
+    @Mock private ScreenshotHardwareBuffer mScreenshotHardwareBuffer;
+    @Mock private ScreenshotSync mScreenshotSync;
+
+    private AppClipsScreenshotHelperService mAppClipsScreenshotHelperService;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mAppClipsScreenshotHelperService = new AppClipsScreenshotHelperService(mBubblesOptional);
+    }
+
+    @Test
+    public void emptyBubbles_shouldReturnNull() throws RemoteException {
+        when(mBubblesOptional.isEmpty()).thenReturn(true);
+
+        assertThat(getInterface().takeScreenshot(DEFAULT_DISPLAY)).isNull();
+    }
+
+    @Test
+    public void bubblesPresent_screenshotFailed_ShouldReturnNull() throws RemoteException {
+        when(mBubblesOptional.isEmpty()).thenReturn(false);
+        when(mBubblesOptional.get()).thenReturn(mBubbles);
+        when(mBubbles.getScreenshotExcludingBubble(DEFAULT_DISPLAY)).thenReturn(mScreenshotSync);
+        when(mScreenshotSync.get()).thenReturn(null);
+
+        assertThat(getInterface().takeScreenshot(DEFAULT_DISPLAY)).isNull();
+    }
+
+    @Test
+    public void bubblesPresent_screenshotSuccess_shouldReturnScreenshot() throws RemoteException {
+        when(mBubblesOptional.isEmpty()).thenReturn(false);
+        when(mBubblesOptional.get()).thenReturn(mBubbles);
+        when(mBubbles.getScreenshotExcludingBubble(DEFAULT_DISPLAY)).thenReturn(mScreenshotSync);
+        when(mScreenshotSync.get()).thenReturn(mScreenshotHardwareBuffer);
+        when(mScreenshotHardwareBuffer.getHardwareBuffer()).thenReturn(FAKE_HARDWARE_BUFFER);
+        when(mScreenshotHardwareBuffer.getColorSpace()).thenReturn(FAKE_COLOR_SPACE);
+
+        assertThat(getInterface().takeScreenshot(DEFAULT_DISPLAY)).isEqualTo(
+                EXPECTED_SCREENSHOT_BUFFER);
+    }
+
+    private IAppClipsScreenshotHelperService getInterface() {
+        return IAppClipsScreenshotHelperService.Stub.asInterface(
+                mAppClipsScreenshotHelperService.onBind(FAKE_INTENT));
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java
new file mode 100644
index 0000000..b55fe36
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsServiceTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.appclips;
+
+import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.statusbar.IAppClipsService;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dagger.qualifiers.Application;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.wm.shell.bubbles.Bubbles;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+@RunWith(AndroidJUnit4.class)
+public final class AppClipsServiceTest extends SysuiTestCase {
+
+    private static final Intent FAKE_INTENT = new Intent();
+    private static final int FAKE_TASK_ID = 42;
+    private static final String EMPTY = "";
+
+    @Mock @Application private Context mMockContext;
+    @Mock private FeatureFlags mFeatureFlags;
+    @Mock private Optional<Bubbles> mOptionalBubbles;
+    @Mock private Bubbles mBubbles;
+    @Mock private DevicePolicyManager mDevicePolicyManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void flagOff_shouldReturnFalse() throws RemoteException {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(false);
+
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isFalse();
+    }
+
+    @Test
+    public void emptyBubbles_shouldReturnFalse() throws RemoteException {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(true);
+
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isFalse();
+    }
+
+    @Test
+    public void taskIdNotAppBubble_shouldReturnFalse() throws RemoteException {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(false);
+
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isFalse();
+    }
+
+    @Test
+    public void dpmScreenshotBlocked_shouldReturnFalse() throws RemoteException {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(true);
+        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(true);
+
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isFalse();
+    }
+
+    @Test
+    public void configComponentNameNotValid_shouldReturnFalse() throws RemoteException {
+        when(mMockContext.getString(anyInt())).thenReturn(EMPTY);
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(true);
+        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(false);
+
+        assertThat(getInterfaceWithMockContext()
+                .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isFalse();
+    }
+
+    @Test
+    public void allPrerequisitesSatisfy_shouldReturnTrue() throws RemoteException {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(eq((FAKE_TASK_ID)))).thenReturn(true);
+        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(false);
+
+        assertThat(getInterfaceWithRealContext()
+                .canLaunchCaptureContentActivityForNote(FAKE_TASK_ID)).isTrue();
+    }
+
+    private IAppClipsService getInterfaceWithRealContext() {
+        AppClipsService appClipsService = new AppClipsService(getContext(), mFeatureFlags,
+                mOptionalBubbles, mDevicePolicyManager);
+        return getInterfaceFromService(appClipsService);
+    }
+
+    private IAppClipsService getInterfaceWithMockContext() {
+        AppClipsService appClipsService = new AppClipsService(mMockContext, mFeatureFlags,
+                mOptionalBubbles, mDevicePolicyManager);
+        return getInterfaceFromService(appClipsService);
+    }
+
+    private static IAppClipsService getInterfaceFromService(AppClipsService appClipsService) {
+        IBinder iBinder = appClipsService.onBind(FAKE_INTENT);
+        return IAppClipsService.Stub.asInterface(iBinder);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
new file mode 100644
index 0000000..295d127
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
@@ -0,0 +1,269 @@
+/*
+ * 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.appclips;
+
+import static android.app.Instrumentation.ActivityResult;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_USER_CANCELED;
+import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED;
+import static android.content.Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE;
+
+import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
+import static com.android.systemui.screenshot.AppClipsTrampolineActivity.ACTION_FINISH_FROM_TRAMPOLINE;
+import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
+import static com.android.systemui.screenshot.AppClipsTrampolineActivity.PERMISSION_SELF;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.intercepting.SingleActivityFactory;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.notetask.NoteTaskController;
+import com.android.systemui.screenshot.AppClipsTrampolineActivity;
+import com.android.wm.shell.bubbles.Bubbles;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+@RunWith(AndroidTestingRunner.class)
+public final class AppClipsTrampolineActivityTest extends SysuiTestCase {
+
+    private static final String TEST_URI_STRING = "www.test-uri.com";
+    private static final Uri TEST_URI = Uri.parse(TEST_URI_STRING);
+    private static final int TIME_OUT = 5000;
+
+    @Mock
+    private DevicePolicyManager mDevicePolicyManager;
+    @Mock
+    private FeatureFlags mFeatureFlags;
+    @Mock
+    private Optional<Bubbles> mOptionalBubbles;
+    @Mock
+    private Bubbles mBubbles;
+    @Mock
+    private NoteTaskController mNoteTaskController;
+    @Main
+    private Handler mMainHandler;
+
+    // Using the deprecated ActivityTestRule and SingleActivityFactory to help with injecting mocks
+    // and getting result from activity both of which are difficult to do in newer APIs.
+    private final SingleActivityFactory<AppClipsTrampolineActivityTestable> mFactory =
+            new SingleActivityFactory<>(AppClipsTrampolineActivityTestable.class) {
+                @Override
+                protected AppClipsTrampolineActivityTestable create(Intent unUsed) {
+                    return new AppClipsTrampolineActivityTestable(mDevicePolicyManager,
+                            mFeatureFlags, mOptionalBubbles, mNoteTaskController, mMainHandler);
+                }
+            };
+
+    @Rule
+    public final ActivityTestRule<AppClipsTrampolineActivityTestable> mActivityRule =
+            new ActivityTestRule<>(mFactory, false, false);
+
+    private Context mContext;
+    private Intent mActivityIntent;
+    private ComponentName mExpectedComponentName;
+    private Intent mKillAppClipsActivityBroadcast;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = getContext();
+        mMainHandler = mContext.getMainThreadHandler();
+
+        mActivityIntent = new Intent(mContext, AppClipsTrampolineActivityTestable.class);
+        mExpectedComponentName = ComponentName.unflattenFromString(
+                mContext.getString(
+                        R.string.config_screenshotAppClipsActivityComponent));
+        mKillAppClipsActivityBroadcast = new Intent(ACTION_FINISH_FROM_TRAMPOLINE)
+                .setComponent(mExpectedComponentName)
+                .setPackage(mExpectedComponentName.getPackageName());
+    }
+
+    @After
+    public void tearDown() {
+        mContext.sendBroadcast(mKillAppClipsActivityBroadcast, PERMISSION_SELF);
+        mActivityRule.finishActivity();
+    }
+
+    @Test
+    public void configComponentName_shouldResolve() {
+        // Verify component name is setup - has package and class name.
+        assertThat(mExpectedComponentName).isNotNull();
+        assertThat(mExpectedComponentName.getPackageName()).isNotEmpty();
+        assertThat(mExpectedComponentName.getClassName()).isNotEmpty();
+
+        // Verify an intent when launched with above component resolves to the same component to
+        // confirm that component from above is available in framework.
+        Intent appClipsActivityIntent = new Intent();
+        appClipsActivityIntent.setComponent(mExpectedComponentName);
+        ResolveInfo resolveInfo = getContext().getPackageManager().resolveActivity(
+                appClipsActivityIntent, PackageManager.ResolveInfoFlags.of(0));
+        ActivityInfo activityInfo = resolveInfo.activityInfo;
+
+        assertThat(activityInfo.packageName).isEqualTo(
+                mExpectedComponentName.getPackageName());
+        assertThat(activityInfo.name).isEqualTo(mExpectedComponentName.getClassName());
+    }
+
+    @Test
+    public void flagOff_shouldFinishWithResultCancel() {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(false);
+
+        mActivityRule.launchActivity(mActivityIntent);
+
+        assertThat(mActivityRule.getActivityResult().getResultCode())
+                .isEqualTo(Activity.RESULT_CANCELED);
+    }
+
+    @Test
+    public void bubblesEmpty_shouldFinishWithFailed() {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(true);
+
+        mActivityRule.launchActivity(mActivityIntent);
+
+        ActivityResult actualResult = mActivityRule.getActivityResult();
+        assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
+        assertThat(getStatusCodeExtra(actualResult.getResultData()))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+    }
+
+    @Test
+    public void taskIdNotAppBubble_shouldFinishWithWindowModeUnsupported() {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(anyInt())).thenReturn(false);
+
+        mActivityRule.launchActivity(mActivityIntent);
+
+        ActivityResult actualResult = mActivityRule.getActivityResult();
+        assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
+        assertThat(getStatusCodeExtra(actualResult.getResultData()))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED);
+    }
+
+    @Test
+    public void dpmScreenshotBlocked_shouldFinishWithBlockedByAdmin() {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(anyInt())).thenReturn(true);
+        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(true);
+
+        mActivityRule.launchActivity(mActivityIntent);
+
+        ActivityResult actualResult = mActivityRule.getActivityResult();
+        assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
+        assertThat(getStatusCodeExtra(actualResult.getResultData()))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN);
+    }
+
+    @Test
+    public void startAppClipsActivity_userCanceled_shouldReturnUserCanceled() {
+        mockToSatisfyAllPrerequisites();
+
+        AppClipsTrampolineActivityTestable activity = mActivityRule.launchActivity(mActivityIntent);
+        waitForIdleSync();
+
+        Bundle bundle = new Bundle();
+        bundle.putInt(EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE,
+                CAPTURE_CONTENT_FOR_NOTE_USER_CANCELED);
+        activity.getResultReceiverForTest().send(Activity.RESULT_OK, bundle);
+        waitForIdleSync();
+
+        ActivityResult actualResult = mActivityRule.getActivityResult();
+        assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
+        assertThat(getStatusCodeExtra(actualResult.getResultData()))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_USER_CANCELED);
+    }
+
+    @Test
+    public void startAppClipsActivity_shouldReturnSuccess() {
+        mockToSatisfyAllPrerequisites();
+
+        AppClipsTrampolineActivityTestable activity = mActivityRule.launchActivity(mActivityIntent);
+        waitForIdleSync();
+
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(EXTRA_SCREENSHOT_URI, TEST_URI);
+        bundle.putInt(EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE, CAPTURE_CONTENT_FOR_NOTE_SUCCESS);
+        activity.getResultReceiverForTest().send(Activity.RESULT_OK, bundle);
+        waitForIdleSync();
+
+        ActivityResult actualResult = mActivityRule.getActivityResult();
+        assertThat(actualResult.getResultCode()).isEqualTo(Activity.RESULT_OK);
+        assertThat(getStatusCodeExtra(actualResult.getResultData()))
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_SUCCESS);
+        assertThat(actualResult.getResultData().getData()).isEqualTo(TEST_URI);
+    }
+
+    private void mockToSatisfyAllPrerequisites() {
+        when(mFeatureFlags.isEnabled(SCREENSHOT_APP_CLIPS)).thenReturn(true);
+        when(mOptionalBubbles.isEmpty()).thenReturn(false);
+        when(mOptionalBubbles.get()).thenReturn(mBubbles);
+        when(mBubbles.isAppBubbleTaskId(anyInt())).thenReturn(true);
+        when(mDevicePolicyManager.getScreenCaptureDisabled(eq(null))).thenReturn(false);
+    }
+
+    public static final class AppClipsTrampolineActivityTestable extends
+            AppClipsTrampolineActivity {
+
+        public AppClipsTrampolineActivityTestable(DevicePolicyManager devicePolicyManager,
+                FeatureFlags flags,
+                Optional<Bubbles> optionalBubbles,
+                NoteTaskController noteTaskController,
+                @Main Handler mainHandler) {
+            super(devicePolicyManager, flags, optionalBubbles, noteTaskController, mainHandler);
+        }
+    }
+
+    private static int getStatusCodeExtra(Intent intent) {
+        return intent.getIntExtra(EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE, -100);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java
new file mode 100644
index 0000000..d5af7ce1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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 static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.net.Uri;
+import android.os.UserHandle;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.screenshot.appclips.AppClipsCrossProcessHelper;
+
+import com.google.common.util.concurrent.Futures;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.time.ZonedDateTime;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+
+@RunWith(AndroidJUnit4.class)
+public final class AppClipsViewModelTest extends SysuiTestCase {
+
+    private static final Bitmap FAKE_BITMAP = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
+    private static final Drawable FAKE_DRAWABLE = new ShapeDrawable();
+    private static final Rect FAKE_RECT = new Rect();
+    private static final Uri FAKE_URI = Uri.parse("www.test-uri.com");
+
+    @Mock private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
+    @Mock private ImageExporter mImageExporter;
+
+    private com.android.systemui.screenshot.AppClipsViewModel mViewModel;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mViewModel = new AppClipsViewModel.Factory(mAppClipsCrossProcessHelper, mImageExporter,
+                getContext().getMainExecutor(), directExecutor()).create(AppClipsViewModel.class);
+    }
+
+    @Test
+    public void performScreenshot_fails_shouldUpdateErrorWithFailed() {
+        when(mAppClipsCrossProcessHelper.takeScreenshot()).thenReturn(null);
+
+        mViewModel.performScreenshot();
+        waitForIdleSync();
+
+        verify(mAppClipsCrossProcessHelper).takeScreenshot();
+        assertThat(mViewModel.getErrorLiveData().getValue())
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+        assertThat(mViewModel.getResultLiveData().getValue()).isNull();
+    }
+
+    @Test
+    public void performScreenshot_succeeds_shouldUpdateScreenshotWithBitmap() {
+        when(mAppClipsCrossProcessHelper.takeScreenshot()).thenReturn(FAKE_BITMAP);
+
+        mViewModel.performScreenshot();
+        waitForIdleSync();
+
+        verify(mAppClipsCrossProcessHelper).takeScreenshot();
+        assertThat(mViewModel.getErrorLiveData().getValue()).isNull();
+        assertThat(mViewModel.getScreenshot().getValue()).isEqualTo(FAKE_BITMAP);
+    }
+
+    @Test
+    public void saveScreenshot_throwsError_shouldUpdateErrorWithFailed() {
+        when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), any(
+                ZonedDateTime.class), any(UserHandle.class))).thenReturn(
+                Futures.immediateFailedFuture(new ExecutionException(new Throwable())));
+
+        mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT);
+        waitForIdleSync();
+
+        assertThat(mViewModel.getErrorLiveData().getValue())
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+        assertThat(mViewModel.getResultLiveData().getValue()).isNull();
+    }
+
+    @Test
+    public void saveScreenshot_failsSilently_shouldUpdateErrorWithFailed() {
+        when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), any(
+                ZonedDateTime.class), any(UserHandle.class))).thenReturn(
+                Futures.immediateFuture(new ImageExporter.Result()));
+
+        mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT);
+        waitForIdleSync();
+
+        assertThat(mViewModel.getErrorLiveData().getValue())
+                .isEqualTo(CAPTURE_CONTENT_FOR_NOTE_FAILED);
+        assertThat(mViewModel.getResultLiveData().getValue()).isNull();
+    }
+
+    @Test
+    public void saveScreenshot_succeeds_shouldUpdateResultWithUri() {
+        ImageExporter.Result result = new ImageExporter.Result();
+        result.uri = FAKE_URI;
+        when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), any(
+                ZonedDateTime.class), any(UserHandle.class))).thenReturn(
+                Futures.immediateFuture(result));
+
+        mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT);
+        waitForIdleSync();
+
+        assertThat(mViewModel.getErrorLiveData().getValue()).isNull();
+        assertThat(mViewModel.getResultLiveData().getValue()).isEqualTo(FAKE_URI);
+    }
+}
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 4d7741ad..78bebb9 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
@@ -27,6 +27,7 @@
 import com.android.systemui.plugins.ClockId
 import com.android.systemui.plugins.ClockMetadata
 import com.android.systemui.plugins.ClockProviderPlugin
+import com.android.systemui.plugins.ClockSettings
 import com.android.systemui.plugins.PluginListener
 import com.android.systemui.plugins.PluginManager
 import com.android.systemui.util.mockito.argumentCaptor
@@ -59,7 +60,7 @@
     private lateinit var pluginListener: PluginListener<ClockProviderPlugin>
     private lateinit var registry: ClockRegistry
 
-    private var settingValue: String = ""
+    private var settingValue: ClockSettings? = null
 
     companion object {
         private fun failFactory(): ClockController {
@@ -79,7 +80,8 @@
         private val thumbnailCallbacks = mutableMapOf<ClockId, () -> Drawable?>()
 
         override fun getClocks() = metadata
-        override fun createClock(id: ClockId): ClockController = createCallbacks[id]!!()
+        override fun createClock(settings: ClockSettings): ClockController =
+            createCallbacks[settings.clockId!!]!!()
         override fun getClockThumbnail(id: ClockId): Drawable? = thumbnailCallbacks[id]!!()
 
         fun addClock(
@@ -110,7 +112,7 @@
             userHandle = UserHandle.USER_ALL,
             defaultClockProvider = fakeDefaultProvider
         ) {
-            override var currentClockId: ClockId
+            override var settings: ClockSettings?
                 get() = settingValue
                 set(value) { settingValue = value }
         }
@@ -185,7 +187,7 @@
             .addClock("clock_1", "clock 1")
             .addClock("clock_2", "clock 2")
 
-        settingValue = "clock_3"
+        settingValue = ClockSettings("clock_3", null, null)
         val plugin2 = FakeClockPlugin()
             .addClock("clock_3", "clock 3", { mockClock })
             .addClock("clock_4", "clock 4")
@@ -203,7 +205,7 @@
             .addClock("clock_1", "clock 1")
             .addClock("clock_2", "clock 2")
 
-        settingValue = "clock_3"
+        settingValue = ClockSettings("clock_3", null, null)
         val plugin2 = FakeClockPlugin()
             .addClock("clock_3", "clock 3")
             .addClock("clock_4", "clock 4")
@@ -222,7 +224,7 @@
             .addClock("clock_1", "clock 1")
             .addClock("clock_2", "clock 2")
 
-        settingValue = "clock_3"
+        settingValue = ClockSettings("clock_3", null, null)
         val plugin2 = FakeClockPlugin()
             .addClock("clock_3", "clock 3", { mockClock })
             .addClock("clock_4", "clock 4")
@@ -242,8 +244,8 @@
 
     @Test
     fun jsonDeserialization_gotExpectedObject() {
-        val expected = ClockRegistry.ClockSetting("ID", 500)
-        val actual = ClockRegistry.ClockSetting.deserialize("""{
+        val expected = ClockSettings("ID", null, 500)
+        val actual = ClockSettings.deserialize("""{
             "clockId":"ID",
             "_applied_timestamp":500
         }""")
@@ -252,15 +254,15 @@
 
     @Test
     fun jsonDeserialization_noTimestamp_gotExpectedObject() {
-        val expected = ClockRegistry.ClockSetting("ID", null)
-        val actual = ClockRegistry.ClockSetting.deserialize("{\"clockId\":\"ID\"}")
+        val expected = ClockSettings("ID", null, null)
+        val actual = ClockSettings.deserialize("{\"clockId\":\"ID\"}")
         assertEquals(expected, actual)
     }
 
     @Test
     fun jsonDeserialization_nullTimestamp_gotExpectedObject() {
-        val expected = ClockRegistry.ClockSetting("ID", null)
-        val actual = ClockRegistry.ClockSetting.deserialize("""{
+        val expected = ClockSettings("ID", null, null)
+        val actual = ClockSettings.deserialize("""{
             "clockId":"ID",
             "_applied_timestamp":null
         }""")
@@ -269,22 +271,22 @@
 
     @Test(expected = JSONException::class)
     fun jsonDeserialization_noId_threwException() {
-        val expected = ClockRegistry.ClockSetting("ID", 500)
-        val actual = ClockRegistry.ClockSetting.deserialize("{\"_applied_timestamp\":500}")
+        val expected = ClockSettings("ID", null, 500)
+        val actual = ClockSettings.deserialize("{\"_applied_timestamp\":500}")
         assertEquals(expected, actual)
     }
 
     @Test
     fun jsonSerialization_gotExpectedString() {
         val expected = "{\"clockId\":\"ID\",\"_applied_timestamp\":500}"
-        val actual = ClockRegistry.ClockSetting.serialize( ClockRegistry.ClockSetting("ID", 500))
+        val actual = ClockSettings.serialize(ClockSettings("ID", null, 500))
         assertEquals(expected, actual)
     }
 
     @Test
     fun jsonSerialization_noTimestamp_gotExpectedString() {
         val expected = "{\"clockId\":\"ID\"}"
-        val actual = ClockRegistry.ClockSetting.serialize( ClockRegistry.ClockSetting("ID", null))
+        val actual = ClockSettings.serialize(ClockSettings("ID", null, null))
         assertEquals(expected, actual)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index a7588dd..cd2efc0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -114,7 +114,8 @@
     @Test
     fun defaultClock_events_onTimeTick() {
         val clock = provider.createClock(DEFAULT_CLOCK_ID)
-        clock.events.onTimeTick()
+        clock.smallClock.events.onTimeTick()
+        clock.largeClock.events.onTimeTick()
 
         verify(mockSmallClockView).refreshTime()
         verify(mockLargeClockView).refreshTime()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
index 7693fee..9eccbb6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
@@ -471,4 +471,142 @@
         mExecutor.runAllReady();
         verify(callback).onConditionsChanged(true);
     }
+
+    /**
+     * Ensures that the result of a condition being true leads to its nested condition being
+     * activated.
+     */
+    @Test
+    public void testNestedCondition() {
+        mCondition1.fakeUpdateCondition(false);
+        final Monitor.Callback callback =
+                mock(Monitor.Callback.class);
+
+        mCondition2.fakeUpdateCondition(false);
+
+        // Create a nested condition
+        mConditionMonitor.addSubscription(new Monitor.Subscription.Builder(
+                new Monitor.Subscription.Builder(callback)
+                        .addCondition(mCondition2)
+                        .build())
+                .addCondition(mCondition1)
+                .build());
+
+        mExecutor.runAllReady();
+
+        // Ensure the nested condition callback is not called at all.
+        verify(callback, never()).onActiveChanged(anyBoolean());
+        verify(callback, never()).onConditionsChanged(anyBoolean());
+
+        // Update the inner condition to true and ensure that the nested condition is not triggered.
+        mCondition2.fakeUpdateCondition(true);
+        verify(callback, never()).onConditionsChanged(anyBoolean());
+        mCondition2.fakeUpdateCondition(false);
+
+        // Set outer condition and make sure the inner condition becomes active and reports that
+        // conditions aren't met
+        mCondition1.fakeUpdateCondition(true);
+        mExecutor.runAllReady();
+
+        verify(callback).onActiveChanged(eq(true));
+        verify(callback).onConditionsChanged(eq(false));
+
+        Mockito.clearInvocations(callback);
+
+        // Update the inner condition and make sure the callback is updated.
+        mCondition2.fakeUpdateCondition(true);
+        mExecutor.runAllReady();
+
+        verify(callback).onConditionsChanged(true);
+
+        Mockito.clearInvocations(callback);
+        // Invalidate outer condition and make sure callback is informed, but the last state is
+        // not affected.
+        mCondition1.fakeUpdateCondition(false);
+        mExecutor.runAllReady();
+
+        verify(callback).onActiveChanged(eq(false));
+        verify(callback, never()).onConditionsChanged(anyBoolean());
+    }
+
+    /**
+     * Ensures a subscription is predicated on its precondition.
+     */
+    @Test
+    public void testPrecondition() {
+        mCondition1.fakeUpdateCondition(false);
+        final Monitor.Callback callback =
+                mock(Monitor.Callback.class);
+
+        mCondition2.fakeUpdateCondition(false);
+
+        // Create a nested condition
+        mConditionMonitor.addSubscription(new Monitor.Subscription.Builder(callback)
+                .addPrecondition(mCondition1)
+                .addCondition(mCondition2)
+                .build());
+
+        mExecutor.runAllReady();
+
+        // Ensure the nested condition callback is not called at all.
+        verify(callback, never()).onActiveChanged(anyBoolean());
+        verify(callback, never()).onConditionsChanged(anyBoolean());
+
+        // Update the condition to true and ensure that the nested condition is not triggered.
+        mCondition2.fakeUpdateCondition(true);
+        verify(callback, never()).onConditionsChanged(anyBoolean());
+        mCondition2.fakeUpdateCondition(false);
+
+        // Set precondition and make sure the inner condition becomes active and reports that
+        // conditions aren't met
+        mCondition1.fakeUpdateCondition(true);
+        mExecutor.runAllReady();
+
+        verify(callback).onActiveChanged(eq(true));
+        verify(callback).onConditionsChanged(eq(false));
+
+        Mockito.clearInvocations(callback);
+
+        // Update the condition and make sure the callback is updated.
+        mCondition2.fakeUpdateCondition(true);
+        mExecutor.runAllReady();
+
+        verify(callback).onConditionsChanged(true);
+
+        Mockito.clearInvocations(callback);
+        // Invalidate precondition and make sure callback is informed, but the last state is
+        // not affected.
+        mCondition1.fakeUpdateCondition(false);
+        mExecutor.runAllReady();
+
+        verify(callback).onActiveChanged(eq(false));
+        verify(callback, never()).onConditionsChanged(anyBoolean());
+    }
+
+    /**
+     * Ensure preconditions are applied to every subscription added to a monitor.
+     */
+    @Test
+    public void testPreconditionMonitor() {
+        final Monitor.Callback callback =
+                mock(Monitor.Callback.class);
+
+        mCondition2.fakeUpdateCondition(true);
+        final Monitor monitor = new Monitor(mExecutor, new HashSet<>(Arrays.asList(mCondition1)));
+
+        monitor.addSubscription(new Monitor.Subscription.Builder(callback)
+                .addCondition(mCondition2)
+                .build());
+
+        mExecutor.runAllReady();
+
+        verify(callback, never()).onActiveChanged(anyBoolean());
+        verify(callback, never()).onConditionsChanged(anyBoolean());
+
+        mCondition1.fakeUpdateCondition(true);
+        mExecutor.runAllReady();
+
+        verify(callback).onActiveChanged(eq(true));
+        verify(callback).onConditionsChanged(eq(true));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index b1ca1c0..f581154 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -18,8 +18,6 @@
 import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT;
 import static android.inputmethodservice.InputMethodService.IME_INVISIBLE;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT;
 
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -158,7 +156,7 @@
 
     @Test
     public void testShowTransient() {
-        int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+        int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars();
         mCommandQueue.showTransient(DEFAULT_DISPLAY, types, true /* isGestureOnSystemBar */);
         waitForIdleSync();
         verify(mCallbacks).showTransient(eq(DEFAULT_DISPLAY), eq(types), eq(true));
@@ -166,7 +164,7 @@
 
     @Test
     public void testShowTransientForSecondaryDisplay() {
-        int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+        int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars();
         mCommandQueue.showTransient(SECONDARY_DISPLAY, types, true /* isGestureOnSystemBar */);
         waitForIdleSync();
         verify(mCallbacks).showTransient(eq(SECONDARY_DISPLAY), eq(types), eq(true));
@@ -174,7 +172,7 @@
 
     @Test
     public void testAbortTransient() {
-        int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+        int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars();
         mCommandQueue.abortTransient(DEFAULT_DISPLAY, types);
         waitForIdleSync();
         verify(mCallbacks).abortTransient(eq(DEFAULT_DISPLAY), eq(types));
@@ -182,7 +180,7 @@
 
     @Test
     public void testAbortTransientForSecondaryDisplay() {
-        int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+        int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars();
         mCommandQueue.abortTransient(SECONDARY_DISPLAY, types);
         waitForIdleSync();
         verify(mCallbacks).abortTransient(eq(SECONDARY_DISPLAY), eq(types));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 0806a62..1ac7eaa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -631,6 +631,82 @@
     }
 
     @Test
+    public void onBiometricHelp_coEx_fpFailure_faceAlreadyUnlocked() {
+        createController();
+
+        // GIVEN face has already unlocked the device
+        when(mKeyguardUpdateMonitor.getUserUnlockedWithFace(anyInt())).thenReturn(true);
+
+        String message = "A message";
+        mController.setVisible(true);
+
+        // WHEN there's a fingerprint not recognized message
+        mController.getKeyguardCallback().onBiometricHelp(
+                BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED,
+                message,
+                BiometricSourceType.FINGERPRINT);
+
+        // THEN show sequential messages such as: 'Unlocked by face' and
+        // 'Swipe up to open'
+        verifyIndicationMessage(
+                INDICATION_TYPE_BIOMETRIC_MESSAGE,
+                mContext.getString(R.string.keyguard_face_successful_unlock));
+        verifyIndicationMessage(
+                INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
+                mContext.getString(R.string.keyguard_unlock));
+    }
+
+    @Test
+    public void onBiometricHelp_coEx_fpFailure_trustAgentAlreadyUnlocked() {
+        createController();
+
+        // GIVEN trust agent has already unlocked the device
+        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
+
+        String message = "A message";
+        mController.setVisible(true);
+
+        // WHEN there's a fingerprint not recognized message
+        mController.getKeyguardCallback().onBiometricHelp(
+                BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED,
+                message,
+                BiometricSourceType.FINGERPRINT);
+
+        // THEN show sequential messages such as: 'Kept unlocked by TrustAgent' and
+        // 'Swipe up to open'
+        verifyIndicationMessage(
+                INDICATION_TYPE_BIOMETRIC_MESSAGE,
+                mContext.getString(R.string.keyguard_indication_trust_unlocked));
+        verifyIndicationMessage(
+                INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
+                mContext.getString(R.string.keyguard_unlock));
+    }
+
+    @Test
+    public void onBiometricHelp_coEx_fpFailure_trustAgentUnlocked_emptyTrustGrantedMessage() {
+        createController();
+
+        // GIVEN trust agent has already unlocked the device & trust granted message is empty
+        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
+        mController.showTrustGrantedMessage(false, "");
+
+        String message = "A message";
+        mController.setVisible(true);
+
+        // WHEN there's a fingerprint not recognized message
+        mController.getKeyguardCallback().onBiometricHelp(
+                BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED,
+                message,
+                BiometricSourceType.FINGERPRINT);
+
+        // THEN show action to unlock (ie: 'Swipe up to open')
+        verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE);
+        verifyIndicationMessage(
+                INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
+                mContext.getString(R.string.keyguard_unlock));
+    }
+
+    @Test
     public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() {
         createController();
         String message = mContext.getString(R.string.keyguard_unlock);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index 2423f13..d6225c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -32,7 +32,9 @@
 import android.view.View
 import android.widget.FrameLayout
 import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.plugins.ActivityStarter
@@ -104,6 +106,9 @@
     private lateinit var keyguardBypassController: KeyguardBypassController
 
     @Mock
+    private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+
+    @Mock
     private lateinit var deviceProvisionedController: DeviceProvisionedController
 
     @Mock
@@ -113,6 +118,9 @@
     private lateinit var handler: Handler
 
     @Mock
+    private lateinit var datePlugin: BcSmartspaceDataPlugin
+
+    @Mock
     private lateinit var weatherPlugin: BcSmartspaceDataPlugin
 
     @Mock
@@ -122,6 +130,9 @@
     private lateinit var configPlugin: BcSmartspaceConfigPlugin
 
     @Mock
+    private lateinit var dumpManager: DumpManager
+
+    @Mock
     private lateinit var controllerListener: SmartspaceTargetListener
 
     @Captor
@@ -155,6 +166,7 @@
         KeyguardBypassController.OnBypassStateChangedListener
     private lateinit var deviceProvisionedListener: DeviceProvisionedListener
 
+    private lateinit var dateSmartspaceView: SmartspaceView
     private lateinit var weatherSmartspaceView: SmartspaceView
     private lateinit var smartspaceView: SmartspaceView
 
@@ -190,6 +202,8 @@
         `when`(secureSettings.getUriFor(NOTIF_ON_LOCKSCREEN_SETTING))
                 .thenReturn(fakeNotifOnLockscreenSettingUri)
         `when`(smartspaceManager.createSmartspaceSession(any())).thenReturn(smartspaceSession)
+        `when`(datePlugin.getView(any())).thenReturn(
+                createDateSmartspaceView(), createDateSmartspaceView())
         `when`(weatherPlugin.getView(any())).thenReturn(
                 createWeatherSmartspaceView(), createWeatherSmartspaceView())
         `when`(plugin.getView(any())).thenReturn(createSmartspaceView(), createSmartspaceView())
@@ -217,10 +231,13 @@
                 statusBarStateController,
                 deviceProvisionedController,
                 keyguardBypassController,
+                keyguardUpdateMonitor,
+                dumpManager,
                 execution,
                 executor,
                 bgExecutor,
                 handler,
+                Optional.of(datePlugin),
                 Optional.of(weatherPlugin),
                 Optional.of(plugin),
                 Optional.of(configPlugin),
@@ -275,7 +292,8 @@
 
         // THEN the listener is registered to the underlying plugin
         verify(plugin).registerListener(controllerListener)
-        // The listener is registered only for the plugin, not the weather plugin.
+        // The listener is registered only for the plugin, not the date, or weather plugin.
+        verify(datePlugin, never()).registerListener(any())
         verify(weatherPlugin, never()).registerListener(any())
     }
 
@@ -289,7 +307,8 @@
 
         // THEN the listener is subsequently registered
         verify(plugin).registerListener(controllerListener)
-        // The listener is registered only for the plugin, not the weather plugin.
+        // The listener is registered only for the plugin, not the date, or the weather plugin.
+        verify(datePlugin, never()).registerListener(any())
         verify(weatherPlugin, never()).registerListener(any())
     }
 
@@ -308,6 +327,7 @@
         verify(plugin).registerSmartspaceEventNotifier(null)
         verify(weatherPlugin).onTargetsAvailable(emptyList())
         verify(weatherPlugin).registerSmartspaceEventNotifier(null)
+        verify(datePlugin).registerSmartspaceEventNotifier(null)
     }
 
     @Test
@@ -357,6 +377,7 @@
         configChangeListener.onThemeChanged()
 
         // We update the new text color to match the wallpaper color
+        verify(dateSmartspaceView).setPrimaryTextColor(anyInt())
         verify(weatherSmartspaceView).setPrimaryTextColor(anyInt())
         verify(smartspaceView).setPrimaryTextColor(anyInt())
     }
@@ -384,6 +405,7 @@
         statusBarStateListener.onDozeAmountChanged(0.1f, 0.7f)
 
         // We pass that along to the view
+        verify(dateSmartspaceView).setDozeAmount(0.7f)
         verify(weatherSmartspaceView).setDozeAmount(0.7f)
         verify(smartspaceView).setDozeAmount(0.7f)
     }
@@ -502,6 +524,8 @@
         verify(plugin).onTargetsAvailable(eq(listOf(targets[0], targets[1], targets[2])))
         // No filtering is applied for the weather plugin
         verify(weatherPlugin).onTargetsAvailable(eq(targets))
+        // No targets needed for the date plugin
+        verify(datePlugin, never()).onTargetsAvailable(any())
     }
 
     @Test
@@ -633,6 +657,18 @@
 
     private fun connectSession() {
         if (controller.isDateWeatherDecoupled()) {
+            val dateView = controller.buildAndConnectDateView(fakeParent)
+            dateSmartspaceView = dateView as SmartspaceView
+            fakeParent.addView(dateView)
+            controller.stateChangeListener.onViewAttachedToWindow(dateView)
+
+            verify(dateSmartspaceView).setUiSurface(
+                    BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
+            verify(dateSmartspaceView).registerDataProvider(datePlugin)
+
+            verify(dateSmartspaceView).setPrimaryTextColor(anyInt())
+            verify(dateSmartspaceView).setDozeAmount(0.5f)
+
             val weatherView = controller.buildAndConnectWeatherView(fakeParent)
             weatherSmartspaceView = weatherView as SmartspaceView
             fakeParent.addView(weatherView)
@@ -686,6 +722,7 @@
         verify(smartspaceView).setDozeAmount(0.5f)
 
         if (controller.isDateWeatherDecoupled()) {
+            clearInvocations(dateSmartspaceView)
             clearInvocations(weatherSmartspaceView)
         }
         clearInvocations(smartspaceView)
@@ -734,7 +771,38 @@
         ).thenReturn(if (value) 1 else 0)
     }
 
-    // Separate function for the weather view, which doesn't implement all functions in interface.
+    // Separate function for the date view, which implements a specific subset of all functions.
+    private fun createDateSmartspaceView(): SmartspaceView {
+        return spy(object : View(context), SmartspaceView {
+            override fun registerDataProvider(plugin: BcSmartspaceDataPlugin?) {
+            }
+
+            override fun setPrimaryTextColor(color: Int) {
+            }
+
+            override fun setIsDreaming(isDreaming: Boolean) {
+            }
+
+            override fun setUiSurface(uiSurface: String) {
+            }
+
+            override fun setDozeAmount(amount: Float) {
+            }
+
+            override fun setIntentStarter(intentStarter: BcSmartspaceDataPlugin.IntentStarter?) {
+            }
+
+            override fun setFalsingManager(falsingManager: FalsingManager?) {
+            }
+
+            override fun setDnd(image: Drawable?, description: String?) {
+            }
+
+            override fun setNextAlarm(image: Drawable?, description: String?) {
+            }
+        })
+    }
+    // Separate function for the weather view, which implements a specific subset of all functions.
     private fun createWeatherSmartspaceView(): SmartspaceView {
         return spy(object : View(context), SmartspaceView {
             override fun registerDataProvider(plugin: BcSmartspaceDataPlugin?) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
index af52459..701cf95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
@@ -117,6 +117,10 @@
         extras.putBoolean(SHOW_WHEN_UNPROVISIONED_FLAG, true);
         mNotification.extras = extras;
 
+        // GIVEN notification has the permission to display during setup
+        when(mIPackageManager.checkUidPermission(SETUP_NOTIF_PERMISSION, NOTIF_UID))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+
         // THEN don't filter out the notification
         assertFalse(mDeviceProvisionedFilter.shouldFilterOut(mEntry, 0));
     }
@@ -126,10 +130,15 @@
         // GIVEN device is unprovisioned
         when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(false);
 
-        // GIVEN notification does not have the flag to allow the notification during setup
+        // GIVEN notification has a flag to allow the notification during setup
         Bundle extras = new Bundle();
+        extras.putBoolean(SHOW_WHEN_UNPROVISIONED_FLAG, true);
         mNotification.extras = extras;
 
+        // GIVEN notification does NOT have permission to display during setup
+        when(mIPackageManager.checkUidPermission(SETUP_NOTIF_PERMISSION, NOTIF_UID))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
+
         // THEN filter out the notification
         assertTrue(mDeviceProvisionedFilter.shouldFilterOut(mEntry, 0));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
index 33b94e3..bd03903 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
+import java.lang.RuntimeException
 import kotlinx.coroutines.Dispatchers
 import org.junit.Before
 import org.junit.Test
@@ -113,6 +114,24 @@
         assertThat(data).hasSize(2)
     }
 
+    @Test
+    fun onPullAtom_throwsInterruptedException_failsGracefully() {
+        val pipeline: NotifPipeline = mock()
+        whenever(pipeline.allNotifs).thenAnswer { throw InterruptedException("Timeout") }
+        val logger = NotificationMemoryLogger(pipeline, statsManager, immediate, bgExecutor)
+        assertThat(logger.onPullAtom(SysUiStatsLog.NOTIFICATION_MEMORY_USE, mutableListOf()))
+            .isEqualTo(StatsManager.PULL_SKIP)
+    }
+
+    @Test
+    fun onPullAtom_throwsRuntimeException_failsGracefully() {
+        val pipeline: NotifPipeline = mock()
+        whenever(pipeline.allNotifs).thenThrow(RuntimeException("Something broke!"))
+        val logger = NotificationMemoryLogger(pipeline, statsManager, immediate, bgExecutor)
+        assertThat(logger.onPullAtom(SysUiStatsLog.NOTIFICATION_MEMORY_USE, mutableListOf()))
+            .isEqualTo(StatsManager.PULL_SKIP)
+    }
+
     private fun createLoggerWithNotifications(
         notifications: List<Notification>
     ): NotificationMemoryLogger {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index ed3f710..7e69efa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -264,6 +264,19 @@
     }
 
     @Test
+    public void notifPositionAlignedWithClockAndBurnInOffsetInSplitShadeMode() {
+        setSplitShadeTopMargin(100); // this makes clock to be at 100
+        givenAOD();
+        mIsSplitShade = true;
+        givenMaxBurnInOffset(100);
+        givenHighestBurnInOffset(); // this makes clock to be at 200
+        // WHEN the position algorithm is run
+        positionClock();
+        // THEN the notif padding adjusts for burn-in offset: clock position - burn-in offset
+        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(100);
+    }
+
+    @Test
     public void clockPositionedDependingOnMarginInSplitShade() {
         setSplitShadeTopMargin(400);
         givenLockScreen();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
index 6fb6893..8aaa57f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -23,6 +23,8 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
@@ -33,7 +35,10 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarMobileView;
 import com.android.systemui.statusbar.StatusBarWifiView;
@@ -46,6 +51,8 @@
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
 import com.android.systemui.statusbar.pipeline.wifi.ui.WifiUiAdapter;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.tuner.TunerService;
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 
 import org.junit.Before;
@@ -87,6 +94,61 @@
         testCallOnAdd_forManager(manager);
     }
 
+    @Test
+    public void testRemoveIcon_ignoredForNewPipeline() {
+        IconManager manager = mock(IconManager.class);
+
+        // GIVEN the new pipeline is on
+        StatusBarPipelineFlags flags = mock(StatusBarPipelineFlags.class);
+        when(flags.isIconControlledByFlags("test_icon")).thenReturn(true);
+
+        StatusBarIconController iconController = new StatusBarIconControllerImpl(
+                mContext,
+                mock(CommandQueue.class),
+                mock(DemoModeController.class),
+                mock(ConfigurationController.class),
+                mock(TunerService.class),
+                mock(DumpManager.class),
+                mock(StatusBarIconList.class),
+                flags
+        );
+
+        iconController.addIconGroup(manager);
+
+        // WHEN a request to remove a new icon is sent
+        iconController.removeIcon("test_icon", 0);
+
+        // THEN it is not removed for those icons
+        verify(manager, never()).onRemoveIcon(anyInt());
+    }
+
+    @Test
+    public void testRemoveAllIconsForSlot_ignoredForNewPipeline() {
+        IconManager manager = mock(IconManager.class);
+
+        // GIVEN the new pipeline is on
+        StatusBarPipelineFlags flags = mock(StatusBarPipelineFlags.class);
+        when(flags.isIconControlledByFlags("test_icon")).thenReturn(true);
+
+        StatusBarIconController iconController = new StatusBarIconControllerImpl(
+                mContext,
+                mock(CommandQueue.class),
+                mock(DemoModeController.class),
+                mock(ConfigurationController.class),
+                mock(TunerService.class),
+                mock(DumpManager.class),
+                mock(StatusBarIconList.class),
+                flags
+        );
+
+        iconController.addIconGroup(manager);
+
+        // WHEN a request to remove a new icon is sent
+        iconController.removeAllIconsForSlot("test_icon");
+
+        // THEN it is not removed for those icons
+        verify(manager, never()).onRemoveIcon(anyInt());
+    }
 
     private <T extends IconManager & TestableIconManager> void testCallOnAdd_forManager(T manager) {
         StatusBarIconHolder holder = holderForType(TYPE_ICON);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 36e76f4..85e8c34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -23,10 +23,12 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -45,6 +47,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.R;
 import com.android.systemui.SysuiBaseFragmentTest;
 import com.android.systemui.dump.DumpManager;
@@ -67,6 +70,8 @@
 import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
+import com.android.systemui.statusbar.window.StatusBarWindowStateListener;
 import com.android.systemui.util.CarrierConfigTracker;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.settings.SecureSettings;
@@ -79,6 +84,9 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
 @SmallTest
@@ -118,6 +126,12 @@
     private StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
     @Mock
     private DumpManager mDumpManager;
+    @Mock
+    private StatusBarWindowStateController mStatusBarWindowStateController;
+    @Mock
+    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+    private List<StatusBarWindowStateListener> mStatusBarWindowStateListeners = new ArrayList<>();
 
     public CollapsedStatusBarFragmentTest() {
         super(CollapsedStatusBarFragment.class);
@@ -127,6 +141,14 @@
     public void setup() {
         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
         mDependency.injectMockDependency(DarkIconDispatcher.class);
+
+        // Keep the window state listeners so we can dispatch to them to test the status bar
+        // fragment's response.
+        doAnswer(invocation -> {
+            mStatusBarWindowStateListeners.add(invocation.getArgument(0));
+            return null;
+        }).when(mStatusBarWindowStateController).addListener(
+                any(StatusBarWindowStateListener.class));
     }
 
     @Test
@@ -414,6 +436,27 @@
         assertFalse(contains);
     }
 
+    @Test
+    public void testStatusBarIcons_hiddenThroughoutCameraLaunch() {
+        final CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        mockSecureCameraLaunch(fragment, true /* launched */);
+
+        // Status icons should be invisible or gone, but certainly not VISIBLE.
+        assertNotEquals(View.VISIBLE, getEndSideContentView().getVisibility());
+        assertNotEquals(View.VISIBLE, getClockView().getVisibility());
+
+        mockSecureCameraLaunchFinished();
+
+        assertNotEquals(View.VISIBLE, getEndSideContentView().getVisibility());
+        assertNotEquals(View.VISIBLE, getClockView().getVisibility());
+
+        mockSecureCameraLaunch(fragment, false /* launched */);
+
+        assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
+        assertEquals(View.VISIBLE, getClockView().getVisibility());
+    }
+
     @Override
     protected Fragment instantiate(Context context, String className, Bundle arguments) {
         MockitoAnnotations.initMocks(this);
@@ -455,7 +498,9 @@
                 mOperatorNameViewControllerFactory,
                 mSecureSettings,
                 mExecutor,
-                mDumpManager);
+                mDumpManager,
+                mStatusBarWindowStateController,
+                mKeyguardUpdateMonitor);
     }
 
     private void setUpDaggerComponent() {
@@ -478,6 +523,35 @@
                 mNotificationAreaInner);
     }
 
+    /**
+     * Configure mocks to return values consistent with the secure camera animating itself launched
+     * over the keyguard.
+     */
+    private void mockSecureCameraLaunch(CollapsedStatusBarFragment fragment, boolean launched) {
+        when(mKeyguardUpdateMonitor.isSecureCameraLaunchedOverKeyguard()).thenReturn(launched);
+        when(mKeyguardStateController.isOccluded()).thenReturn(launched);
+
+        if (launched) {
+            fragment.onCameraLaunchGestureDetected(0 /* source */);
+        } else {
+            for (StatusBarWindowStateListener listener : mStatusBarWindowStateListeners) {
+                listener.onStatusBarWindowStateChanged(StatusBarManager.WINDOW_STATE_SHOWING);
+            }
+        }
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+    }
+
+    /**
+     * Configure mocks to return values consistent with the secure camera showing over the keyguard
+     * with its launch animation finished.
+     */
+    private void mockSecureCameraLaunchFinished() {
+        for (StatusBarWindowStateListener listener : mStatusBarWindowStateListeners) {
+            listener.onStatusBarWindowStateChanged(StatusBarManager.WINDOW_STATE_HIDDEN);
+        }
+    }
+
     private CollapsedStatusBarFragment resumeAndGetFragment() {
         mFragments.dispatchResume();
         processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
index f822ba0..45189cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
@@ -19,7 +19,8 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.table.TableRowLogger
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION_IN
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION_OUT
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CARRIER_NETWORK_CHANGE
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CDMA_LEVEL
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CONNECTION_STATE
@@ -54,7 +55,19 @@
         assertThat(logger.changes)
             .contains(Pair(COL_CONNECTION_STATE, connection.dataConnectionState.toString()))
         assertThat(logger.changes)
-            .contains(Pair(COL_ACTIVITY_DIRECTION, connection.dataActivityDirection.toString()))
+            .contains(
+                Pair(
+                    COL_ACTIVITY_DIRECTION_IN,
+                    connection.dataActivityDirection.hasActivityIn.toString(),
+                )
+            )
+        assertThat(logger.changes)
+            .contains(
+                Pair(
+                    COL_ACTIVITY_DIRECTION_OUT,
+                    connection.dataActivityDirection.hasActivityOut.toString(),
+                )
+            )
         assertThat(logger.changes)
             .contains(
                 Pair(COL_CARRIER_NETWORK_CHANGE, connection.carrierNetworkChangeActive.toString())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt
new file mode 100644
index 0000000..63cb30c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfigTest.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.model
+
+import android.os.PersistableBundle
+import android.telephony.CarrierConfigManager
+import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL
+import android.telephony.CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import org.junit.Before
+import org.junit.Test
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+class SystemUiCarrierConfigTest : SysuiTestCase() {
+
+    lateinit var underTest: SystemUiCarrierConfig
+
+    @Before
+    fun setUp() {
+        underTest = SystemUiCarrierConfig(SUB_1_ID, createTestConfig())
+    }
+
+    @Test
+    fun `process new config - reflected by isUsingDefault`() {
+        // Starts out using the defaults
+        assertThat(underTest.isUsingDefault).isTrue()
+
+        // ANY new config means we're no longer tracking defaults
+        underTest.processNewCarrierConfig(createTestConfig())
+
+        assertThat(underTest.isUsingDefault).isFalse()
+    }
+
+    @Test
+    fun `process new config - updates all flows`() {
+        assertThat(underTest.shouldInflateSignalStrength.value).isFalse()
+        assertThat(underTest.showOperatorNameInStatusBar.value).isFalse()
+
+        underTest.processNewCarrierConfig(
+            configWithOverrides(
+                KEY_INFLATE_SIGNAL_STRENGTH_BOOL to true,
+                KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL to true,
+            )
+        )
+
+        assertThat(underTest.shouldInflateSignalStrength.value).isTrue()
+        assertThat(underTest.showOperatorNameInStatusBar.value).isTrue()
+    }
+
+    @Test
+    fun `process new config - defaults to false for config overrides`() {
+        // This case is only apparent when:
+        //   1. The default is true
+        //   2. The override config has no value for a given key
+        // In this case (per the old code) we would use the default value of false, despite there
+        // being no override key present in the override config
+
+        underTest =
+            SystemUiCarrierConfig(
+                SUB_1_ID,
+                configWithOverrides(
+                    KEY_INFLATE_SIGNAL_STRENGTH_BOOL to true,
+                    KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL to true,
+                )
+            )
+
+        assertThat(underTest.isUsingDefault).isTrue()
+        assertThat(underTest.shouldInflateSignalStrength.value).isTrue()
+        assertThat(underTest.showOperatorNameInStatusBar.value).isTrue()
+
+        // Process a new config with no keys
+        underTest.processNewCarrierConfig(PersistableBundle())
+
+        assertThat(underTest.isUsingDefault).isFalse()
+        assertThat(underTest.shouldInflateSignalStrength.value).isFalse()
+        assertThat(underTest.showOperatorNameInStatusBar.value).isFalse()
+    }
+
+    companion object {
+        private const val SUB_1_ID = 1
+
+        /**
+         * In order to keep us from having to update every place that might want to create a config,
+         * make sure to add new keys here
+         */
+        fun createTestConfig() =
+            PersistableBundle().also {
+                it.putBoolean(CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false)
+                it.putBoolean(CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL, false)
+            }
+
+        /** Override the default config with the given (key, value) pair */
+        fun configWithOverride(key: String, override: Boolean): PersistableBundle =
+            createTestConfig().also { it.putBoolean(key, override) }
+
+        /** Override any number of configs from the default */
+        fun configWithOverrides(vararg overrides: Pair<String, Boolean>) =
+            createTestConfig().also { config ->
+                overrides.forEach { (key, value) -> config.putBoolean(key, value) }
+            }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
new file mode 100644
index 0000000..521c67f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.repository
+
+import android.content.Intent
+import android.os.PersistableBundle
+import android.telephony.CarrierConfigManager
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
+import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
+import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+import org.mockito.MockitoSession
+import org.mockito.quality.Strictness
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+class CarrierConfigRepositoryTest : SysuiTestCase() {
+    private val testDispatcher = UnconfinedTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+
+    private lateinit var underTest: CarrierConfigRepository
+    private lateinit var mockitoSession: MockitoSession
+    private lateinit var carrierConfigCoreStartable: CarrierConfigCoreStartable
+
+    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var carrierConfigManager: CarrierConfigManager
+    @Mock private lateinit var dumpManager: DumpManager
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        mockitoSession =
+            mockitoSession()
+                .initMocks(this)
+                .mockStatic(CarrierConfigManager::class.java)
+                .strictness(Strictness.LENIENT)
+                .startMocking()
+
+        whenever(CarrierConfigManager.getDefaultConfig()).thenReturn(DEFAULT_CONFIG)
+
+        whenever(carrierConfigManager.getConfigForSubId(anyInt())).thenAnswer { invocation ->
+            when (invocation.getArgument(0) as Int) {
+                1 -> CONFIG_1
+                2 -> CONFIG_2
+                else -> null
+            }
+        }
+
+        underTest =
+            CarrierConfigRepository(
+                fakeBroadcastDispatcher,
+                carrierConfigManager,
+                dumpManager,
+                logger,
+                testScope.backgroundScope,
+            )
+
+        carrierConfigCoreStartable =
+            CarrierConfigCoreStartable(underTest, testScope.backgroundScope)
+    }
+
+    @After
+    fun tearDown() {
+        mockitoSession.finishMocking()
+    }
+
+    @Test
+    fun `carrier config stream produces int-bundle pairs`() =
+        testScope.runTest {
+            var latest: Pair<Int, PersistableBundle>? = null
+            val job = underTest.carrierConfigStream.onEach { latest = it }.launchIn(this)
+
+            sendConfig(SUB_ID_1)
+            assertThat(latest).isEqualTo(Pair(SUB_ID_1, CONFIG_1))
+
+            sendConfig(SUB_ID_2)
+            assertThat(latest).isEqualTo(Pair(SUB_ID_2, CONFIG_2))
+
+            job.cancel()
+        }
+
+    @Test
+    fun `carrier config stream ignores invalid subscriptions`() =
+        testScope.runTest {
+            var latest: Pair<Int, PersistableBundle>? = null
+            val job = underTest.carrierConfigStream.onEach { latest = it }.launchIn(this)
+
+            sendConfig(INVALID_SUBSCRIPTION_ID)
+
+            assertThat(latest).isNull()
+
+            job.cancel()
+        }
+
+    @Test
+    fun `getOrCreateConfig - uses default config if no override`() {
+        val config = underTest.getOrCreateConfigForSubId(123)
+        assertThat(config.isUsingDefault).isTrue()
+    }
+
+    @Test
+    fun `getOrCreateConfig - uses override if exists`() {
+        val config = underTest.getOrCreateConfigForSubId(SUB_ID_1)
+        assertThat(config.isUsingDefault).isFalse()
+    }
+
+    @Test
+    fun `config - updates while config stream is collected`() =
+        testScope.runTest {
+            CONFIG_1.putBoolean(CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false)
+
+            carrierConfigCoreStartable.start()
+
+            val config = underTest.getOrCreateConfigForSubId(SUB_ID_1)
+            assertThat(config.shouldInflateSignalStrength.value).isFalse()
+
+            CONFIG_1.putBoolean(CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL, true)
+            sendConfig(SUB_ID_1)
+
+            assertThat(config.shouldInflateSignalStrength.value).isTrue()
+        }
+
+    private fun sendConfig(subId: Int) {
+        fakeBroadcastDispatcher.registeredReceivers.forEach { receiver ->
+            receiver.onReceive(
+                context,
+                Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)
+                    .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, subId)
+            )
+        }
+    }
+
+    companion object {
+        private const val SUB_ID_1 = 1
+        private const val SUB_ID_2 = 2
+
+        private val DEFAULT_CONFIG = createTestConfig()
+        private val CONFIG_1 = createTestConfig()
+        private val CONFIG_2 = createTestConfig()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
index 0add905e..cb9eb70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
@@ -71,9 +71,6 @@
             ?: FakeMobileConnectionRepository(subId, tableLogBuffer).also { subIdRepos[subId] = it }
     }
 
-    private val _globalMobileDataSettingChangedEvent = MutableStateFlow(Unit)
-    override val globalMobileDataSettingChangedEvent = _globalMobileDataSettingChangedEvent
-
     override val defaultDataSubRatConfig = MutableStateFlow(MobileMappings.Config())
 
     private val _defaultMobileIconMapping = MutableStateFlow(TEST_MAPPING)
@@ -94,10 +91,6 @@
         _mobileConnectivity.value = model
     }
 
-    suspend fun triggerGlobalMobileDataSettingChangedEvent() {
-        _globalMobileDataSettingChangedEvent.emit(Unit)
-    }
-
     fun setActiveMobileDataSubscriptionId(subId: Int) {
         _activeMobileDataSubscriptionId.value = subId
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 0859d14..4da2104 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.demomode.DemoMode
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.TableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoMobileConnectionsRepository
@@ -40,7 +41,6 @@
 import com.android.systemui.util.mockito.kotlinArgumentCaptor
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.settings.FakeSettings
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
@@ -82,10 +82,10 @@
     @Mock private lateinit var subscriptionManager: SubscriptionManager
     @Mock private lateinit var telephonyManager: TelephonyManager
     @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var summaryLogger: TableLogBuffer
     @Mock private lateinit var demoModeController: DemoModeController
     @Mock private lateinit var dumpManager: DumpManager
 
-    private val globalSettings = FakeSettings()
     private val fakeNetworkEventsFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
     private val mobileMappings = FakeMobileMappingsProxy()
 
@@ -116,9 +116,9 @@
                 subscriptionManager,
                 telephonyManager,
                 logger,
+                summaryLogger,
                 mobileMappings,
                 fakeBroadcastDispatcher,
-                globalSettings,
                 context,
                 IMMEDIATE,
                 scope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index c02a4df..da208a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -16,24 +16,33 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
 
+import android.telephony.ServiceState
+import android.telephony.SignalStrength
+import android.telephony.TelephonyCallback
+import android.telephony.TelephonyManager
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.TableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_EMERGENCY
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_OPERATOR
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 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 com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
+import java.io.PrintWriter
+import java.io.StringWriter
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.test.TestScope
@@ -55,24 +64,18 @@
 class FullMobileConnectionRepositoryTest : SysuiTestCase() {
     private lateinit var underTest: FullMobileConnectionRepository
 
+    private val systemClock = FakeSystemClock()
     private val testDispatcher = UnconfinedTestDispatcher()
     private val testScope = TestScope(testDispatcher)
-    private val mobileMappings = FakeMobileMappingsProxy()
-    private val tableLogBuffer = mock<TableLogBuffer>()
+    private val tableLogBuffer = TableLogBuffer(maxSize = 100, name = "TestName", systemClock)
     private val mobileFactory = mock<MobileConnectionRepositoryImpl.Factory>()
     private val carrierMergedFactory = mock<CarrierMergedConnectionRepository.Factory>()
 
-    private lateinit var connectionsRepo: FakeMobileConnectionsRepository
-    private val globalMobileDataSettingChangedEvent: Flow<Unit>
-        get() = connectionsRepo.globalMobileDataSettingChangedEvent
-
     private lateinit var mobileRepo: FakeMobileConnectionRepository
     private lateinit var carrierMergedRepo: FakeMobileConnectionRepository
 
     @Before
     fun setUp() {
-        connectionsRepo = FakeMobileConnectionsRepository(mobileMappings, tableLogBuffer)
-
         mobileRepo = FakeMobileConnectionRepository(SUB_ID, tableLogBuffer)
         carrierMergedRepo = FakeMobileConnectionRepository(SUB_ID, tableLogBuffer)
 
@@ -82,7 +85,6 @@
                     any(),
                     eq(DEFAULT_NAME),
                     eq(SEP),
-                    eq(globalMobileDataSettingChangedEvent),
                 )
             )
             .thenReturn(mobileRepo)
@@ -109,7 +111,6 @@
                     tableLogBuffer,
                     DEFAULT_NAME,
                     SEP,
-                    globalMobileDataSettingChangedEvent
                 )
         }
 
@@ -310,7 +311,6 @@
                     startingIsCarrierMerged = false,
                     DEFAULT_NAME,
                     SEP,
-                    globalMobileDataSettingChangedEvent,
                 )
 
             val connection1Repeat =
@@ -319,7 +319,6 @@
                     startingIsCarrierMerged = false,
                     DEFAULT_NAME,
                     SEP,
-                    globalMobileDataSettingChangedEvent,
                 )
 
             assertThat(connection1.tableLogBuffer)
@@ -345,7 +344,6 @@
                     startingIsCarrierMerged = false,
                     DEFAULT_NAME,
                     SEP,
-                    globalMobileDataSettingChangedEvent,
                 )
 
             // WHEN a connection with the same sub ID but carrierMerged = true is created
@@ -355,7 +353,6 @@
                     startingIsCarrierMerged = true,
                     DEFAULT_NAME,
                     SEP,
-                    globalMobileDataSettingChangedEvent,
                 )
 
             // THEN the same table is re-used
@@ -363,8 +360,214 @@
                 .isSameInstanceAs(connection1Repeat.tableLogBuffer)
         }
 
-    // TODO(b/238425913): Verify that the logging switches correctly (once the carrier merged repo
-    //   implements logging).
+    @Test
+    fun connectionInfo_logging_notCarrierMerged_getsUpdates() =
+        testScope.runTest {
+            // SETUP: Use real repositories to verify the diffing still works. (See b/267501739.)
+            val telephonyManager = mock<TelephonyManager>()
+            createRealMobileRepo(telephonyManager)
+            createRealCarrierMergedRepo(FakeWifiRepository())
+
+            initializeRepo(startingIsCarrierMerged = false)
+
+            val job = underTest.connectionInfo.launchIn(this)
+
+            // WHEN we set up some mobile connection info
+            val serviceState = ServiceState()
+            serviceState.setOperatorName("longName", "OpTypical", "1")
+            serviceState.isEmergencyOnly = false
+            getTelephonyCallbackForType<TelephonyCallback.ServiceStateListener>(telephonyManager)
+                .onServiceStateChanged(serviceState)
+
+            // THEN it's logged to the buffer
+            assertThat(dumpBuffer()).contains("$COL_OPERATOR${BUFFER_SEPARATOR}OpTypical")
+            assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}false")
+
+            // WHEN we update mobile connection info
+            val serviceState2 = ServiceState()
+            serviceState2.setOperatorName("longName", "OpDiff", "1")
+            serviceState2.isEmergencyOnly = true
+            getTelephonyCallbackForType<TelephonyCallback.ServiceStateListener>(telephonyManager)
+                .onServiceStateChanged(serviceState2)
+
+            // THEN the updates are logged
+            assertThat(dumpBuffer()).contains("$COL_OPERATOR${BUFFER_SEPARATOR}OpDiff")
+            assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}true")
+
+            job.cancel()
+        }
+
+    @Test
+    fun connectionInfo_logging_carrierMerged_getsUpdates() =
+        testScope.runTest {
+            // SETUP: Use real repositories to verify the diffing still works. (See b/267501739.)
+            createRealMobileRepo(mock())
+            val wifiRepository = FakeWifiRepository()
+            createRealCarrierMergedRepo(wifiRepository)
+
+            initializeRepo(startingIsCarrierMerged = true)
+
+            val job = underTest.connectionInfo.launchIn(this)
+
+            // WHEN we set up carrier merged info
+            val networkId = 2
+            wifiRepository.setWifiNetwork(
+                WifiNetworkModel.CarrierMerged(
+                    networkId,
+                    SUB_ID,
+                    level = 3,
+                )
+            )
+
+            // THEN the carrier merged info is logged
+            assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}3")
+
+            // WHEN we update the info
+            wifiRepository.setWifiNetwork(
+                WifiNetworkModel.CarrierMerged(
+                    networkId,
+                    SUB_ID,
+                    level = 1,
+                )
+            )
+
+            // THEN the updates are logged
+            assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}1")
+
+            job.cancel()
+        }
+
+    @Test
+    fun connectionInfo_logging_updatesWhenCarrierMergedUpdates() =
+        testScope.runTest {
+            // SETUP: Use real repositories to verify the diffing still works. (See b/267501739.)
+            val telephonyManager = mock<TelephonyManager>()
+            createRealMobileRepo(telephonyManager)
+
+            val wifiRepository = FakeWifiRepository()
+            createRealCarrierMergedRepo(wifiRepository)
+
+            initializeRepo(startingIsCarrierMerged = false)
+
+            val job = underTest.connectionInfo.launchIn(this)
+
+            // WHEN we set up some mobile connection info
+            val signalStrength = mock<SignalStrength>()
+            whenever(signalStrength.level).thenReturn(1)
+
+            getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>(telephonyManager)
+                .onSignalStrengthsChanged(signalStrength)
+
+            // THEN it's logged to the buffer
+            assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}1")
+
+            // WHEN isCarrierMerged is set to true
+            val networkId = 2
+            wifiRepository.setWifiNetwork(
+                WifiNetworkModel.CarrierMerged(
+                    networkId,
+                    SUB_ID,
+                    level = 3,
+                )
+            )
+            underTest.setIsCarrierMerged(true)
+
+            // THEN the carrier merged info is logged
+            assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}3")
+
+            // WHEN the carrier merge network is updated
+            wifiRepository.setWifiNetwork(
+                WifiNetworkModel.CarrierMerged(
+                    networkId,
+                    SUB_ID,
+                    level = 4,
+                )
+            )
+
+            // THEN the new level is logged
+            assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}4")
+
+            // WHEN isCarrierMerged is set to false
+            underTest.setIsCarrierMerged(false)
+
+            // THEN the typical info is logged
+            // Note: Since our first logs also had the typical info, we need to search the log
+            // contents for after our carrier merged level log.
+            val fullBuffer = dumpBuffer()
+            val carrierMergedContentIndex = fullBuffer.indexOf("${BUFFER_SEPARATOR}4")
+            val bufferAfterCarrierMerged = fullBuffer.substring(carrierMergedContentIndex)
+            assertThat(bufferAfterCarrierMerged).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}1")
+
+            // WHEN the normal network is updated
+            val newMobileInfo =
+                MobileConnectionModel(
+                    operatorAlphaShort = "Mobile Operator 2",
+                    primaryLevel = 0,
+                )
+            mobileRepo.setConnectionInfo(newMobileInfo)
+
+            // THEN the new level is logged
+            assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}0")
+
+            job.cancel()
+        }
+
+    @Test
+    fun connectionInfo_logging_doesNotLogUpdatesForNotActiveRepo() =
+        testScope.runTest {
+            // SETUP: Use real repositories to verify the diffing still works. (See b/267501739.)
+            val telephonyManager = mock<TelephonyManager>()
+            createRealMobileRepo(telephonyManager)
+
+            val wifiRepository = FakeWifiRepository()
+            createRealCarrierMergedRepo(wifiRepository)
+
+            // WHEN isCarrierMerged = false
+            initializeRepo(startingIsCarrierMerged = false)
+
+            val job = underTest.connectionInfo.launchIn(this)
+
+            val signalStrength = mock<SignalStrength>()
+            whenever(signalStrength.level).thenReturn(1)
+            getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>(telephonyManager)
+                .onSignalStrengthsChanged(signalStrength)
+
+            // THEN updates to the carrier merged level aren't logged
+            val networkId = 2
+            wifiRepository.setWifiNetwork(
+                WifiNetworkModel.CarrierMerged(
+                    networkId,
+                    SUB_ID,
+                    level = 4,
+                )
+            )
+            assertThat(dumpBuffer()).doesNotContain("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}4")
+
+            wifiRepository.setWifiNetwork(
+                WifiNetworkModel.CarrierMerged(
+                    networkId,
+                    SUB_ID,
+                    level = 3,
+                )
+            )
+            assertThat(dumpBuffer()).doesNotContain("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}3")
+
+            // WHEN isCarrierMerged is set to true
+            underTest.setIsCarrierMerged(true)
+
+            // THEN updates to the normal level aren't logged
+            whenever(signalStrength.level).thenReturn(5)
+            getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>(telephonyManager)
+                .onSignalStrengthsChanged(signalStrength)
+            assertThat(dumpBuffer()).doesNotContain("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}5")
+
+            whenever(signalStrength.level).thenReturn(6)
+            getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>(telephonyManager)
+                .onSignalStrengthsChanged(signalStrength)
+            assertThat(dumpBuffer()).doesNotContain("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}6")
+
+            job.cancel()
+        }
 
     private fun initializeRepo(startingIsCarrierMerged: Boolean) {
         underTest =
@@ -374,16 +577,74 @@
                 tableLogBuffer,
                 DEFAULT_NAME,
                 SEP,
-                globalMobileDataSettingChangedEvent,
                 testScope.backgroundScope,
                 mobileFactory,
                 carrierMergedFactory,
             )
     }
 
+    private fun createRealMobileRepo(
+        telephonyManager: TelephonyManager,
+    ): MobileConnectionRepositoryImpl {
+        whenever(telephonyManager.subscriptionId).thenReturn(SUB_ID)
+
+        val realRepo =
+            MobileConnectionRepositoryImpl(
+                context,
+                SUB_ID,
+                defaultNetworkName = NetworkNameModel.Default("default"),
+                networkNameSeparator = SEP,
+                telephonyManager,
+                systemUiCarrierConfig = mock(),
+                fakeBroadcastDispatcher,
+                mobileMappingsProxy = mock(),
+                testDispatcher,
+                logger = mock(),
+                tableLogBuffer,
+                testScope.backgroundScope,
+            )
+        whenever(
+                mobileFactory.build(
+                    eq(SUB_ID),
+                    any(),
+                    eq(DEFAULT_NAME),
+                    eq(SEP),
+                )
+            )
+            .thenReturn(realRepo)
+
+        return realRepo
+    }
+
+    private fun createRealCarrierMergedRepo(
+        wifiRepository: FakeWifiRepository,
+    ): CarrierMergedConnectionRepository {
+        wifiRepository.setIsWifiEnabled(true)
+        wifiRepository.setIsWifiDefault(true)
+        val realRepo =
+            CarrierMergedConnectionRepository(
+                SUB_ID,
+                tableLogBuffer,
+                defaultNetworkName = NetworkNameModel.Default("default"),
+                testScope.backgroundScope,
+                wifiRepository,
+            )
+        whenever(carrierMergedFactory.build(eq(SUB_ID), any(), eq(DEFAULT_NAME)))
+            .thenReturn(realRepo)
+
+        return realRepo
+    }
+
+    private fun dumpBuffer(): String {
+        val outputWriter = StringWriter()
+        tableLogBuffer.dump(PrintWriter(outputWriter), arrayOf())
+        return outputWriter.toString()
+    }
+
     private companion object {
         const val SUB_ID = 42
         private val DEFAULT_NAME = NetworkNameModel.Default("default name")
         private const val SEP = "-"
+        private const val BUFFER_SEPARATOR = "|"
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index d6b8c0d..1a5cc9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -17,8 +17,7 @@
 package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
 
 import android.content.Intent
-import android.os.UserHandle
-import android.provider.Settings
+import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL
 import android.telephony.CellSignalStrengthCdma
 import android.telephony.NetworkRegistrationInfo
 import android.telephony.ServiceState
@@ -41,6 +40,8 @@
 import android.telephony.TelephonyManager.DATA_CONNECTING
 import android.telephony.TelephonyManager.DATA_DISCONNECTED
 import android.telephony.TelephonyManager.DATA_DISCONNECTING
+import android.telephony.TelephonyManager.DATA_HANDOVER_IN_PROGRESS
+import android.telephony.TelephonyManager.DATA_SUSPENDED
 import android.telephony.TelephonyManager.DATA_UNKNOWN
 import android.telephony.TelephonyManager.ERI_OFF
 import android.telephony.TelephonyManager.ERI_ON
@@ -59,6 +60,9 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.configWithOverride
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
 import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
@@ -67,10 +71,8 @@
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
 import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -83,7 +85,6 @@
 import org.junit.Before
 import org.junit.Test
 import org.mockito.Mock
-import org.mockito.Mockito
 import org.mockito.MockitoAnnotations
 
 @Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@@ -99,12 +100,15 @@
 
     private val scope = CoroutineScope(IMMEDIATE)
     private val mobileMappings = FakeMobileMappingsProxy()
-    private val globalSettings = FakeSettings()
+    private val systemUiCarrierConfig =
+        SystemUiCarrierConfig(
+            SUB_1_ID,
+            createTestConfig(),
+        )
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        globalSettings.userId = UserHandle.USER_ALL
         whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
 
         connectionsRepo = FakeMobileConnectionsRepository(mobileMappings, tableLogger)
@@ -116,9 +120,8 @@
                 DEFAULT_NAME,
                 SEP,
                 telephonyManager,
-                globalSettings,
+                systemUiCarrierConfig,
                 fakeBroadcastDispatcher,
-                connectionsRepo.globalMobileDataSettingChangedEvent,
                 mobileMappings,
                 IMMEDIATE,
                 logger,
@@ -255,6 +258,37 @@
         }
 
     @Test
+    fun testFlowForSubId_dataConnectionState_suspended() =
+        runBlocking(IMMEDIATE) {
+            var latest: MobileConnectionModel? = null
+            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+            val callback =
+                getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
+            callback.onDataConnectionStateChanged(DATA_SUSPENDED, 200 /* unused */)
+
+            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Suspended)
+
+            job.cancel()
+        }
+
+    @Test
+    fun testFlowForSubId_dataConnectionState_handoverInProgress() =
+        runBlocking(IMMEDIATE) {
+            var latest: MobileConnectionModel? = null
+            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+            val callback =
+                getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
+            callback.onDataConnectionStateChanged(DATA_HANDOVER_IN_PROGRESS, 200 /* unused */)
+
+            assertThat(latest?.dataConnectionState)
+                .isEqualTo(DataConnectionState.HandoverInProgress)
+
+            job.cancel()
+        }
+
+    @Test
     fun testFlowForSubId_dataConnectionState_unknown() =
         runBlocking(IMMEDIATE) {
             var latest: MobileConnectionModel? = null
@@ -270,6 +304,21 @@
         }
 
     @Test
+    fun testFlowForSubId_dataConnectionState_invalid() =
+        runBlocking(IMMEDIATE) {
+            var latest: MobileConnectionModel? = null
+            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+
+            val callback =
+                getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
+            callback.onDataConnectionStateChanged(45, 200 /* unused */)
+
+            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Invalid)
+
+            job.cancel()
+        }
+
+    @Test
     fun testFlowForSubId_dataActivity() =
         runBlocking(IMMEDIATE) {
             var latest: MobileConnectionModel? = null
@@ -352,52 +401,26 @@
     @Test
     fun dataEnabled_initial_false() =
         runBlocking(IMMEDIATE) {
-            whenever(telephonyManager.isDataConnectionAllowed).thenReturn(true)
-
-            assertThat(underTest.dataEnabled.value).isFalse()
-        }
-
-    @Test
-    fun dataEnabled_isEnabled_true() =
-        runBlocking(IMMEDIATE) {
-            whenever(telephonyManager.isDataConnectionAllowed).thenReturn(true)
-            val job = underTest.dataEnabled.launchIn(this)
-
-            assertThat(underTest.dataEnabled.value).isTrue()
-
-            job.cancel()
-        }
-
-    @Test
-    fun dataEnabled_isDisabled() =
-        runBlocking(IMMEDIATE) {
             whenever(telephonyManager.isDataConnectionAllowed).thenReturn(false)
-            val job = underTest.dataEnabled.launchIn(this)
 
             assertThat(underTest.dataEnabled.value).isFalse()
-
-            job.cancel()
         }
 
     @Test
-    fun isDataConnectionAllowed_subIdSettingUpdate_valueUpdated() =
+    fun `is data enabled - tracks telephony callback`() =
         runBlocking(IMMEDIATE) {
-            val subIdSettingName = "${Settings.Global.MOBILE_DATA}$SUB_1_ID"
-
             var latest: Boolean? = null
             val job = underTest.dataEnabled.onEach { latest = it }.launchIn(this)
 
-            // We don't read the setting directly, we query telephony when changes happen
             whenever(telephonyManager.isDataConnectionAllowed).thenReturn(false)
-            globalSettings.putInt(subIdSettingName, 0)
-            assertThat(latest).isFalse()
+            assertThat(underTest.dataEnabled.value).isFalse()
 
-            whenever(telephonyManager.isDataConnectionAllowed).thenReturn(true)
-            globalSettings.putInt(subIdSettingName, 1)
+            val callback = getTelephonyCallbackForType<TelephonyCallback.DataEnabledListener>()
+
+            callback.onDataEnabledChanged(true, 1)
             assertThat(latest).isTrue()
 
-            whenever(telephonyManager.isDataConnectionAllowed).thenReturn(false)
-            globalSettings.putInt(subIdSettingName, 0)
+            callback.onDataEnabledChanged(false, 1)
             assertThat(latest).isFalse()
 
             job.cancel()
@@ -418,8 +441,6 @@
     fun `roaming - cdma - queries telephony manager`() =
         runBlocking(IMMEDIATE) {
             var latest: Boolean? = null
-            // Start the telephony collection job so that cdmaRoaming starts updating
-            val telephonyJob = underTest.connectionInfo.launchIn(this)
             val job = underTest.cdmaRoaming.onEach { latest = it }.launchIn(this)
 
             val cb = getTelephonyCallbackForType<ServiceStateListener>()
@@ -439,7 +460,6 @@
 
             assertThat(latest).isTrue()
 
-            telephonyJob.cancel()
             job.cancel()
         }
 
@@ -625,16 +645,31 @@
             job.cancel()
         }
 
-    private fun getTelephonyCallbacks(): List<TelephonyCallback> {
-        val callbackCaptor = argumentCaptor<TelephonyCallback>()
-        Mockito.verify(telephonyManager).registerTelephonyCallback(any(), callbackCaptor.capture())
-        return callbackCaptor.allValues
-    }
+    @Test
+    fun `number of levels - uses carrier config`() =
+        runBlocking(IMMEDIATE) {
+            var latest: Int? = null
+            val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isEqualTo(DEFAULT_NUM_LEVELS)
+
+            systemUiCarrierConfig.processNewCarrierConfig(
+                configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, true)
+            )
+
+            assertThat(latest).isEqualTo(DEFAULT_NUM_LEVELS + 1)
+
+            systemUiCarrierConfig.processNewCarrierConfig(
+                configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false)
+            )
+
+            assertThat(latest).isEqualTo(DEFAULT_NUM_LEVELS)
+
+            job.cancel()
+        }
 
     private inline fun <reified T> getTelephonyCallbackForType(): T {
-        val cbs = getTelephonyCallbacks().filterIsInstance<T>()
-        assertThat(cbs.size).isEqualTo(1)
-        return cbs[0]
+        return MobileTelephonyHelpers.getTelephonyCallbackForType(telephonyManager)
     }
 
     /** Convenience constructor for SignalStrength */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index db8172a..fef0981 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -23,7 +23,6 @@
 import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
 import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
 import android.os.ParcelUuid
-import android.provider.Settings
 import android.telephony.CarrierConfigManager
 import android.telephony.SubscriptionInfo
 import android.telephony.SubscriptionManager
@@ -39,6 +38,7 @@
 import com.android.systemui.log.table.TableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
@@ -49,7 +49,6 @@
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth.assertThat
 import java.util.UUID
 import kotlinx.coroutines.CoroutineScope
@@ -80,16 +79,17 @@
     private lateinit var carrierMergedFactory: CarrierMergedConnectionRepository.Factory
     private lateinit var fullConnectionFactory: FullMobileConnectionRepository.Factory
     private lateinit var wifiRepository: FakeWifiRepository
+    private lateinit var carrierConfigRepository: CarrierConfigRepository
     @Mock private lateinit var connectivityManager: ConnectivityManager
     @Mock private lateinit var subscriptionManager: SubscriptionManager
     @Mock private lateinit var telephonyManager: TelephonyManager
     @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var summaryLogger: TableLogBuffer
     @Mock private lateinit var logBufferFactory: TableLogBufferFactory
 
     private val mobileMappings = FakeMobileMappingsProxy()
 
     private val scope = CoroutineScope(IMMEDIATE)
-    private val globalSettings = FakeSettings()
 
     @Before
     fun setUp() {
@@ -119,16 +119,25 @@
 
         wifiRepository = FakeWifiRepository()
 
+        carrierConfigRepository =
+            CarrierConfigRepository(
+                fakeBroadcastDispatcher,
+                mock(),
+                mock(),
+                logger,
+                scope,
+            )
+
         connectionFactory =
             MobileConnectionRepositoryImpl.Factory(
                 fakeBroadcastDispatcher,
                 context = context,
                 telephonyManager = telephonyManager,
                 bgDispatcher = IMMEDIATE,
-                globalSettings = globalSettings,
                 logger = logger,
                 mobileMappingsProxy = mobileMappings,
                 scope = scope,
+                carrierConfigRepository = carrierConfigRepository,
             )
         carrierMergedFactory =
             CarrierMergedConnectionRepository.Factory(
@@ -149,9 +158,9 @@
                 subscriptionManager,
                 telephonyManager,
                 logger,
+                summaryLogger,
                 mobileMappings,
                 fakeBroadcastDispatcher,
-                globalSettings,
                 context,
                 IMMEDIATE,
                 scope,
@@ -544,24 +553,6 @@
         }
 
     @Test
-    fun globalMobileDataSettingsChangedEvent_producesOnSettingChange() =
-        runBlocking(IMMEDIATE) {
-            var produced = false
-            val job =
-                underTest.globalMobileDataSettingChangedEvent
-                    .onEach { produced = true }
-                    .launchIn(this)
-
-            assertThat(produced).isFalse()
-
-            globalSettings.putInt(Settings.Global.MOBILE_DATA, 0)
-
-            assertThat(produced).isTrue()
-
-            job.cancel()
-        }
-
-    @Test
     fun mobileConnectivity_isConnected_isNotValidated() =
         runBlocking(IMMEDIATE) {
             val caps = createCapabilities(connected = true, validated = false)
@@ -627,9 +618,9 @@
                     subscriptionManager,
                     telephonyManager,
                     logger,
+                    summaryLogger,
                     mobileMappings,
                     fakeBroadcastDispatcher,
-                    globalSettings,
                     context,
                     IMMEDIATE,
                     scope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt
new file mode 100644
index 0000000..621f793
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.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.statusbar.pipeline.mobile.data.repository.prod
+
+import android.telephony.TelephonyCallback
+import android.telephony.TelephonyManager
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.google.common.truth.Truth.assertThat
+import org.mockito.Mockito.verify
+
+/** Helper methods for telephony-related callbacks for mobile tests. */
+object MobileTelephonyHelpers {
+    fun getTelephonyCallbacks(mockTelephonyManager: TelephonyManager): List<TelephonyCallback> {
+        val callbackCaptor = argumentCaptor<TelephonyCallback>()
+        verify(mockTelephonyManager).registerTelephonyCallback(any(), callbackCaptor.capture())
+        return callbackCaptor.allValues
+    }
+
+    inline fun <reified T> getTelephonyCallbackForType(mockTelephonyManager: TelephonyManager): T {
+        val cbs = getTelephonyCallbacks(mockTelephonyManager).filterIsInstance<T>()
+        assertThat(cbs.size).isEqualTo(1)
+        return cbs[0]
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt
index 7aeaa48..b9eda717dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt
@@ -71,6 +71,8 @@
     private val _numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS)
     override val numberOfLevels = _numberOfLevels
 
+    override val isForceHidden = MutableStateFlow(false)
+
     fun setIconGroup(group: SignalIcon.MobileIconGroup) {
         _iconGroup.value = group
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
index 172755c..2699316 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
@@ -73,6 +73,8 @@
     private val _isUserSetup = MutableStateFlow(true)
     override val isUserSetup = _isUserSetup
 
+    override val isForceHidden = MutableStateFlow(false)
+
     /** Always returns a new fake interactor */
     override fun createMobileConnectionInteractorForSubId(subId: Int): MobileIconInteractor {
         return FakeMobileIconInteractor(tableLogBuffer)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index c42aba5..f87f651 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -66,6 +66,7 @@
                 mobileIconsInteractor.defaultMobileIconGroup,
                 mobileIconsInteractor.defaultDataSubId,
                 mobileIconsInteractor.isDefaultConnectionFailed,
+                mobileIconsInteractor.isForceHidden,
                 connectionRepository,
             )
     }
@@ -550,6 +551,21 @@
             job.cancel()
         }
 
+    @Test
+    fun isForceHidden_matchesParent() =
+        runBlocking(IMMEDIATE) {
+            var latest: Boolean? = null
+            val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
+
+            mobileIconsInteractor.isForceHidden.value = true
+            assertThat(latest).isTrue()
+
+            mobileIconsInteractor.isForceHidden.value = false
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
     companion object {
         private val IMMEDIATE = Dispatchers.Main.immediate
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index 1b62d5c..f8a9783 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -27,7 +27,10 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.util.CarrierConfigTracker
+import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -49,6 +52,7 @@
 @SmallTest
 class MobileIconsInteractorTest : SysuiTestCase() {
     private lateinit var underTest: MobileIconsInteractor
+    private lateinit var connectivityRepository: FakeConnectivityRepository
     private lateinit var connectionsRepository: FakeMobileConnectionsRepository
     private val userSetupRepository = FakeUserSetupRepository()
     private val mobileMappingsProxy = FakeMobileMappingsProxy()
@@ -62,6 +66,8 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
+        connectivityRepository = FakeConnectivityRepository()
+
         connectionsRepository = FakeMobileConnectionsRepository(mobileMappingsProxy, tableLogBuffer)
         connectionsRepository.setMobileConnectionRepositoryMap(
             mapOf(
@@ -77,6 +83,9 @@
             MobileIconsInteractorImpl(
                 connectionsRepository,
                 carrierConfigTracker,
+                logger = mock(),
+                tableLogger = mock(),
+                connectivityRepository,
                 userSetupRepository,
                 testScope.backgroundScope,
             )
@@ -607,6 +616,32 @@
             job.cancel()
         }
 
+    @Test
+    fun isForceHidden_repoHasMobileHidden_true() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
+
+            connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.MOBILE))
+
+            assertThat(latest).isTrue()
+
+            job.cancel()
+        }
+
+    @Test
+    fun isForceHidden_repoDoesNotHaveMobileHidden_false() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
+
+            connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.WIFI))
+
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
     companion object {
         private val tableLogBuffer =
             TableLogBuffer(8, "MobileIconsInteractorTest", FakeSystemClock())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
index a2c1209..e68a397 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
@@ -29,12 +29,14 @@
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.statusbar.StatusBarIconView
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
+import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -58,31 +60,37 @@
 
     @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
     @Mock private lateinit var tableLogBuffer: TableLogBuffer
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
     @Mock private lateinit var constants: ConnectivityConstants
+    private lateinit var interactor: FakeMobileIconInteractor
+    private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
+    private lateinit var airplaneModeInteractor: AirplaneModeInteractor
 
+    private lateinit var viewModelCommon: MobileIconViewModel
     private lateinit var viewModel: LocationBasedMobileViewModel
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
+        // This line was necessary to make the onDarkChanged and setStaticDrawableColor tests pass.
+        // But, it maybe *shouldn't* be necessary.
+        whenever(constants.hasDataCapabilities).thenReturn(true)
+
         testableLooper = TestableLooper.get(this)
 
-        val interactor = FakeMobileIconInteractor(tableLogBuffer)
-
-        val viewModelCommon =
-            MobileIconViewModel(
-                subscriptionId = 1,
-                interactor,
-                logger,
-                constants,
-                testScope.backgroundScope,
+        airplaneModeRepository = FakeAirplaneModeRepository()
+        airplaneModeInteractor =
+            AirplaneModeInteractor(
+                airplaneModeRepository,
+                FakeConnectivityRepository(),
             )
-        viewModel = QsMobileIconViewModel(viewModelCommon, statusBarPipelineFlags)
+
+        interactor = FakeMobileIconInteractor(tableLogBuffer)
+        createViewModel()
     }
 
     // Note: The following tests are more like integration tests, since they stand up a full
-    // [WifiViewModel] and test the interactions between the view, view-binder, and view-model.
+    // [MobileIconViewModel] and test the interactions between the view, view-binder, and
+    // view-model.
 
     @Test
     fun setVisibleState_icon_iconShownDotHidden() {
@@ -130,7 +138,25 @@
     }
 
     @Test
-    fun isIconVisible_alwaysTrue() {
+    fun isIconVisible_noData_outputsFalse() {
+        whenever(constants.hasDataCapabilities).thenReturn(false)
+        createViewModel()
+
+        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
+
+        ViewUtils.attachView(view)
+        testableLooper.processAllMessages()
+
+        assertThat(view.isIconVisible).isFalse()
+
+        ViewUtils.detachView(view)
+    }
+
+    @Test
+    fun isIconVisible_hasData_outputsTrue() {
+        whenever(constants.hasDataCapabilities).thenReturn(true)
+        createViewModel()
+
         val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
 
         ViewUtils.attachView(view)
@@ -142,6 +168,34 @@
     }
 
     @Test
+    fun isIconVisible_notAirplaneMode_outputsTrue() {
+        airplaneModeRepository.setIsAirplaneMode(false)
+
+        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
+
+        ViewUtils.attachView(view)
+        testableLooper.processAllMessages()
+
+        assertThat(view.isIconVisible).isTrue()
+
+        ViewUtils.detachView(view)
+    }
+
+    @Test
+    fun isIconVisible_airplaneMode_outputsTrue() {
+        airplaneModeRepository.setIsAirplaneMode(true)
+
+        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
+
+        ViewUtils.attachView(view)
+        testableLooper.processAllMessages()
+
+        assertThat(view.isIconVisible).isFalse()
+
+        ViewUtils.detachView(view)
+    }
+
+    @Test
     fun onDarkChanged_iconHasNewColor() {
         whenever(statusBarPipelineFlags.useDebugColoring()).thenReturn(false)
         val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
@@ -184,6 +238,18 @@
     private fun View.getDotView(): View {
         return this.requireViewById(R.id.status_bar_dot)
     }
+
+    private fun createViewModel() {
+        viewModelCommon =
+            MobileIconViewModel(
+                subscriptionId = 1,
+                interactor,
+                airplaneModeInteractor,
+                constants,
+                testScope.backgroundScope,
+            )
+        viewModel = QsMobileIconViewModel(viewModelCommon, statusBarPipelineFlags)
+    }
 }
 
 private const val SLOT_NAME = "TestSlotName"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
index c960a06..f983030 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
@@ -21,10 +21,13 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
+import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModelTest.Companion.defaultSignal
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.launchIn
@@ -46,8 +49,8 @@
     private lateinit var qsIcon: QsMobileIconViewModel
     private lateinit var keyguardIcon: KeyguardMobileIconViewModel
     private lateinit var interactor: FakeMobileIconInteractor
+    private lateinit var airplaneModeInteractor: AirplaneModeInteractor
     @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
     @Mock private lateinit var constants: ConnectivityConstants
     @Mock private lateinit var tableLogBuffer: TableLogBuffer
 
@@ -57,6 +60,11 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
+        airplaneModeInteractor =
+            AirplaneModeInteractor(
+                FakeAirplaneModeRepository(),
+                FakeConnectivityRepository(),
+            )
         interactor = FakeMobileIconInteractor(tableLogBuffer)
         interactor.apply {
             setLevel(1)
@@ -68,7 +76,13 @@
             isDataConnected.value = true
         }
         commonImpl =
-            MobileIconViewModel(SUB_1_ID, interactor, logger, constants, testScope.backgroundScope)
+            MobileIconViewModel(
+                SUB_1_ID,
+                interactor,
+                airplaneModeInteractor,
+                constants,
+                testScope.backgroundScope,
+            )
 
         homeIcon = HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags)
         qsIcon = QsMobileIconViewModel(commonImpl, statusBarPipelineFlags)
@@ -78,14 +92,14 @@
     @Test
     fun `location based view models receive same icon id when common impl updates`() =
         testScope.runTest {
-            var latestHome: Int? = null
-            val homeJob = homeIcon.iconId.onEach { latestHome = it }.launchIn(this)
+            var latestHome: SignalIconModel? = null
+            val homeJob = homeIcon.icon.onEach { latestHome = it }.launchIn(this)
 
-            var latestQs: Int? = null
-            val qsJob = qsIcon.iconId.onEach { latestQs = it }.launchIn(this)
+            var latestQs: SignalIconModel? = null
+            val qsJob = qsIcon.icon.onEach { latestQs = it }.launchIn(this)
 
-            var latestKeyguard: Int? = null
-            val keyguardJob = keyguardIcon.iconId.onEach { latestKeyguard = it }.launchIn(this)
+            var latestKeyguard: SignalIconModel? = null
+            val keyguardJob = keyguardIcon.icon.onEach { latestKeyguard = it }.launchIn(this)
 
             var expected = defaultSignal(level = 1)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
index a24e29ae..bec276a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
@@ -17,16 +17,20 @@
 package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
 
 import androidx.test.filters.SmallTest
-import com.android.settingslib.graph.SignalDrawable
+import com.android.settingslib.AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH
+import com.android.settingslib.AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH_NONE
 import com.android.settingslib.mobile.TelephonyIcons.THREE_G
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -47,7 +51,8 @@
 class MobileIconViewModelTest : SysuiTestCase() {
     private lateinit var underTest: MobileIconViewModel
     private lateinit var interactor: FakeMobileIconInteractor
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
+    private lateinit var airplaneModeInteractor: AirplaneModeInteractor
     @Mock private lateinit var constants: ConnectivityConstants
     @Mock private lateinit var tableLogBuffer: TableLogBuffer
 
@@ -57,6 +62,15 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
+        whenever(constants.hasDataCapabilities).thenReturn(true)
+
+        airplaneModeRepository = FakeAirplaneModeRepository()
+        airplaneModeInteractor =
+            AirplaneModeInteractor(
+                airplaneModeRepository,
+                FakeConnectivityRepository(),
+            )
+
         interactor = FakeMobileIconInteractor(tableLogBuffer)
         interactor.apply {
             setLevel(1)
@@ -67,15 +81,94 @@
             setNumberOfLevels(4)
             isDataConnected.value = true
         }
-        underTest =
-            MobileIconViewModel(SUB_1_ID, interactor, logger, constants, testScope.backgroundScope)
+        createAndSetViewModel()
     }
 
     @Test
+    fun isVisible_notDataCapable_alwaysFalse() =
+        testScope.runTest {
+            // Create a new view model here so the constants are properly read
+            whenever(constants.hasDataCapabilities).thenReturn(false)
+            createAndSetViewModel()
+
+            var latest: Boolean? = null
+            val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
+    @Test
+    fun isVisible_notAirplane_notForceHidden_true() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
+
+            airplaneModeRepository.setIsAirplaneMode(false)
+            interactor.isForceHidden.value = false
+
+            assertThat(latest).isTrue()
+
+            job.cancel()
+        }
+
+    @Test
+    fun isVisible_airplane_false() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
+
+            airplaneModeRepository.setIsAirplaneMode(true)
+            interactor.isForceHidden.value = false
+
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
+    @Test
+    fun isVisible_forceHidden_false() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
+
+            airplaneModeRepository.setIsAirplaneMode(false)
+            interactor.isForceHidden.value = true
+
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
+    @Test
+    fun isVisible_respondsToUpdates() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
+
+            airplaneModeRepository.setIsAirplaneMode(false)
+            interactor.isForceHidden.value = false
+
+            assertThat(latest).isTrue()
+
+            airplaneModeRepository.setIsAirplaneMode(true)
+            assertThat(latest).isFalse()
+
+            airplaneModeRepository.setIsAirplaneMode(false)
+            assertThat(latest).isTrue()
+
+            interactor.isForceHidden.value = true
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
+    @Test
     fun iconId_correctLevel_notCutout() =
         testScope.runTest {
-            var latest: Int? = null
-            val job = underTest.iconId.onEach { latest = it }.launchIn(this)
+            var latest: SignalIconModel? = null
+            val job = underTest.icon.onEach { latest = it }.launchIn(this)
             val expected = defaultSignal()
 
             assertThat(latest).isEqualTo(expected)
@@ -88,8 +181,8 @@
         testScope.runTest {
             interactor.setIsDefaultDataEnabled(false)
 
-            var latest: Int? = null
-            val job = underTest.iconId.onEach { latest = it }.launchIn(this)
+            var latest: SignalIconModel? = null
+            val job = underTest.icon.onEach { latest = it }.launchIn(this)
             val expected = defaultSignal(level = 1, connected = false)
 
             assertThat(latest).isEqualTo(expected)
@@ -100,8 +193,8 @@
     @Test
     fun `icon - uses empty state - when not in service`() =
         testScope.runTest {
-            var latest: Int? = null
-            val job = underTest.iconId.onEach { latest = it }.launchIn(this)
+            var latest: SignalIconModel? = null
+            val job = underTest.icon.onEach { latest = it }.launchIn(this)
 
             interactor.isInService.value = false
 
@@ -122,6 +215,39 @@
         }
 
     @Test
+    fun contentDescription_notInService_usesNoPhone() =
+        testScope.runTest {
+            var latest: ContentDescription? = null
+            val job = underTest.contentDescription.onEach { latest = it }.launchIn(this)
+
+            interactor.isInService.value = false
+
+            assertThat((latest as ContentDescription.Resource).res)
+                .isEqualTo(PHONE_SIGNAL_STRENGTH_NONE)
+
+            job.cancel()
+        }
+
+    @Test
+    fun contentDescription_inService_usesLevel() =
+        testScope.runTest {
+            var latest: ContentDescription? = null
+            val job = underTest.contentDescription.onEach { latest = it }.launchIn(this)
+
+            interactor.isInService.value = true
+
+            interactor.level.value = 2
+            assertThat((latest as ContentDescription.Resource).res)
+                .isEqualTo(PHONE_SIGNAL_STRENGTH[2])
+
+            interactor.level.value = 0
+            assertThat((latest as ContentDescription.Resource).res)
+                .isEqualTo(PHONE_SIGNAL_STRENGTH[0])
+
+            job.cancel()
+        }
+
+    @Test
     fun networkType_dataEnabled_groupIsRepresented() =
         testScope.runTest {
             val expected =
@@ -329,14 +455,7 @@
         testScope.runTest {
             // Create a new view model here so the constants are properly read
             whenever(constants.shouldShowActivityConfig).thenReturn(false)
-            underTest =
-                MobileIconViewModel(
-                    SUB_1_ID,
-                    interactor,
-                    logger,
-                    constants,
-                    testScope.backgroundScope,
-                )
+            createAndSetViewModel()
 
             var inVisible: Boolean? = null
             val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
@@ -368,14 +487,7 @@
         testScope.runTest {
             // Create a new view model here so the constants are properly read
             whenever(constants.shouldShowActivityConfig).thenReturn(true)
-            underTest =
-                MobileIconViewModel(
-                    SUB_1_ID,
-                    interactor,
-                    logger,
-                    constants,
-                    testScope.backgroundScope,
-                )
+            createAndSetViewModel()
 
             var inVisible: Boolean? = null
             val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
@@ -424,6 +536,16 @@
             containerJob.cancel()
         }
 
+    private fun createAndSetViewModel() {
+        underTest = MobileIconViewModel(
+            SUB_1_ID,
+            interactor,
+            airplaneModeInteractor,
+            constants,
+            testScope.backgroundScope,
+        )
+    }
+
     companion object {
         private const val SUB_1_ID = 1
 
@@ -431,10 +553,11 @@
         fun defaultSignal(
             level: Int = 1,
             connected: Boolean = true,
-        ): Int {
-            return SignalDrawable.getState(level, /* numLevels */ 4, !connected)
+        ): SignalIconModel {
+            return SignalIconModel(level, numberOfLevels = 4, showExclamationMark = !connected)
         }
 
-        fun emptySignal(): Int = SignalDrawable.getEmptyState(4)
+        fun emptySignal(): SignalIconModel =
+            SignalIconModel(level = 0, numberOfLevels = 4, showExclamationMark = true)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
index 58b50c7..d9268a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
@@ -20,11 +20,14 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.statusbar.phone.StatusBarLocation
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
+import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -46,6 +49,7 @@
     private lateinit var underTest: MobileIconsViewModel
     private val interactor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
 
+    private lateinit var airplaneModeInteractor: AirplaneModeInteractor
     @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
     @Mock private lateinit var logger: ConnectivityPipelineLogger
     @Mock private lateinit var constants: ConnectivityConstants
@@ -57,6 +61,12 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
+        airplaneModeInteractor =
+            AirplaneModeInteractor(
+                FakeAirplaneModeRepository(),
+                FakeConnectivityRepository(),
+            )
+
         val subscriptionIdsFlow =
             interactor.filteredSubscriptions
                 .map { subs -> subs.map { it.subscriptionId } }
@@ -66,6 +76,7 @@
             MobileIconsViewModel(
                 subscriptionIdsFlow,
                 interactor,
+                airplaneModeInteractor,
                 logger,
                 constants,
                 testScope.backgroundScope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
index 3fe6983..e4c8fd0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.pipeline.shared.ui.view
 
+import android.graphics.Rect
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
@@ -118,6 +119,22 @@
         assertThat(view.isIconVisible).isEqualTo(false)
     }
 
+    @Test
+    fun getDrawingRect_takesTranslationIntoAccount() {
+        val view = createAndInitView()
+
+        view.translationX = 50f
+        view.translationY = 60f
+
+        val drawingRect = Rect()
+        view.getDrawingRect(drawingRect)
+
+        assertThat(drawingRect.left).isEqualTo(view.left + 50)
+        assertThat(drawingRect.right).isEqualTo(view.right + 50)
+        assertThat(drawingRect.top).isEqualTo(view.top + 60)
+        assertThat(drawingRect.bottom).isEqualTo(view.bottom + 60)
+    }
+
     private fun createAndInitView(): ModernStatusBarView {
         val view = ModernStatusBarView(context, null)
         binding = TestBinding()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
index e1668e8..d51c514 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.stylus
 
+import android.app.ActivityManager
 import android.app.Notification
 import android.content.BroadcastReceiver
 import android.content.Context
@@ -27,6 +28,7 @@
 import android.view.InputDevice
 import androidx.core.app.NotificationManagerCompat
 import androidx.test.filters.SmallTest
+import com.android.internal.logging.UiEventLogger
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.mockito.any
@@ -54,15 +56,23 @@
 @SmallTest
 class StylusUsiPowerUiTest : SysuiTestCase() {
     @Mock lateinit var notificationManager: NotificationManagerCompat
+
     @Mock lateinit var inputManager: InputManager
+
     @Mock lateinit var handler: Handler
+
     @Mock lateinit var btStylusDevice: InputDevice
+
+    @Mock lateinit var uiEventLogger: UiEventLogger
+
     @Captor lateinit var notificationCaptor: ArgumentCaptor<Notification>
 
     private lateinit var stylusUsiPowerUi: StylusUsiPowerUI
     private lateinit var broadcastReceiver: BroadcastReceiver
     private lateinit var contextSpy: Context
 
+    private val uid = ActivityManager.getCurrentUser()
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -80,7 +90,8 @@
         whenever(btStylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
         whenever(btStylusDevice.bluetoothAddress).thenReturn("SO:ME:AD:DR:ES")
 
-        stylusUsiPowerUi = StylusUsiPowerUI(contextSpy, notificationManager, inputManager, handler)
+        stylusUsiPowerUi =
+            StylusUsiPowerUI(contextSpy, notificationManager, inputManager, handler, uiEventLogger)
         broadcastReceiver = stylusUsiPowerUi.receiver
     }
 
@@ -197,6 +208,19 @@
     }
 
     @Test
+    fun updateBatteryState_showsNotification_logsNotificationShown() {
+        stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
+
+        verify(uiEventLogger, times(1))
+            .logWithPosition(
+                StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_SHOWN,
+                uid,
+                contextSpy.packageName,
+                10
+            )
+    }
+
+    @Test
     fun broadcastReceiver_clicked_hasInputDeviceId_startsUsiDetailsActivity() {
         val intent = Intent(StylusUsiPowerUI.ACTION_CLICKED_LOW_BATTERY)
         val activityIntentCaptor = argumentCaptor<Intent>()
@@ -219,4 +243,32 @@
 
         verify(contextSpy, never()).startActivity(any())
     }
+
+    @Test
+    fun broadcastReceiver_clicked_logsNotificationClicked() {
+        val intent = Intent(StylusUsiPowerUI.ACTION_CLICKED_LOW_BATTERY)
+        broadcastReceiver.onReceive(contextSpy, intent)
+
+        verify(uiEventLogger, times(1))
+            .logWithPosition(
+                StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_CLICKED,
+                uid,
+                contextSpy.packageName,
+                100
+            )
+    }
+
+    @Test
+    fun broadcastReceiver_dismissed_logsNotificationDismissed() {
+        val intent = Intent(StylusUsiPowerUI.ACTION_DISMISSED_LOW_BATTERY)
+        broadcastReceiver.onReceive(contextSpy, intent)
+
+        verify(uiEventLogger, times(1))
+            .logWithPosition(
+                StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_DISMISSED,
+                uid,
+                contextSpy.packageName,
+                100
+            )
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt
index 756397a..74ed7fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationTest.kt
@@ -42,13 +42,35 @@
                 pixelDensity = 2f,
                 color = Color.RED,
                 opacity = 30,
-                shouldFillRipple = true,
+                baseRingFadeParams =
+                    RippleShader.FadeParams(
+                        fadeInStart = 0f,
+                        fadeInEnd = 0.3f,
+                        fadeOutStart = 0.5f,
+                        fadeOutEnd = 1f
+                    ),
+                sparkleRingFadeParams =
+                    RippleShader.FadeParams(
+                        fadeInStart = 0.1f,
+                        fadeInEnd = 0.2f,
+                        fadeOutStart = 0.7f,
+                        fadeOutEnd = 0.9f
+                    ),
+                centerFillFadeParams =
+                    RippleShader.FadeParams(
+                        fadeInStart = 0f,
+                        fadeInEnd = 0.1f,
+                        fadeOutStart = 0.2f,
+                        fadeOutEnd = 0.3f
+                    ),
                 sparkleStrength = 0.3f
             )
         val rippleAnimation = RippleAnimation(config)
 
         with(rippleAnimation.rippleShader) {
-            assertThat(rippleFill).isEqualTo(config.shouldFillRipple)
+            assertThat(baseRingFadeParams).isEqualTo(config.baseRingFadeParams)
+            assertThat(sparkleRingFadeParams).isEqualTo(config.sparkleRingFadeParams)
+            assertThat(centerFillFadeParams).isEqualTo(config.centerFillFadeParams)
             assertThat(pixelDensity).isEqualTo(config.pixelDensity)
             assertThat(color).isEqualTo(ColorUtils.setAlphaComponent(config.color, config.opacity))
             assertThat(sparkleStrength).isEqualTo(config.sparkleStrength)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
index dd04ac4..fc7436a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
@@ -79,6 +79,7 @@
     @Mock private lateinit var viewUtil: ViewUtil
     @Mock private lateinit var vibratorHelper: VibratorHelper
     @Mock private lateinit var swipeGestureHandler: SwipeChipbarAwayGestureHandler
+    private lateinit var chipbarAnimator: TestChipbarAnimator
     private lateinit var fakeWakeLockBuilder: WakeLockFake.Builder
     private lateinit var fakeWakeLock: WakeLockFake
     private lateinit var fakeClock: FakeSystemClock
@@ -98,6 +99,7 @@
         fakeWakeLockBuilder.setWakeLock(fakeWakeLock)
 
         uiEventLoggerFake = UiEventLoggerFake()
+        chipbarAnimator = TestChipbarAnimator()
 
         underTest =
             ChipbarCoordinator(
@@ -109,6 +111,7 @@
                 configurationController,
                 dumpManager,
                 powerManager,
+                chipbarAnimator,
                 falsingManager,
                 falsingCollector,
                 swipeGestureHandler,
@@ -371,6 +374,26 @@
         verify(vibratorHelper).vibrate(VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK))
     }
 
+    /** Regression test for b/266119467. */
+    @Test
+    fun displayView_animationFailure_viewsStillBecomeVisible() {
+        chipbarAnimator.allowAnimation = false
+
+        underTest.displayView(
+            createChipbarInfo(
+                Icon.Resource(R.id.check_box, null),
+                Text.Loaded("text"),
+                endItem = ChipbarEndItem.Loading,
+            )
+        )
+
+        val view = getChipbarView()
+        assertThat(view.getInnerView().alpha).isEqualTo(1f)
+        assertThat(view.getStartIconView().alpha).isEqualTo(1f)
+        assertThat(view.getLoadingIcon().alpha).isEqualTo(1f)
+        assertThat(view.getChipTextView().alpha).isEqualTo(1f)
+    }
+
     @Test
     fun updateView_viewUpdated() {
         // First, display a view
@@ -453,6 +476,25 @@
         verify(windowManager).removeView(chipbarView)
     }
 
+    /** Regression test for b/266209420. */
+    @Test
+    fun removeView_animationFailure_viewStillRemoved() {
+        chipbarAnimator.allowAnimation = false
+
+        underTest.displayView(
+            createChipbarInfo(
+                Icon.Resource(R.drawable.ic_cake, contentDescription = null),
+                Text.Loaded("title text"),
+                endItem = ChipbarEndItem.Error,
+            ),
+        )
+        val chipbarView = getChipbarView()
+
+        underTest.removeView(DEVICE_ID, "test reason")
+
+        verify(windowManager).removeView(chipbarView)
+    }
+
     @Test
     fun swipeToDismiss_false_neverListensForGesture() {
         underTest.displayView(
@@ -560,8 +602,9 @@
 
     private fun ViewGroup.getStartIconView() = this.requireViewById<ImageView>(R.id.start_icon)
 
-    private fun ViewGroup.getChipText(): String =
-        (this.requireViewById<TextView>(R.id.text)).text as String
+    private fun ViewGroup.getChipTextView() = this.requireViewById<TextView>(R.id.text)
+
+    private fun ViewGroup.getChipText(): String = this.getChipTextView().text as String
 
     private fun ViewGroup.getLoadingIcon(): View = this.requireViewById(R.id.loading)
 
@@ -574,6 +617,25 @@
         verify(windowManager).addView(viewCaptor.capture(), any())
         return viewCaptor.value as ViewGroup
     }
+
+    /** Test class that lets us disallow animations. */
+    inner class TestChipbarAnimator : ChipbarAnimator() {
+        var allowAnimation: Boolean = true
+
+        override fun animateViewIn(innerView: ViewGroup, onAnimationEnd: Runnable): Boolean {
+            if (!allowAnimation) {
+                return false
+            }
+            return super.animateViewIn(innerView, onAnimationEnd)
+        }
+
+        override fun animateViewOut(innerView: ViewGroup, onAnimationEnd: Runnable): Boolean {
+            if (!allowAnimation) {
+                return false
+            }
+            return super.animateViewOut(innerView, onAnimationEnd)
+        }
+    }
 }
 
 private const val TIMEOUT = 10000
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
index f4226bc..3d75967 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
@@ -25,6 +25,8 @@
 import androidx.test.filters.SmallTest
 import com.android.internal.util.LatencyTracker
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -105,8 +107,13 @@
             }
 
         keyguardRepository = FakeKeyguardRepository()
+        val featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
         val keyguardInteractor =
-            KeyguardInteractor(repository = keyguardRepository, commandQueue = commandQueue)
+            KeyguardInteractor(
+                repository = keyguardRepository,
+                commandQueue = commandQueue,
+                featureFlags = featureFlags
+            )
 
         // Needs to be run on the main thread
         runBlocking(IMMEDIATE) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
index 034c618..9312643 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
@@ -17,12 +17,17 @@
 
 package com.android.systemui.user.data.repository
 
+import android.app.IActivityManager
+import android.app.UserSwitchObserver
 import android.content.pm.UserInfo
+import android.os.IRemoteCallback
 import android.os.UserHandle
 import android.os.UserManager
 import android.provider.Settings
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
 import com.android.systemui.settings.FakeUserTracker
 import com.android.systemui.user.data.model.UserSwitcherSettingsModel
 import com.android.systemui.util.settings.FakeSettings
@@ -39,7 +44,14 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
 import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyString
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
 
@@ -48,6 +60,8 @@
 class UserRepositoryImplTest : SysuiTestCase() {
 
     @Mock private lateinit var manager: UserManager
+    @Mock private lateinit var activityManager: IActivityManager
+    @Captor private lateinit var userSwitchObserver: ArgumentCaptor<UserSwitchObserver>
 
     private lateinit var underTest: UserRepositoryImpl
 
@@ -114,6 +128,11 @@
 
     @Test
     fun refreshUsers() = runSelfCancelingTest {
+        val mainUserId = 10
+        val mainUser = mock(UserHandle::class.java)
+        whenever(manager.mainUser).thenReturn(mainUser)
+        whenever(mainUser.identifier).thenReturn(mainUserId)
+
         underTest = create(this)
         val initialExpectedValue =
             setUpUsers(
@@ -152,6 +171,7 @@
         assertThat(selectedUserInfo).isEqualTo(thirdExpectedValue[1])
         assertThat(selectedUserInfo?.isGuest).isTrue()
         assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedNonGuestUserId)
+        assertThat(underTest.mainUserId).isEqualTo(mainUserId)
     }
 
     @Test
@@ -214,6 +234,34 @@
         assertThat(selectedUserInfo?.id).isEqualTo(1)
     }
 
+    @Test
+    fun userSwitchingInProgress_registersOnlyOneUserSwitchObserver() = runSelfCancelingTest {
+        underTest = create(this)
+
+        underTest.userSwitchingInProgress.launchIn(this)
+        underTest.userSwitchingInProgress.launchIn(this)
+        underTest.userSwitchingInProgress.launchIn(this)
+
+        verify(activityManager, times(1)).registerUserSwitchObserver(any(), anyString())
+    }
+
+    @Test
+    fun userSwitchingInProgress_propagatesStateFromActivityManager() = runSelfCancelingTest {
+        underTest = create(this)
+        verify(activityManager)
+            .registerUserSwitchObserver(userSwitchObserver.capture(), anyString())
+
+        userSwitchObserver.value.onUserSwitching(0, mock(IRemoteCallback::class.java))
+
+        var mostRecentSwitchingValue = false
+        underTest.userSwitchingInProgress.onEach { mostRecentSwitchingValue = it }.launchIn(this)
+
+        assertThat(mostRecentSwitchingValue).isTrue()
+
+        userSwitchObserver.value.onUserSwitchComplete(0)
+        assertThat(mostRecentSwitchingValue).isFalse()
+    }
+
     private fun createUserInfo(
         id: Int,
         isGuest: Boolean,
@@ -280,6 +328,8 @@
         }
 
     private fun create(scope: CoroutineScope = TestCoroutineScope()): UserRepositoryImpl {
+        val featureFlags = FakeFeatureFlags()
+        featureFlags.set(FACE_AUTH_REFACTOR, true)
         return UserRepositoryImpl(
             appContext = context,
             manager = manager,
@@ -288,6 +338,8 @@
             backgroundDispatcher = IMMEDIATE,
             globalSettings = globalSettings,
             tracker = tracker,
+            activityManager = activityManager,
+            featureFlags = featureFlags,
         )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
index fb781e8..cc23485 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
@@ -204,10 +204,12 @@
         }
 
     @Test
-    fun `exit - last non-guest was removed - returns to system`() =
+    fun `exit - last non-guest was removed - returns to main user`() =
         runBlocking(IMMEDIATE) {
             val removedUserId = 310
+            val mainUserId = 10
             repository.lastSelectedNonGuestUserId = removedUserId
+            repository.mainUserId = mainUserId
             repository.setSelectedUserInfo(GUEST_USER_INFO)
 
             underTest.exit(
@@ -221,7 +223,7 @@
 
             verify(manager, never()).markGuestForDeletion(anyInt())
             verify(manager, never()).removeUser(anyInt())
-            verify(switchUser).invoke(UserHandle.USER_SYSTEM)
+            verify(switchUser).invoke(mainUserId)
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index 7380ca4..3538d9b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -119,8 +119,11 @@
             SUPERVISED_USER_CREATION_APP_PACKAGE,
         )
 
-        featureFlags = FakeFeatureFlags()
-        featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+        featureFlags =
+            FakeFeatureFlags().apply {
+                set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+                set(Flags.FACE_AUTH_REFACTOR, true)
+            }
         userRepository = FakeUserRepository()
         keyguardRepository = FakeKeyguardRepository()
         telephonyRepository = FakeTelephonyRepository()
@@ -141,6 +144,7 @@
                     KeyguardInteractor(
                         repository = keyguardRepository,
                         commandQueue = commandQueue,
+                        featureFlags = featureFlags,
                     ),
                 manager = manager,
                 applicationScope = testScope.backgroundScope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index 46f38ed..8f0375f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -82,7 +82,6 @@
 
     private val userRepository = FakeUserRepository()
     private val keyguardRepository = FakeKeyguardRepository()
-    private val featureFlags = FakeFeatureFlags()
     private lateinit var guestUserInteractor: GuestUserInteractor
     private lateinit var refreshUsersScheduler: RefreshUsersScheduler
 
@@ -233,6 +232,11 @@
         }
 
     private fun viewModel(): StatusBarUserChipViewModel {
+        val featureFlags =
+            FakeFeatureFlags().apply {
+                set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+                set(Flags.FACE_AUTH_REFACTOR, true)
+            }
         return StatusBarUserChipViewModel(
             context = context,
             interactor =
@@ -244,9 +248,9 @@
                         KeyguardInteractor(
                             repository = keyguardRepository,
                             commandQueue = commandQueue,
+                            featureFlags = featureFlags,
                         ),
-                    featureFlags =
-                        FakeFeatureFlags().apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) },
+                    featureFlags = featureFlags,
                     manager = manager,
                     applicationScope = testScope.backgroundScope,
                     telephonyInteractor =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index 1d57d0b..71a112c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -134,6 +134,11 @@
                 resetOrExitSessionReceiver = resetOrExitSessionReceiver,
             )
 
+        val featureFlags =
+            FakeFeatureFlags().apply {
+                set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+                set(Flags.FACE_AUTH_REFACTOR, true)
+            }
         underTest =
             UserSwitcherViewModel.Factory(
                     userInteractor =
@@ -145,11 +150,9 @@
                                 KeyguardInteractor(
                                     repository = keyguardRepository,
                                     commandQueue = commandQueue,
+                                    featureFlags = featureFlags
                                 ),
-                            featureFlags =
-                                FakeFeatureFlags().apply {
-                                    set(Flags.FULL_SCREEN_USER_SWITCHER, false)
-                                },
+                            featureFlags = featureFlags,
                             manager = manager,
                             applicationScope = testScope.backgroundScope,
                             telephonyInteractor =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionalCoreStartableTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionalCoreStartableTest.java
new file mode 100644
index 0000000..5ef62c1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionalCoreStartableTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.condition;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.CoreStartable;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shared.condition.Condition;
+import com.android.systemui.shared.condition.Monitor;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class ConditionalCoreStartableTest extends SysuiTestCase {
+    public static class FakeConditionalCoreStartable extends ConditionalCoreStartable {
+        interface Callback {
+            void onStart();
+            void bootCompleted();
+        }
+
+        private final Callback mCallback;
+
+        public FakeConditionalCoreStartable(Monitor monitor, Set<Condition> conditions,
+                Callback callback) {
+            super(monitor, conditions);
+            mCallback = callback;
+        }
+
+        @Override
+        protected void onStart() {
+            mCallback.onStart();
+        }
+
+        @Override
+        protected void bootCompleted() {
+            mCallback.bootCompleted();
+        }
+    }
+
+
+    final Set<Condition> mConditions = new HashSet<>();
+
+    @Mock
+    Condition mCondition;
+
+    @Mock
+    Monitor mMonitor;
+
+    @Mock
+    FakeConditionalCoreStartable.Callback mCallback;
+
+    @Mock
+    Monitor.Subscription.Token mSubscriptionToken;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mConditions.clear();
+    }
+
+    /**
+     * Verifies that {@link ConditionalCoreStartable#onStart()} is predicated on conditions being
+     * met.
+     */
+    @Test
+    public void testOnStartCallback() {
+        final CoreStartable coreStartable =
+                new FakeConditionalCoreStartable(mMonitor,
+                        new HashSet<>(Arrays.asList(mCondition)),
+                        mCallback);
+
+        when(mMonitor.addSubscription(any())).thenReturn(mSubscriptionToken);
+        coreStartable.start();
+
+        final ArgumentCaptor<Monitor.Subscription> subscriptionCaptor = ArgumentCaptor.forClass(
+                Monitor.Subscription.class);
+        verify(mMonitor).addSubscription(subscriptionCaptor.capture());
+
+        final Monitor.Subscription subscription = subscriptionCaptor.getValue();
+
+        assertThat(subscription.getConditions()).containsExactly(mCondition);
+
+        verify(mCallback, never()).onStart();
+
+        subscription.getCallback().onConditionsChanged(true);
+
+        verify(mCallback).onStart();
+        verify(mMonitor).removeSubscription(mSubscriptionToken);
+    }
+
+
+    /**
+     * Verifies that {@link ConditionalCoreStartable#bootCompleted()} ()} is predicated on
+     * conditions being met.
+     */
+    @Test
+    public void testBootCompleted() {
+        final CoreStartable coreStartable =
+                new FakeConditionalCoreStartable(mMonitor,
+                        new HashSet<>(Arrays.asList(mCondition)),
+                        mCallback);
+
+        when(mMonitor.addSubscription(any())).thenReturn(mSubscriptionToken);
+        coreStartable.onBootCompleted();
+
+        final ArgumentCaptor<Monitor.Subscription> subscriptionCaptor = ArgumentCaptor.forClass(
+                Monitor.Subscription.class);
+        verify(mMonitor).addSubscription(subscriptionCaptor.capture());
+
+        final Monitor.Subscription subscription = subscriptionCaptor.getValue();
+
+        assertThat(subscription.getConditions()).containsExactly(mCondition);
+
+        verify(mCallback, never()).bootCompleted();
+
+        subscription.getCallback().onConditionsChanged(true);
+
+        verify(mCallback).bootCompleted();
+        verify(mMonitor).removeSubscription(mSubscriptionToken);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 9d518ac..c6b4c92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -74,6 +74,7 @@
 import android.testing.TestableLooper;
 import android.util.Pair;
 import android.util.SparseArray;
+import android.view.IWindowManager;
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
@@ -392,7 +393,8 @@
                 syncExecutor,
                 mock(Handler.class),
                 mTaskViewTransitions,
-                mock(SyncTransactionQueue.class));
+                mock(SyncTransactionQueue.class),
+                mock(IWindowManager.class));
         mBubbleController.setExpandListener(mBubbleExpandListener);
         spyOn(mBubbleController);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
index 6357a09..3179285 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
@@ -20,6 +20,7 @@
 import android.content.pm.LauncherApps;
 import android.os.Handler;
 import android.os.UserManager;
+import android.view.IWindowManager;
 import android.view.WindowManager;
 
 import com.android.internal.statusbar.IStatusBarService;
@@ -72,13 +73,14 @@
             ShellExecutor shellMainExecutor,
             Handler shellMainHandler,
             TaskViewTransitions taskViewTransitions,
-            SyncTransactionQueue syncQueue) {
+            SyncTransactionQueue syncQueue,
+            IWindowManager wmService) {
         super(context, shellInit, shellCommandHandler, shellController, data, Runnable::run,
                 floatingContentCoordinator, dataRepository, statusBarService, windowManager,
                 windowManagerShellWrapper, userManager, launcherApps, bubbleLogger,
                 taskStackListener, shellTaskOrganizer, positioner, displayController,
                 oneHandedOptional, dragAndDropController, shellMainExecutor, shellMainHandler,
-                new SyncExecutor(), taskViewTransitions, syncQueue);
+                new SyncExecutor(), taskViewTransitions, syncQueue, wmService);
         setInflateSynchronously(true);
         onInit();
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
index b7a8d2e..9b4f496 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
@@ -18,6 +18,8 @@
 
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.EmptyCoroutineContext
+import kotlin.properties.ReadOnlyProperty
+import kotlin.reflect.KProperty
 import kotlinx.coroutines.CoroutineStart
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.Flow
@@ -25,16 +27,35 @@
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 
-/** Collect [flow] in a new [Job] and return a getter for the last collected value. */
+/**
+ * Collect [flow] in a new [Job] and return a getter for the last collected value.
+ * ```
+ * fun myTest() = runTest {
+ *   // ...
+ *   val actual by collectLastValue(underTest.flow)
+ *   assertThat(actual).isEqualTo(expected)
+ * }
+ * ```
+ */
 fun <T> TestScope.collectLastValue(
     flow: Flow<T>,
     context: CoroutineContext = EmptyCoroutineContext,
     start: CoroutineStart = CoroutineStart.DEFAULT,
-): () -> T? {
+): FlowValue<T?> {
     var lastValue: T? = null
     backgroundScope.launch(context, start) { flow.collect { lastValue = it } }
-    return {
+    return FlowValueImpl {
         runCurrent()
         lastValue
     }
 }
+
+/** @see collectLastValue */
+interface FlowValue<T> : ReadOnlyProperty<Any?, T?> {
+    operator fun invoke(): T?
+}
+
+private class FlowValueImpl<T>(private val block: () -> T?) : FlowValue<T> {
+    override operator fun invoke(): T? = block()
+    override fun getValue(thisRef: Any?, property: KProperty<*>): T? = invoke()
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
similarity index 74%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricRepository.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
index f3e52de..01dac36 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
@@ -17,15 +17,24 @@
 
 package com.android.systemui.keyguard.data.repository
 
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 
-class FakeBiometricRepository : BiometricRepository {
+class FakeBiometricSettingsRepository : BiometricSettingsRepository {
 
     private val _isFingerprintEnrolled = MutableStateFlow<Boolean>(false)
     override val isFingerprintEnrolled: StateFlow<Boolean> = _isFingerprintEnrolled.asStateFlow()
 
+    private val _isFaceEnrolled = MutableStateFlow(false)
+    override val isFaceEnrolled: Flow<Boolean>
+        get() = _isFaceEnrolled
+
+    private val _isFaceAuthEnabled = MutableStateFlow(false)
+    override val isFaceAuthenticationEnabled: Flow<Boolean>
+        get() = _isFaceAuthEnabled
+
     private val _isStrongBiometricAllowed = MutableStateFlow(false)
     override val isStrongBiometricAllowed = _isStrongBiometricAllowed.asStateFlow()
 
@@ -44,4 +53,12 @@
     fun setFingerprintEnabledByDevicePolicy(isFingerprintEnabledByDevicePolicy: Boolean) {
         _isFingerprintEnabledByDevicePolicy.value = isFingerprintEnabledByDevicePolicy
     }
+
+    fun setFaceEnrolled(isFaceEnrolled: Boolean) {
+        _isFaceEnrolled.value = isFaceEnrolled
+    }
+
+    fun setIsFaceAuthEnabled(enabled: Boolean) {
+        _isFaceAuthEnabled.value = enabled
+    }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
new file mode 100644
index 0000000..d0383e9
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.repository
+
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
+import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
+import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/** Fake implementation of [KeyguardRepository] */
+class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
+    private val _primaryBouncerVisible = MutableStateFlow(false)
+    override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
+    private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
+    override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
+    private val _primaryBouncerShowingSoon = MutableStateFlow(false)
+    override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
+    private val _primaryBouncerHide = MutableStateFlow(false)
+    override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
+    private val _primaryBouncerStartingToHide = MutableStateFlow(false)
+    override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
+    private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
+    override val primaryBouncerStartingDisappearAnimation =
+        _primaryBouncerDisappearAnimation.asStateFlow()
+    private val _primaryBouncerScrimmed = MutableStateFlow(false)
+    override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
+    private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
+    override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
+    private val _keyguardPosition = MutableStateFlow(0f)
+    override val keyguardPosition = _keyguardPosition.asStateFlow()
+    private val _onScreenTurnedOff = MutableStateFlow(false)
+    override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
+    private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
+    override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
+    private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
+    override val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
+    private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
+    override val showMessage = _showMessage.asStateFlow()
+    private val _resourceUpdateRequests = MutableStateFlow(false)
+    override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
+    override val bouncerPromptReason = 0
+    override val bouncerErrorMessage: CharSequence? = null
+    private val _isAlternateBouncerVisible = MutableStateFlow(false)
+    override val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
+    override var lastAlternateBouncerVisibleTime: Long = 0L
+    private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
+    override val isAlternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow()
+
+    override fun setPrimaryScrimmed(isScrimmed: Boolean) {
+        _primaryBouncerScrimmed.value = isScrimmed
+    }
+
+    override fun setPrimaryVisible(isVisible: Boolean) {
+        _primaryBouncerVisible.value = isVisible
+    }
+
+    override fun setAlternateVisible(isVisible: Boolean) {
+        _isAlternateBouncerVisible.value = isVisible
+    }
+
+    override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
+        _isAlternateBouncerUIAvailable.value = isAvailable
+    }
+
+    override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
+        _primaryBouncerShow.value = keyguardBouncerModel
+    }
+
+    override fun setPrimaryShowingSoon(showingSoon: Boolean) {
+        _primaryBouncerShowingSoon.value = showingSoon
+    }
+
+    override fun setPrimaryHide(hide: Boolean) {
+        _primaryBouncerHide.value = hide
+    }
+
+    override fun setPrimaryStartingToHide(startingToHide: Boolean) {
+        _primaryBouncerStartingToHide.value = startingToHide
+    }
+
+    override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
+        _primaryBouncerDisappearAnimation.value = runnable
+    }
+
+    override fun setPanelExpansion(panelExpansion: Float) {
+        _panelExpansionAmount.value = panelExpansion
+    }
+
+    override fun setKeyguardPosition(keyguardPosition: Float) {
+        _keyguardPosition.value = keyguardPosition
+    }
+
+    override fun setResourceUpdateRequests(willUpdateResources: Boolean) {
+        _resourceUpdateRequests.value = willUpdateResources
+    }
+
+    override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
+        _showMessage.value = bouncerShowMessageModel
+    }
+
+    override fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
+        _keyguardAuthenticated.value = keyguardAuthenticated
+    }
+
+    override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
+        _isBackButtonEnabled.value = isBackButtonEnabled
+    }
+
+    override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
+        _onScreenTurnedOff.value = onScreenTurnedOff
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeDisplayTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeDisplayTracker.kt
index 6ae7c34..1403cea 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeDisplayTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeDisplayTracker.kt
@@ -21,7 +21,7 @@
 import android.view.Display
 import java.util.concurrent.Executor
 
-class FakeDisplayTracker internal constructor(val context: Context) : DisplayTracker {
+class FakeDisplayTracker constructor(val context: Context) : DisplayTracker {
     val displayManager: DisplayManager = context.getSystemService(DisplayManager::class.java)!!
     override var defaultDisplayId: Int = Display.DEFAULT_DISPLAY
     override var allDisplays: Array<Display> = displayManager.displays
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
index ea5a302..53bb340 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
@@ -28,6 +28,10 @@
 import kotlinx.coroutines.yield
 
 class FakeUserRepository : UserRepository {
+    companion object {
+        // User id to represent a non system (human) user id. We presume this is the main user.
+        private const val MAIN_USER_ID = 10
+    }
 
     private val _userSwitcherSettings = MutableStateFlow(UserSwitcherSettingsModel())
     override val userSwitcherSettings: Flow<UserSwitcherSettingsModel> =
@@ -39,7 +43,12 @@
     private val _selectedUserInfo = MutableStateFlow<UserInfo?>(null)
     override val selectedUserInfo: Flow<UserInfo> = _selectedUserInfo.filterNotNull()
 
-    override var lastSelectedNonGuestUserId: Int = UserHandle.USER_SYSTEM
+    private val _userSwitchingInProgress = MutableStateFlow(false)
+    override val userSwitchingInProgress: Flow<Boolean>
+        get() = _userSwitchingInProgress
+
+    override var mainUserId: Int = MAIN_USER_ID
+    override var lastSelectedNonGuestUserId: Int = mainUserId
 
     private var _isGuestUserAutoCreated: Boolean = false
     override val isGuestUserAutoCreated: Boolean
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 12e7226..12a8230 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -306,6 +306,10 @@
     // Package: android
     NOTE_BT_APM_NOTIFICATION = 74;
 
+    // Inform that USB is configured as a Universal Video Class gadget
+    // Package: android
+    NOTE_USB_UVC = 75;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/OWNERS b/services/OWNERS
index eace906..3ce5ae1 100644
--- a/services/OWNERS
+++ b/services/OWNERS
@@ -3,6 +3,8 @@
 # art-team@ manages the system server profile
 per-file art-profile* = calin@google.com, ngeoffray@google.com, vmarko@google.com
 
+per-file java/com/android/server/HsumBootUserInitializer.java = file:/MULTIUSER_OWNERS
+
 per-file java/com/android/server/* = patb@google.com #{LAST_RESORT_SUGGESTION}
 per-file tests/servicestests/src/com/android/server/systemconfig/* = patb@google.com
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index c87d1c8..8e7d277 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -229,17 +229,12 @@
     }
 
     void onDisplayAdded(@NonNull Display display) {
-        if (mInstalled) {
-            resetStreamStateForDisplay(display.getDisplayId());
-            enableFeaturesForDisplay(display);
-        }
+        enableFeaturesForDisplayIfInstalled(display);
+
     }
 
     void onDisplayRemoved(int displayId) {
-        if (mInstalled) {
-            disableFeaturesForDisplay(displayId);
-            resetStreamStateForDisplay(displayId);
-        }
+        disableFeaturesForDisplayIfInstalled(displayId);
     }
 
     @Override
@@ -479,6 +474,9 @@
 
         final Context displayContext = mContext.createDisplayContext(display);
         final int displayId = display.getDisplayId();
+        if (mAms.isDisplayProxyed(displayId)) {
+            return;
+        }
         if (!mServiceDetectsGestures.contains(displayId)) {
             mServiceDetectsGestures.put(displayId, false);
         }
@@ -613,6 +611,18 @@
             mEventHandler.remove(displayId);
         }
     }
+    void enableFeaturesForDisplayIfInstalled(Display display) {
+        if (mInstalled) {
+            resetStreamStateForDisplay(display.getDisplayId());
+            enableFeaturesForDisplay(display);
+        }
+    }
+    void disableFeaturesForDisplayIfInstalled(int displayId) {
+        if (mInstalled) {
+            disableFeaturesForDisplay(displayId);
+            resetStreamStateForDisplay(displayId);
+        }
+    }
 
     private void disableDisplayIndependentFeatures() {
         if (mAutoclickController != null) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e824205..d3593f0 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -32,6 +32,7 @@
 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
 import static android.view.accessibility.AccessibilityManager.CONTRAST_DEFAULT_VALUE;
 import static android.view.accessibility.AccessibilityManager.CONTRAST_NOT_SET;
+import static android.view.accessibility.AccessibilityManager.FlashNotificationReason;
 import static android.view.accessibility.AccessibilityManager.ShortcutType;
 
 import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME;
@@ -314,6 +315,8 @@
     boolean mInputSessionRequested;
     private SparseArray<SurfaceControl> mA11yOverlayLayers = new SparseArray<>();
 
+    private final FlashNotificationsController mFlashNotificationsController;
+
     private AccessibilityUserState getCurrentUserStateLocked() {
         return getUserStateLocked(mCurrentUserId);
     }
@@ -441,6 +444,7 @@
             mInputFilter = inputFilter;
             mHasInputFilter = true;
         }
+        mFlashNotificationsController = new FlashNotificationsController(mContext);
         init();
     }
 
@@ -470,7 +474,8 @@
                 new MagnificationScaleProvider(mContext));
         mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
         mCaptioningManagerImpl = new CaptioningManagerImpl(mContext);
-        mProxyManager = new ProxyManager(mLock, mA11yWindowManager);
+        mProxyManager = new ProxyManager(mLock, mA11yWindowManager, mContext);
+        mFlashNotificationsController = new FlashNotificationsController(mContext);
         init();
     }
 
@@ -612,6 +617,16 @@
         }
     }
 
+    private void onSomePackagesChangedLocked() {
+        final AccessibilityUserState userState = getCurrentUserStateLocked();
+        // Reload the installed services since some services may have different attributes
+        // or resolve info (does not support equals), etc. Remove them then to force reload.
+        userState.mInstalledServices.clear();
+        if (readConfigurationForUserStateLocked(userState)) {
+            onUserStateChangedLocked(userState);
+        }
+    }
+
     private void registerBroadcastReceivers() {
         PackageMonitor monitor = new PackageMonitor() {
             @Override
@@ -627,15 +642,7 @@
                     if (getChangingUserId() != mCurrentUserId) {
                         return;
                     }
-                    // We will update when the automation service dies.
-                    final AccessibilityUserState userState = getCurrentUserStateLocked();
-                    // We have to reload the installed services since some services may
-                    // have different attributes, resolve info (does not support equals),
-                    // etc. Remove them then to force reload.
-                    userState.mInstalledServices.clear();
-                    if (readConfigurationForUserStateLocked(userState)) {
-                        onUserStateChangedLocked(userState);
-                    }
+                    onSomePackagesChangedLocked();
                 }
             }
 
@@ -767,6 +774,24 @@
         // package changes
         monitor.register(mContext, null,  UserHandle.ALL, true);
 
+        // Register an additional observer for new packages using PackageManagerInternal, which
+        // generally notifies observers much sooner than the BroadcastReceiver-based PackageMonitor.
+        final PackageManagerInternal pm = LocalServices.getService(
+                PackageManagerInternal.class);
+        if (pm != null) {
+            pm.getPackageList(new PackageManagerInternal.PackageListObserver() {
+                @Override
+                public void onPackageAdded(String packageName, int uid) {
+                    final int userId = UserHandle.getUserId(uid);
+                    synchronized (mLock) {
+                        if (userId == mCurrentUserId) {
+                            onSomePackagesChangedLocked();
+                        }
+                    }
+                }
+            });
+        }
+
         // user change and unlock
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
@@ -2470,6 +2495,7 @@
                     }
                     inputFilter = mInputFilter;
                     setInputFilter = true;
+                    mProxyManager.setAccessibilityInputFilter(mInputFilter);
                 }
                 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags);
                 mInputFilter.setCombinedGenericMotionEventSources(
@@ -2700,6 +2726,7 @@
         somethingChanged |= readMagnificationModeForDefaultDisplayLocked(userState);
         somethingChanged |= readMagnificationCapabilitiesLocked(userState);
         somethingChanged |= readMagnificationFollowTypingLocked(userState);
+        somethingChanged |= readAlwaysOnMagnificationLocked(userState);
         somethingChanged |= readUiContrastLocked(userState);
         return somethingChanged;
     }
@@ -3859,6 +3886,10 @@
         return mProxyManager.unregisterProxy(displayId);
     }
 
+    boolean isDisplayProxyed(int displayId) {
+        return mProxyManager.isProxyed(displayId);
+    }
+
     @Override public float getUiContrast() {
         if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
             mTraceManager.logTrace(LOG_TAG + ".getUiContrast", FLAGS_ACCESSIBILITY_MANAGER);
@@ -3873,6 +3904,40 @@
     }
 
     @Override
+    public boolean startFlashNotificationSequence(String opPkg,
+            @FlashNotificationReason int reason, IBinder token) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return mFlashNotificationsController.startFlashNotificationSequence(opPkg,
+                    reason, token);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public boolean stopFlashNotificationSequence(String opPkg) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return mFlashNotificationsController.stopFlashNotificationSequence(opPkg);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public boolean startFlashNotificationEvent(String opPkg,
+            @FlashNotificationReason int reason, String reasonPkg) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return mFlashNotificationsController.startFlashNotificationEvent(opPkg,
+                    reason, reasonPkg);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
         synchronized (mLock) {
@@ -4319,6 +4384,10 @@
         private final Uri mMagnificationFollowTypingUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED);
 
+        // TODO: replace name with Settings Secure Key
+        private final Uri mAlwaysOnMagnificationUri = Settings.Secure.getUriFor(
+                "accessibility_magnification_always_on_enabled");
+
         private final Uri mUiContrastUri = Settings.Secure.getUriFor(
                 CONTRAST_LEVEL);
 
@@ -4363,6 +4432,8 @@
             contentResolver.registerContentObserver(
                     mMagnificationFollowTypingUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
+                    mAlwaysOnMagnificationUri, false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(
                     mUiContrastUri, false, this, UserHandle.USER_ALL);
         }
 
@@ -4433,6 +4504,8 @@
                     }
                 } else if (mMagnificationFollowTypingUri.equals(uri)) {
                     readMagnificationFollowTypingLocked(userState);
+                } else if (mAlwaysOnMagnificationUri.equals(uri)) {
+                    readAlwaysOnMagnificationLocked(userState);
                 } else if (mUiContrastUri.equals(uri)) {
                     if (readUiContrastLocked(userState)) {
                         updateUiContrastLocked(userState);
@@ -4546,6 +4619,23 @@
         return false;
     }
 
+    boolean readAlwaysOnMagnificationLocked(AccessibilityUserState userState) {
+        // TODO: replace name const with Settings Secure Key
+        final boolean isSettingsAlwaysOnEnabled = Settings.Secure.getIntForUser(
+                mContext.getContentResolver(),
+                "accessibility_magnification_always_on_enabled",
+                0, userState.mUserId) == 1;
+        final boolean isAlwaysOnFeatureFlagEnabled = mMagnificationController
+                .isAlwaysOnMagnificationFeatureFlagEnabled();
+        final boolean isAlwaysOnEnabled = isAlwaysOnFeatureFlagEnabled && isSettingsAlwaysOnEnabled;
+        if (isAlwaysOnEnabled != userState.isAlwaysOnMagnificationEnabled()) {
+            userState.setAlwaysOnMagnificationEnabled(isAlwaysOnEnabled);
+            mMagnificationController.setAlwaysOnMagnificationEnabled(isAlwaysOnEnabled);
+            return true;
+        }
+        return false;
+    }
+
     @Override
     public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
         mMainHandler.sendMessage(
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
index ce269f5..4806001 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
@@ -78,7 +78,8 @@
             | AccessibilityEvent.TYPE_VIEW_SCROLLED
             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
-            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
+            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+            | AccessibilityEvent.TYPE_VIEW_TARGETED_BY_SCROLL;
 
     /**
      * Methods that should find their way into separate modules, but are still in AMS
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 43730fc..1c9ce3c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -136,6 +136,8 @@
     private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
     // Whether the following typing focus feature for magnification is enabled.
     private boolean mMagnificationFollowTypingEnabled = true;
+    // Whether the always on magnification feature is enabled.
+    private boolean mAlwaysOnMagnificationEnabled = false;
 
     /** The stroke width of the focus rectangle in pixels */
     private int mFocusStrokeWidth;
@@ -221,6 +223,7 @@
         mFocusStrokeWidth = mFocusStrokeWidthDefaultValue;
         mFocusColor = mFocusColorDefaultValue;
         mMagnificationFollowTypingEnabled = true;
+        mAlwaysOnMagnificationEnabled = false;
         mUiContrast = CONTRAST_NOT_SET;
     }
 
@@ -531,6 +534,8 @@
                 .append(String.valueOf(mIsAudioDescriptionByDefaultRequested));
         pw.append(", magnificationFollowTypingEnabled=")
                 .append(String.valueOf(mMagnificationFollowTypingEnabled));
+        pw.append(", alwaysOnMagnificationEnabled=")
+                .append(String.valueOf(mAlwaysOnMagnificationEnabled));
         pw.append("}");
         pw.println();
         pw.append("     shortcut key:{");
@@ -711,6 +716,14 @@
         return mMagnificationFollowTypingEnabled;
     }
 
+    public void setAlwaysOnMagnificationEnabled(boolean enabled) {
+        mAlwaysOnMagnificationEnabled = enabled;
+    }
+
+    public boolean isAlwaysOnMagnificationEnabled() {
+        return mAlwaysOnMagnificationEnabled;
+    }
+
     /**
      * Sets the magnification mode to the given display.
      *
diff --git a/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
new file mode 100644
index 0000000..b1fa5b1
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
@@ -0,0 +1,936 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import static android.view.accessibility.AccessibilityManager.FLASH_REASON_ALARM;
+import static android.view.accessibility.AccessibilityManager.FLASH_REASON_PREVIEW;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.animation.ObjectAnimator;
+import android.annotation.ColorInt;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.hardware.display.DisplayManager;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.AudioPlaybackConfiguration;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.Display;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager.FlashNotificationReason;
+import android.view.animation.AccelerateInterpolator;
+import android.widget.FrameLayout;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+class FlashNotificationsController {
+    private static final String LOG_TAG = "FlashNotifController";
+    private static final boolean DEBUG = true;
+
+    private static final String WAKE_LOCK_TAG = "a11y:FlashNotificationsController";
+
+    /** The tag for flash notification which is triggered by short/long preview. */
+    private static final String TAG_PREVIEW = "preview";
+    /** The tag for flash notification which is triggered by alarm. */
+    private static final String TAG_ALARM = "alarm";
+
+    /** The default flashing type: triggered by an event. It'll flash 2 times in a short period. */
+    private static final int TYPE_DEFAULT = 1;
+    /**
+     * The sequence flashing type: usually triggered by call/alarm. It'll flash infinitely until the
+     * call/alarm ends.
+     */
+    private static final int TYPE_SEQUENCE = 2;
+    /**
+     * The long preview flashing type: it's only for screen flash preview. It'll flash only 1 time
+     * with a long period to show the screen flash effect more clearly.
+     */
+    private static final int TYPE_LONG_PREVIEW = 3;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "TYPE_" }, value = {
+            TYPE_DEFAULT,
+            TYPE_SEQUENCE,
+            TYPE_LONG_PREVIEW
+    })
+    @interface FlashNotificationType {}
+
+    private static final int TYPE_DEFAULT_ON_MS = 350;
+    private static final int TYPE_DEFAULT_OFF_MS = 250;
+    private static final int TYPE_SEQUENCE_ON_MS = 700;
+    private static final int TYPE_SEQUENCE_OFF_MS = 700;
+    private static final int TYPE_LONG_PREVIEW_ON_MS = 5000;
+    private static final int TYPE_LONG_PREVIEW_OFF_MS = 1000;
+    private static final int TYPE_DEFAULT_SCREEN_DELAY_MS = 300;
+
+    private static final int SCREEN_FADE_DURATION_MS = 200;
+    private static final int SCREEN_FADE_OUT_TIMEOUT_MS = 10;
+
+    @ColorInt
+    private static final int SCREEN_DEFAULT_COLOR = 0x00FFFF00;
+    @ColorInt
+    private static final int SCREEN_DEFAULT_ALPHA = 0x66000000;
+    @ColorInt
+    private static final int SCREEN_DEFAULT_COLOR_WITH_ALPHA =
+            SCREEN_DEFAULT_COLOR | SCREEN_DEFAULT_ALPHA;
+
+    // TODO(b/266775677): Make protected-broadcast intent
+    @VisibleForTesting
+    static final String ACTION_FLASH_NOTIFICATION_START_PREVIEW =
+            "com.android.internal.intent.action.FLASH_NOTIFICATION_START_PREVIEW";
+    // TODO(b/266775677): Make protected-broadcast intent
+    @VisibleForTesting
+    static final String ACTION_FLASH_NOTIFICATION_STOP_PREVIEW =
+            "com.android.internal.intent.action.FLASH_NOTIFICATION_STOP_PREVIEW";
+    @VisibleForTesting
+    static final String EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR =
+            "com.android.internal.intent.extra.FLASH_NOTIFICATION_PREVIEW_COLOR";
+    @VisibleForTesting
+    static final String EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE =
+            "com.android.internal.intent.extra.FLASH_NOTIFICATION_PREVIEW_TYPE";
+
+    @VisibleForTesting
+    static final int PREVIEW_TYPE_SHORT = 0;
+    @VisibleForTesting
+    static final int PREVIEW_TYPE_LONG = 1;
+
+    // TODO(b/266775683): Move to settings provider
+    @VisibleForTesting
+    static final String SETTING_KEY_CAMERA_FLASH_NOTIFICATION = "camera_flash_notification";
+    // TODO(b/266775683): Move to settings provider
+    @VisibleForTesting
+    static final String SETTING_KEY_SCREEN_FLASH_NOTIFICATION = "screen_flash_notification";
+    // TODO(b/266775683): Move to settings provider
+    @VisibleForTesting
+    static final String SETTING_KEY_SCREEN_FLASH_NOTIFICATION_COLOR =
+            "screen_flash_notification_color_global";
+
+    /**
+     * Timeout of the wake lock (5 minutes). It should normally never triggered, the wakelock
+     * should be released after the flashing notification is completed.
+     */
+    private static final long WAKE_LOCK_TIMEOUT_MS = 5 * 60 * 1000;
+
+    private final Context mContext;
+    private final DisplayManager mDisplayManager;
+    private final PowerManager.WakeLock mWakeLock;
+    @GuardedBy("mFlashNotifications")
+    private final LinkedList<FlashNotification> mFlashNotifications = new LinkedList<>();
+    private final Handler mMainHandler;
+    private final Handler mCallbackHandler;
+    private boolean mIsTorchTouched = false;
+    private boolean mIsTorchOn = false;
+    private boolean mIsCameraFlashNotificationEnabled = false;
+    private boolean mIsScreenFlashNotificationEnabled = false;
+    private boolean mIsAlarming = false;
+    private int mDisplayState = Display.STATE_OFF;
+    private boolean mIsCameraOpened = false;
+    private CameraManager mCameraManager;
+    private String mCameraId = null;
+
+    private final CameraManager.TorchCallback mTorchCallback = new CameraManager.TorchCallback() {
+        @Override
+        public void onTorchModeChanged(String cameraId, boolean enabled) {
+            if (mCameraId != null && mCameraId.equals(cameraId)) {
+                mIsTorchOn = enabled;
+                if (DEBUG) Log.d(LOG_TAG, "onTorchModeChanged, set mIsTorchOn=" + enabled);
+            }
+        }
+    };
+    @VisibleForTesting
+    final CameraManager.AvailabilityCallback mTorchAvailabilityCallback =
+            new CameraManager.AvailabilityCallback() {
+                @Override
+                public void onCameraOpened(@NonNull String cameraId, @NonNull String packageId) {
+                    if (mCameraId != null && mCameraId.equals(cameraId)) {
+                        mIsCameraOpened = true;
+                    }
+                }
+
+                @Override
+                public void onCameraClosed(@NonNull String cameraId) {
+                    if (mCameraId != null && mCameraId.equals(cameraId)) {
+                        mIsCameraOpened = false;
+                    }
+                }
+            };
+    private View mScreenFlashNotificationOverlayView;
+    private FlashNotification mCurrentFlashNotification;
+
+    private final AudioManager.AudioPlaybackCallback mAudioPlaybackCallback =
+            new AudioManager.AudioPlaybackCallback() {
+                @Override
+                public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
+                    boolean isAlarmActive = false;
+                    if (configs != null) {
+                        isAlarmActive = configs.stream()
+                                .anyMatch(config -> config.isActive()
+                                        && config.getAudioAttributes().getUsage()
+                                        == AudioAttributes.USAGE_ALARM);
+                    }
+
+                    if (mIsAlarming != isAlarmActive) {
+                        if (DEBUG) Log.d(LOG_TAG, "alarm state changed: " + isAlarmActive);
+                        if (isAlarmActive) {
+                            startFlashNotificationSequenceForAlarm();
+                        } else {
+                            stopFlashNotificationSequenceForAlarm();
+                        }
+                        mIsAlarming = isAlarmActive;
+                    }
+                }
+            };
+    private volatile FlashNotificationThread mThread;
+    private final Handler mFlashNotificationHandler;
+    @VisibleForTesting
+    final FlashBroadcastReceiver mFlashBroadcastReceiver;
+
+
+    FlashNotificationsController(Context context) {
+        this(context, getStartedHandler("FlashNotificationThread"), getStartedHandler(LOG_TAG));
+    }
+
+    @VisibleForTesting
+    FlashNotificationsController(Context context, Handler flashNotificationHandler,
+            Handler callbackHandler) {
+        mContext = context;
+        mMainHandler = new Handler(mContext.getMainLooper());
+        mFlashNotificationHandler = flashNotificationHandler;
+        mCallbackHandler = callbackHandler;
+
+        new FlashContentObserver(mMainHandler).register(mContext.getContentResolver());
+
+        final IntentFilter broadcastFilter = new IntentFilter();
+        broadcastFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
+        broadcastFilter.addAction(ACTION_FLASH_NOTIFICATION_START_PREVIEW);
+        broadcastFilter.addAction(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW);
+        mFlashBroadcastReceiver = new FlashBroadcastReceiver();
+        mContext.registerReceiver(mFlashBroadcastReceiver, broadcastFilter);
+
+        final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
+        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG);
+
+        mDisplayManager = mContext.getSystemService(DisplayManager.class);
+        final DisplayManager.DisplayListener displayListener =
+                new DisplayManager.DisplayListener() {
+                    @Override
+                    public void onDisplayAdded(int displayId) {
+                    }
+
+                    @Override
+                    public void onDisplayRemoved(int displayId) {
+                    }
+
+                    @Override
+                    public void onDisplayChanged(int displayId) {
+                        if (mDisplayManager != null) {
+                            Display display = mDisplayManager.getDisplay(displayId);
+                            if (display != null) {
+                                mDisplayState = display.getState();
+                            }
+                        }
+                    }
+                };
+
+        if (mDisplayManager != null) {
+            mDisplayManager.registerDisplayListener(displayListener, null);
+        }
+    }
+
+    private static Handler getStartedHandler(String tag) {
+        HandlerThread handlerThread = new HandlerThread(tag);
+        handlerThread.start();
+        return handlerThread.getThreadHandler();
+    }
+
+
+    boolean startFlashNotificationSequence(String opPkg,
+            @FlashNotificationReason int reason, IBinder token) {
+        final FlashNotification flashNotification = new FlashNotification(opPkg, TYPE_SEQUENCE,
+                getScreenFlashColorPreference(reason),
+                token, () -> stopFlashNotification(opPkg));
+
+        if (!flashNotification.tryLinkToDeath()) return false;
+
+        requestStartFlashNotification(flashNotification);
+        return true;
+    }
+
+    boolean stopFlashNotificationSequence(String opPkg) {
+        stopFlashNotification(opPkg);
+        return true;
+    }
+
+    boolean startFlashNotificationEvent(String opPkg, int reason, String reasonPkg) {
+        requestStartFlashNotification(new FlashNotification(opPkg, TYPE_DEFAULT,
+                getScreenFlashColorPreference(reason, reasonPkg)));
+        return true;
+    }
+
+    private void startFlashNotificationShortPreview() {
+        requestStartFlashNotification(new FlashNotification(TAG_PREVIEW, TYPE_DEFAULT,
+                getScreenFlashColorPreference(FLASH_REASON_PREVIEW)));
+    }
+
+    private void startFlashNotificationLongPreview(@ColorInt int color) {
+        requestStartFlashNotification(new FlashNotification(TAG_PREVIEW, TYPE_LONG_PREVIEW,
+                color));
+    }
+
+    private void stopFlashNotificationLongPreview() {
+        stopFlashNotification(TAG_PREVIEW);
+    }
+
+    private void startFlashNotificationSequenceForAlarm() {
+        requestStartFlashNotification(new FlashNotification(TAG_ALARM, TYPE_SEQUENCE,
+                getScreenFlashColorPreference(FLASH_REASON_ALARM)));
+    }
+
+    private void stopFlashNotificationSequenceForAlarm() {
+        stopFlashNotification(TAG_ALARM);
+    }
+
+    private void requestStartFlashNotification(FlashNotification flashNotification) {
+        if (DEBUG) Log.d(LOG_TAG, "requestStartFlashNotification");
+
+        mIsCameraFlashNotificationEnabled = Settings.System.getIntForUser(
+                mContext.getContentResolver(), SETTING_KEY_CAMERA_FLASH_NOTIFICATION, 0,
+                UserHandle.USER_CURRENT) != 0;
+        mIsScreenFlashNotificationEnabled = Settings.System.getIntForUser(
+                mContext.getContentResolver(), SETTING_KEY_SCREEN_FLASH_NOTIFICATION, 0,
+                UserHandle.USER_CURRENT) != 0;
+
+        // To prevent unexpectedly screen flash when screen is off, delays the TYPE_DEFAULT screen
+        // flash since mDisplayState is not refreshed to STATE_OFF immediately after screen is
+        // turned off. No need to delay TYPE_SEQUENCE screen flash as calls and alarms will always
+        // wake up the screen.
+        // TODO(b/267121704) refactor the logic to remove delay workaround
+        if (flashNotification.mType == TYPE_DEFAULT && mIsScreenFlashNotificationEnabled) {
+            mMainHandler.sendMessageDelayed(
+                    obtainMessage(FlashNotificationsController::startFlashNotification, this,
+                            flashNotification), TYPE_DEFAULT_SCREEN_DELAY_MS);
+            if (DEBUG) Log.i(LOG_TAG, "give some delay for flash notification");
+        } else {
+            startFlashNotification(flashNotification);
+        }
+    }
+
+    private void stopFlashNotification(String tag) {
+        if (DEBUG) Log.i(LOG_TAG, "stopFlashNotification: tag=" + tag);
+        synchronized (mFlashNotifications) {
+            final FlashNotification notification = removeFlashNotificationLocked(tag);
+            if (mCurrentFlashNotification != null && notification == mCurrentFlashNotification) {
+                stopFlashNotificationLocked();
+                startNextFlashNotificationLocked();
+            }
+        }
+    }
+
+    private void prepareForCameraFlashNotification() {
+        mCameraManager = mContext.getSystemService(CameraManager.class);
+
+        if (mCameraManager != null) {
+            try {
+                mCameraId = getCameraId();
+            } catch (CameraAccessException e) {
+                Log.e(LOG_TAG, "CameraAccessException", e);
+            }
+            mCameraManager.registerTorchCallback(mTorchCallback, null);
+        }
+    }
+
+    private String getCameraId() throws CameraAccessException {
+        String[] ids = mCameraManager.getCameraIdList();
+
+        for (String id : ids) {
+            CameraCharacteristics c = mCameraManager.getCameraCharacteristics(id);
+            Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
+            Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
+            if (flashAvailable != null && lensFacing != null
+                    && flashAvailable && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
+                if (DEBUG) Log.d(LOG_TAG, "Found valid camera, cameraId=" + id);
+                return id;
+            }
+        }
+        return null;
+    }
+
+    private void showScreenNotificationOverlayView(@ColorInt int color) {
+        mMainHandler.sendMessage(obtainMessage(
+                FlashNotificationsController::showScreenNotificationOverlayViewMainThread,
+                this, color));
+    }
+
+    private void hideScreenNotificationOverlayView() {
+        mMainHandler.sendMessage(obtainMessage(
+                FlashNotificationsController::fadeOutScreenNotificationOverlayViewMainThread,
+                this));
+        mMainHandler.sendMessageDelayed(obtainMessage(
+                FlashNotificationsController::hideScreenNotificationOverlayViewMainThread,
+                this), SCREEN_FADE_DURATION_MS + SCREEN_FADE_OUT_TIMEOUT_MS);
+    }
+
+    private void showScreenNotificationOverlayViewMainThread(@ColorInt int color) {
+        if (DEBUG) Log.d(LOG_TAG, "showScreenNotificationOverlayViewMainThread");
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+                PixelFormat.TRANSLUCENT);
+        params.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+        params.layoutInDisplayCutoutMode =
+                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        params.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
+
+        // Main display
+        if (mScreenFlashNotificationOverlayView == null) {
+            mScreenFlashNotificationOverlayView = getScreenNotificationOverlayView(color);
+            mContext.getSystemService(WindowManager.class).addView(
+                    mScreenFlashNotificationOverlayView, params);
+            fadeScreenNotificationOverlayViewMainThread(mScreenFlashNotificationOverlayView, true);
+        }
+    }
+
+    private void fadeOutScreenNotificationOverlayViewMainThread() {
+        if (DEBUG) Log.d(LOG_TAG, "fadeOutScreenNotificationOverlayViewMainThread");
+        if (mScreenFlashNotificationOverlayView != null) {
+            fadeScreenNotificationOverlayViewMainThread(mScreenFlashNotificationOverlayView, false);
+        }
+    }
+
+    private void fadeScreenNotificationOverlayViewMainThread(View view, boolean in) {
+        ObjectAnimator fade = ObjectAnimator.ofFloat(view, "alpha", in ? 0.0f : 1.0f,
+                in ? 1.0f : 0.0f);
+        fade.setInterpolator(new AccelerateInterpolator());
+        fade.setAutoCancel(true);
+        fade.setDuration(SCREEN_FADE_DURATION_MS);
+        fade.start();
+    }
+
+    private void hideScreenNotificationOverlayViewMainThread() {
+        if (DEBUG) Log.d(LOG_TAG, "hideScreenNotificationOverlayViewMainThread");
+        if (mScreenFlashNotificationOverlayView != null) {
+            mScreenFlashNotificationOverlayView.setVisibility(View.GONE);
+            mContext.getSystemService(WindowManager.class).removeView(
+                    mScreenFlashNotificationOverlayView);
+            mScreenFlashNotificationOverlayView = null;
+        }
+    }
+
+    private View getScreenNotificationOverlayView(@ColorInt int color) {
+        View screenNotificationOverlayView = new FrameLayout(mContext);
+        screenNotificationOverlayView.setBackgroundColor(color);
+        screenNotificationOverlayView.setAlpha(0.0f);
+        return screenNotificationOverlayView;
+    }
+
+    @ColorInt
+    private int getScreenFlashColorPreference(@FlashNotificationReason int reason,
+            String reasonPkg) {
+        // TODO(b/267121466) implement getting color per reason, reasonPkg basis
+        return getScreenFlashColorPreference();
+    }
+
+    @ColorInt
+    private int getScreenFlashColorPreference(@FlashNotificationReason int reason) {
+        // TODO(b/267121466) implement getting color per reason basis
+        return getScreenFlashColorPreference();
+    }
+
+    @ColorInt
+    private int getScreenFlashColorPreference() {
+        return Settings.System.getIntForUser(mContext.getContentResolver(),
+                SETTING_KEY_SCREEN_FLASH_NOTIFICATION_COLOR, SCREEN_DEFAULT_COLOR_WITH_ALPHA,
+                UserHandle.USER_CURRENT);
+    }
+
+    private void startFlashNotification(@NonNull FlashNotification flashNotification) {
+        final int type = flashNotification.mType;
+        final String tag = flashNotification.mTag;
+        if (DEBUG) Log.i(LOG_TAG, "startFlashNotification: type=" + type + ", tag=" + tag);
+
+        if (!(mIsCameraFlashNotificationEnabled
+                || mIsScreenFlashNotificationEnabled
+                || flashNotification.mForceStartScreenFlash)) {
+            if (DEBUG) Log.d(LOG_TAG, "Flash notification is disabled");
+            return;
+        }
+
+        if (mIsCameraOpened) {
+            if (DEBUG) Log.d(LOG_TAG, "Since camera for torch is opened, block notification.");
+            return;
+        }
+
+        if (mIsCameraFlashNotificationEnabled && mCameraId == null) {
+            prepareForCameraFlashNotification();
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            synchronized (mFlashNotifications) {
+                if (type == TYPE_DEFAULT || type == TYPE_LONG_PREVIEW) {
+                    if (mCurrentFlashNotification != null) {
+                        if (DEBUG) {
+                            Log.i(LOG_TAG,
+                                    "Default type of flash notification can not work because "
+                                            + "previous flash notification is working");
+                        }
+                    } else {
+                        startFlashNotificationLocked(flashNotification);
+                    }
+                } else if (type == TYPE_SEQUENCE) {
+                    if (mCurrentFlashNotification != null) {
+                        removeFlashNotificationLocked(tag);
+                        stopFlashNotificationLocked();
+                    }
+                    mFlashNotifications.addFirst(flashNotification);
+                    startNextFlashNotificationLocked();
+                } else {
+                    Log.e(LOG_TAG, "Unavailable flash notification type");
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @GuardedBy("mFlashNotifications")
+    private FlashNotification removeFlashNotificationLocked(String tag) {
+        ListIterator<FlashNotification> iterator = mFlashNotifications.listIterator(0);
+        while (iterator.hasNext()) {
+            FlashNotification notification = iterator.next();
+            if (notification != null && notification.mTag.equals(tag)) {
+                iterator.remove();
+                notification.tryUnlinkToDeath();
+                if (DEBUG) {
+                    Log.i(LOG_TAG,
+                            "removeFlashNotificationLocked: tag=" + notification.mTag);
+                }
+                return notification;
+            }
+        }
+        if (mCurrentFlashNotification != null && mCurrentFlashNotification.mTag.equals(tag)) {
+            mCurrentFlashNotification.tryUnlinkToDeath();
+            return mCurrentFlashNotification;
+        }
+        return null;
+    }
+
+    @GuardedBy("mFlashNotifications")
+    private void stopFlashNotificationLocked() {
+        if (mThread != null) {
+            if (DEBUG) {
+                Log.i(LOG_TAG,
+                        "stopFlashNotificationLocked: tag=" + mThread.mFlashNotification.mTag);
+            }
+            mThread.cancel();
+            mThread = null;
+        }
+        doCameraFlashNotificationOff();
+        doScreenFlashNotificationOff();
+    }
+
+    @GuardedBy("mFlashNotifications")
+    private void startNextFlashNotificationLocked() {
+        if (DEBUG) Log.i(LOG_TAG, "startNextFlashNotificationLocked");
+        if (mFlashNotifications.size() <= 0) {
+            mCurrentFlashNotification = null;
+            return;
+        }
+        startFlashNotificationLocked(mFlashNotifications.getFirst());
+    }
+
+    @GuardedBy("mFlashNotifications")
+    private void startFlashNotificationLocked(@NonNull final FlashNotification notification) {
+        if (DEBUG) {
+            Log.i(LOG_TAG, "startFlashNotificationLocked: type=" + notification.mType + ", tag="
+                    + notification.mTag);
+        }
+        mCurrentFlashNotification = notification;
+        mThread = new FlashNotificationThread(notification);
+        mFlashNotificationHandler.post(mThread);
+    }
+
+    private boolean isDozeMode() {
+        return mDisplayState == Display.STATE_DOZE || mDisplayState == Display.STATE_DOZE_SUSPEND;
+    }
+
+    private void doCameraFlashNotificationOn() {
+        if (mIsCameraFlashNotificationEnabled && !mIsTorchOn) {
+            doCameraFlashNotification(true);
+        }
+        if (DEBUG) {
+            Log.i(LOG_TAG, "doCameraFlashNotificationOn: "
+                    + "isCameraFlashNotificationEnabled=" + mIsCameraFlashNotificationEnabled
+                    + ", isTorchOn=" + mIsTorchOn
+                    + ", isTorchTouched=" + mIsTorchTouched);
+        }
+    }
+
+    private void doCameraFlashNotificationOff() {
+        if (mIsTorchTouched) {
+            doCameraFlashNotification(false);
+        }
+        if (DEBUG) {
+            Log.i(LOG_TAG, "doCameraFlashNotificationOff: "
+                    + "isCameraFlashNotificationEnabled=" + mIsCameraFlashNotificationEnabled
+                    + ", isTorchOn=" + mIsTorchOn
+                    + ", isTorchTouched=" + mIsTorchTouched);
+        }
+    }
+
+    private void doScreenFlashNotificationOn(@ColorInt int color, boolean forceStartScreenFlash) {
+        final boolean isDoze = isDozeMode();
+        if ((mIsScreenFlashNotificationEnabled || forceStartScreenFlash) && !isDoze) {
+            showScreenNotificationOverlayView(color);
+        }
+        if (DEBUG) {
+            Log.i(LOG_TAG, "doScreenFlashNotificationOn: "
+                    + "isScreenFlashNotificationEnabled=" + mIsScreenFlashNotificationEnabled
+                    + ", isDozeMode=" + isDoze
+                    + ", color=" + Integer.toHexString(color));
+        }
+    }
+
+    private void doScreenFlashNotificationOff() {
+        hideScreenNotificationOverlayView();
+        if (DEBUG) {
+            Log.i(LOG_TAG, "doScreenFlashNotificationOff: "
+                    + "isScreenFlashNotificationEnabled=" + mIsScreenFlashNotificationEnabled);
+        }
+    }
+
+    private void doCameraFlashNotification(boolean on) {
+        if (DEBUG) Log.d(LOG_TAG, "doCameraFlashNotification: " + on + " mCameraId : " + mCameraId);
+        if (mCameraManager != null && mCameraId != null) {
+            try {
+                mCameraManager.setTorchMode(mCameraId, on);
+                mIsTorchTouched = on;
+            } catch (CameraAccessException e) {
+                Log.e(LOG_TAG, "Failed to setTorchMode: " + e);
+            }
+        } else {
+            Log.e(LOG_TAG, "Can not use camera flash notification, please check CameraManager!");
+        }
+    }
+
+    private static class FlashNotification {
+        // Tag could be the requesting package name or constants like TAG_PREVIEW and TAG_ALARM.
+        private final String mTag;
+        @FlashNotificationType
+        private final int mType;
+        private final int mOnDuration;
+        private final int mOffDuration;
+        @ColorInt
+        private final int mColor;
+        private int mRepeat;
+        @Nullable
+        private final IBinder mToken;
+        @Nullable
+        private final IBinder.DeathRecipient mDeathRecipient;
+        private final boolean mForceStartScreenFlash;
+
+        private FlashNotification(String tag, @FlashNotificationType int type,
+                @ColorInt int color) {
+            this(tag, type, color, null, null);
+        }
+
+        private FlashNotification(String tag, @FlashNotificationType int type, @ColorInt int color,
+                IBinder token, IBinder.DeathRecipient deathRecipient) {
+            mType = type;
+            mTag = tag;
+            mColor = color;
+            mToken = token;
+            mDeathRecipient = deathRecipient;
+
+            switch (type) {
+                case TYPE_SEQUENCE:
+                    mOnDuration = TYPE_SEQUENCE_ON_MS;
+                    mOffDuration = TYPE_SEQUENCE_OFF_MS;
+                    mRepeat = 0; // indefinite
+                    mForceStartScreenFlash = false;
+                    break;
+                case TYPE_LONG_PREVIEW:
+                    mOnDuration = TYPE_LONG_PREVIEW_ON_MS;
+                    mOffDuration = TYPE_LONG_PREVIEW_OFF_MS;
+                    mRepeat = 1;
+                    mForceStartScreenFlash = true;
+                    break;
+                case TYPE_DEFAULT:
+                default:
+                    mOnDuration = TYPE_DEFAULT_ON_MS;
+                    mOffDuration = TYPE_DEFAULT_OFF_MS;
+                    mRepeat = 2;
+                    mForceStartScreenFlash = false;
+                    break;
+            }
+        }
+
+        boolean tryLinkToDeath() {
+            if (mToken == null || mDeathRecipient == null) return false;
+
+            try {
+                mToken.linkToDeath(mDeathRecipient, 0);
+                return true;
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "RemoteException", e);
+                return false;
+            }
+        }
+
+        boolean tryUnlinkToDeath() {
+            if (mToken == null || mDeathRecipient == null) return false;
+            try {
+                mToken.unlinkToDeath(mDeathRecipient, 0);
+                return true;
+            } catch (Exception ignored) {
+                return false;
+            }
+        }
+    }
+
+    private class FlashNotificationThread extends Thread {
+        private final FlashNotification mFlashNotification;
+        private boolean mForceStop;
+        @ColorInt
+        private int mColor = Color.TRANSPARENT;
+        private boolean mShouldDoScreenFlash = false;
+        private boolean mShouldDoCameraFlash = false;
+
+        private FlashNotificationThread(@NonNull FlashNotification flashNotification) {
+            mFlashNotification = flashNotification;
+            mForceStop = false;
+        }
+
+        @Override
+        public void run() {
+            if (DEBUG) Log.d(LOG_TAG, "run started: " + mFlashNotification.mTag);
+            Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
+            mColor = mFlashNotification.mColor;
+            mShouldDoScreenFlash = (Color.alpha(mColor) != Color.TRANSPARENT)
+                    || mFlashNotification.mForceStartScreenFlash;
+            mShouldDoCameraFlash = mFlashNotification.mType != TYPE_LONG_PREVIEW;
+            synchronized (this) {
+                mWakeLock.acquire(WAKE_LOCK_TIMEOUT_MS);
+                try {
+                    startFlashNotification();
+                } finally {
+                    doScreenFlashNotificationOff();
+                    doCameraFlashNotificationOff();
+                    try {
+                        mWakeLock.release();
+                    } catch (RuntimeException e) {
+                        Log.e(LOG_TAG, "Error while releasing FlashNotificationsController"
+                                + " wakelock (already released by the system?)");
+                    }
+                }
+            }
+            synchronized (mFlashNotifications) {
+                if (mThread == this) {
+                    mThread = null;
+                }
+                // Unlink to death recipient for not interrupted flash notification. For flash
+                // notification interrupted and stopped by stopFlashNotification(), unlink to
+                // death is already handled in stopFlashNotification().
+                if (!mForceStop) {
+                    mFlashNotification.tryUnlinkToDeath();
+                    mCurrentFlashNotification = null;
+                }
+            }
+            if (DEBUG) Log.d(LOG_TAG, "run finished: " + mFlashNotification.mTag);
+        }
+
+        private void startFlashNotification() {
+            synchronized (this) {
+                while (!mForceStop) {
+                    if (mFlashNotification.mType != TYPE_SEQUENCE
+                            && mFlashNotification.mRepeat >= 0) {
+                        if (mFlashNotification.mRepeat-- == 0) {
+                            break;
+                        }
+                    }
+                    if (mShouldDoScreenFlash) {
+                        doScreenFlashNotificationOn(mColor,
+                                mFlashNotification.mForceStartScreenFlash);
+                    }
+                    if (mShouldDoCameraFlash) {
+                        doCameraFlashNotificationOn();
+                    }
+                    delay(mFlashNotification.mOnDuration);
+                    doScreenFlashNotificationOff();
+                    doCameraFlashNotificationOff();
+                    if (mForceStop) {
+                        break;
+                    }
+                    delay(mFlashNotification.mOffDuration);
+                }
+            }
+        }
+
+        void cancel() {
+            if (DEBUG) Log.d(LOG_TAG, "run canceled: " + mFlashNotification.mTag);
+            synchronized (this) {
+                mThread.mForceStop = true;
+                mThread.notify();
+            }
+        }
+
+        private void delay(long duration) {
+            if (duration > 0) {
+                long bedtime = duration + SystemClock.uptimeMillis();
+                do {
+                    try {
+                        this.wait(duration);
+                    } catch (InterruptedException ignored) {
+                    }
+                    if (mForceStop) {
+                        break;
+                    }
+                    duration = bedtime - SystemClock.uptimeMillis();
+                } while (duration > 0);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    class FlashBroadcastReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            // Some system services not properly initiated before boot complete. Should do the
+            // initialization after receiving ACTION_BOOT_COMPLETED.
+            if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+                if (UserHandle.myUserId() != ActivityManager.getCurrentUser()) {
+                    return;
+                }
+
+                mIsCameraFlashNotificationEnabled = Settings.System.getIntForUser(
+                        mContext.getContentResolver(), SETTING_KEY_CAMERA_FLASH_NOTIFICATION, 0,
+                        UserHandle.USER_CURRENT) != 0;
+                if (mIsCameraFlashNotificationEnabled) {
+                    prepareForCameraFlashNotification();
+                } else {
+                    if (mCameraManager != null) {
+                        mCameraManager.unregisterTorchCallback(mTorchCallback);
+                    }
+                }
+
+                final AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+                if (audioManager != null) {
+                    audioManager.registerAudioPlaybackCallback(mAudioPlaybackCallback,
+                            mCallbackHandler);
+                }
+
+                mCameraManager = mContext.getSystemService(CameraManager.class);
+                mCameraManager.registerAvailabilityCallback(mTorchAvailabilityCallback,
+                        mCallbackHandler);
+
+            } else if (ACTION_FLASH_NOTIFICATION_START_PREVIEW.equals(intent.getAction())) {
+                if (DEBUG) Log.i(LOG_TAG, "ACTION_FLASH_NOTIFICATION_START_PREVIEW");
+                final int color = intent.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR,
+                        Color.TRANSPARENT);
+                final int type = intent.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE,
+                        PREVIEW_TYPE_SHORT);
+                if (type == PREVIEW_TYPE_LONG) {
+                    startFlashNotificationLongPreview(color);
+                } else if (type == PREVIEW_TYPE_SHORT) {
+                    startFlashNotificationShortPreview();
+                }
+            } else if (ACTION_FLASH_NOTIFICATION_STOP_PREVIEW.equals(intent.getAction())) {
+                if (DEBUG) Log.i(LOG_TAG, "ACTION_FLASH_NOTIFICATION_STOP_PREVIEW");
+                stopFlashNotificationLongPreview();
+            }
+        }
+    }
+
+    private final class FlashContentObserver extends ContentObserver {
+        private final Uri mCameraFlashNotificationUri = Settings.System.getUriFor(
+                SETTING_KEY_CAMERA_FLASH_NOTIFICATION);
+        private final Uri mScreenFlashNotificationUri = Settings.System.getUriFor(
+                SETTING_KEY_SCREEN_FLASH_NOTIFICATION);
+
+        FlashContentObserver(Handler handler) {
+            super(handler);
+        }
+
+        void register(ContentResolver contentResolver) {
+            contentResolver.registerContentObserver(mCameraFlashNotificationUri, false, this,
+                    UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(mScreenFlashNotificationUri, false, this,
+                    UserHandle.USER_ALL);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            if (mCameraFlashNotificationUri.equals(uri)) {
+                mIsCameraFlashNotificationEnabled = Settings.System.getIntForUser(
+                        mContext.getContentResolver(), SETTING_KEY_CAMERA_FLASH_NOTIFICATION, 0,
+                        UserHandle.USER_CURRENT) != 0;
+                if (mIsCameraFlashNotificationEnabled) {
+                    prepareForCameraFlashNotification();
+                } else {
+                    mIsTorchOn = false;
+                    if (mCameraManager != null) {
+                        mCameraManager.unregisterTorchCallback(mTorchCallback);
+                    }
+                }
+            } else if (mScreenFlashNotificationUri.equals(uri)) {
+                mIsScreenFlashNotificationEnabled = Settings.System.getIntForUser(
+                        mContext.getContentResolver(), SETTING_KEY_SCREEN_FLASH_NOTIFICATION, 0,
+                        UserHandle.USER_CURRENT) != 0;
+            }
+        }
+    }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
index 54cdb04..2530338 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
@@ -19,10 +19,12 @@
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.content.ComponentName;
 import android.content.Context;
+import android.hardware.display.DisplayManager;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.SparseArray;
+import android.view.Display;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
@@ -47,6 +49,8 @@
 
     private final Object mLock;
 
+    private final Context mContext;
+
     // Used to determine if we should notify AccessibilityManager clients of updates.
     // TODO(254545943): Separate this so each display id has its own state. Currently there is no
     // way to identify from AccessibilityManager which proxy state should be returned.
@@ -57,9 +61,12 @@
 
     private AccessibilityWindowManager mA11yWindowManager;
 
-    ProxyManager(Object lock, AccessibilityWindowManager awm) {
+    private AccessibilityInputFilter mA11yInputFilter;
+
+    ProxyManager(Object lock, AccessibilityWindowManager awm, Context context) {
         mLock = lock;
         mA11yWindowManager = awm;
+        mContext = context;
     }
 
     /**
@@ -109,6 +116,9 @@
             connection.mSystemSupport.onClientChangeLocked(true);
         }
 
+        if (mA11yInputFilter != null) {
+            mA11yInputFilter.disableFeaturesForDisplayIfInstalled(displayId);
+        }
         connection.initializeServiceInterface(client);
     }
 
@@ -120,14 +130,25 @@
     }
 
     private boolean clearConnection(int displayId) {
+        boolean removed = false;
         synchronized (mLock) {
             if (mProxyA11yServiceConnections.contains(displayId)) {
                 mProxyA11yServiceConnections.remove(displayId);
-                return true;
+                removed = true;
             }
         }
-        mA11yWindowManager.stopTrackingDisplayProxy(displayId);
-        return false;
+        if (removed) {
+            mA11yWindowManager.stopTrackingDisplayProxy(displayId);
+            if (mA11yInputFilter != null) {
+                final DisplayManager displayManager = (DisplayManager)
+                        mContext.getSystemService(Context.DISPLAY_SERVICE);
+                final Display proxyDisplay = displayManager.getDisplay(displayId);
+                if (proxyDisplay != null) {
+                    mA11yInputFilter.enableFeaturesForDisplayIfInstalled(proxyDisplay);
+                }
+            }
+        }
+        return removed;
     }
 
     /**
@@ -251,4 +272,8 @@
             proxy.notifyClearAccessibilityNodeInfoCache();
         }
     }
+
+    void setAccessibilityInputFilter(AccessibilityInputFilter filter) {
+        mA11yInputFilter = filter;
+    }
 }
\ No newline at end of file
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java b/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java
new file mode 100644
index 0000000..ed45e7b
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.magnification;
+
+import android.provider.DeviceConfig;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Encapsulates the feature flags for always on magnification. {@see DeviceConfig}
+ *
+ * @hide
+ */
+public class AlwaysOnMagnificationFeatureFlag {
+
+    private static final String NAMESPACE = DeviceConfig.NAMESPACE_WINDOW_MANAGER;
+    private static final String FEATURE_NAME_ENABLE_ALWAYS_ON_MAGNIFICATION =
+            "AlwaysOnMagnifier__enable_always_on_magnifier";
+
+    private AlwaysOnMagnificationFeatureFlag() {}
+
+    /** Returns true if the feature flag is enabled for always on magnification */
+    public static boolean isAlwaysOnMagnificationEnabled() {
+        return DeviceConfig.getBoolean(
+                NAMESPACE,
+                FEATURE_NAME_ENABLE_ALWAYS_ON_MAGNIFICATION,
+                /* defaultValue= */ false);
+    }
+
+    /** Sets the feature flag. Only used for testing; requires shell permissions. */
+    @VisibleForTesting
+    public static boolean setAlwaysOnMagnificationEnabled(boolean isEnabled) {
+        return DeviceConfig.setProperty(
+                NAMESPACE,
+                FEATURE_NAME_ENABLE_ALWAYS_ON_MAGNIFICATION,
+                Boolean.toString(isEnabled),
+                /* makeDefault= */ false);
+    }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index de7184c..d7c5b5d 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -52,10 +52,12 @@
 import android.view.animation.DecelerateInterpolator;
 
 import com.android.internal.R;
+import com.android.internal.accessibility.common.MagnificationConstants;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
+import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accessibility.AccessibilityTraceManager;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -98,7 +100,8 @@
     private final Rect mTempRect = new Rect();
     // Whether the following typing focus feature for magnification is enabled.
     private boolean mMagnificationFollowTypingEnabled = true;
-
+    // Whether the always on magnification feature is enabled.
+    private boolean mAlwaysOnMagnificationEnabled = false;
     private final DisplayManagerInternal mDisplayManagerInternal;
 
     /**
@@ -290,18 +293,15 @@
 
         @Override
         public void onDisplaySizeChanged() {
-            // Treat as context change and reset
-            final Message m = PooledLambda.obtainMessage(
-                    FullScreenMagnificationController::resetIfNeeded,
-                    FullScreenMagnificationController.this, mDisplayId, true);
-            mControllerCtx.getHandler().sendMessage(m);
+            // Treat as context change
+            onUserContextChanged();
         }
 
         @Override
         public void onUserContextChanged() {
             final Message m = PooledLambda.obtainMessage(
-                    FullScreenMagnificationController::resetIfNeeded,
-                    FullScreenMagnificationController.this, mDisplayId, true);
+                    FullScreenMagnificationController::onUserContextChanged,
+                    FullScreenMagnificationController.this, mDisplayId);
             mControllerCtx.getHandler().sendMessage(m);
         }
 
@@ -371,6 +371,7 @@
 
             final MagnificationConfig config = new MagnificationConfig.Builder()
                     .setMode(MAGNIFICATION_MODE_FULLSCREEN)
+                    .setActivated(mMagnificationActivated)
                     .setScale(scale)
                     .setCenterX(getCenterX())
                     .setCenterY(getCenterY()).build();
@@ -793,6 +794,33 @@
         return mMagnificationFollowTypingEnabled;
     }
 
+    void setAlwaysOnMagnificationEnabled(boolean enabled) {
+        mAlwaysOnMagnificationEnabled = enabled;
+    }
+
+    boolean isAlwaysOnMagnificationEnabled() {
+        return mAlwaysOnMagnificationEnabled;
+    }
+
+    /**
+     * if the magnifier with given displayId is activated:
+     * 1. if {@link #isAlwaysOnMagnificationEnabled()}, zoom the magnifier to 100%,
+     * 2. otherwise, reset the magnification.
+     *
+     * @param displayId The logical display id.
+     */
+    void onUserContextChanged(int displayId) {
+        synchronized (mLock) {
+            if (isAlwaysOnMagnificationEnabled()) {
+                setScaleAndCenter(displayId, 1.0f, Float.NaN, Float.NaN,
+                        true,
+                        AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+            } else {
+                reset(displayId, true);
+            }
+        }
+    }
+
     /**
      * Remove the display magnification with given id.
      *
@@ -1156,11 +1184,14 @@
     }
 
     /**
-     * Persists the default display magnification scale to the current user's settings.
+     * Persists the default display magnification scale to the current user's settings
+     * <strong>if scale is >= {@link MagnificationConstants.PERSISTED_SCALE_MIN_VALUE}</strong>.
+     * We assume if the scale is < {@link MagnificationConstants.PERSISTED_SCALE_MIN_VALUE}, there
+     * will be no obvious magnification effect.
      */
     public void persistScale(int displayId) {
         final float scale = getScale(Display.DEFAULT_DISPLAY);
-        if (scale < 2.0f) {
+        if (scale < MagnificationConstants.PERSISTED_SCALE_MIN_VALUE) {
             return;
         }
         mScaleProvider.putScale(scale, displayId);
@@ -1175,7 +1206,8 @@
      */
     public float getPersistedScale(int displayId) {
         return MathUtils.constrain(mScaleProvider.getScale(displayId),
-                2.0f, MagnificationScaleProvider.MAX_SCALE);
+                MagnificationConstants.PERSISTED_SCALE_MIN_VALUE,
+                MagnificationScaleProvider.MAX_SCALE);
     }
 
     /**
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 6bf37a1..9c84c04 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -445,12 +445,12 @@
      */
     final class ViewportDraggingState implements State {
 
-        /** Whether to disable zoom after dragging ends */
-        @VisibleForTesting boolean mActivatedBeforeDrag;
-        /** Whether to restore scale after dragging ends */
-        private boolean mZoomedInTemporary;
-        /** The cached scale for recovering after dragging ends */
-        private float mScaleBeforeZoomedInTemporary;
+        /**
+         * The cached scale for recovering after dragging ends.
+         * If the scale >= 1.0, the magnifier needs to recover to scale.
+         * Otherwise, the magnifier should be disabled.
+         */
+        @VisibleForTesting float mScaleToRecoverAfterDraggingEnd = Float.NaN;
 
         private boolean mLastMoveOutsideMagnifiedRegion;
 
@@ -460,8 +460,7 @@
             final int action = event.getActionMasked();
             switch (action) {
                 case ACTION_POINTER_DOWN: {
-                    clear();
-                    transitionTo(mPanningScalingState);
+                    clearAndTransitToPanningScalingState();
                 }
                 break;
                 case ACTION_MOVE: {
@@ -484,14 +483,18 @@
 
                 case ACTION_UP:
                 case ACTION_CANCEL: {
-                    if (mActivatedBeforeDrag) {
-                        if (mZoomedInTemporary) {
-                            zoomToScale(mScaleBeforeZoomedInTemporary, event.getX(), event.getY());
-                        }
+                    // If mScaleToRecoverAfterDraggingEnd >= 1.0, the dragging state is triggered
+                    // by zoom in temporary, and the magnifier needs to recover to original scale
+                    // after exiting dragging state.
+                    // Otherwise, the magnifier should be disabled.
+                    if (mScaleToRecoverAfterDraggingEnd >= 1.0f) {
+                        zoomToScale(mScaleToRecoverAfterDraggingEnd, event.getX(),
+                                event.getY());
                     } else {
                         zoomOff();
                     }
                     clear();
+                    mScaleToRecoverAfterDraggingEnd = Float.NaN;
                     transitionTo(mDetectingState);
                 }
                     break;
@@ -504,27 +507,49 @@
             }
         }
 
-        public void prepareForZoomInTemporary() {
-            mViewportDraggingState.mActivatedBeforeDrag =
-                    mFullScreenMagnificationController.isActivated(mDisplayId);
+        private boolean isAlwaysOnMagnificationEnabled() {
+            return mFullScreenMagnificationController.isAlwaysOnMagnificationEnabled();
+        }
 
-            mViewportDraggingState.mZoomedInTemporary = true;
-            mViewportDraggingState.mScaleBeforeZoomedInTemporary =
-                    mFullScreenMagnificationController.getScale(mDisplayId);
+        public void prepareForZoomInTemporary(boolean shortcutTriggered) {
+            boolean shouldRecoverAfterDraggingEnd;
+            if (mFullScreenMagnificationController.isActivated(mDisplayId)) {
+                // For b/267210808, if always-on feature is not enabled, we keep the expected
+                // behavior. If users tap shortcut and then tap-and-hold to zoom in temporary,
+                // the magnifier should be disabled after release.
+                // If always-on feature is enabled, in the same scenario the magnifier would
+                // zoom to 1.0 and keep activated.
+                if (shortcutTriggered) {
+                    shouldRecoverAfterDraggingEnd = isAlwaysOnMagnificationEnabled();
+                } else {
+                    shouldRecoverAfterDraggingEnd = true;
+                }
+            } else {
+                shouldRecoverAfterDraggingEnd = false;
+            }
+
+            mScaleToRecoverAfterDraggingEnd = shouldRecoverAfterDraggingEnd
+                    ? mFullScreenMagnificationController.getScale(mDisplayId) : Float.NaN;
+        }
+
+        private void clearAndTransitToPanningScalingState() {
+            final float scaleToRecovery = mScaleToRecoverAfterDraggingEnd;
+            clear();
+            mScaleToRecoverAfterDraggingEnd = scaleToRecovery;
+            transitionTo(mPanningScalingState);
         }
 
         @Override
         public void clear() {
             mLastMoveOutsideMagnifiedRegion = false;
 
-            mZoomedInTemporary = false;
-            mScaleBeforeZoomedInTemporary = 1.0f;
+            mScaleToRecoverAfterDraggingEnd = Float.NaN;
         }
 
         @Override
         public String toString() {
             return "ViewportDraggingState{"
-                    + "mActivatedBeforeDrag=" + mActivatedBeforeDrag
+                    + "mScaleToRecoverAfterDraggingEnd=" + mScaleToRecoverAfterDraggingEnd
                     + ", mLastMoveOutsideMagnifiedRegion=" + mLastMoveOutsideMagnifiedRegion
                     + '}';
         }
@@ -921,13 +946,14 @@
         void transitionToViewportDraggingStateAndClear(MotionEvent down) {
 
             if (DEBUG_DETECTING) Slog.i(mLogTag, "onTripleTapAndHold()");
+            final boolean shortcutTriggered = mShortcutTriggered;
             clear();
 
             // Triple tap and hold also belongs to triple tap event.
             final boolean enabled = !isActivated();
             logMagnificationTripleTap(enabled);
 
-            mViewportDraggingState.prepareForZoomInTemporary();
+            mViewportDraggingState.prepareForZoomInTemporary(shortcutTriggered);
 
             zoomInTemporary(down.getX(), down.getY());
 
@@ -992,9 +1018,8 @@
                 mFullScreenMagnificationController.getPersistedScale(mDisplayId),
                 MIN_SCALE, MAX_SCALE);
 
-        final float scale = MathUtils.constrain(Math.max(currentScale + 1.0f, persistedScale),
-                MIN_SCALE, MAX_SCALE);
-
+        final boolean isActivated = mFullScreenMagnificationController.isActivated(mDisplayId);
+        final float scale = isActivated ? (currentScale + 1.0f) : persistedScale;
         zoomToScale(scale, centerX, centerY);
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
index 129bc16..a6e6bd7 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -284,6 +284,7 @@
         }
         synchronized (mLock) {
             final int targetMode = config.getMode();
+            final boolean targetActivated = config.isActivated();
             final PointF currentCenter = getCurrentMagnificationCenterLocked(displayId, targetMode);
             final PointF magnificationCenter = new PointF(config.getCenterX(), config.getCenterY());
             if (currentCenter != null) {
@@ -310,20 +311,30 @@
                     : config.getScale();
             try {
                 setTransitionState(displayId, targetMode);
-
+                // Activate or deactivate target mode depending on config activated value
                 if (targetMode == MAGNIFICATION_MODE_WINDOW) {
                     screenMagnificationController.reset(displayId, false);
-                    windowMagnificationMgr.enableWindowMagnification(displayId,
-                            targetScale, magnificationCenter.x, magnificationCenter.y,
-                            animate ? STUB_ANIMATION_CALLBACK : null, id);
+                    if (targetActivated) {
+                        windowMagnificationMgr.enableWindowMagnification(displayId,
+                                targetScale, magnificationCenter.x, magnificationCenter.y,
+                                animate ? STUB_ANIMATION_CALLBACK : null, id);
+                    } else {
+                        windowMagnificationMgr.disableWindowMagnification(displayId, false);
+                    }
                 } else if (targetMode == MAGNIFICATION_MODE_FULLSCREEN) {
                     windowMagnificationMgr.disableWindowMagnification(displayId, false, null);
-                    if (!screenMagnificationController.isRegistered(displayId)) {
-                        screenMagnificationController.register(displayId);
+                    if (targetActivated) {
+                        if (!screenMagnificationController.isRegistered(displayId)) {
+                            screenMagnificationController.register(displayId);
+                        }
+                        screenMagnificationController.setScaleAndCenter(displayId, targetScale,
+                                magnificationCenter.x, magnificationCenter.y, animate,
+                                id);
+                    } else {
+                        if (screenMagnificationController.isRegistered(displayId)) {
+                            screenMagnificationController.reset(displayId, false);
+                        }
                     }
-                    screenMagnificationController.setScaleAndCenter(displayId, targetScale,
-                            magnificationCenter.x, magnificationCenter.y, animate,
-                            id);
                 }
             } finally {
                 // Reset transition state after enabling target mode.
@@ -454,6 +465,7 @@
         if (shouldNotifyMagnificationChange(displayId, MAGNIFICATION_MODE_WINDOW)) {
             final MagnificationConfig config = new MagnificationConfig.Builder()
                     .setMode(MAGNIFICATION_MODE_WINDOW)
+                    .setActivated(getWindowMagnificationMgr().isWindowMagnifierEnabled(displayId))
                     .setScale(getWindowMagnificationMgr().getScale(displayId))
                     .setCenterX(bounds.exactCenterX())
                     .setCenterY(bounds.exactCenterY()).build();
@@ -665,6 +677,19 @@
         getFullScreenMagnificationController().setMagnificationFollowTypingEnabled(enabled);
     }
 
+    /**
+     * Called when the always on magnification feature is switched.
+     *
+     * @param enabled Enable the always on magnification feature
+     */
+    public void setAlwaysOnMagnificationEnabled(boolean enabled) {
+        getFullScreenMagnificationController().setAlwaysOnMagnificationEnabled(enabled);
+    }
+
+    public boolean isAlwaysOnMagnificationFeatureFlagEnabled() {
+        return AlwaysOnMagnificationFeatureFlag.isAlwaysOnMagnificationEnabled();
+    }
+
     private DisableMagnificationCallback getDisableMagnificationEndRunnableLocked(
             int displayId) {
         return mMagnificationEndRunnableSparseArray.get(displayId);
@@ -834,6 +859,7 @@
                                 new MagnificationConfig.Builder();
                         Region region = new Region();
                         configBuilder.setMode(MAGNIFICATION_MODE_FULLSCREEN)
+                                .setActivated(screenMagnificationController.isActivated(mDisplayId))
                                 .setScale(screenMagnificationController.getScale(mDisplayId))
                                 .setCenterX(screenMagnificationController.getCenterX(mDisplayId))
                                 .setCenterY(screenMagnificationController.getCenterY(mDisplayId));
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
index 75fe026..5cf2a63 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
@@ -79,6 +79,7 @@
             final FullScreenMagnificationController fullScreenMagnificationController =
                     mController.getFullScreenMagnificationController();
             builder.setMode(mode)
+                    .setActivated(mController.isActivated(displayId, MAGNIFICATION_MODE_FULLSCREEN))
                     .setScale(fullScreenMagnificationController.getScale(displayId))
                     .setCenterX(fullScreenMagnificationController.getCenterX(displayId))
                     .setCenterY(fullScreenMagnificationController.getCenterY(displayId));
@@ -86,9 +87,13 @@
             final WindowMagnificationManager windowMagnificationManager =
                     mController.getWindowMagnificationMgr();
             builder.setMode(mode)
+                    .setActivated(mController.isActivated(displayId, MAGNIFICATION_MODE_WINDOW))
                     .setScale(windowMagnificationManager.getScale(displayId))
                     .setCenterX(windowMagnificationManager.getCenterX(displayId))
                     .setCenterY(windowMagnificationManager.getCenterY(displayId));
+        } else {
+            // For undefined mode, set enabled to false
+            builder.setActivated(false);
         }
         return builder.build();
     }
@@ -118,15 +123,26 @@
         if (configMode == MAGNIFICATION_MODE_DEFAULT) {
             configMode = getControllingMode(displayId);
         }
+        // Check should activate or deactivate the target mode in config
+        boolean configActivated = config.isActivated();
         if (configMode == MAGNIFICATION_MODE_FULLSCREEN) {
-            return setScaleAndCenterForFullScreenMagnification(displayId, config.getScale(),
-                    config.getCenterX(), config.getCenterY(),
-                    animate, id);
+            if (configActivated) {
+                return setScaleAndCenterForFullScreenMagnification(displayId, config.getScale(),
+                        config.getCenterX(), config.getCenterY(),
+                        animate, id);
+            } else {
+                return resetFullscreenMagnification(displayId, animate);
+            }
         } else if (configMode == MAGNIFICATION_MODE_WINDOW) {
-            return mController.getWindowMagnificationMgr().enableWindowMagnification(displayId,
-                    config.getScale(), config.getCenterX(), config.getCenterY(),
-                    animate ? STUB_ANIMATION_CALLBACK : null,
-                    id);
+            if (configActivated) {
+                return mController.getWindowMagnificationMgr().enableWindowMagnification(displayId,
+                        config.getScale(), config.getCenterX(), config.getCenterY(),
+                        animate ? STUB_ANIMATION_CALLBACK : null,
+                        id);
+            } else {
+                return mController.getWindowMagnificationMgr()
+                        .disableWindowMagnification(displayId, false);
+            }
         }
         return false;
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index cf30a5a..c58e9a6 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -71,7 +71,7 @@
     private static final boolean DEBUG_DETECTING = false | DEBUG_ALL;
 
     //Ensure the range has consistency with FullScreenMagnificationGestureHandler.
-    private static final float MIN_SCALE = 2.0f;
+    private static final float MIN_SCALE = 1.0f;
     private static final float MAX_SCALE = MagnificationScaleProvider.MAX_SCALE;
 
     private final WindowMagnificationManager mWindowMagnificationMgr;
@@ -222,6 +222,8 @@
         if (DEBUG_DETECTING) {
             Slog.i(mLogTag, "onTripleTapAndHold()");
         }
+        mViewportDraggingState.mEnabledBeforeDrag =
+                mWindowMagnificationMgr.isWindowMagnifierEnabled(mDisplayId);
         enableWindowMagnifier(up.getX(), up.getY(),
                 WindowMagnificationManager.WINDOW_POSITION_AT_TOP_LEFT);
         mTripleTapAndHoldStartedTime = SystemClock.uptimeMillis();
@@ -230,7 +232,9 @@
 
     @VisibleForTesting
     void releaseTripleTapAndHold() {
-        mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, true);
+        if (!mViewportDraggingState.mEnabledBeforeDrag) {
+            mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, true);
+        }
         transitionTo(mDetectingState);
         if (mTripleTapAndHoldStartedTime != 0) {
             final long duration = SystemClock.uptimeMillis() - mTripleTapAndHoldStartedTime;
@@ -377,6 +381,9 @@
      */
     final class ViewportDraggingState implements State {
 
+        /** Whether to disable zoom after dragging ends */
+        boolean mEnabledBeforeDrag;
+
         private float mLastX = Float.NaN;
         private float mLastY = Float.NaN;
 
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
index 09c6ca3..d9391f4 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
@@ -37,6 +37,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.util.MathUtils;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -45,6 +46,7 @@
 import android.view.accessibility.IWindowMagnificationConnectionCallback;
 import android.view.accessibility.MagnificationAnimationCallback;
 
+import com.android.internal.accessibility.common.MagnificationConstants;
 import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -631,7 +633,7 @@
      * @param clear {@true} Clears the state of window magnification.
      * @return {@code true} if the magnification is turned to be disabled successfully
      */
-    boolean disableWindowMagnification(int displayId, boolean clear) {
+    public boolean disableWindowMagnification(int displayId, boolean clear) {
         return disableWindowMagnification(displayId, clear, STUB_ANIMATION_CALLBACK);
     }
 
@@ -696,7 +698,6 @@
      * @param displayId The logical display id.
      * @return {@code true} if the window magnification is enabled.
      */
-    @VisibleForTesting
     public boolean isWindowMagnifierEnabled(int displayId) {
         synchronized (mLock) {
             WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
@@ -715,18 +716,24 @@
      *         scale if none is available
      */
     float getPersistedScale(int displayId) {
-        return mScaleProvider.getScale(displayId);
+        return MathUtils.constrain(mScaleProvider.getScale(displayId),
+                MagnificationConstants.PERSISTED_SCALE_MIN_VALUE,
+                MagnificationScaleProvider.MAX_SCALE);
     }
 
     /**
-     * Persists the default display magnification scale to the current user's settings. Only the
-     * value of the default display is persisted in user's settings.
+     * Persists the default display magnification scale to the current user's settings
+     * <strong>if scale is >= {@link MagnificationConstants.PERSISTED_SCALE_MIN_VALUE}</strong>.
+     * We assume if the scale is < {@link MagnificationConstants.PERSISTED_SCALE_MIN_VALUE}, there
+     * will be no obvious magnification effect.
+     * Only the value of the default display is persisted in user's settings.
      */
     void persistScale(int displayId) {
         float scale = getScale(displayId);
-        if (scale != 1.0f) {
-            mScaleProvider.putScale(scale, displayId);
+        if (scale < MagnificationConstants.PERSISTED_SCALE_MIN_VALUE) {
+            return;
         }
+        mScaleProvider.putScale(scale, displayId);
     }
 
     /**
diff --git a/services/api/current.txt b/services/api/current.txt
index f7d6ee9..a4deed3 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -225,6 +225,15 @@
 
 }
 
+package com.android.server.security {
+
+  public final class FileIntegrity {
+    method public static void setUpFsVerity(@NonNull java.io.File) throws java.io.IOException;
+    method public static void setUpFsVerity(@NonNull android.os.ParcelFileDescriptor) throws java.io.IOException;
+  }
+
+}
+
 package com.android.server.stats {
 
   public final class StatsHelper {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 7df4899..e86d997 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1028,8 +1028,9 @@
             intent.setComponent(provider.getInfoLocked(mContext).configure);
             intent.setFlags(secureFlags);
 
-            final ActivityOptions options = ActivityOptions.makeBasic();
-            options.setIgnorePendingIntentCreatorForegroundState(true);
+            final ActivityOptions options =
+                    ActivityOptions.makeBasic().setPendingIntentCreatorBackgroundActivityStartMode(
+                            ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED);
 
             // All right, create the sender.
             final long identity = Binder.clearCallingIdentity();
diff --git a/services/art-profile b/services/art-profile
index 2bb85a4..132b9ab 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -20484,12 +20484,12 @@
 Lcom/android/server/usage/UsageStatsShellCommand;
 Lcom/android/server/usage/UserUsageStatsService$StatsUpdatedListener;
 Lcom/android/server/usb/UsbAlsaJackDetector;
+Lcom/android/server/usb/UsbAlsaMidiDevice$2;
+Lcom/android/server/usb/UsbAlsaMidiDevice$3;
+Lcom/android/server/usb/UsbAlsaMidiDevice$InputReceiverProxy;
+Lcom/android/server/usb/UsbAlsaMidiDevice;
 Lcom/android/server/usb/UsbDeviceManager;
 Lcom/android/server/usb/UsbHostManager;
-Lcom/android/server/usb/UsbMidiDevice$2;
-Lcom/android/server/usb/UsbMidiDevice$3;
-Lcom/android/server/usb/UsbMidiDevice$InputReceiverProxy;
-Lcom/android/server/usb/UsbMidiDevice;
 Lcom/android/server/usb/descriptors/UsbDescriptor;
 Lcom/android/server/usb/descriptors/UsbInterfaceDescriptor;
 Lcom/android/server/utils/AlarmQueue$1;
diff --git a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java
index 5f1da7b..590f472 100644
--- a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java
+++ b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java
@@ -315,7 +315,12 @@
                 event.mFillRequestSentTimestampMs,
                 event.mFillResponseReceivedTimestampMs,
                 event.mSuggestionSentTimestampMs,
-                event.mSuggestionPresentedTimestampMs);
+                event.mSuggestionPresentedTimestampMs,
+                //TODO(b/265051751): add new framework logging.
+                /* selected_dataset_id= */ 0,
+                /* dialog_dismissed= */ false,
+                /* negative_cta_button_clicked= */ false,
+                /* positive_cta_button_clicked= */ false);
         mEventInternal = Optional.empty();
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 939047f..2b529bf 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -24,6 +24,7 @@
 import static android.service.autofill.FillEventHistory.Event.UI_TYPE_UNKNOWN;
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
+import static android.service.autofill.FillRequest.FLAG_PCC_DETECTION;
 import static android.service.autofill.FillRequest.FLAG_RESET_FILL_DIALOG_STATE;
 import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG;
 import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
@@ -384,6 +385,11 @@
      */
     private final AssistDataReceiverImpl mAssistReceiver = new AssistDataReceiverImpl();
 
+    /**
+     * Receiver of assist data for pcc purpose
+     */
+    private final PccAssistDataReceiverImpl mPccAssistReceiver = new PccAssistDataReceiverImpl();
+
     @Nullable
     private ClientSuggestionsSession mClientSuggestionsSession;
 
@@ -698,6 +704,89 @@
         }
     }
 
+    /**
+     * Assist Data Receiver for PCC
+     */
+    private final class PccAssistDataReceiverImpl extends IAssistDataReceiver.Stub {
+        // TODO: Uncomment lines below after field classification service definition merged
+        // @GuardedBy("mLock")
+        // private FieldClassificationRequest mPendingFieldClassifitacionRequest;
+        // @GuardedBy("mLock")
+        // private FieldClassificationRequest mLastFieldClassifitacionRequest;
+
+        @GuardedBy("mLock")
+        void maybeRequestFieldClassificationFromServiceLocked() {
+            // TODO: Uncomment lines below after field classification service definition merged
+            // if (mPendingFieldClassifitacionRequest == null) {
+            //     return;
+            // }
+            // mLastFieldClassifitacionRequest = mPendingFieldClassifitacionRequest;
+            //
+            // mRemoteFieldClassificationService.onFieldClassificationRequest(
+            //        mPendingFieldClassifitacionRequest);
+            //
+            // mPendingFieldClassifitacionRequest = null;
+        }
+
+        @Override
+        public void onHandleAssistData(Bundle resultData) throws RemoteException {
+            // TODO: add a check if pcc field classification service is present
+            final AssistStructure structure = resultData.getParcelable(ASSIST_KEY_STRUCTURE,
+                android.app.assist.AssistStructure.class);
+            if (structure == null) {
+                Slog.e(TAG, "No assist structure for pcc detection - "
+                    + "app might have crashed providing it");
+                return;
+            }
+
+            final Bundle receiverExtras = resultData.getBundle(ASSIST_KEY_RECEIVER_EXTRAS);
+            if (receiverExtras == null) {
+                Slog.e(TAG, "No receiver extras for pcc detection - "
+                    + "app might have crashed providing it");
+                return;
+            }
+
+            final int requestId = receiverExtras.getInt(EXTRA_REQUEST_ID);
+
+            if (sVerbose) {
+                Slog.v(TAG, "New structure for requestId " + requestId + ": " + structure);
+            }
+
+            synchronized (mLock) {
+                // TODO(b/35708678): Must fetch the data so it's available later on handleSave(),
+                // even if the activity is gone by then, but structure .ensureData() gives a
+                // ONE_WAY warning because system_service could block on app calls. We need to
+                // change AssistStructure so it provides a "one-way" writeToParcel() method that
+                // sends all the data
+                try {
+                    structure.ensureDataForAutofill();
+                } catch (RuntimeException e) {
+                    wtf(e, "Exception lazy loading assist structure for %s: %s",
+                        structure.getActivityComponent(), e);
+                    return;
+                }
+
+                final ArrayList<AutofillId> ids = Helper.getAutofillIds(structure,
+                    /* autofillableOnly= */false);
+                for (int i = 0; i < ids.size(); i++) {
+                    ids.get(i).setSessionId(Session.this.id);
+                }
+
+                // TODO: Uncomment lines below after field classification service definition merged
+                // FieldClassificationRequest request = new FieldClassificationRequest(structure);
+                //
+                // mPendingFieldClassifitacionRequest = request;
+                //
+                // maybeRequestFieldClassificationFromServiceLocked();
+            }
+        }
+
+        @Override
+        public void onHandleAssistScreenshot(Bitmap screenshot) {
+            // Do nothing
+        }
+    }
+
     /** Creates {@link PendingIntent} for autofill service to send a delayed fill. */
     private PendingIntent createPendingIntent(int requestId) {
         Slog.d(TAG, "createPendingIntent for request " + requestId);
@@ -1062,6 +1151,32 @@
     }
 
     @GuardedBy("mLock")
+    private void requestAssistStructureForPccLocked(int flags) {
+        // Get request id
+        int requestId;
+        // TODO(b/158623971): Update this to prevent possible overflow
+        do {
+            requestId = sIdCounter.getAndIncrement();
+        } while (requestId == INVALID_REQUEST_ID);
+
+        // Call requestAutofilLData
+        try {
+            final Bundle receiverExtras = new Bundle();
+            receiverExtras.putInt(EXTRA_REQUEST_ID, requestId);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if (!ActivityTaskManager.getService().requestAutofillData(mPccAssistReceiver,
+                    receiverExtras, mActivityToken, flags)) {
+                    Slog.w(TAG, "failed to request autofill data for pcc: " + mActivityToken);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        } catch (RemoteException e) {
+        }
+    }
+
+    @GuardedBy("mLock")
     private void requestAssistStructureLocked(int requestId, int flags) {
         try {
             final Bundle receiverExtras = new Bundle();
@@ -3095,6 +3210,12 @@
             mSessionFlags.mFillDialogDisabled = false;
         }
 
+        /* request assist structure for pcc */
+        if ((flags & FLAG_PCC_DETECTION) != 0) {
+            requestAssistStructureForPccLocked(flags);
+            return;
+        }
+
         switch(action) {
             case ACTION_START_SESSION:
                 // View is triggering autofill.
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index b68adab..756dcd2 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -361,7 +361,6 @@
         params.width = WindowManager.LayoutParams.MATCH_PARENT;
         params.accessibilityTitle = context.getString(R.string.autofill_save_accessibility_title);
         params.windowAnimations = R.style.AutofillSaveAnimation;
-        params.setTrustedOverlay();
 
         show();
     }
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 998c9c2..7261709 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -551,7 +551,7 @@
         mPackageManagerBinder = AppGlobals.getPackageManager();
         mActivityManager = ActivityManager.getService();
         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
-        mScheduledBackupEligibility = getEligibilityRules(mPackageManager, userId,
+        mScheduledBackupEligibility = getEligibilityRules(mPackageManager, userId, mContext,
                 BackupDestination.CLOUD);
 
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -4118,13 +4118,14 @@
 
     public BackupEligibilityRules getEligibilityRulesForOperation(
             @BackupDestination int backupDestination) {
-        return getEligibilityRules(mPackageManager, mUserId, backupDestination);
+        return getEligibilityRules(mPackageManager, mUserId, mContext, backupDestination);
     }
 
     private static BackupEligibilityRules getEligibilityRules(PackageManager packageManager,
-            int userId, @BackupDestination int backupDestination) {
+            int userId, Context context, @BackupDestination int backupDestination) {
         return new BackupEligibilityRules(packageManager,
-                LocalServices.getService(PackageManagerInternal.class), userId, backupDestination);
+                LocalServices.getService(PackageManagerInternal.class), userId, context,
+                backupDestination);
     }
 
     /** Prints service state for 'dumpsys backup'. */
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 515a172..2374dee 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -112,7 +112,9 @@
             BackupEligibilityRules eligibilityRules = new BackupEligibilityRules(
                     mBackupManagerService.getPackageManager(),
                     LocalServices.getService(PackageManagerInternal.class),
-                    mBackupManagerService.getUserId(), BackupDestination.ADB_BACKUP);
+                    mBackupManagerService.getUserId(),
+                    mBackupManagerService.getContext(),
+                    BackupDestination.ADB_BACKUP);
             FullRestoreEngine mEngine = new FullRestoreEngine(mBackupManagerService,
                     mOperationStorage, null, mObserver, null, null,
                     true, 0 /*unused*/, true, eligibilityRules);
diff --git a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
index 2ee9174..7c47f1e 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
@@ -31,6 +31,7 @@
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.compat.annotation.Overridable;
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -39,10 +40,12 @@
 import android.content.pm.SigningInfo;
 import android.os.Build;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
+import com.android.server.backup.SetUtils;
 import com.android.server.backup.transport.BackupTransportClient;
 import com.android.server.backup.transport.TransportConnection;
 
@@ -56,13 +59,26 @@
  */
 public class BackupEligibilityRules {
     private static final boolean DEBUG = false;
-    // List of system packages that are eligible for backup in non-system users.
-    private static final Set<String> systemPackagesAllowedForAllUsers = Sets.newArraySet(
-            PACKAGE_MANAGER_SENTINEL, PLATFORM_PACKAGE_NAME, WALLPAPER_PACKAGE, SETTINGS_PACKAGE);
+
+    /**
+     * List of system packages that are eligible for backup in "profile" users (such as work
+     * profile). See {@link UserManager#isProfile()}. This is a subset of {@link
+     * #systemPackagesAllowedForNonSystemUsers}
+     */
+    private static final Set<String> systemPackagesAllowedForProfileUser =
+            Sets.newArraySet(PACKAGE_MANAGER_SENTINEL, PLATFORM_PACKAGE_NAME);
+
+    /**
+     * List of system packages that are eligible for backup in non-system users.
+     */
+    private static final Set<String> systemPackagesAllowedForNonSystemUsers = SetUtils.union(
+            systemPackagesAllowedForProfileUser,
+            Sets.newArraySet(WALLPAPER_PACKAGE, SETTINGS_PACKAGE));
 
     private final PackageManager mPackageManager;
     private final PackageManagerInternal mPackageManagerInternal;
     private final int mUserId;
+    private boolean mIsProfileUser = false;
     @BackupDestination  private final int mBackupDestination;
 
     /**
@@ -85,19 +101,23 @@
 
     public static BackupEligibilityRules forBackup(PackageManager packageManager,
             PackageManagerInternal packageManagerInternal,
-            int userId) {
-        return new BackupEligibilityRules(packageManager, packageManagerInternal, userId,
+            int userId,
+            Context context) {
+        return new BackupEligibilityRules(packageManager, packageManagerInternal, userId, context,
                 BackupDestination.CLOUD);
     }
 
     public BackupEligibilityRules(PackageManager packageManager,
             PackageManagerInternal packageManagerInternal,
             int userId,
+            Context context,
             @BackupDestination int backupDestination) {
         mPackageManager = packageManager;
         mPackageManagerInternal = packageManagerInternal;
         mUserId = userId;
         mBackupDestination = backupDestination;
+        UserManager userManager = context.getSystemService(UserManager.class);
+        mIsProfileUser = userManager.isProfile();
     }
 
     /**
@@ -125,11 +145,17 @@
 
         // 2. they run as a system-level uid
         if (UserHandle.isCore(app.uid)) {
-            // and the backup is happening for a non-system user on a package that is not explicitly
-            // allowed.
-            if (mUserId != UserHandle.USER_SYSTEM
-                    && !systemPackagesAllowedForAllUsers.contains(app.packageName)) {
-                return false;
+            // and the backup is happening for a non-system user or profile on a package that is
+            // not explicitly allowed.
+            if (mUserId != UserHandle.USER_SYSTEM) {
+                if (mIsProfileUser && !systemPackagesAllowedForProfileUser.contains(
+                        app.packageName)) {
+                    return false;
+                }
+                if (!mIsProfileUser && !systemPackagesAllowedForNonSystemUsers.contains(
+                        app.packageName)) {
+                    return false;
+                }
             }
 
             // or do not supply their own backup agent
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index 8e8bac4..0accb9f 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -160,7 +160,8 @@
                             PackageManagerInternal pmi = LocalServices.getService(
                                     PackageManagerInternal.class);
                             BackupEligibilityRules eligibilityRules =
-                                    BackupEligibilityRules.forBackup(packageManager, pmi, userId);
+                                    BackupEligibilityRules.forBackup(packageManager, pmi, userId,
+                                            context);
                             if (eligibilityRules.signaturesMatch(sigs, pkg)) {
                                 // If this is a system-uid app without a declared backup agent,
                                 // don't restore any of the file data.
diff --git a/services/backup/java/com/android/server/backup/utils/SetUtils.java b/services/backup/java/com/android/server/backup/utils/SetUtils.java
new file mode 100644
index 0000000..ecd628f
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/utils/SetUtils.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.utils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Helper class containing common operation on {@link java.util.Set}.
+ */
+public final class SetUtils {
+    // Statics only
+    private SetUtils() {}
+
+    /**
+     * Returns union of two sets.
+     */
+    public static <T> Set<T> union(Set<T> set1, Set<T> set2) {
+        Set<T> unionSet = new HashSet<>(set1);
+        unionSet.addAll(set2);
+        return unionSet;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index 6963248..71ca8ca 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -47,6 +47,7 @@
 import android.app.backup.BackupManagerMonitor;
 import android.app.backup.FullBackup;
 import android.app.backup.IBackupManagerMonitor;
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -384,13 +385,14 @@
      * @param info - file metadata.
      * @param signatures - array of signatures parsed from backup file.
      * @param userId - ID of the user for which restore is performed.
+     * @param context - Context instance.
      * @return a restore policy constant.
      */
     public RestorePolicy chooseRestorePolicy(PackageManager packageManager,
             boolean allowApks, FileMetadata info, Signature[] signatures,
-            PackageManagerInternal pmi, int userId) {
+            PackageManagerInternal pmi, int userId, Context context) {
         return chooseRestorePolicy(packageManager, allowApks, info, signatures, pmi, userId,
-                BackupEligibilityRules.forBackup(packageManager, pmi, userId));
+                BackupEligibilityRules.forBackup(packageManager, pmi, userId, context));
     }
 
     /**
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index b74dfcb..0f2ba35 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -1097,7 +1097,7 @@
     }
 
     /**
-     * Remove the revoked association form the cache and also remove the uid form the map if
+     * Remove the revoked association from the cache and also remove the uid from the map if
      * there are other associations with the same package still pending for role holder removal.
      *
      * @see #mRevokedAssociationsPendingRoleHolderRemoval
@@ -1116,7 +1116,7 @@
             final boolean shouldKeepUidForRemoval = any(
                     getPendingRoleHolderRemovalAssociationsForUser(userId),
                     ai -> packageName.equals(ai.getPackageName()));
-            // Do not remove the uid form the map since other associations with
+            // Do not remove the uid from the map since other associations with
             // the same packageName still pending for role holder removal.
             if (!shouldKeepUidForRemoval) {
                 mUidsPendingRoleHolderRemoval.remove(uid);
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index 6b2e893..e52f1d9 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.WindowConfiguration;
 import android.app.compat.CompatChanges;
 import android.companion.virtual.VirtualDeviceManager.ActivityListener;
@@ -302,14 +303,14 @@
     }
 
     @Override
-    public void onTopActivityChanged(ComponentName topActivity, int uid) {
+    public void onTopActivityChanged(ComponentName topActivity, int uid, @UserIdInt int userId) {
         // Don't send onTopActivityChanged() callback when topActivity is null because it's defined
         // as @NonNull in ActivityListener interface. Sends onDisplayEmpty() callback instead when
         // there is no activity running on virtual display.
         if (mActivityListener != null && topActivity != null) {
             // Post callback on the main thread so it doesn't block activity launching
             mHandler.post(() ->
-                    mActivityListener.onTopActivityChanged(mDisplayId, topActivity));
+                    mActivityListener.onTopActivityChanged(mDisplayId, topActivity, userId));
         }
     }
 
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 3100277..7fce442 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -26,6 +26,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityOptions;
 import android.app.PendingIntent;
@@ -137,7 +138,18 @@
             @Override
             public void onTopActivityChanged(int displayId, ComponentName topActivity) {
                 try {
-                    mActivityListener.onTopActivityChanged(displayId, topActivity);
+                    mActivityListener.onTopActivityChanged(displayId, topActivity,
+                            UserHandle.USER_NULL);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Unable to call mActivityListener", e);
+                }
+            }
+
+            @Override
+            public void onTopActivityChanged(int displayId, ComponentName topActivity,
+                    @UserIdInt int userId) {
+                try {
+                    mActivityListener.onTopActivityChanged(displayId, topActivity, userId);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Unable to call mActivityListener", e);
                 }
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index b41664f..54c47b2 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -52,6 +52,7 @@
 import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UEventObserver;
 import android.os.UserHandle;
@@ -161,6 +162,7 @@
     private int mLowBatteryWarningLevel;
     private int mLastLowBatteryWarningLevel;
     private int mLowBatteryCloseWarningLevel;
+    private int mBatteryNearlyFullLevel;
     private int mShutdownBatteryTemperature;
 
     private int mPlugType;
@@ -574,6 +576,10 @@
                 EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
                         mHealthInfo.batteryStatus, mHealthInfo.batteryHealth, mHealthInfo.batteryPresent ? 1 : 0,
                         mPlugType, mHealthInfo.batteryTechnology);
+                SystemProperties.set(
+                        "debug.tracing.battery_status",
+                        Integer.toString(mHealthInfo.batteryStatus));
+                SystemProperties.set("debug.tracing.plug_type", Integer.toString(mPlugType));
             }
             if (mHealthInfo.batteryLevel != mLastBatteryLevel) {
                 // Don't do this just from voltage or temperature changes, that is
@@ -1207,6 +1213,8 @@
                     com.android.internal.R.integer.config_notificationsBatteryLedOn);
             mBatteryLedOff = context.getResources().getInteger(
                     com.android.internal.R.integer.config_notificationsBatteryLedOff);
+            mBatteryNearlyFullLevel = context.getResources().getInteger(
+                    com.android.internal.R.integer.config_notificationsBatteryNearlyFullLevel);
         }
 
         /**
@@ -1229,7 +1237,8 @@
                 }
             } else if (status == BatteryManager.BATTERY_STATUS_CHARGING
                     || status == BatteryManager.BATTERY_STATUS_FULL) {
-                if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {
+                if (status == BatteryManager.BATTERY_STATUS_FULL
+                        || level >= mBatteryNearlyFullLevel) {
                     // Solid green when full or charging and nearly full
                     mBatteryLight.setColor(mBatteryFullARGB);
                 } else {
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index f93f504..eafd3e0 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -34,6 +34,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ApexStagedEvent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.Checksum;
 import android.content.pm.IBackgroundInstallControlService;
 import android.content.pm.IPackageManagerNative;
 import android.content.pm.IStagedApexObserver;
@@ -84,6 +85,7 @@
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.pm.ApexManager;
 import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackageSplit;
 import com.android.server.pm.pkg.PackageState;
 
 import libcore.util.HexEncoding;
@@ -96,7 +98,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executors;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
 /**
@@ -121,15 +122,6 @@
 
     static final long RECORD_MEASUREMENTS_COOLDOWN_MS = 24 * 60 * 60 * 1000;
 
-    @VisibleForTesting
-    static final String BUNDLE_PACKAGE_NAME = "package-name";
-    @VisibleForTesting
-    static final String BUNDLE_PACKAGE_IS_APEX = "package-is-apex";
-    @VisibleForTesting
-    static final String BUNDLE_CONTENT_DIGEST_ALGORITHM = "content-digest-algo";
-    @VisibleForTesting
-    static final String BUNDLE_CONTENT_DIGEST = "content-digest";
-
     static final String APEX_PRELOAD_LOCATION_ERROR = "could-not-be-determined";
 
     // used for indicating any type of error during MBA measurement
@@ -171,29 +163,6 @@
             return mVbmetaDigest;
         }
 
-        @Override
-        public List getApexInfo() {
-            List<Bundle> results = new ArrayList<>();
-
-            for (PackageInfo packageInfo : getCurrentInstalledApexs()) {
-                PackageState packageState = mPackageManagerInternal.getPackageStateInternal(
-                        packageInfo.packageName);
-                if (packageState == null) {
-                    Slog.w(TAG, "Package state is unavailable, ignoring the package "
-                            + packageInfo.packageName);
-                    continue;
-                }
-                Bundle apexMeasurement = measurePackage(packageState);
-                if (apexMeasurement == null) {
-                    Slog.w(TAG, "Skipping the missing APEX in " + packageState.getPath());
-                    continue;
-                }
-                results.add(apexMeasurement);
-            }
-
-            return results;
-        }
-
         /**
          * A helper function to compute the SHA256 digest of APK package signer.
          * @param signingInfo The signingInfo of a package, usually {@link PackageInfo#signingInfo}.
@@ -218,58 +187,102 @@
             return resultList.toArray(new String[1]);
         }
 
-        /**
-         * Perform basic measurement (i.e. content digest) on a given package.
+        /*
+         * Perform basic measurement (i.e. content digest) on a given app, including the split APKs.
+         *
          * @param packageState The package to be measured.
-         * @return a {@link android.os.Bundle} that packs the measurement result with the following
-         *         keys: {@link #BUNDLE_PACKAGE_NAME},
-         *               {@link #BUNDLE_PACKAGE_IS_APEX}
-         *               {@link #BUNDLE_CONTENT_DIGEST_ALGORITHM}
-         *               {@link #BUNDLE_CONTENT_DIGEST}
+         * @param mbaStatus Assign this value of MBA status to the returned elements.
+         * @return a @{@code List<IBinaryTransparencyService.AppInfo>}
          */
-        private @Nullable Bundle measurePackage(PackageState packageState) {
-            Bundle result = new Bundle();
-
+        private @NonNull List<IBinaryTransparencyService.AppInfo> collectAppInfo(
+                PackageState packageState, int mbaStatus) {
             // compute content digest
             if (DEBUG) {
                 Slog.d(TAG, "Computing content digest for " + packageState.getPackageName() + " at "
                         + packageState.getPath());
             }
+
+            var results = new ArrayList<IBinaryTransparencyService.AppInfo>();
+
+            // Same attributes across base and splits.
+            String packageName = packageState.getPackageName();
+            long versionCode = packageState.getVersionCode();
+            String[] signerDigests =
+                    computePackageSignerSha256Digests(packageState.getSigningInfo());
+
             AndroidPackage pkg = packageState.getAndroidPackage();
-            if (pkg == null) {
-                Slog.w(TAG, "Skipping the missing APK in " + packageState.getPath());
-                return null;
+            for (AndroidPackageSplit split : pkg.getSplits()) {
+                var appInfo = new IBinaryTransparencyService.AppInfo();
+                appInfo.packageName = packageName;
+                appInfo.longVersion = versionCode;
+                appInfo.splitName = split.getName();  // base's split name is null
+                // Signer digests are consistent between splits, guaranteed by Package Manager.
+                appInfo.signerDigests = signerDigests;
+                appInfo.mbaStatus = mbaStatus;
+
+                // Only digest and split name are different between splits.
+                Checksum checksum = measureApk(split.getPath());
+                appInfo.digest = checksum.getValue();
+                appInfo.digestAlgorithm = checksum.getType();
+
+                results.add(appInfo);
             }
-            Map<Integer, byte[]> contentDigests = computeApkContentDigest(pkg.getBaseApkPath());
-            result.putString(BUNDLE_PACKAGE_NAME, pkg.getPackageName());
+
+            // InstallSourceInfo is only available per package name, so store it only on the base
+            // APK. It's not current currently available in PackageState (there's a TODO), to we
+            // need to extract manually with another call.
+            //
+            // Base APK is already the 0-th split from getSplits() and can't be null.
+            AppInfo base = results.get(0);
+            InstallSourceInfo installSourceInfo = getInstallSourceInfo(
+                    packageState.getPackageName());
+            if (installSourceInfo != null) {
+                base.initiator = installSourceInfo.getInitiatingPackageName();
+                SigningInfo initiatorSignerInfo =
+                        installSourceInfo.getInitiatingPackageSigningInfo();
+                if (initiatorSignerInfo != null) {
+                    base.initiatorSignerDigests =
+                        computePackageSignerSha256Digests(initiatorSignerInfo);
+                }
+                base.installer = installSourceInfo.getInstallingPackageName();
+                base.originator = installSourceInfo.getOriginatingPackageName();
+            }
+
+            return results;
+        }
+
+        /**
+         * Perform basic measurement (i.e. content digest) on a given APK.
+         *
+         * @param apkPath The APK (or APEX, since it's also an APK) file to be measured.
+         * @return a {@link android.content.pm.Checksum} with preferred digest algorithm type and
+         *         the checksum.
+         */
+        private @Nullable Checksum measureApk(@NonNull String apkPath) {
+            // compute content digest
+            Map<Integer, byte[]> contentDigests = computeApkContentDigest(apkPath);
             if (contentDigests == null) {
-                Slog.d(TAG, "Failed to compute content digest for " + pkg.getBaseApkPath());
-                result.putInt(BUNDLE_CONTENT_DIGEST_ALGORITHM, 0);
-                result.putByteArray(BUNDLE_CONTENT_DIGEST, null);
-                return result;
+                Slog.d(TAG, "Failed to compute content digest for " + apkPath);
+                return new Checksum(0, new byte[] { -1 });
             }
 
             // in this iteration, we'll be supporting only 2 types of digests:
             // CHUNKED_SHA256 and CHUNKED_SHA512.
             // And only one of them will be available per package.
             if (contentDigests.containsKey(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256)) {
-                Integer algorithmId = ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256;
-                result.putInt(BUNDLE_CONTENT_DIGEST_ALGORITHM, algorithmId);
-                result.putByteArray(BUNDLE_CONTENT_DIGEST, contentDigests.get(algorithmId));
+                return new Checksum(
+                        Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
+                        contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256));
             } else if (contentDigests.containsKey(
                     ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512)) {
-                Integer algorithmId = ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512;
-                result.putInt(BUNDLE_CONTENT_DIGEST_ALGORITHM, algorithmId);
-                result.putByteArray(BUNDLE_CONTENT_DIGEST, contentDigests.get(algorithmId));
+                return new Checksum(
+                        Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512,
+                        contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512));
             } else {
                 // TODO(b/259423111): considering putting the raw values for the algorithm & digest
                 //  into the bundle to track potential other digest algorithms that may be in use
-                result.putInt(BUNDLE_CONTENT_DIGEST_ALGORITHM, 0);
-                result.putByteArray(BUNDLE_CONTENT_DIGEST, null);
+                return new Checksum(0, new byte[] { -1 });
             }
-            result.putBoolean(BUNDLE_PACKAGE_IS_APEX, packageState.isApex());
-
-            return result;
         }
 
 
@@ -287,7 +300,7 @@
          * - dynamically installed mobile bundled apps (MBAs) (new in Android U)
          */
         public void recordMeasurementsForAllPackages() {
-            // check if we should record the resulting measurements
+            // check if we should measure and record
             long currentTimeMs = System.currentTimeMillis();
             if ((currentTimeMs - mMeasurementsLastRecordedMs) < RECORD_MEASUREMENTS_COOLDOWN_MS) {
                 Slog.d(TAG, "Skip measurement since the last measurement was only taken at "
@@ -331,7 +344,7 @@
             if (CompatChanges.isChangeEnabled(LOG_MBA_INFO)) {
                 // lastly measure all newly installed MBAs
                 List<IBinaryTransparencyService.AppInfo> allMbaInfo =
-                        collectAllMbaInfo(packagesMeasured);
+                        collectAllSilentInstalledMbaInfo(packagesMeasured);
                 for (IBinaryTransparencyService.AppInfo appInfo : allUpdatedPreloadInfo) {
                     packagesMeasured.putBoolean(appInfo.packageName, true);
                     writeAppInfoToLog(appInfo);
@@ -357,18 +370,22 @@
                     continue;
                 }
 
-                Bundle apexMeasurement = measurePackage(packageState);
-                if (apexMeasurement == null) {
-                    Slog.w(TAG, "Skipping the missing APEX in " + packageState.getPath());
+                AndroidPackage pkg = packageState.getAndroidPackage();
+                if (pkg == null) {
+                    Slog.w(TAG, "Skipping the missing APK in " + pkg.getPath());
+                    continue;
+                }
+                Checksum apexChecksum = measureApk(pkg.getPath());
+                if (apexChecksum == null) {
+                    Slog.w(TAG, "Skipping the missing APEX in " + pkg.getPath());
                     continue;
                 }
 
                 var apexInfo = new IBinaryTransparencyService.ApexInfo();
                 apexInfo.packageName = packageState.getPackageName();
                 apexInfo.longVersion = packageState.getVersionCode();
-                apexInfo.digest = apexMeasurement.getByteArray(BUNDLE_CONTENT_DIGEST);
-                apexInfo.digestAlgorithm =
-                        apexMeasurement.getInt(BUNDLE_CONTENT_DIGEST_ALGORITHM);
+                apexInfo.digest = apexChecksum.getValue();
+                apexInfo.digestAlgorithm = apexChecksum.getType();
                 apexInfo.signerDigests =
                         computePackageSignerSha256Digests(packageState.getSigningInfo());
 
@@ -399,28 +416,16 @@
                 Slog.d(TAG, "Preload " + packageState.getPackageName() + " at "
                         + packageState.getPath() + " has likely been updated.");
 
-                Bundle packageMeasurement = measurePackage(packageState);
-                if (packageMeasurement == null) {
-                    Slog.w(TAG, "Skipping the missing APK in " + packageState.getPath());
-                    return;
-                }
-
-                var appInfo = new IBinaryTransparencyService.AppInfo();
-                appInfo.packageName = packageState.getPackageName();
-                appInfo.longVersion = packageState.getVersionCode();
-                appInfo.digest = packageMeasurement.getByteArray(BUNDLE_CONTENT_DIGEST);
-                appInfo.digestAlgorithm =
-                        packageMeasurement.getInt(BUNDLE_CONTENT_DIGEST_ALGORITHM);
-                appInfo.signerDigests =
-                        computePackageSignerSha256Digests(packageState.getSigningInfo());
-                appInfo.mbaStatus = MBA_STATUS_UPDATED_PRELOAD;
-
-                results.add(appInfo);
+                List<IBinaryTransparencyService.AppInfo> resultsForApp = collectAppInfo(
+                        packageState, MBA_STATUS_UPDATED_PRELOAD);
+                results.addAll(resultsForApp);
             });
             return results;
         }
 
-        public List<IBinaryTransparencyService.AppInfo> collectAllMbaInfo(Bundle packagesToSkip) {
+        @Override
+        public List<IBinaryTransparencyService.AppInfo> collectAllSilentInstalledMbaInfo(
+                Bundle packagesToSkip) {
             var results = new ArrayList<IBinaryTransparencyService.AppInfo>();
             for (PackageInfo packageInfo : getNewlyInstalledMbas()) {
                 if (packagesToSkip.containsKey(packageInfo.packageName)) {
@@ -434,42 +439,9 @@
                     continue;
                 }
 
-                Bundle packageMeasurement = measurePackage(packageState);
-                if (packageMeasurement == null) {
-                    Slog.w(TAG, "Skipping the missing APK in " + packageState.getPath());
-                    continue;
-                }
-                if (DEBUG) {
-                    Slog.d(TAG,
-                            "Extracting InstallSourceInfo for " + packageState.getPackageName());
-                }
-                var appInfo = new IBinaryTransparencyService.AppInfo();
-                appInfo.packageName = packageState.getPackageName();
-                appInfo.longVersion = packageState.getVersionCode();
-                appInfo.digest = packageMeasurement.getByteArray(BUNDLE_CONTENT_DIGEST);
-                appInfo.digestAlgorithm =
-                    packageMeasurement.getInt(BUNDLE_CONTENT_DIGEST_ALGORITHM);
-                appInfo.signerDigests =
-                        computePackageSignerSha256Digests(packageState.getSigningInfo());
-                appInfo.mbaStatus = MBA_STATUS_NEW_INSTALL;
-
-                // Install source isn't currently available in PackageState (there's a TODO).
-                // Extract manually with another call.
-                InstallSourceInfo installSourceInfo = getInstallSourceInfo(
-                        packageState.getPackageName());
-                if (installSourceInfo != null) {
-                    appInfo.initiator = installSourceInfo.getInitiatingPackageName();
-                    SigningInfo initiatorSignerInfo =
-                            installSourceInfo.getInitiatingPackageSigningInfo();
-                    if (initiatorSignerInfo != null) {
-                        appInfo.initiatorSignerDigests =
-                                computePackageSignerSha256Digests(initiatorSignerInfo);
-                    }
-                    appInfo.installer = installSourceInfo.getInstallingPackageName();
-                    appInfo.originator = installSourceInfo.getOriginatingPackageName();
-                }
-
-                results.add(appInfo);
+                List<IBinaryTransparencyService.AppInfo> resultsForApp = collectAppInfo(
+                        packageState, MBA_STATUS_NEW_INSTALL);
+                results.addAll(resultsForApp);
             }
             return results;
         }
@@ -612,7 +584,7 @@
                             + packageInfo.applicationInfo.sourceDir);
                     if (packageInfo.applicationInfo.sourceDir.startsWith("/data/apex/")) {
                         String origPackageFilepath = getOriginalApexPreinstalledLocation(
-                                packageInfo.packageName, packageInfo.applicationInfo.sourceDir);
+                                packageInfo.packageName);
                         pw.println("|--> Pre-installed package install location: "
                                 + origPackageFilepath);
 
@@ -1230,10 +1202,8 @@
      * JobService to measure all covered binaries and record result to Westworld.
      */
     public static class UpdateMeasurementsJobService extends JobService {
-        private static AtomicBoolean sScheduled = new AtomicBoolean();
         private static long sTimeLastRanMs = 0;
-        private static final int DO_BINARY_MEASUREMENTS_JOB_ID =
-                UpdateMeasurementsJobService.class.hashCode();
+        private static final int DO_BINARY_MEASUREMENTS_JOB_ID = 1740526926;
 
         @Override
         public boolean onStartJob(JobParameters params) {
@@ -1256,7 +1226,6 @@
                     return;
                 }
                 sTimeLastRanMs = System.currentTimeMillis();
-                sScheduled.set(false);
                 jobFinished(params, false);
             }).start();
 
@@ -1277,7 +1246,7 @@
                 return;
             }
 
-            if (sScheduled.get()) {
+            if (jobScheduler.getPendingJob(DO_BINARY_MEASUREMENTS_JOB_ID) != null) {
                 Slog.d(TAG, "A measurement job has already been scheduled.");
                 return;
             }
@@ -1303,7 +1272,6 @@
                 Slog.e(TAG, "Failed to schedule job to measure binaries.");
                 return;
             }
-            sScheduled.set(true);
             Slog.d(TAG, TextUtils.formatSimple(
                     "Job %d to measure binaries was scheduled successfully.",
                     DO_BINARY_MEASUREMENTS_JOB_ID));
@@ -1660,8 +1628,7 @@
     }
 
     @NonNull
-    private String getOriginalApexPreinstalledLocation(String packageName,
-            String currentInstalledLocation) {
+    private String getOriginalApexPreinstalledLocation(String packageName) {
         try {
             final String moduleName = apexPackageNameToModuleName(packageName);
             IApexService apexService = IApexService.Stub.asInterface(
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index f149fda..742c94a 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -46,6 +46,7 @@
 
 import com.android.internal.telephony.IMms;
 import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.server.uri.NeededUriGrants;
 import com.android.server.uri.UriGrantsManagerInternal;
 
@@ -342,8 +343,11 @@
             // Check if user is associated with the subscription
             if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(mContext, subId,
                     Binder.getCallingUserHandle())) {
-                // TODO(b/258629881): Display error dialog.
-		return;
+                if (TelephonyUtils.isUidForeground(mContext, Binder.getCallingUid())) {
+                    TelephonyUtils.showErrorIfSubscriptionAssociatedWithManagedProfile(mContext,
+                            subId);
+                }
+                return;
             }
 
             if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 5eb0db1..6fd6afe 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -182,7 +182,6 @@
     public void onStart() {
         // Do init on a separate thread, will join in PHASE_ACTIVITY_MANAGER_READY
         SystemServerInitThreadPool.submit(() -> {
-            mAllowedUid = getAllowedUid();
             enforceChecksumValidity();
             formatIfOemUnlockEnabled();
             publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService);
@@ -202,6 +201,8 @@
                 Thread.currentThread().interrupt();
                 throw new IllegalStateException("Service " + TAG + " init interrupted", e);
             }
+            // The user responsible for FRP should exist by now.
+            mAllowedUid = getAllowedUid();
             LocalServices.addService(PersistentDataBlockManagerInternal.class, mInternalService);
         }
         super.onBootPhase(phase);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 6435869..0252492 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3380,8 +3380,9 @@
                     appInfo.manageSpaceActivityName);
             intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
 
-            final ActivityOptions options = ActivityOptions.makeBasic();
-            options.setIgnorePendingIntentCreatorForegroundState(true);
+            final ActivityOptions options = ActivityOptions.makeBasic()
+                    .setPendingIntentCreatorBackgroundActivityStartMode(
+                            ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED);
 
             PendingIntent activity = PendingIntent.getActivity(targetAppContext, requestCode,
                     intent,
@@ -3747,8 +3748,12 @@
                     // Return both read only and write only volumes. When includeSharedProfile is
                     // true, all the volumes of userIdSharingMedia should be returned when queried
                     // from the user it shares media with
+                    // Public Volumes will be also be returned if visible to the
+                    // userIdSharingMedia with.
                     match = vol.isVisibleForUser(userId)
                             || (!vol.isVisible() && includeInvisible && vol.getPath() != null)
+                            || (vol.getType() == VolumeInfo.TYPE_PUBLIC
+                                    && vol.isVisibleForUser(userIdSharingMedia))
                             || (includeSharedProfile && vol.isVisibleForUser(userIdSharingMedia));
                 }
                 if (!match) continue;
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 4854c37..4b76127 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -333,6 +333,11 @@
     // Update ownership for system applications and the installers eligible to update them.
     private final ArrayMap<String, String> mUpdateOwnersForSystemApps = new ArrayMap<>();
 
+    // Set of package names that should not be marked as "stopped" during initial device boot
+    // or when adding a new user. A new package not contained in this set will be
+    // marked as stopped by the system
+    @NonNull private final Set<String> mInitialNonStoppedSystemPackages = new ArraySet<>();
+
     /**
      * Map of system pre-defined, uniquely named actors; keys are namespace,
      * value maps actor name to package name.
@@ -527,6 +532,10 @@
                 ? null : mOverlayConfigSignaturePackage;
     }
 
+    public Set<String> getInitialNonStoppedSystemPackages() {
+        return mInitialNonStoppedSystemPackages;
+    }
+
     /**
      * Only use for testing. Do NOT use in production code.
      * @param readPermissions false to create an empty SystemConfig; true to read the permissions.
@@ -1445,6 +1454,19 @@
                         }
                         XmlUtils.skipCurrentTag(parser);
                     } break;
+                    case "initial-package-state": {
+                        String pkgName = parser.getAttributeValue(null, "package");
+                        String stopped = parser.getAttributeValue(null, "stopped");
+                        if (TextUtils.isEmpty(pkgName)) {
+                            Slog.w(TAG, "<" + name + "> without package in " + permFile
+                                    + " at " + parser.getPositionDescription());
+                        } else if (TextUtils.isEmpty(stopped)) {
+                            Slog.w(TAG, "<" + name + "> without stopped in " + permFile
+                                    + " at " + parser.getPositionDescription());
+                        } else if (!Boolean.parseBoolean(stopped)) {
+                            mInitialNonStoppedSystemPackages.add(pkgName);
+                        }
+                    }
                     default: {
                         Slog.w(TAG, "Tag " + name + " is unknown in "
                                 + permFile + " at " + parser.getPositionDescription());
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index ae65dcb..c5b0f05 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -39,6 +39,26 @@
                 }
             ],
             "file_patterns": ["BinaryTransparencyService\\.java"]
+        },
+        {
+            "name": "BinaryTransparencyHostTest",
+            "file_patterns": [
+                "BinaryTransparencyService\\.java"
+            ]
+        },
+        {
+            "name": "CtsMediaProjectionTestCases",
+            "options": [
+                {
+                    "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+                },
+                {
+                    "exclude-annotation": "androidx.test.filters.FlakyTest"
+                },
+                {
+                    "exclude-annotation": "org.junit.Ignore"
+                }
+            ]
         }
     ],
     "presubmit-large": [
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index f0b168d..56d0b59 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -20,6 +20,9 @@
 import static android.Manifest.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND;
 import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
 import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL;
+import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
 import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
@@ -175,6 +178,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.service.voice.HotwordDetectionService;
+import android.service.voice.VisualQueryDetectionService;
 import android.stats.devicepolicy.DevicePolicyEnums;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -3808,6 +3813,17 @@
                 inSharedIsolatedProcess);
     }
 
+    // TODO(b/265746493): Special case for HotwordDetectionService and
+    // VisualQueryDetectionService. Need a cleaner way to append this seInfo.
+    private String generateAdditionalSeInfoFromService(Intent service) {
+        if (service != null && service.getAction() != null
+                && (service.getAction().equals(HotwordDetectionService.SERVICE_INTERFACE)
+                || service.getAction().equals(VisualQueryDetectionService.SERVICE_INTERFACE))) {
+            return ":isolatedComputeApp";
+        }
+        return "";
+    }
+
     private ServiceLookupResult retrieveServiceLocked(Intent service,
             String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
             String sdkSandboxClientAppPackage, String resolvedType,
@@ -3925,6 +3941,7 @@
                 r.mRecentCallingPackage = callingPackage;
                 r.mRecentCallingUid = callingUid;
             }
+            r.appInfo.seInfo += generateAdditionalSeInfoFromService(service);
             return new ServiceLookupResult(r, resolution.getAlias());
         }
 
@@ -4150,6 +4167,7 @@
                     return null;
                 }
             }
+            r.appInfo.seInfo += generateAdditionalSeInfoFromService(service);
             return new ServiceLookupResult(r, resolution.getAlias());
         }
         return null;
@@ -7380,6 +7398,12 @@
         int ret = shouldAllowFgsStartForegroundNoBindingCheckLocked(allowWhileInUse, callingPid,
                 callingUid, callingPackage, r, backgroundStartPrivileges);
 
+        // If an app (App 1) is bound by another app (App 2) that could start an FGS, then App 1
+        // is also allowed to start an FGS. We check all the binding
+        // in canBindingClientStartFgsLocked() to do this check.
+        // (Note we won't check more than 1 level of binding.)
+        // [bookmark: 61867f60-007c-408c-a2c4-e19e96056135] -- this code is referred to from
+        // OomAdjuster.
         String bindFromPackage = null;
         if (ret == REASON_DENIED) {
             bindFromPackage = canBindingClientStartFgsLocked(callingUid);
@@ -7395,10 +7419,13 @@
                     .getTargetSdkVersion(callingPackage);
         } catch (PackageManager.NameNotFoundException ignored) {
         }
+        final boolean uidBfsl = (mAm.getUidProcessCapabilityLocked(callingUid)
+                & PROCESS_CAPABILITY_BFSL) != 0;
         final String debugInfo =
                 "[callingPackage: " + callingPackage
                         + "; callingUid: " + callingUid
                         + "; uidState: " + ProcessList.makeProcStateString(uidState)
+                        + "; uidBFSL: " + (uidBfsl ? "[BFSL]" : "n/a")
                         + "; intent: " + intent
                         + "; code:" + reasonCodeToString(ret)
                         + "; tempAllowListReason:<"
@@ -7437,11 +7464,15 @@
         }
 
         if (ret == REASON_DENIED) {
+            final boolean uidBfsl =
+                    (mAm.getUidProcessCapabilityLocked(callingUid) & PROCESS_CAPABILITY_BFSL) != 0;
             final Integer allowedType = mAm.mProcessList.searchEachLruProcessesLOSP(false, app -> {
                 if (app.uid == callingUid) {
                     final ProcessStateRecord state = app.mState;
-                    if (state.isAllowedStartFgs()) { // Procstate <= BFGS?
-                        return getReasonCodeFromProcState(state.getCurProcState());
+                    final int procstate = state.getCurProcState();
+                    if ((procstate <= PROCESS_STATE_BOUND_TOP)
+                            || (uidBfsl && (procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE))) {
+                        return getReasonCodeFromProcState(procstate);
                     } else {
                         final ActiveInstrumentation instr = app.getActiveInstrumentation();
                         if (instr != null
@@ -7669,6 +7700,8 @@
         }
         final int callerTargetSdkVersion = r.mRecentCallerApplicationInfo != null
                 ? r.mRecentCallerApplicationInfo.targetSdkVersion : 0;
+
+        // TODO(short-service): Log BFSL too.
         FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                 r.appInfo.uid,
                 r.shortInstanceName,
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index ef79351..e1d1f6c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -770,10 +770,6 @@
     // initialized in the constructor.
     public int CUR_MAX_EMPTY_PROCESSES;
 
-    /** @see mEnforceReceiverExportedFlagRequirement */
-    private static final String KEY_ENFORCE_RECEIVER_EXPORTED_FLAG_REQUIREMENT =
-            "enforce_exported_flag_requirement";
-
     /** @see #mNoKillCachedProcessesUntilBootCompleted */
     private static final String KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED =
             "no_kill_cached_processes_until_boot_completed";
@@ -782,9 +778,6 @@
     private static final String KEY_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS =
             "no_kill_cached_processes_post_boot_completed_duration_millis";
 
-    /** @see mEnforceReceiverExportedFlagRequirement */
-    private static final boolean DEFAULT_ENFORCE_RECEIVER_EXPORTED_FLAG_REQUIREMENT = true;
-
     /** @see #mNoKillCachedProcessesUntilBootCompleted */
     private static final boolean DEFAULT_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED = true;
 
@@ -793,15 +786,6 @@
             DEFAULT_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS = 600_000;
 
     /**
-     * If true, enforce the requirement that dynamically registered receivers specify one of
-     * {@link android.content.Context#RECEIVER_EXPORTED} or
-     * {@link android.content.Context#RECEIVER_NOT_EXPORTED} if registering for any non-system
-     * broadcasts.
-     */
-    volatile boolean mEnforceReceiverExportedFlagRequirement =
-            DEFAULT_ENFORCE_RECEIVER_EXPORTED_FLAG_REQUIREMENT;
-
-    /**
      * If true, do not kill excessive cached processes proactively, until user-0 is unlocked.
      * @see #mNoKillCachedProcessesPostBootCompletedDurationMillis
      */
@@ -971,6 +955,20 @@
             DEFAULT_SHORT_FGS_PROC_STATE_EXTRA_WAIT_DURATION;
 
     /**
+     * If enabled, when starting an application, the system will wait for a
+     * {@link ActivityManagerService#finishAttachApplication} from the app before scheduling
+     * Broadcasts or Services to it.
+     */
+    private static final String KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION =
+            "enable_wait_for_finish_attach_application";
+
+    private static final boolean DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION = true;
+
+    /** @see #KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION */
+    public volatile boolean mEnableWaitForFinishAttachApplication =
+            DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION;
+
+    /**
      * If a "short service" doesn't finish within this after the timeout (
      * {@link #KEY_SHORT_FGS_TIMEOUT_DURATION}), then we'll declare an ANR.
      * i.e. if the timeout is 60 seconds, and this ANR extra duration is 5 seconds, then
@@ -1112,9 +1110,6 @@
                             case KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED:
                                 updateNoKillCachedProcessesUntilBootCompleted();
                                 break;
-                            case KEY_ENFORCE_RECEIVER_EXPORTED_FLAG_REQUIREMENT:
-                                updateEnforceReceiverExportedFlagRequirement();
-                                break;
                             case KEY_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS:
                                 updateNoKillCachedProcessesPostBootCompletedDurationMillis();
                                 break;
@@ -1144,6 +1139,10 @@
                                 break;
                             case KEY_TOP_TO_FGS_GRACE_DURATION:
                                 updateTopToFgsGraceDuration();
+                                break;
+                            case KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION:
+                                updateEnableWaitForFinishAttachApplication();
+                                break;
                             default:
                                 break;
                         }
@@ -1616,13 +1615,6 @@
                 DEFAULT_DEFER_BOOT_COMPLETED_BROADCAST);
     }
 
-    private void updateEnforceReceiverExportedFlagRequirement() {
-        mEnforceReceiverExportedFlagRequirement = DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
-                KEY_ENFORCE_RECEIVER_EXPORTED_FLAG_REQUIREMENT,
-                DEFAULT_ENFORCE_RECEIVER_EXPORTED_FLAG_REQUIREMENT);
-    }
-
     private void updateNoKillCachedProcessesUntilBootCompleted() {
         mNoKillCachedProcessesUntilBootCompleted = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -1866,6 +1858,13 @@
                 DEFAULT_SHORT_FGS_ANR_EXTRA_WAIT_DURATION);
     }
 
+    private void updateEnableWaitForFinishAttachApplication() {
+        mEnableWaitForFinishAttachApplication = DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION,
+                DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION);
+    }
+
     @NeverCompile // Avoid size overhead of debugging code.
     void dump(PrintWriter pw) {
         pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
@@ -2002,8 +2001,6 @@
         pw.print("="); pw.println(mPrioritizeAlarmBroadcasts);
         pw.print("  "); pw.print(KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED);
         pw.print("="); pw.println(mNoKillCachedProcessesUntilBootCompleted);
-        pw.print("  "); pw.print(KEY_ENFORCE_RECEIVER_EXPORTED_FLAG_REQUIREMENT);
-        pw.print("="); pw.println(mEnforceReceiverExportedFlagRequirement);
         pw.print("  "); pw.print(KEY_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS);
         pw.print("="); pw.println(mNoKillCachedProcessesPostBootCompletedDurationMillis);
         pw.print("  "); pw.print(KEY_MAX_EMPTY_TIME_MILLIS);
@@ -2055,5 +2052,7 @@
         pw.print("  CUR_TRIM_EMPTY_PROCESSES="); pw.println(CUR_TRIM_EMPTY_PROCESSES);
         pw.print("  CUR_TRIM_CACHED_PROCESSES="); pw.println(CUR_TRIM_CACHED_PROCESSES);
         pw.print("  OOMADJ_UPDATE_QUICK="); pw.println(OOMADJ_UPDATE_QUICK);
+        pw.print("  ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION=");
+        pw.println(mEnableWaitForFinishAttachApplication);
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 57a89e3..c759af5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -87,6 +87,7 @@
 import static android.os.Process.getTotalMemory;
 import static android.os.Process.isThreadInProcess;
 import static android.os.Process.killProcess;
+import static android.os.Process.killProcessGroup;
 import static android.os.Process.killProcessQuiet;
 import static android.os.Process.myPid;
 import static android.os.Process.myUid;
@@ -969,13 +970,6 @@
             }
             return false;
         }
-
-        boolean doRemoveIfNoThreadInternal(int pid, ProcessRecord app) {
-            if (app == null || app.getThread() != null) {
-                return false;
-            }
-            return doRemoveInternal(pid, app);
-        }
     }
 
     private final PendingStartActivityUids mPendingStartActivityUids;
@@ -1007,7 +1001,7 @@
      * method.
      */
     @GuardedBy("this")
-    void removePidLocked(int pid, ProcessRecord app) {
+    boolean removePidLocked(int pid, ProcessRecord app) {
         final boolean removed;
         synchronized (mPidsSelfLocked) {
             removed = mPidsSelfLocked.doRemoveInternal(pid, app);
@@ -1018,26 +1012,6 @@
             }
             mAtmInternal.onProcessUnMapped(pid);
         }
-    }
-
-    /**
-     * Removes the process record from the map if it doesn't have a thread.
-     * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
-     * method.
-     */
-    @GuardedBy("this")
-    private boolean removePidIfNoThreadLocked(ProcessRecord app) {
-        final boolean removed;
-        final int pid = app.getPid();
-        synchronized (mPidsSelfLocked) {
-            removed = mPidsSelfLocked.doRemoveIfNoThreadInternal(pid, app);
-        }
-        if (removed) {
-            synchronized (sActiveProcessInfoSelfLocked) {
-                sActiveProcessInfoSelfLocked.remove(pid);
-            }
-            mAtmInternal.onProcessUnMapped(pid);
-        }
         return removed;
     }
 
@@ -1820,11 +1794,13 @@
                 synchronized (ActivityManagerService.this) {
                     final int appId = msg.arg1;
                     final int userId = msg.arg2;
-                    Bundle bundle = (Bundle) msg.obj;
-                    String pkg = bundle.getString("pkg");
-                    String reason = bundle.getString("reason");
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    String pkg = (String) args.arg1;
+                    String reason = (String) args.arg2;
+                    int exitInfoReason = (int) args.arg3;
+                    args.recycle();
                     forceStopPackageLocked(pkg, appId, false, false, true, false,
-                            false, userId, reason);
+                            false, userId, reason, exitInfoReason);
                 }
             } break;
 
@@ -2339,7 +2315,7 @@
         mAppErrors = null;
         mPackageWatchdog = null;
         mAppOpsService = mInjector.getAppOpsService(null /* file */, null /* handler */);
-        mBatteryStatsService = null;
+        mBatteryStatsService = mInjector.getBatteryStatsService();
         mHandler = new MainHandler(handlerThread.getLooper());
         mHandlerThread = handlerThread;
         mConstants = new ActivityManagerConstants(mContext, this, mHandler);
@@ -2354,7 +2330,7 @@
         mIntentFirewall = null;
         mProcessStats = new ProcessStatsService(this, mContext.getCacheDir());
         mCpHelper = new ContentProviderHelper(this, false);
-        mServices = null;
+        mServices = mInjector.getActiveServices(this);
         mSystemThread = null;
         mUiHandler = injector.getUiHandler(null /* service */);
         mUidObserverController = new UidObserverController(mUiHandler);
@@ -3301,8 +3277,7 @@
         ProcessRecord record = mProcessList.getLRURecordForAppLOSP(threadBinder);
         if (record != null) return record;
 
-        // Validation: if it isn't in the LRU list, it shouldn't exist, but let's
-        // double-check that.
+        // Validation: if it isn't in the LRU list, it shouldn't exist, but let's double-check that.
         final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
                 mProcessList.getProcessNamesLOSP().getMap();
         for (int i = pmap.size()-1; i >= 0; i--) {
@@ -3311,8 +3286,10 @@
                 final ProcessRecord proc = procs.valueAt(j);
                 final IApplicationThread procThread = proc.getThread();
                 if (procThread != null && procThread.asBinder() == threadBinder) {
-                    Slog.wtf(TAG, "getRecordForApp: exists in name list but not in LRU list: "
-                            + proc);
+                    if (!proc.isPendingFinishAttach()) {
+                        Slog.wtf(TAG, "getRecordForApp: exists in name list but not in LRU list: "
+                                + proc);
+                    }
                     return proc;
                 }
             }
@@ -4236,7 +4213,8 @@
      * The pkg name and app id have to be specified.
      */
     @Override
-    public void killApplication(String pkg, int appId, int userId, String reason) {
+    public void killApplication(String pkg, int appId, int userId, String reason,
+            int exitInfoReason) {
         if (pkg == null) {
             return;
         }
@@ -4252,10 +4230,11 @@
             Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
             msg.arg1 = appId;
             msg.arg2 = userId;
-            Bundle bundle = new Bundle();
-            bundle.putString("pkg", pkg);
-            bundle.putString("reason", reason);
-            msg.obj = bundle;
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = pkg;
+            args.arg2 = reason;
+            args.arg3 = exitInfoReason;
+            msg.obj = args;
             mHandler.sendMessage(msg);
         } else {
             throw new SecurityException(callerUid + " cannot kill pkg: " +
@@ -4645,7 +4624,20 @@
     @GuardedBy("this")
     final boolean forceStopPackageLocked(String packageName, int appId,
             boolean callerWillRestart, boolean purgeCache, boolean doit,
-            boolean evenPersistent, boolean uninstalling, int userId, String reason) {
+            boolean evenPersistent, boolean uninstalling, int userId, String reasonString) {
+
+        int reason = packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
+                : ApplicationExitInfo.REASON_USER_REQUESTED;
+        return forceStopPackageLocked(packageName, appId, callerWillRestart, purgeCache, doit,
+                evenPersistent, uninstalling, userId, reasonString, reason);
+
+    }
+
+    @GuardedBy("this")
+    final boolean forceStopPackageLocked(String packageName, int appId,
+            boolean callerWillRestart, boolean purgeCache, boolean doit,
+            boolean evenPersistent, boolean uninstalling, int userId, String reasonString,
+            int reason) {
         int i;
 
         if (userId == UserHandle.USER_ALL && packageName == null) {
@@ -4661,9 +4653,9 @@
         if (doit) {
             if (packageName != null) {
                 Slog.i(TAG, "Force stopping " + packageName + " appid=" + appId
-                        + " user=" + userId + ": " + reason);
+                        + " user=" + userId + ": " + reasonString);
             } else {
-                Slog.i(TAG, "Force stopping u" + userId + ": " + reason);
+                Slog.i(TAG, "Force stopping u" + userId + ": " + reasonString);
             }
 
             mAppErrors.resetProcessCrashTime(packageName == null, appId, userId);
@@ -4675,15 +4667,20 @@
             // becomes visible when killing its other processes with visible activities.
             didSomething = mAtmInternal.onForceStopPackage(
                     packageName, doit, evenPersistent, userId);
+            int subReason;
+            if (reason == ApplicationExitInfo.REASON_USER_REQUESTED) {
+                subReason = ApplicationExitInfo.SUBREASON_FORCE_STOP;
+            } else {
+                subReason = ApplicationExitInfo.SUBREASON_UNKNOWN;
+            }
 
             didSomething |= mProcessList.killPackageProcessesLSP(packageName, appId, userId,
                     ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit,
                     evenPersistent, true /* setRemoved */, uninstalling,
-                    packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
-                    : ApplicationExitInfo.REASON_USER_REQUESTED,
-                    ApplicationExitInfo.SUBREASON_FORCE_STOP,
+                    reason,
+                    subReason,
                     (packageName == null ? ("stop user " + userId) : ("stop " + packageName))
-                    + " due to " + reason);
+                    + " due to " + reasonString);
         }
 
         if (mServices.bringDownDisabledPackageServicesLocked(
@@ -4744,7 +4741,7 @@
     @GuardedBy("this")
     void handleProcessStartOrKillTimeoutLocked(ProcessRecord app, boolean isKillTimeout) {
         final int pid = app.getPid();
-        boolean gone = isKillTimeout || removePidIfNoThreadLocked(app);
+        boolean gone = isKillTimeout || removePidLocked(pid, app);
 
         if (gone) {
             if (isKillTimeout) {
@@ -4825,7 +4822,7 @@
     }
 
     @GuardedBy("this")
-    private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
+    private void attachApplicationLocked(@NonNull IApplicationThread thread,
             int pid, int callingUid, long startSeq) {
 
         // Find the application record that is being attached...  either via
@@ -4890,7 +4887,7 @@
                     // Ignore exceptions.
                 }
             }
-            return false;
+            return;
         }
 
         // If this application record is still attached to a previous
@@ -4915,7 +4912,7 @@
             mProcessList.startProcessLocked(app,
                     new HostingRecord(HostingRecord.HOSTING_TYPE_LINK_FAIL, processName),
                     ZYGOTE_POLICY_FLAG_EMPTY);
-            return false;
+            return;
         }
 
         EventLogTags.writeAmProcBound(app.userId, pid, app.processName);
@@ -4938,8 +4935,6 @@
             app.setUnlocked(StorageManager.isUserKeyUnlocked(app.userId));
         }
 
-        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
-
         boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
         List<ProviderInfo> providers = normalMode
                                             ? mCpHelper.generateApplicationProvidersLocked(app)
@@ -5090,6 +5085,8 @@
                 profilerInfo = null;
             }
 
+            app.setBindApplicationTime(bindApplicationTimeMillis);
+
             // Make app active after binding application or client may be running requests (e.g
             // starting activities) before it is ready.
             synchronized (mProcLock) {
@@ -5103,6 +5100,19 @@
                 app.mProfile.setLastRequestedGc(now);
                 app.mProfile.setLastLowMemory(now);
             }
+
+            // Remove this record from the list of starting applications.
+            mPersistentStartingProcesses.remove(app);
+            if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) {
+                Slog.v(TAG_PROCESSES, "Attach application locked removing on hold: " + app);
+            }
+            mProcessesOnHold.remove(app);
+
+            if (!mConstants.mEnableWaitForFinishAttachApplication) {
+                finishAttachApplicationInner(startSeq, callingUid, pid);
+            } else {
+                app.setPendingFinishAttach(true);
+            }
         } catch (Exception e) {
             // We need kill the process group here. (b/148588589)
             Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
@@ -5111,99 +5121,8 @@
             app.killLocked("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
                     true);
             handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);
-            return false;
+            return;
         }
-
-        // Remove this record from the list of starting applications.
-        mPersistentStartingProcesses.remove(app);
-        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
-                "Attach application locked removing on hold: " + app);
-        mProcessesOnHold.remove(app);
-
-        boolean badApp = false;
-        boolean didSomething = false;
-
-        // See if the top visible activity is waiting to run in this process...
-        if (normalMode) {
-            try {
-                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
-            } catch (Exception e) {
-                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
-                badApp = true;
-            }
-        }
-
-        // Find any services that should be running in this process...
-        if (!badApp) {
-            try {
-                didSomething |= mServices.attachApplicationLocked(app, processName);
-                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
-            } catch (Exception e) {
-                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
-                badApp = true;
-            }
-        }
-
-        // Check if a next-broadcast receiver is in this process...
-        if (!badApp) {
-            try {
-                for (BroadcastQueue queue : mBroadcastQueues) {
-                    didSomething |= queue.onApplicationAttachedLocked(app);
-                }
-                checkTime(startTime, "attachApplicationLocked: after dispatching broadcasts");
-            } catch (Exception e) {
-                // If the app died trying to launch the receiver we declare it 'bad'
-                Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
-                badApp = true;
-            }
-        }
-
-        // Check whether the next backup agent is in this process...
-        if (!badApp && backupTarget != null && backupTarget.app == app) {
-            if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
-                    "New app is backup target, launching agent for " + app);
-            notifyPackageUse(backupTarget.appInfo.packageName,
-                             PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
-            try {
-                thread.scheduleCreateBackupAgent(backupTarget.appInfo,
-                        backupTarget.backupMode, backupTarget.userId,
-                        backupTarget.backupDestination);
-            } catch (Exception e) {
-                Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
-                badApp = true;
-            }
-        }
-
-        if (badApp) {
-            app.killLocked("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
-                    true);
-            handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);
-            return false;
-        }
-
-        if (!didSomething) {
-            updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
-            checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
-        }
-
-
-        final HostingRecord hostingRecord = app.getHostingRecord();
-        String shortAction = getShortAction(hostingRecord.getAction());
-        FrameworkStatsLog.write(
-                FrameworkStatsLog.PROCESS_START_TIME,
-                app.info.uid,
-                pid,
-                app.info.packageName,
-                FrameworkStatsLog.PROCESS_START_TIME__TYPE__COLD,
-                app.getStartElapsedTime(),
-                (int) (bindApplicationTimeMillis - app.getStartUptime()),
-                (int) (SystemClock.uptimeMillis() - app.getStartUptime()),
-                hostingRecord.getType(),
-                hostingRecord.getName(),
-                shortAction,
-                HostingRecord.getHostingTypeIdStatsd(hostingRecord.getType()),
-                HostingRecord.getTriggerTypeForStatsd(hostingRecord.getTriggerType()));
-        return true;
     }
 
     @Override
@@ -5220,6 +5139,154 @@
         }
     }
 
+    private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
+        final long startTime = SystemClock.uptimeMillis();
+        // Find the application record that is being attached...  either via
+        // the pid if we are running in multiple processes, or just pull the
+        // next app record if we are emulating process with anonymous threads.
+        final ProcessRecord app;
+        synchronized (mPidsSelfLocked) {
+            app = mPidsSelfLocked.get(pid);
+        }
+
+        if (app != null && app.getStartUid() == uid && app.getStartSeq() == startSeq) {
+            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+        } else {
+            Slog.wtf(TAG, "Mismatched or missing ProcessRecord: " + app + ". Pid: " + pid
+                    + ". Uid: " + uid);
+            killProcess(pid);
+            killProcessGroup(uid, pid);
+            mProcessList.noteAppKill(pid, uid,
+                    ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
+                    ApplicationExitInfo.SUBREASON_UNKNOWN,
+                    "wrong startSeq");
+            synchronized (this) {
+                app.killLocked("unexpected process record",
+                        ApplicationExitInfo.REASON_OTHER, true);
+            }
+            return;
+        }
+
+        synchronized (this) {
+            // Mark the finish attach application phase as completed
+            app.setPendingFinishAttach(false);
+
+            final boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
+            final String processName = app.processName;
+            boolean badApp = false;
+            boolean didSomething = false;
+
+            // See if the top visible activity is waiting to run in this process...
+            if (normalMode) {
+                try {
+                    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
+                } catch (Exception e) {
+                    Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
+                    badApp = true;
+                }
+            }
+
+            // Find any services that should be running in this process...
+            if (!badApp) {
+                try {
+                    didSomething |= mServices.attachApplicationLocked(app, processName);
+                    checkTime(startTime, "finishAttachApplicationInner: "
+                            + "after mServices.attachApplicationLocked");
+                } catch (Exception e) {
+                    Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
+                    badApp = true;
+                }
+            }
+
+            // Check if a next-broadcast receiver is in this process...
+            if (!badApp) {
+                try {
+                    for (BroadcastQueue queue : mBroadcastQueues) {
+                        didSomething |= queue.onApplicationAttachedLocked(app);
+                    }
+                    checkTime(startTime, "finishAttachApplicationInner: "
+                            + "after dispatching broadcasts");
+                } catch (Exception e) {
+                    // If the app died trying to launch the receiver we declare it 'bad'
+                    Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
+                    badApp = true;
+                }
+            }
+
+            // Check whether the next backup agent is in this process...
+            final BackupRecord backupTarget = mBackupTargets.get(app.userId);
+            if (!badApp && backupTarget != null && backupTarget.app == app) {
+                if (DEBUG_BACKUP) {
+                    Slog.v(TAG_BACKUP,
+                            "New app is backup target, launching agent for " + app);
+                }
+
+                notifyPackageUse(backupTarget.appInfo.packageName,
+                        PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
+                try {
+                    app.getThread().scheduleCreateBackupAgent(backupTarget.appInfo,
+                            backupTarget.backupMode, backupTarget.userId,
+                            backupTarget.backupDestination);
+                } catch (Exception e) {
+                    Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
+                    badApp = true;
+                }
+            }
+
+            if (badApp) {
+                app.killLocked("error during init",
+                        ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
+                handleAppDiedLocked(app, pid, false, true, false /* fromBinderDied */);
+                return;
+            }
+
+            if (!didSomething) {
+                updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
+                checkTime(startTime, "finishAttachApplicationInner: after updateOomAdjLocked");
+            }
+
+            final HostingRecord hostingRecord = app.getHostingRecord();
+            final String shortAction = getShortAction(hostingRecord.getAction());
+            FrameworkStatsLog.write(
+                    FrameworkStatsLog.PROCESS_START_TIME,
+                    app.info.uid,
+                    pid,
+                    app.info.packageName,
+                    FrameworkStatsLog.PROCESS_START_TIME__TYPE__COLD,
+                    app.getStartElapsedTime(),
+                    (int) (app.getBindApplicationTime() - app.getStartUptime()),
+                    (int) (SystemClock.uptimeMillis() - app.getStartUptime()),
+                    hostingRecord.getType(),
+                    hostingRecord.getName(),
+                    shortAction,
+                    HostingRecord.getHostingTypeIdStatsd(hostingRecord.getType()),
+                    HostingRecord.getTriggerTypeForStatsd(hostingRecord.getTriggerType()));
+        }
+    }
+
+    @Override
+    public final void finishAttachApplication(long startSeq) {
+        final int pid = Binder.getCallingPid();
+        final int uid = Binder.getCallingUid();
+
+        if (!mConstants.mEnableWaitForFinishAttachApplication) {
+            Slog.i(TAG, "Flag disabled. Ignoring finishAttachApplication from uid: "
+                    + uid + ". pid: " + pid);
+            return;
+        }
+
+        if (pid == MY_PID && uid == SYSTEM_UID) {
+            return;
+        }
+
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            finishAttachApplicationInner(startSeq, uid, pid);
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
     /**
      * @return The last part of the string of an intent's action.
      */
@@ -5874,6 +5941,11 @@
         return mProcessList.getUidProcStateLOSP(uid);
     }
 
+    @GuardedBy("this")
+    int getUidProcessCapabilityLocked(int uid) {
+        return mProcessList.getUidProcessCapabilityLOSP(uid);
+    }
+
     // =========================================================
     // PROCESS INFO
     // =========================================================
@@ -13210,8 +13282,10 @@
         // restored. This distinction is important for system-process packages that live in the
         // system user's process but backup/restore data for non-system users.
         // TODO (b/123688746): Handle all system-process packages with singleton check.
-        final int instantiatedUserId =
-                PLATFORM_PACKAGE_NAME.equals(packageName) ? UserHandle.USER_SYSTEM : targetUserId;
+        boolean useSystemUser = PLATFORM_PACKAGE_NAME.equals(packageName)
+                || getPackageManagerInternal().getSystemUiServiceComponent().getPackageName()
+                        .equals(packageName);
+        final int instantiatedUserId = useSystemUser ? UserHandle.USER_SYSTEM : targetUserId;
 
         IPackageManager pm = AppGlobals.getPackageManager();
         ApplicationInfo app = null;
@@ -13588,8 +13662,7 @@
             // broadcasts, or the receiver is null (a sticky broadcast). Sticky broadcasts should
             // not be used generally, so we will be marking them as exported by default
             boolean requireExplicitFlagForDynamicReceivers = CompatChanges.isChangeEnabled(
-                    DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, callingUid)
-                    && mConstants.mEnforceReceiverExportedFlagRequirement;
+                    DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, callingUid);
             // STOPSHIP(b/259139792): Allow apps that are currently targeting U and in process of
             // updating their receivers to be exempt from this requirement until their receivers
             // are flagged.
@@ -14352,12 +14425,13 @@
                                 final boolean killProcess =
                                         !intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
                                 final boolean fullUninstall = removed && !replacing;
+
                                 if (removed) {
                                     if (killProcess) {
                                         forceStopPackageLocked(ssp, UserHandle.getAppId(
                                                 intent.getIntExtra(Intent.EXTRA_UID, -1)),
                                                 false, true, true, false, fullUninstall, userId,
-                                                removed ? "pkg removed" : "pkg changed");
+                                                "pkg removed");
                                         getPackageManagerInternal()
                                                 .onPackageProcessKilledForUninstall(ssp);
                                     } else {
@@ -14388,14 +14462,25 @@
                                     }
                                 } else {
                                     if (killProcess) {
+                                        int reason;
+                                        int subReason;
+                                        if (replacing) {
+                                            reason = ApplicationExitInfo.REASON_PACKAGE_UPDATED;
+                                            subReason = ApplicationExitInfo.SUBREASON_UNKNOWN;
+                                        } else {
+                                            reason =
+                                                    ApplicationExitInfo.REASON_PACKAGE_STATE_CHANGE;
+                                            subReason = ApplicationExitInfo.SUBREASON_UNKNOWN;
+                                        }
+
                                         final int extraUid = intent.getIntExtra(Intent.EXTRA_UID,
                                                 -1);
                                         synchronized (mProcLock) {
                                             mProcessList.killPackageProcessesLSP(ssp,
                                                     UserHandle.getAppId(extraUid),
                                                     userId, ProcessList.INVALID_ADJ,
-                                                    ApplicationExitInfo.REASON_USER_REQUESTED,
-                                                    ApplicationExitInfo.SUBREASON_PACKAGE_UPDATE,
+                                                    reason,
+                                                    subReason,
                                                     "change " + ssp);
                                         }
                                     }
@@ -16630,7 +16715,8 @@
     }
 
     @Override
-    public boolean startUserInBackgroundVisibleOnDisplay(int userId, int displayId) {
+    public boolean startUserInBackgroundVisibleOnDisplay(int userId, int displayId,
+            @Nullable IProgressListener unlockListener) {
         int[] displayIds = getDisplayIdsForStartingVisibleBackgroundUsers();
         boolean validDisplay = false;
         if (displayIds != null) {
@@ -16647,11 +16733,11 @@
         }
 
         if (DEBUG_MU) {
-            Slogf.d(TAG_MU, "Calling startUserOnSecondaryDisplay(%d, %d) using injector %s", userId,
-                    displayId, mInjector);
+            Slogf.d(TAG_MU, "Calling startUserOnSecondaryDisplay(%d, %d, %s) using injector %s",
+                    userId, displayId, unlockListener, mInjector);
         }
         // Permission check done inside UserController.
-        return mInjector.startUserInBackgroundVisibleOnDisplay(userId, displayId);
+        return mInjector.startUserInBackgroundVisibleOnDisplay(userId, displayId, unlockListener);
     }
 
     @Override
@@ -18974,14 +19060,20 @@
                 return null;
             }
 
-            // Starts with all displays but DEFAULT_DISPLAY
-            int[] displayIds = new int[allDisplays.length - 1];
+            boolean allowOnDefaultDisplay = UserManager
+                    .isVisibleBackgroundUsersOnDefaultDisplayEnabled();
+            int displaysSize = allDisplays.length;
+            if (!allowOnDefaultDisplay) {
+                displaysSize--;
+            }
+            int[] displayIds = new int[displaysSize];
 
-            // TODO(b/247592632): check for other properties like isSecure or proper display type
             int numberValidDisplays = 0;
             for (Display display : allDisplays) {
                 int displayId = display.getDisplayId();
-                if (display.isValid() && displayId != Display.DEFAULT_DISPLAY) {
+                // TODO(b/247592632): check other properties like isSecure or proper display type
+                if (display.isValid()
+                        && (allowOnDefaultDisplay || displayId != Display.DEFAULT_DISPLAY)) {
                     displayIds[numberValidDisplays++] = displayId;
                 }
             }
@@ -18993,14 +19085,15 @@
                 // STOPSHIP: if not removed, it should at least be unit tested
                 String testingProp = "fw.display_ids_for_starting_users_for_testing_purposes";
                 int displayId = SystemProperties.getInt(testingProp, Display.DEFAULT_DISPLAY);
-                if (displayId != Display.DEFAULT_DISPLAY && displayId > 0) {
-                    Slogf.w(TAG, "getSecondaryDisplayIdsForStartingBackgroundUsers(): no valid "
+                if (allowOnDefaultDisplay && displayId == Display.DEFAULT_DISPLAY
+                        || displayId > 0) {
+                    Slogf.w(TAG, "getDisplayIdsForStartingVisibleBackgroundUsers(): no valid "
                             + "display found, but returning %d as set by property %s", displayId,
                             testingProp);
                     return new int[] { displayId };
                 }
-                Slogf.e(TAG, "getDisplayIdsForStartingBackgroundUsers(): no valid display on %s",
-                        Arrays.toString(allDisplays));
+                Slogf.e(TAG, "getDisplayIdsForStartingVisibleBackgroundUsers(): no valid display"
+                        + " on %s", Arrays.toString(allDisplays));
                 return null;
             }
 
@@ -19025,8 +19118,10 @@
         /**
          * Called by {@code AMS.startUserInBackgroundVisibleOnDisplay()}.
          */
-        public boolean startUserInBackgroundVisibleOnDisplay(int userId, int displayId) {
-            return mUserController.startUserVisibleOnDisplay(userId, displayId);
+        public boolean startUserInBackgroundVisibleOnDisplay(int userId, int displayId,
+                @Nullable IProgressListener unlockProgressListener) {
+            return mUserController.startUserVisibleOnDisplay(userId, displayId,
+                    unlockProgressListener);
         }
 
         /**
@@ -19036,6 +19131,21 @@
             return new ProcessList();
         }
 
+        /**
+         * Returns the {@link BatteryStatsService} instance
+         */
+        public BatteryStatsService getBatteryStatsService() {
+            return new BatteryStatsService(mContext, SystemServiceManager.ensureSystemDir(),
+                BackgroundThread.get().getHandler());
+        }
+
+        /**
+         * Returns the {@link ActiveServices} instance
+         */
+        public ActiveServices getActiveServices(ActivityManagerService service) {
+            return new ActiveServices(service);
+        }
+
         private boolean ensureHasNetworkManagementInternal() {
             if (mNmi == null) {
                 mNmi = LocalServices.getService(NetworkManagementInternal.class);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 3ab1cd7..db283c7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -16,6 +16,10 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
@@ -1823,16 +1827,20 @@
         final InputStream mInput;
         final int mUid;
 
+        final int mMask;
+
         static final int STATE_NORMAL = 0;
 
         int mState;
 
-        MyUidObserver(ActivityManagerService service, PrintWriter pw, InputStream input, int uid) {
+        MyUidObserver(ActivityManagerService service, PrintWriter pw, InputStream input, int uid,
+                int mask) {
             mInterface = service;
             mInternal = service;
             mPw = pw;
             mInput = input;
             mUid = uid;
+            mMask = mask;
         }
 
         @Override
@@ -1847,7 +1855,7 @@
                     mPw.print(" seq ");
                     mPw.print(procStateSeq);
                     mPw.print(" capability ");
-                    mPw.println(capability);
+                    mPw.println(capability & mMask);
                     mPw.flush();
                 } finally {
                     StrictMode.setThreadPolicy(oldPolicy);
@@ -1998,9 +2006,19 @@
     int runWatchUids(PrintWriter pw) throws RemoteException {
         String opt;
         int uid = -1;
+
+        // Because a lot of CTS won't ignore capabilities newly added, we report
+        // only the following capabilities -- the ones we had on Android T -- by default.
+        int mask = PROCESS_CAPABILITY_FOREGROUND_LOCATION
+                | PROCESS_CAPABILITY_FOREGROUND_CAMERA
+                | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
+                | PROCESS_CAPABILITY_NETWORK;
+
         while ((opt=getNextOption()) != null) {
             if (opt.equals("--oom")) {
                 uid = Integer.parseInt(getNextArgRequired());
+            } else if (opt.equals("--mask")) {
+                mask = Integer.parseInt(getNextArgRequired());
             } else {
                 getErrPrintWriter().println("Error: Unknown option: " + opt);
                 return -1;
@@ -2008,7 +2026,7 @@
             }
         }
 
-        MyUidObserver controller = new MyUidObserver(mInternal, pw, getRawInputStream(), uid);
+        MyUidObserver controller = new MyUidObserver(mInternal, pw, getRawInputStream(), uid, mask);
         controller.run();
         return 0;
     }
@@ -2243,9 +2261,10 @@
                     pw.println("Not supported");
                     return -1;
                 }
-                Slogf.d(TAG, "calling startUserInBackgroundVisibleOnDisplay(%d,%d)", userId,
-                        displayId);
-                success = mInterface.startUserInBackgroundVisibleOnDisplay(userId, displayId);
+                Slogf.d(TAG, "calling startUserInBackgroundVisibleOnDisplay(%d, %d, %s)", userId,
+                        displayId, waiter);
+                success = mInterface.startUserInBackgroundVisibleOnDisplay(userId, displayId,
+                        waiter);
                 displaySuffix = " on display " + displayId;
             }
             if (wait && success) {
@@ -3849,6 +3868,7 @@
 
     int runListDisplaysForStartingUsers(PrintWriter pw) throws RemoteException {
         int[] displayIds = mInterface.getDisplayIdsForStartingVisibleBackgroundUsers();
+        // NOTE: format below cannot be changed as it's used by ITestDevice
         pw.println(displayIds == null || displayIds.length == 0
                 ? "none"
                 : Arrays.toString(displayIds));
@@ -4079,9 +4099,14 @@
             pw.println("      -p: only show events related to a specific process / package");
             pw.println("      -s: simple mode, only show a summary line for each event");
             pw.println("      -c: assume the input is always [c]ontinue");
-            pw.println("  watch-uids [--oom <uid>]");
+            pw.println("  watch-uids [--oom <uid>] [--mask <capabilities integer>]");
             pw.println("      Start watching for and reporting uid state changes.");
             pw.println("      --oom: specify a uid for which to report detailed change messages.");
+            pw.println("      --mask: Specify PROCESS_CAPABILITY_XXX mask to report. ");
+            pw.println("              By default, it only reports FOREGROUND_LOCATION (1)");
+            pw.println("              FOREGROUND_CAMERA (2), FOREGROUND_MICROPHONE (4)");
+            pw.println("              and NETWORK (8). New capabilities added on or after");
+            pw.println("              Android UDC will not be reported by default.");
             pw.println("  hang [--allow-restart]");
             pw.println("      Hang the system.");
             pw.println("      --allow-restart: allow watchdog to perform normal system restart");
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index f09622f..f73594c 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -2880,7 +2880,7 @@
                                 checkinStats.setPowerProfileLocked(mPowerProfile);
                                 checkinStats.readSummaryFromParcel(in);
                                 in.recycle();
-                                checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
+                                checkinStats.dumpCheckin(mContext, pw, apps, flags,
                                         historyStart);
                                 mStats.mCheckinFile.delete();
                                 return;
@@ -2892,17 +2892,15 @@
                     }
                 }
             }
-            if (DBG) Slog.d(TAG, "begin dumpCheckinLocked from UID " + Binder.getCallingUid());
+            if (DBG) Slog.d(TAG, "begin dumpCheckin from UID " + Binder.getCallingUid());
             awaitCompletion();
-            synchronized (mStats) {
-                mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
-                if (writeData) {
-                    mStats.writeAsyncLocked();
-                }
+            mStats.dumpCheckin(mContext, pw, apps, flags, historyStart);
+            if (writeData) {
+                mStats.writeAsyncLocked();
             }
-            if (DBG) Slog.d(TAG, "end dumpCheckinLocked");
+            if (DBG) Slog.d(TAG, "end dumpCheckin");
         } else {
-            if (DBG) Slog.d(TAG, "begin dumpLocked from UID " + Binder.getCallingUid());
+            if (DBG) Slog.d(TAG, "begin dump from UID " + Binder.getCallingUid());
             awaitCompletion();
 
             mStats.dump(mContext, pw, flags, reqUid, historyStart);
@@ -2912,7 +2910,7 @@
             pw.println();
             mCpuWakeupStats.dump(new IndentingPrintWriter(pw, "  "), SystemClock.elapsedRealtime());
 
-            if (DBG) Slog.d(TAG, "end dumpLocked");
+            if (DBG) Slog.d(TAG, "end dump");
         }
     }
 
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 2689193..913f151 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -742,9 +742,6 @@
                         "compactApp " + app.mOptRecord.getReqCompactSource().name() + " "
                                 + app.mOptRecord.getReqCompactProfile().name() + " " + processName);
             }
-            Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, ATRACE_COMPACTION_TRACK,
-                    "compactApp " + app.mOptRecord.getReqCompactSource().name() + " "
-                            + app.mOptRecord.getReqCompactProfile().name() + " " + processName);
             app.mOptRecord.setHasPendingCompact(true);
             app.mOptRecord.setForceCompact(force);
             mPendingCompactionProcesses.add(app);
@@ -1820,7 +1817,8 @@
                     try {
                         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                                 "Compact " + resolvedAction.name() + ": " + name
-                                        + " lastOomAdjReason: " + oomAdjReason);
+                                        + " lastOomAdjReason: " + oomAdjReason
+                                        + " source: " + compactSource.name());
                         long zramUsedKbBefore = getUsedZramMemory();
                         long startCpuTime = threadCpuTimeNs();
                         mProcessDependencies.performCompaction(resolvedAction, pid);
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 5cdcd42..ef15beb 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -38,6 +38,8 @@
 
 per-file ContentProviderHelper.java = varunshah@google.com, omakoto@google.com, jsharkey@google.com, yamasani@google.com
 
+per-file CachedAppOptimizer.java = file:/PERFORMANCE_OWNERS
+
 # Multiuser
 per-file User* = file:/MULTIUSER_OWNERS
 
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index e02dda6..f11a3be 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
@@ -1242,7 +1243,7 @@
         for (int i = numLru - 1; i >= 0; i--) {
             ProcessRecord app = lruList.get(i);
             final ProcessStateRecord state = app.mState;
-            if (!app.isKilledByAm() && app.getThread() != null) {
+            if (!app.isKilledByAm() && app.getThread() != null && !app.isPendingFinishAttach()) {
                 // We don't need to apply the update for the process which didn't get computed
                 if (state.getCompletedAdjSeq() == mAdjSeq) {
                     applyOomAdjLSP(app, true, now, nowElapsed, oomAdjReason);
@@ -1706,7 +1707,7 @@
             state.setCurRawAdj(state.getMaxAdj());
             state.setHasForegroundActivities(false);
             state.setCurrentSchedulingGroup(SCHED_GROUP_DEFAULT);
-            state.setCurCapability(PROCESS_CAPABILITY_ALL);
+            state.setCurCapability(PROCESS_CAPABILITY_ALL); // BFSL allowed
             state.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT);
             // System processes can do UI, and when they do we want to have
             // them trim their memory after the user leaves the UI.  To
@@ -1788,6 +1789,7 @@
             schedGroup = SCHED_GROUP_DEFAULT;
             state.setAdjType("instrumentation");
             procState = PROCESS_STATE_FOREGROUND_SERVICE;
+            capability |= PROCESS_CAPABILITY_BFSL;
             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
             }
@@ -1880,37 +1882,28 @@
                 adjType = "fg-service";
                 newAdj = PERCEPTIBLE_APP_ADJ;
                 newProcState = PROCESS_STATE_FOREGROUND_SERVICE;
+                capabilityFromFGS |= PROCESS_CAPABILITY_BFSL;
+
+            } else if (hasShortForegroundServices) {
+
+                // For short FGS.
+                adjType = "fg-service-short";
+
+                // We use MEDIUM_APP_ADJ + 1 so we can tell apart EJ
+                // (which uses MEDIUM_APP_ADJ + 1)
+                // from short-FGS.
+                // (We use +1 and +2, not +0 and +1, to be consistent with the following
+                // RECENT_FOREGROUND_APP_ADJ tweak)
+                newAdj = PERCEPTIBLE_MEDIUM_APP_ADJ + 1;
+
+                // We give the FGS procstate, but not PROCESS_CAPABILITY_BFSL, so
+                // short-fgs can't start FGS from the background.
+                newProcState = PROCESS_STATE_FOREGROUND_SERVICE;
 
             } else if (state.hasOverlayUi()) {
                 adjType = "has-overlay-ui";
                 newAdj = PERCEPTIBLE_APP_ADJ;
                 newProcState = PROCESS_STATE_IMPORTANT_FOREGROUND;
-
-            } else if (hasForegroundServices) {
-                // If we get here, hasNonShortForegroundServices() must be false.
-
-                // TODO(short-service): Proactively run OomAjudster when the grace period finish.
-                if (!hasShortForegroundServices) {
-                    // All the short-FGSes within this process are timed out. Don't promote to FGS.
-                    // TODO(short-service): Should we set some unique oom-adj to make it detectable,
-                    // in a long trace?
-                } else {
-                    // For short FGS.
-                    adjType = "fg-service-short";
-                    // We use MEDIUM_APP_ADJ + 1 so we can tell apart EJ
-                    // (which uses MEDIUM_APP_ADJ + 1)
-                    // from short-FGS.
-                    // (We use +1 and +2, not +0 and +1, to be consistent with the following
-                    // RECENT_FOREGROUND_APP_ADJ tweak)
-                    newAdj = PERCEPTIBLE_MEDIUM_APP_ADJ + 1;
-
-                    // Short-FGS gets a below-BFGS procstate, so it can't start another FGS from it.
-                    newProcState = PROCESS_STATE_IMPORTANT_FOREGROUND;
-
-                    // Same as EJ, we explicitly grant network access to short FGS,
-                    // even when battery saver or data saver is enabled.
-                    capabilityFromFGS |= PROCESS_CAPABILITY_NETWORK;
-                }
             }
 
             if (adjType != null) {
@@ -2220,6 +2213,11 @@
                         app.mOptRecord.setShouldNotFreeze(true);
                     }
 
+                    // We always propagate PROCESS_CAPABILITY_BFSL over bindings here,
+                    // but, right before actually setting it to the process,
+                    // we check the final procstate, and remove it if the procsate is below BFGS.
+                    capability |= getBfslCapabilityFromClient(client);
+
                     if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
                         if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
                             capability |= cstate.getCurCapability();
@@ -2319,6 +2317,14 @@
                                         && adj >= (lbAdj = PERCEPTIBLE_LOW_APP_ADJ)) {
                                     newAdj = PERCEPTIBLE_LOW_APP_ADJ;
                                 } else if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0
+                                        && (cr.flags & Context.BIND_NOT_FOREGROUND) == 0
+                                        && clientAdj < PERCEPTIBLE_APP_ADJ
+                                        && adj >= (lbAdj = PERCEPTIBLE_APP_ADJ)) {
+                                    // This is for user-initiated jobs.
+                                    // We use APP_ADJ + 1 here, so we can tell them apart from FGS.
+                                    newAdj = PERCEPTIBLE_APP_ADJ + 1;
+                                } else if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0
+                                        && (cr.flags & Context.BIND_NOT_FOREGROUND) != 0
                                         && clientAdj < PERCEPTIBLE_APP_ADJ
                                         && adj >= (lbAdj = (PERCEPTIBLE_MEDIUM_APP_ADJ + 2))) {
                                     // This is for expedited jobs.
@@ -2532,6 +2538,11 @@
                 int clientAdj = cstate.getCurRawAdj();
                 int clientProcState = cstate.getCurRawProcState();
 
+                // We always propagate PROCESS_CAPABILITY_BFSL to providers here,
+                // but, right before actually setting it to the process,
+                // we check the final procstate, and remove it if the procsate is below BFGS.
+                capability |= getBfslCapabilityFromClient(client);
+
                 if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                     // If the other app is cached for any reason, for purposes here
                     // we are going to consider it empty.
@@ -2710,6 +2721,11 @@
 
         capability |= getDefaultCapability(app, procState);
 
+        // Procstates below BFGS should never have this capability.
+        if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+            capability &= ~PROCESS_CAPABILITY_BFSL;
+        }
+
         // Do final modification to adj.  Everything we do between here and applying
         // the final setAdj must be done in this function, because we will also use
         // it when computing the final cached adj later.  Note that we don't need to
@@ -2735,9 +2751,9 @@
             case PROCESS_STATE_PERSISTENT:
             case PROCESS_STATE_PERSISTENT_UI:
             case PROCESS_STATE_TOP:
-                return PROCESS_CAPABILITY_ALL;
+                return PROCESS_CAPABILITY_ALL; // BFSL allowed
             case PROCESS_STATE_BOUND_TOP:
-                return PROCESS_CAPABILITY_NETWORK;
+                return PROCESS_CAPABILITY_NETWORK | PROCESS_CAPABILITY_BFSL;
             case PROCESS_STATE_FOREGROUND_SERVICE:
                 if (app.getActiveInstrumentation() != null) {
                     return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK ;
@@ -2755,6 +2771,53 @@
     }
 
     /**
+     * @return the BFSL capability from a client (of a service binding or provider).
+     */
+    int getBfslCapabilityFromClient(ProcessRecord client) {
+        // Procstates above FGS should always have this flag. We shouldn't need this logic,
+        // but let's do it just in case.
+        if (client.mState.getCurProcState() < PROCESS_STATE_FOREGROUND_SERVICE) {
+            return PROCESS_CAPABILITY_BFSL;
+        }
+        // Otherwise, use the process's cur capability.
+
+        // Note: BFSL is a per-UID check, not per-process, but here, the BFSL capability is still
+        // propagated on a per-process basis.
+        //
+        // For example, consider this case:
+        // - There are App 1 and App 2.
+        // - App 1 has two processes
+        //   Proc #1A, procstate BFGS with CAPABILITY_BFSL
+        //   Proc #1B, procstate FGS with no CAPABILITY_BFSL (i.e. process has a short FGS)
+        //        And this process binds to Proc #2 of App 2.
+        //
+        //       (Note because #1A has CAPABILITY_BFSL, App 1's UidRecord has CAPABILITY_BFSL.)
+        //
+        // - App 2 has one process:
+        //   Proc #2, procstate FGS due to the above binding, _with no CAPABILITY_BFSL_.
+        //
+        // In this case, #2 will not get CAPABILITY_BFSL because the binding client (#1B)
+        // doesn't have this capability. (Even though App 1's UidRecord has it.)
+        //
+        // This may look weird, because App 2 _is_ still BFSL allowed, because "it's bound by
+        // an app that is BFSL-allowed". (See [bookmark: 61867f60-007c-408c-a2c4-e19e96056135]
+        // in ActiveServices.)
+        //
+        // So why don't we propagate PROCESS_CAPABILITY_BFSL from App 1's UID record?
+        // This is because short-FGS acts like "below BFGS" as far as BFSL is concerned,
+        // similar to how JobScheduler jobs are below BFGS and apps can't start FGS from there.
+        //
+        // If #1B was running a job instead of a short-FGS, then its procstate would be below BFGS.
+        // Then #2's procstate would also be below BFGS. So #2 wouldn't get CAPABILITY_BFSL.
+        // Similarly, if #1B has a short FGS, even though the procstate of #1B and #2 would be FGS,
+        // they both still wouldn't get CAPABILITY_BFSL.
+        //
+        // However, again, because #2 is bound by App 1, which is BFSL-allowed (because of #1A)
+        // App 2 would still BFSL-allowed, due to the aforementioned check in ActiveServices.
+        return client.mState.getCurCapability() & PROCESS_CAPABILITY_BFSL;
+    }
+
+    /**
      * Checks if for the given app and client, there's a cycle that should skip over the client
      * for now or use partial values to evaluate the effect of the client binding.
      * @param app
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 04c0d64..ee315bd 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2514,7 +2514,7 @@
     }
 
     @GuardedBy("mService")
-    private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {
+    String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {
         StringBuilder sb = null;
         if (app.isKilledByAm()) {
             if (sb == null) sb = new StringBuilder();
@@ -3888,7 +3888,7 @@
         return runList;
     }
 
-    @GuardedBy(anyOf = {"mService", "mProfileLock"})
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
     int getLruSizeLOSP() {
         return mLruProcesses.size();
     }
@@ -3896,7 +3896,7 @@
     /**
      * Return the reference to the LRU list, call this function for read-only access
      */
-    @GuardedBy(anyOf = {"mService", "mProfileLock"})
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
     ArrayList<ProcessRecord> getLruProcessesLOSP() {
         return mLruProcesses;
     }
@@ -3904,7 +3904,7 @@
     /**
      * Return the reference to the LRU list, call this function for read/write access
      */
-    @GuardedBy({"mService", "mProfileLock"})
+    @GuardedBy({"mService", "mProcLock"})
     ArrayList<ProcessRecord> getLruProcessesLSP() {
         return mLruProcesses;
     }
@@ -3913,12 +3913,12 @@
      * For test only
      */
     @VisibleForTesting
-    @GuardedBy({"mService", "mProfileLock"})
+    @GuardedBy({"mService", "mProcLock"})
     void setLruProcessServiceStartLSP(int pos) {
         mLruProcessServiceStart = pos;
     }
 
-    @GuardedBy(anyOf = {"mService", "mProfileLock"})
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
     int getLruProcessServiceStartLOSP() {
         return mLruProcessServiceStart;
     }
@@ -3931,7 +3931,7 @@
      *                       to most recent used ProcessRecord.
      * @param callback The callback interface to accept the current ProcessRecord.
      */
-    @GuardedBy(anyOf = {"mService", "mProfileLock"})
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
     void forEachLruProcessesLOSP(boolean iterateForward,
             @NonNull Consumer<ProcessRecord> callback) {
         if (iterateForward) {
@@ -3956,7 +3956,7 @@
      *                 a non-null object, the search will be halted and this object will be used
      *                 as the return value of this search function.
      */
-    @GuardedBy(anyOf = {"mService", "mProfileLock"})
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
     <R> R searchEachLruProcessesLOSP(boolean iterateForward,
             @NonNull Function<ProcessRecord, R> callback) {
         if (iterateForward) {
@@ -3977,17 +3977,17 @@
         return null;
     }
 
-    @GuardedBy(anyOf = {"mService", "mProfileLock"})
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
     boolean isInLruListLOSP(ProcessRecord app) {
         return mLruProcesses.contains(app);
     }
 
-    @GuardedBy(anyOf = {"mService", "mProfileLock"})
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
     int getLruSeqLOSP() {
         return mLruSeq;
     }
 
-    @GuardedBy(anyOf = {"mService", "mProfileLock"})
+    @GuardedBy(anyOf = {"mService", "mProcLock"})
     MyProcessMap getProcessNamesLOSP() {
         return mProcessNames;
     }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index e6cb596..a707202 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -175,6 +175,12 @@
     private boolean mPendingStart;
 
     /**
+     * Process finish attach application is pending.
+     */
+    @GuardedBy("mService")
+    private boolean mPendingFinishAttach;
+
+    /**
      * Seq no. Indicating the latest process start associated with this process record.
      */
     @GuardedBy("mService")
@@ -201,6 +207,11 @@
     private volatile long mStartElapsedTime;
 
     /**
+     * When the process was sent the bindApplication request
+     */
+    private volatile long mBindApplicationTime;
+
+    /**
      * This will be same as {@link #uid} usually except for some apps used during factory testing.
      */
     private volatile int mStartUid;
@@ -698,6 +709,16 @@
     }
 
     @GuardedBy("mService")
+    void setPendingFinishAttach(boolean pendingFinishAttach) {
+        mPendingFinishAttach = pendingFinishAttach;
+    }
+
+    @GuardedBy("mService")
+    boolean isPendingFinishAttach() {
+        return mPendingFinishAttach;
+    }
+
+    @GuardedBy("mService")
     long getStartSeq() {
         return mStartSeq;
     }
@@ -740,6 +761,14 @@
         return mStartElapsedTime;
     }
 
+    long getBindApplicationTime() {
+        return mBindApplicationTime;
+    }
+
+    void setBindApplicationTime(long bindApplicationTime) {
+        mBindApplicationTime = bindApplicationTime;
+    }
+
     int getStartUid() {
         return mStartUid;
     }
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index 2ad2077..71d5d39 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -17,7 +17,6 @@
 package com.android.server.am;
 
 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
@@ -1180,11 +1179,6 @@
     }
 
     @GuardedBy("mService")
-    boolean isAllowedStartFgs() {
-        return mCurProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
-    }
-
-    @GuardedBy("mService")
     boolean isBackgroundRestricted() {
         return mBackgroundRestricted;
     }
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index f22624c..60a7f93 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -80,6 +80,7 @@
     @VisibleForTesting
     static final String[] sDeviceConfigScopes = new String[] {
         DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+        DeviceConfig.NAMESPACE_CAMERA_NATIVE,
         DeviceConfig.NAMESPACE_CONFIGURATION,
         DeviceConfig.NAMESPACE_CONNECTIVITY,
         DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
@@ -103,6 +104,7 @@
         DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_VIRTUALIZATION_FRAMEWORK_NATIVE,
         DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
+        DeviceConfig.NAMESPACE_MEMORY_SAFETY_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_MEMORY_SAFETY_NATIVE,
         DeviceConfig.NAMESPACE_HDMI_CONTROL
     };
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index b617582..bfc022b 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -443,6 +443,8 @@
         sb.append(",");
         sb.append(lastNetworkUpdatedProcStateSeq);
         sb.append(")}");
+        sb.append(" caps=");
+        ActivityManager.printCapabilitiesSummary(sb, mCurCapability);
         return sb.toString();
     }
 }
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index b2e4740..c5b611d 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1560,16 +1560,18 @@
      *
      * @param userId user to be started
      * @param displayId display where the user will be visible
+     * @param unlockListener Listener to be informed when the user has started and unlocked.
      *
      * @return whether the user was started
      */
-    boolean startUserVisibleOnDisplay(@UserIdInt int userId, int displayId) {
+    boolean startUserVisibleOnDisplay(@UserIdInt int userId, int displayId,
+            @Nullable IProgressListener unlockListener) {
         checkCallingHasOneOfThosePermissions("startUserOnDisplay",
                 MANAGE_USERS, INTERACT_ACROSS_USERS);
 
         try {
             return startUserNoChecks(userId, displayId, USER_START_MODE_BACKGROUND_VISIBLE,
-                    /* unlockListener= */ null);
+                    unlockListener);
         } catch (RuntimeException e) {
             Slogf.e(TAG, "startUserOnSecondaryDisplay(%d, %d) failed: %s", userId, displayId, e);
             return false;
@@ -2246,7 +2248,7 @@
         // If there is no challenge set, dismiss the keyguard right away
         if (isUserSwitchUiEnabled && !mInjector.getKeyguardManager().isDeviceSecure(newUserId)) {
             // Wait until the keyguard is dismissed to unfreeze
-            mInjector.dismissKeyguard(runnable, "User Switch");
+            mInjector.dismissKeyguard(runnable);
         } else {
             runnable.run();
         }
@@ -3714,7 +3716,7 @@
             return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
         }
 
-        protected void dismissKeyguard(Runnable runnable, String reason) {
+        protected void dismissKeyguard(Runnable runnable) {
             final AtomicBoolean isFirst = new AtomicBoolean(true);
             final Runnable runOnce = () -> {
                 if (isFirst.getAndSet(false)) {
@@ -3738,7 +3740,7 @@
                 public void onDismissCancelled() throws RemoteException {
                     mHandler.post(runOnce);
                 }
-            }, reason);
+            }, /* message= */ null);
         }
 
         boolean isUsersOnSecondaryDisplaysEnabled() {
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java
index ef0de18..704b425 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java
@@ -106,6 +106,21 @@
     }
 
     @Override
+    public SparseIntArray getNonDefaultPackageModes(String packageName, int userId) {
+        synchronized (mLock) {
+            ArrayMap<String, SparseIntArray> packageModes = mUserPackageModes.get(userId);
+            if (packageModes == null) {
+                return new SparseIntArray();
+            }
+            SparseIntArray opModes = packageModes.get(packageName);
+            if (opModes == null) {
+                return new SparseIntArray();
+            }
+            return opModes.clone();
+        }
+    }
+
+    @Override
     public int getUidMode(int uid, int op) {
         synchronized (mLock) {
             SparseIntArray opModes = mUidModes.get(uid, null);
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java
index d8d0d48..9a564fc 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceInterface.java
@@ -39,6 +39,15 @@
     SparseIntArray getNonDefaultUidModes(int uid);
 
     /**
+     * Returns a copy of non-default app-ops with op as keys and their modes as values for a package
+     * and user.
+     * Returns an empty SparseIntArray if nothing is set.
+     * @param packageName for which we need the app-ops and their modes.
+     * @param userId for which the package is installed in.
+     */
+    SparseIntArray getNonDefaultPackageModes(String packageName, int userId);
+
+    /**
      * Returns the app-op mode for a particular app-op of a uid.
      * Returns default op mode if the op mode for particular uid and op is not set.
      * @param uid user id for which we need the mode.
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java
index ac479b2..b8326ad 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceLoggingDecorator.java
@@ -46,6 +46,13 @@
     }
 
     @Override
+    public SparseIntArray getNonDefaultPackageModes(String packageName, int userId) {
+        Log.i(LOG_TAG, "getNonDefaultPackageModes("
+                + "packageName = " + packageName + ", userId = " + userId + ") ");
+        return mService.getNonDefaultPackageModes(packageName, userId);
+    }
+
+    @Override
     public int getUidMode(int uid, int op) {
         Log.i(LOG_TAG, "getUidMode(uid = " + uid + ", op = " + op + ")");
         return mService.getUidMode(uid, op);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c50f2b7..77f16f9 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -98,6 +98,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PermissionInfo;
+import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION;
 import android.net.Uri;
@@ -153,6 +154,7 @@
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.LocalManagerRegistry;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
 import com.android.server.SystemServerInitThreadPool;
@@ -162,6 +164,7 @@
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 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.component.ParsedAttribution;
 import com.android.server.policy.AppOpsPolicy;
 
@@ -383,6 +386,9 @@
     /** Package Manager internal. Access via {@link #getPackageManagerInternal()} */
     private @Nullable PackageManagerInternal mPackageManagerInternal;
 
+    /** User Manager internal. Access via {@link #getUserManagerInternal()} */
+    private @Nullable UserManagerInternal mUserManagerInternal;
+
     /** Interface for app-op modes.*/
     @VisibleForTesting
     AppOpsCheckingServiceInterface mAppOpsCheckingService;
@@ -525,22 +531,6 @@
             pkgOps = null;
         }
 
-        public boolean isDefault() {
-            boolean areAllPackageModesDefault = true;
-            if (pkgOps != null) {
-                for (String packageName : pkgOps.keySet()) {
-                    if (!mAppOpsCheckingService.arePackageModesDefault(packageName,
-                            UserHandle.getUserId(uid))) {
-                        areAllPackageModesDefault = false;
-                        break;
-                    }
-                }
-            }
-            return (pkgOps == null || pkgOps.isEmpty())
-                    && mAppOpsCheckingService.areUidModesDefault(uid)
-                    && areAllPackageModesDefault;
-        }
-
         // Functions for uid mode access and manipulation.
         public SparseIntArray getNonDefaultUidModes() {
             return mAppOpsCheckingService.getNonDefaultUidModes(uid);
@@ -978,7 +968,7 @@
     public void publish() {
         ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
         LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
-        LocalServices.addService(AppOpsManagerLocal.class, new AppOpsManagerLocalImpl());
+        LocalManagerRegistry.addManager(AppOpsManagerLocal.class, new AppOpsManagerLocalImpl());
     }
 
     /** Handler for work when packages are removed or updated */
@@ -1076,6 +1066,17 @@
         synchronized (this) {
             upgradeLocked(mVersionAtBoot);
         }
+        initializeUidStates();
+
+        getUserManagerInternal().addUserLifecycleListener(
+                new UserManagerInternal.UserLifecycleListener() {
+                    @Override
+                    public void onUserCreated(UserInfo user, Object token) {
+                        initializeUserUidStates(user.id);
+                    }
+
+                    // onUserRemoved handled by #removeUser
+                });
 
         mConstants.startMonitoring(mContext.getContentResolver());
         mHistoricalRegistry.systemReady(mContext.getContentResolver());
@@ -1203,6 +1204,49 @@
     }
 
     /**
+     * Initialize uid state objects for state contained in the checking service.
+     */
+    private void initializeUidStates() {
+        UserManagerInternal umi = getUserManagerInternal();
+        int[] userIds = umi.getUserIds();
+        synchronized (this) {
+            for (int i = 0; i < userIds.length; i++) {
+                int userId = userIds[i];
+                initializeUserUidStatesLocked(userId);
+            }
+        }
+    }
+
+    private void initializeUserUidStates(int userId) {
+        synchronized (this) {
+            initializeUserUidStatesLocked(userId);
+        }
+    }
+
+    private void initializeUserUidStatesLocked(int userId) {
+        ArrayMap<String, ? extends PackageStateInternal> packageStates =
+                getPackageManagerInternal().getPackageStates();
+        for (int j = 0; j < packageStates.size(); j++) {
+            PackageStateInternal packageState = packageStates.valueAt(j);
+            int uid = UserHandle.getUid(userId, packageState.getAppId());
+            UidState uidState = getUidStateLocked(uid, true);
+            if (uidState.pkgOps == null) {
+                uidState.pkgOps = new ArrayMap<>();
+            }
+            String packageName = packageStates.keyAt(j);
+            Ops ops = new Ops(packageName, uidState);
+            uidState.pkgOps.put(packageName, ops);
+
+            SparseIntArray packageModes =
+                    mAppOpsCheckingService.getNonDefaultPackageModes(packageName, userId);
+            for (int k = 0; k < packageModes.size(); k++) {
+                int code = packageModes.get(k);
+                ops.put(code, new Op(uidState, packageName, code, uid));
+            }
+        }
+    }
+
+    /**
      * Sets a policy for handling app ops.
      *
      * @param policy The policy.
@@ -1687,13 +1731,6 @@
                         pkgOps.remove(ops.packageName);
                         mAppOpsCheckingService.removePackage(ops.packageName,
                                 UserHandle.getUserId(uidState.uid));
-                        if (pkgOps.isEmpty()) {
-                            uidState.pkgOps = null;
-                        }
-                        if (uidState.isDefault()) {
-                            uidState.clear();
-                            mUidStates.remove(uid);
-                        }
                     }
                 }
             }
@@ -2147,10 +2184,6 @@
                                 UserHandle.getUserId(uidState.uid));
                     }
                 }
-                if (uidState.isDefault()) {
-                    uidState.clear();
-                    mUidStates.remove(uidState.uid);
-                }
                 if (uidChanged) {
                     uidState.evalForegroundOps();
                 }
@@ -3588,6 +3621,20 @@
     }
 
     /**
+     * @return {@link UserManagerInternal}
+     */
+    private @NonNull UserManagerInternal getUserManagerInternal() {
+        if (mUserManagerInternal == null) {
+            mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
+        }
+        if (mUserManagerInternal == null) {
+            throw new IllegalStateException("UserManagerInternal not loaded");
+        }
+
+        return mUserManagerInternal;
+    }
+
+    /**
      * Create a restriction description matching the properties of the package.
      *
      * @param pkg The package to create the restriction description for
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 88fc51a3..e55bddb 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -692,6 +692,7 @@
 
     // Devices where the framework sends a full scale audio signal, and controls the volume of
     // the external audio system separately.
+    // For possible volume behaviors, see {@link AudioManager.AbsoluteDeviceVolumeBehavior}.
     Map<Integer, AbsoluteVolumeDeviceInfo> mAbsoluteVolumeDeviceInfoMap = new ArrayMap<>();
 
     /**
@@ -702,13 +703,19 @@
         private final List<VolumeInfo> mVolumeInfos;
         private final IAudioDeviceVolumeDispatcher mCallback;
         private final boolean mHandlesVolumeAdjustment;
+        private @AudioManager.AbsoluteDeviceVolumeBehavior int mDeviceVolumeBehavior;
 
-        private AbsoluteVolumeDeviceInfo(AudioDeviceAttributes device, List<VolumeInfo> volumeInfos,
-                IAudioDeviceVolumeDispatcher callback, boolean handlesVolumeAdjustment) {
+        private AbsoluteVolumeDeviceInfo(
+                AudioDeviceAttributes device,
+                List<VolumeInfo> volumeInfos,
+                IAudioDeviceVolumeDispatcher callback,
+                boolean handlesVolumeAdjustment,
+                @AudioManager.AbsoluteDeviceVolumeBehavior int behavior) {
             this.mDevice = device;
             this.mVolumeInfos = volumeInfos;
             this.mCallback = callback;
             this.mHandlesVolumeAdjustment = handlesVolumeAdjustment;
+            this.mDeviceVolumeBehavior = behavior;
         }
 
         /**
@@ -1462,7 +1469,7 @@
 
         mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
 
-        mSoundDoseHelper.configureSafeMediaVolume(/*forced=*/true, TAG);
+        mSoundDoseHelper.configureSafeMedia(/*forced=*/true, TAG);
 
         initA11yMonitoring();
 
@@ -2206,19 +2213,19 @@
                 AudioSystem.STREAM_ASSISTANT : AudioSystem.STREAM_MUSIC;
 
         if (mIsSingleVolume) {
-            mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
+            mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION.clone();
             dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
         } else if (mUseVolumeGroupAliases) {
-            mStreamVolumeAlias = STREAM_VOLUME_ALIAS_NONE;
+            mStreamVolumeAlias = STREAM_VOLUME_ALIAS_NONE.clone();
             dtmfStreamAlias = AudioSystem.STREAM_DTMF;
         } else {
             switch (mPlatformType) {
                 case AudioSystem.PLATFORM_VOICE:
-                    mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
+                    mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE.clone();
                     dtmfStreamAlias = AudioSystem.STREAM_RING;
                     break;
                 default:
-                    mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
+                    mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT.clone();
                     dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
             }
             if (!mNotifAliasRing) {
@@ -3647,11 +3654,12 @@
         synchronized (VolumeStreamState.class) {
             List<Integer> streamsToMute = new ArrayList<>();
             for (int stream = 0; stream < mStreamStates.length; stream++) {
-                if (streamAlias == mStreamVolumeAlias[stream]) {
+                VolumeStreamState vss = mStreamStates[stream];
+                if (streamAlias == mStreamVolumeAlias[stream] && vss.isMutable()) {
                     if (!(readCameraSoundForced()
-                            && (mStreamStates[stream].getStreamType()
+                            && (vss.getStreamType()
                                     == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
-                        boolean changed = mStreamStates[stream].mute(state, /* apply= */ false);
+                        boolean changed = vss.mute(state, /* apply= */ false);
                         if (changed) {
                             streamsToMute.add(stream);
                         }
@@ -5329,7 +5337,8 @@
             if (!shouldMute) {
                 // unmute
                 // ring and notifications volume should never be 0 when not silenced
-                if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
+                if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING
+                        || mStreamVolumeAlias[streamType] == AudioSystem.STREAM_NOTIFICATION) {
                     synchronized (VolumeStreamState.class) {
                         final VolumeStreamState vss = mStreamStates[streamType];
                         for (int i = 0; i < vss.mIndexMap.size(); i++) {
@@ -6060,6 +6069,8 @@
             }
         }
 
+        readVolumeGroupsSettings(userSwitch);
+
         // apply new ringer mode before checking volume for alias streams so that streams
         // muted by ringer mode have the correct volume
         setRingerModeInt(getRingerModeInternal(), false);
@@ -6071,8 +6082,6 @@
         mSoundDoseHelper.restoreMusicActiveMs();
         mSoundDoseHelper.enforceSafeMediaVolumeIfActive(TAG);
 
-        readVolumeGroupsSettings(userSwitch);
-
         if (DEBUG_VOL) {
             Log.d(TAG, "Restoring device volume behavior");
         }
@@ -7055,7 +7064,8 @@
     public void registerDeviceVolumeDispatcherForAbsoluteVolume(boolean register,
             IAudioDeviceVolumeDispatcher cb, String packageName,
             AudioDeviceAttributes device, List<VolumeInfo> volumes,
-            boolean handlesVolumeAdjustment) {
+            boolean handlesVolumeAdjustment,
+            @AudioManager.AbsoluteDeviceVolumeBehavior int deviceVolumeBehavior) {
         // verify permissions
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
                 != PackageManager.PERMISSION_GRANTED
@@ -7071,13 +7081,16 @@
         int deviceOut = device.getInternalType();
         if (register) {
             AbsoluteVolumeDeviceInfo info = new AbsoluteVolumeDeviceInfo(
-                    device, volumes, cb, handlesVolumeAdjustment);
-            boolean volumeBehaviorChanged =
-                    removeAudioSystemDeviceOutFromFullVolumeDevices(deviceOut)
-                    | removeAudioSystemDeviceOutFromFixedVolumeDevices(deviceOut)
-                    | (addAudioSystemDeviceOutToAbsVolumeDevices(deviceOut, info) == null);
+                    device, volumes, cb, handlesVolumeAdjustment, deviceVolumeBehavior);
+            AbsoluteVolumeDeviceInfo oldInfo = mAbsoluteVolumeDeviceInfoMap.get(deviceOut);
+            boolean volumeBehaviorChanged = (oldInfo == null)
+                    || (oldInfo.mDeviceVolumeBehavior != deviceVolumeBehavior);
             if (volumeBehaviorChanged) {
-                dispatchDeviceVolumeBehavior(device, AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
+                removeAudioSystemDeviceOutFromFullVolumeDevices(deviceOut);
+                removeAudioSystemDeviceOutFromFixedVolumeDevices(deviceOut);
+                addAudioSystemDeviceOutToAbsVolumeDevices(deviceOut, info);
+
+                dispatchDeviceVolumeBehavior(device, deviceVolumeBehavior);
             }
             // Update stream volumes to the given device, if specified in a VolumeInfo.
             // Mute state is not updated because it is stream-wide - the only way to mute a
@@ -7169,6 +7182,7 @@
                                 != null);
                 break;
             case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE:
+            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY:
             case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE:
                 throw new IllegalArgumentException("Absolute volume unsupported for now");
         }
@@ -7212,11 +7226,6 @@
         // AudioDeviceInfo.convertDeviceTypeToInternalDevice()
         final int audioSystemDeviceOut = device.getInternalType();
 
-        int setDeviceVolumeBehavior = retrieveStoredDeviceVolumeBehavior(audioSystemDeviceOut);
-        if (setDeviceVolumeBehavior != AudioManager.DEVICE_VOLUME_BEHAVIOR_UNSET) {
-            return setDeviceVolumeBehavior;
-        }
-
         // setDeviceVolumeBehavior has not been explicitly called for the device type. Deduce the
         // current volume behavior.
         if (mFullVolumeDevices.contains(audioSystemDeviceOut)) {
@@ -7228,8 +7237,11 @@
         if (mAbsVolumeMultiModeCaseDevices.contains(audioSystemDeviceOut)) {
             return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE;
         }
-        if (isAbsoluteVolumeDevice(audioSystemDeviceOut)
-                || isA2dpAbsoluteVolumeDevice(audioSystemDeviceOut)
+        if (mAbsoluteVolumeDeviceInfoMap.containsKey(audioSystemDeviceOut)) {
+            return mAbsoluteVolumeDeviceInfoMap.get(audioSystemDeviceOut).mDeviceVolumeBehavior;
+        }
+
+        if (isA2dpAbsoluteVolumeDevice(audioSystemDeviceOut)
                 || AudioSystem.isLeAudioDeviceType(audioSystemDeviceOut)) {
             return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE;
         }
@@ -8478,9 +8490,10 @@
                     }
                     mVolumeGroupState.updateVolumeIndex(groupIndex, device);
                     // Only propage mute of stream when applicable
-                    if (mIndexMin == 0 || isCallStream(mStreamType)) {
+                    if (isMutable()) {
                         // For call stream, align mute only when muted, not when index is set to 0
-                        mVolumeGroupState.mute(forceMuteState ? mIsMuted : groupIndex == 0);
+                        mVolumeGroupState.mute(
+                                forceMuteState ? mIsMuted : groupIndex == 0 || mIsMuted);
                     }
                 }
             }
@@ -8529,6 +8542,12 @@
             return mIsMuted || mIsMutedInternally;
         }
 
+
+        private boolean isMutable() {
+            return isStreamAffectedByMute(mStreamType)
+                    && (mIndexMin == 0 || isCallStream(mStreamType));
+        }
+
         /**
          * Mute/unmute the stream
          * @param state the new mute state
@@ -10236,7 +10255,7 @@
             // reading new configuration "safely" (i.e. under try catch) in case anything
             // goes wrong.
             Configuration config = context.getResources().getConfiguration();
-            mSoundDoseHelper.configureSafeMediaVolume(/*forced*/false, TAG);
+            mSoundDoseHelper.configureSafeMedia(/*forced*/false, TAG);
 
             boolean cameraSoundForced = readCameraSoundForced();
             synchronized (mSettingsLock) {
@@ -10671,6 +10690,13 @@
         pw.println();
     }
 
+    private Set<Integer> getAbsoluteVolumeDevicesWithBehavior(int behavior) {
+        return mAbsoluteVolumeDeviceInfoMap.entrySet().stream()
+                .filter(entry -> entry.getValue().mDeviceVolumeBehavior == behavior)
+                .map(Map.Entry::getKey)
+                .collect(Collectors.toSet());
+    }
+
     private String dumpDeviceTypes(@NonNull Set<Integer> deviceTypes) {
         Iterator<Integer> it = deviceTypes.iterator();
         if (!it.hasNext()) {
@@ -10719,14 +10745,20 @@
         pw.print("  mNotifAliasRing="); pw.println(mNotifAliasRing);
         pw.print("  mFixedVolumeDevices="); pw.println(dumpDeviceTypes(mFixedVolumeDevices));
         pw.print("  mFullVolumeDevices="); pw.println(dumpDeviceTypes(mFullVolumeDevices));
-        pw.print("  mAbsoluteVolumeDevices.keySet()="); pw.println(dumpDeviceTypes(
-                mAbsoluteVolumeDeviceInfoMap.keySet()));
+        pw.print("  absolute volume devices="); pw.println(dumpDeviceTypes(
+                getAbsoluteVolumeDevicesWithBehavior(
+                        AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE)));
+        pw.print("  adjust-only absolute volume devices="); pw.println(dumpDeviceTypes(
+                getAbsoluteVolumeDevicesWithBehavior(
+                        AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY)));
         pw.print("  mExtVolumeController="); pw.println(mExtVolumeController);
         pw.print("  mHdmiAudioSystemClient="); pw.println(mHdmiAudioSystemClient);
         pw.print("  mHdmiPlaybackClient="); pw.println(mHdmiPlaybackClient);
         pw.print("  mHdmiTvClient="); pw.println(mHdmiTvClient);
         pw.print("  mHdmiSystemAudioSupported="); pw.println(mHdmiSystemAudioSupported);
-        pw.print("  mHdmiCecVolumeControlEnabled="); pw.println(mHdmiCecVolumeControlEnabled);
+        synchronized (mHdmiClientLock) {
+            pw.print("  mHdmiCecVolumeControlEnabled="); pw.println(mHdmiCecVolumeControlEnabled);
+        }
         pw.print("  mIsCallScreeningModeSupported="); pw.println(mIsCallScreeningModeSupported);
         pw.print("  mic mute FromSwitch=" + mMicMuteFromSwitch
                         + " FromRestrictions=" + mMicMuteFromRestrictions
@@ -12771,11 +12803,14 @@
     }
 
     /**
-     * Returns whether the input device uses absolute volume behavior. This is distinct
-     * from Bluetooth A2DP absolute volume behavior ({@link #isA2dpAbsoluteVolumeDevice}).
+     * Returns whether the input device uses absolute volume behavior, including its variants.
+     * For included volume behaviors, see {@link AudioManager.AbsoluteDeviceVolumeBehavior}.
+     *
+     * This is distinct from Bluetooth A2DP absolute volume behavior
+     * ({@link #isA2dpAbsoluteVolumeDevice}).
      */
     private boolean isAbsoluteVolumeDevice(int deviceType) {
-        return  mAbsoluteVolumeDeviceInfoMap.containsKey(deviceType);
+        return mAbsoluteVolumeDeviceInfoMap.containsKey(deviceType);
     }
 
     /**
@@ -12879,13 +12914,15 @@
         return mFullVolumeDevices.remove(audioSystemDeviceOut);
     }
 
-    private AbsoluteVolumeDeviceInfo addAudioSystemDeviceOutToAbsVolumeDevices(
-            int audioSystemDeviceOut, AbsoluteVolumeDeviceInfo info) {
+    private void addAudioSystemDeviceOutToAbsVolumeDevices(int audioSystemDeviceOut,
+            AbsoluteVolumeDeviceInfo info) {
         if (DEBUG_VOL) {
             Log.d(TAG, "Adding DeviceType: 0x" + Integer.toHexString(audioSystemDeviceOut)
-                    + " from mAbsoluteVolumeDeviceInfoMap");
+                    + " to mAbsoluteVolumeDeviceInfoMap with behavior "
+                    + AudioDeviceVolumeManager.volumeBehaviorName(info.mDeviceVolumeBehavior)
+            );
         }
-        return mAbsoluteVolumeDeviceInfoMap.put(audioSystemDeviceOut, info);
+        mAbsoluteVolumeDeviceInfoMap.put(audioSystemDeviceOut, info);
     }
 
     private AbsoluteVolumeDeviceInfo removeAudioSystemDeviceOutFromAbsVolumeDevices(
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 42031c6..748c4ce5 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -38,6 +38,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.MathUtils;
 
@@ -55,6 +56,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * Safe media volume management.
@@ -77,14 +79,16 @@
     // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
     // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
     // (when user opts out).
+    // Note: when CSD calculation is enabled the state is set to SAFE_MEDIA_VOLUME_DISABLED
     private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
     private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
     private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2;  // confirmed
     private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3;  // unconfirmed
 
-    private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = SAFE_MEDIA_VOLUME_MSG_START + 1;
+    private static final int MSG_CONFIGURE_SAFE_MEDIA = SAFE_MEDIA_VOLUME_MSG_START + 1;
     private static final int MSG_PERSIST_SAFE_VOLUME_STATE = SAFE_MEDIA_VOLUME_MSG_START + 2;
     private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = SAFE_MEDIA_VOLUME_MSG_START + 3;
+    private static final int MSG_PERSIST_CSD_VALUES = SAFE_MEDIA_VOLUME_MSG_START + 4;
 
     private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
 
@@ -100,14 +104,16 @@
     private static final int CSD_WARNING_TIMEOUT_MS_ACCUMULATION_START = -1;
     private static final int CSD_WARNING_TIMEOUT_MS_MOMENTARY_EXPOSURE = 5000;
 
+    private static final String PERSIST_CSD_RECORD_FIELD_SEPARATOR = ",";
+    private static final String PERSIST_CSD_RECORD_SEPARATOR_CHAR = "|";
+    private static final String PERSIST_CSD_RECORD_SEPARATOR = "\\|";
+
     private final EventLogger mLogger = new EventLogger(AudioService.LOG_NB_EVENTS_SOUND_DOSE,
             "CSD updates");
 
     private int mMcc = 0;
 
-    private final boolean mEnableCsd;
-
-    final Object mSafeMediaVolumeStateLock = new Object();
+    private final Object mSafeMediaVolumeStateLock = new Object();
     private int mSafeMediaVolumeState;
 
     // Used when safe volume warning message display is requested by setStreamVolume(). In this
@@ -148,10 +154,18 @@
     @NonNull private final AudioHandler mAudioHandler;
     @NonNull private final ISafeHearingVolumeController mVolumeController;
 
+    private final boolean mEnableCsd;
+
     private ISoundDose mSoundDose;
+
+    private final Object mCsdStateLock = new Object();
+
+    @GuardedBy("mCsdStateLock")
     private float mCurrentCsd = 0.f;
     // dose at which the next dose reached warning occurs
+    @GuardedBy("mCsdStateLock")
     private float mNextCsdWarning = 1.0f;
+    @GuardedBy("mCsdStateLock")
     private final List<SoundDoseRecord> mDoseRecords = new ArrayList<>();
 
     private final Context mContext;
@@ -169,11 +183,16 @@
         }
 
         public void onNewCsdValue(float currentCsd, SoundDoseRecord[] records) {
+            if (!mEnableCsd) {
+                Log.w(TAG, "onNewCsdValue: csd not supported, ignoring value");
+                return;
+            }
+
             Log.i(TAG, "onNewCsdValue: " + currentCsd);
-            if (mCurrentCsd < currentCsd) {
-                // dose increase: going over next threshold?
-                if ((mCurrentCsd < mNextCsdWarning) && (currentCsd >= mNextCsdWarning)) {
-                    if (mEnableCsd) {
+            synchronized (mCsdStateLock) {
+                if (mCurrentCsd < currentCsd) {
+                    // dose increase: going over next threshold?
+                    if ((mCurrentCsd < mNextCsdWarning) && (currentCsd >= mNextCsdWarning)) {
                         if (mNextCsdWarning == 5.0f) {
                             // 500% dose repeat
                             mVolumeController.postDisplayCsdWarning(
@@ -188,17 +207,18 @@
                                     getTimeoutMsForWarning(
                                             AudioManager.CSD_WARNING_DOSE_REACHED_1X));
                         }
+                        mNextCsdWarning += 1.0f;
                     }
-                    mNextCsdWarning += 1.0f;
+                } else {
+                    // dose decrease: dropping below previous threshold of warning?
+                    if ((currentCsd < mNextCsdWarning - 1.0f) && (
+                            mNextCsdWarning >= 2.0f)) {
+                        mNextCsdWarning -= 1.0f;
+                    }
                 }
-            } else {
-                // dose decrease: dropping below previous threshold of warning?
-                if ((currentCsd < mNextCsdWarning - 1.0f) && (mNextCsdWarning >= 2.0f)) {
-                    mNextCsdWarning -= 1.0f;
-                }
+                mCurrentCsd = currentCsd;
+                updateSoundDoseRecords_l(records, currentCsd);
             }
-            mCurrentCsd = currentCsd;
-            updateSoundDoseRecords(records, currentCsd);
         }
     };
 
@@ -213,20 +233,22 @@
 
         mContext = context;
 
-        mSafeMediaVolumeState = mSettings.getGlobalInt(audioService.getContentResolver(),
-                Settings.Global.AUDIO_SAFE_VOLUME_STATE, 0);
-
         mEnableCsd = mContext.getResources().getBoolean(R.bool.config_audio_csd_enabled_default);
+        if (mEnableCsd) {
+            mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
+        } else {
+            mSafeMediaVolumeState = mSettings.getGlobalInt(audioService.getContentResolver(),
+                    Settings.Global.AUDIO_SAFE_VOLUME_STATE, 0);
+        }
 
         // The default safe volume index read here will be replaced by the actual value when
-        // the mcc is read by onConfigureSafeVolume()
+        // the mcc is read by onConfigureSafeMedia()
+        // For now we use the same index for RS2 initial warning with CSD
         mSafeMediaVolumeIndex = mContext.getResources().getInteger(
                 R.integer.config_safe_media_volume_index) * 10;
 
         mAlarmManager = (AlarmManager) mContext.getSystemService(
                 Context.ALARM_SERVICE);
-
-        initCsd();
     }
 
     float getRs2Value() {
@@ -456,8 +478,8 @@
         }
     }
 
-    /*package*/ void configureSafeMediaVolume(boolean forced, String caller) {
-        int msg = MSG_CONFIGURE_SAFE_MEDIA_VOLUME;
+    /*package*/ void configureSafeMedia(boolean forced, String caller) {
+        int msg = MSG_CONFIGURE_SAFE_MEDIA;
         mAudioHandler.removeMessages(msg);
 
         long time = 0;
@@ -507,8 +529,8 @@
 
     /*package*/ void handleMessage(Message msg) {
         switch (msg.what) {
-            case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
-                onConfigureSafeVolume((msg.arg1 == 1), (String) msg.obj);
+            case MSG_CONFIGURE_SAFE_MEDIA:
+                onConfigureSafeMedia((msg.arg1 == 1), (String) msg.obj);
                 break;
             case MSG_PERSIST_SAFE_VOLUME_STATE:
                 onPersistSafeVolumeState(msg.arg1);
@@ -519,8 +541,13 @@
                         Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
                         UserHandle.USER_CURRENT);
                 break;
+            case MSG_PERSIST_CSD_VALUES:
+                onPersistSoundDoseRecords();
+                break;
+            default:
+                Log.e(TAG, "Unexpected msg to handle: " + msg.what);
+                break;
         }
-
     }
 
     /*package*/ void dump(PrintWriter pw) {
@@ -540,33 +567,47 @@
 
     /*package*/void reset() {
         Log.d(TAG, "Reset the sound dose helper");
-        initCsd();
-    }
-
-    private void initCsd() {
-        synchronized (mSafeMediaVolumeStateLock) {
-            if (mEnableCsd) {
-                Log.v(TAG, "Initializing sound dose");
-
-                mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
-                mSoundDose = AudioSystem.getSoundDoseInterface(mSoundDoseCallback);
-                try {
-                    if (mSoundDose != null && mSoundDose.asBinder().isBinderAlive()) {
-                        if (mCurrentCsd != 0.f) {
-                            Log.d(TAG, "Resetting the saved sound dose value " + mCurrentCsd);
-                            SoundDoseRecord[] records = mDoseRecords.toArray(
-                                    new SoundDoseRecord[0]);
-                            mSoundDose.resetCsd(mCurrentCsd, records);
-                        }
+        mSoundDose = AudioSystem.getSoundDoseInterface(mSoundDoseCallback);
+        synchronized (mCsdStateLock) {
+            try {
+                if (mSoundDose != null && mSoundDose.asBinder().isBinderAlive()) {
+                    if (mCurrentCsd != 0.f) {
+                        Log.d(TAG,
+                                "Resetting the saved sound dose value " + mCurrentCsd);
+                        SoundDoseRecord[] records = mDoseRecords.toArray(
+                                new SoundDoseRecord[0]);
+                        mSoundDose.resetCsd(mCurrentCsd, records);
                     }
-                } catch (RemoteException e) {
-                    // noop
                 }
+            } catch (RemoteException e) {
+                // noop
             }
         }
     }
 
-    private void onConfigureSafeVolume(boolean force, String caller) {
+    private void initCsd() {
+        if (mEnableCsd) {
+            Log.v(TAG, "Initializing sound dose");
+
+            synchronized (mCsdStateLock) {
+                // Restore persisted values
+                mCurrentCsd = parseGlobalSettingFloat(
+                        Settings.Global.AUDIO_SAFE_CSD_CURRENT_VALUE, /* defaultValue= */0.f);
+                mNextCsdWarning = parseGlobalSettingFloat(
+                        Settings.Global.AUDIO_SAFE_CSD_NEXT_WARNING, /* defaultValue= */1.f);
+                final List<SoundDoseRecord> records = persistedStringToRecordList(
+                        mSettings.getGlobalString(mAudioService.getContentResolver(),
+                                Settings.Global.AUDIO_SAFE_CSD_DOSE_RECORDS));
+                if (records != null) {
+                    mDoseRecords.addAll(records);
+                }
+            }
+
+            reset();
+        }
+    }
+
+    private void onConfigureSafeMedia(boolean force, String caller) {
         synchronized (mSafeMediaVolumeStateLock) {
             int mcc = mContext.getResources().getConfiguration().mcc;
             if ((mMcc != mcc) || ((mMcc == 0) && force)) {
@@ -612,6 +653,10 @@
                                 /*obj=*/null), /*delay=*/0);
             }
         }
+
+        if (mEnableCsd) {
+            initCsd();
+        }
     }
 
     private int getTimeoutMsForWarning(@AudioManager.CsdWarning int csdWarning) {
@@ -702,7 +747,8 @@
         return null;
     }
 
-    private void updateSoundDoseRecords(SoundDoseRecord[] newRecords, float currentCsd) {
+    @GuardedBy("mCsdStateLock")
+    private void updateSoundDoseRecords_l(SoundDoseRecord[] newRecords, float currentCsd) {
         long totalDuration = 0;
         for (SoundDoseRecord record : newRecords) {
             Log.i(TAG, "  new record: " + record);
@@ -722,9 +768,87 @@
             }
         }
 
+        mAudioHandler.sendMessageAtTime(mAudioHandler.obtainMessage(MSG_PERSIST_CSD_VALUES,
+                /* arg1= */0, /* arg2= */0, /* obj= */null), /* delay= */0);
+
         mLogger.enqueue(SoundDoseEvent.getDoseUpdateEvent(currentCsd, totalDuration));
     }
 
+    private void onPersistSoundDoseRecords() {
+        synchronized (mCsdStateLock) {
+            mSettings.putGlobalString(mAudioService.getContentResolver(),
+                    Settings.Global.AUDIO_SAFE_CSD_CURRENT_VALUE,
+                    Float.toString(mCurrentCsd));
+            mSettings.putGlobalString(mAudioService.getContentResolver(),
+                    Settings.Global.AUDIO_SAFE_CSD_NEXT_WARNING,
+                    Float.toString(mNextCsdWarning));
+            mSettings.putGlobalString(mAudioService.getContentResolver(),
+                    Settings.Global.AUDIO_SAFE_CSD_DOSE_RECORDS,
+                    mDoseRecords.stream().map(
+                            SoundDoseHelper::recordToPersistedString).collect(
+                            Collectors.joining(PERSIST_CSD_RECORD_SEPARATOR_CHAR)));
+        }
+    }
+
+    private static String recordToPersistedString(SoundDoseRecord record) {
+        return record.timestamp
+                + PERSIST_CSD_RECORD_FIELD_SEPARATOR + record.duration
+                + PERSIST_CSD_RECORD_FIELD_SEPARATOR + record.value
+                + PERSIST_CSD_RECORD_FIELD_SEPARATOR + record.averageMel;
+    }
+
+    private static List<SoundDoseRecord> persistedStringToRecordList(String records) {
+        if (records == null || records.isEmpty()) {
+            return null;
+        }
+        return Arrays.stream(TextUtils.split(records, PERSIST_CSD_RECORD_SEPARATOR)).map(
+                SoundDoseHelper::persistedStringToRecord).filter(Objects::nonNull).collect(
+                Collectors.toList());
+    }
+
+    private static SoundDoseRecord persistedStringToRecord(String record) {
+        if (record == null || record.isEmpty()) {
+            return null;
+        }
+        final String[] fields = TextUtils.split(record, PERSIST_CSD_RECORD_FIELD_SEPARATOR);
+        if (fields.length != 4) {
+            Log.w(TAG, "Expecting 4 fields for a SoundDoseRecord, parsed " + fields.length);
+            return null;
+        }
+
+        final SoundDoseRecord sdRecord = new SoundDoseRecord();
+        try {
+            sdRecord.timestamp = Long.parseLong(fields[0]);
+            sdRecord.duration = Integer.parseInt(fields[1]);
+            sdRecord.value = Float.parseFloat(fields[2]);
+            sdRecord.averageMel = Float.parseFloat(fields[3]);
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "Unable to parse persisted SoundDoseRecord: " + record, e);
+            return null;
+        }
+
+        return sdRecord;
+    }
+
+    private float parseGlobalSettingFloat(String audioSafeCsdCurrentValue, float defaultValue) {
+        String stringValue = mSettings.getGlobalString(mAudioService.getContentResolver(),
+                audioSafeCsdCurrentValue);
+        if (stringValue == null || stringValue.isEmpty()) {
+            Log.v(TAG, "No value stored in settings " + audioSafeCsdCurrentValue);
+            return defaultValue;
+        }
+
+        float value;
+        try {
+            value = Float.parseFloat(stringValue);
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "Error parsing float from settings " + audioSafeCsdCurrentValue, e);
+            value = defaultValue;
+        }
+
+        return value;
+    }
+
     // StreamVolumeCommand contains the information needed to defer the process of
     // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
     private static class StreamVolumeCommand {
diff --git a/services/core/java/com/android/server/backup/SetUtils.java b/services/core/java/com/android/server/backup/SetUtils.java
new file mode 100644
index 0000000..ae70e19
--- /dev/null
+++ b/services/core/java/com/android/server/backup/SetUtils.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Helper class containing common operation on {@link java.util.Set}.
+ */
+public final class SetUtils {
+    // Statics only
+    private SetUtils() {}
+
+    /**
+     * Returns union of two sets.
+     */
+    public static <T> Set<T> union(Set<T> set1, Set<T> set2) {
+        Set<T> unionSet = new HashSet<>(set1);
+        unionSet.addAll(set2);
+        return unionSet;
+    }
+}
diff --git a/services/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java
index 35df3ee..224e34d 100644
--- a/services/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/services/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -30,6 +30,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.Slog;
 
 import com.google.android.collect.Sets;
@@ -84,29 +85,50 @@
     // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
     private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY;
 
-    private static final Set<String> sEligibleForMultiUser = Sets.newArraySet(
-            PERMISSION_HELPER, NOTIFICATION_HELPER, SYNC_SETTINGS_HELPER, APP_LOCALES_HELPER,
-            ACCOUNT_MANAGER_HELPER, USAGE_STATS_HELPER, PREFERRED_HELPER);
+    /**
+     * Helpers that are enabled for "profile" users (such as work profile). See {@link
+     * UserManager#isProfile()}. This is a subset of {@link #sEligibleHelpersForNonSystemUser}.
+     */
+    private static final Set<String> sEligibleHelpersForProfileUser =
+            Sets.newArraySet(
+                    PERMISSION_HELPER,
+                    NOTIFICATION_HELPER,
+                    SYNC_SETTINGS_HELPER,
+                    APP_LOCALES_HELPER);
+
+    /** Helpers that are enabled for full, non-system users. */
+    private static final Set<String> sEligibleHelpersForNonSystemUser =
+            SetUtils.union(sEligibleHelpersForProfileUser,
+                    Sets.newArraySet(ACCOUNT_MANAGER_HELPER, USAGE_STATS_HELPER, PREFERRED_HELPER,
+                            SHORTCUT_MANAGER_HELPER));
 
     private int mUserId = UserHandle.USER_SYSTEM;
+    private boolean mIsProfileUser = false;
 
     @Override
     public void onCreate(UserHandle user, @BackupDestination int backupDestination) {
         super.onCreate(user, backupDestination);
 
         mUserId = user.getIdentifier();
+        if (mUserId != UserHandle.USER_SYSTEM) {
+            Context context = createContextAsUser(user, /* flags= */ 0);
+            UserManager userManager = context.getSystemService(UserManager.class);
+            mIsProfileUser = userManager.isProfile();
+        }
 
-        addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this, mUserId));
-        addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper(mUserId));
-        addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(mUserId));
-        addHelper(PERMISSION_HELPER, new PermissionBackupHelper(mUserId));
-        addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(mUserId));
-        addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper());
-        addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper(mUserId));
-        addHelper(SLICES_HELPER, new SliceBackupHelper(this));
-        addHelper(PEOPLE_HELPER, new PeopleBackupHelper(mUserId));
-        addHelper(APP_LOCALES_HELPER, new AppSpecificLocalesBackupHelper(mUserId));
-        addHelper(APP_GENDER_HELPER, new AppGrammaticalGenderBackupHelper(mUserId));
+        addHelperIfEligibleForUser(
+                SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this, mUserId));
+        addHelperIfEligibleForUser(PREFERRED_HELPER, new PreferredActivityBackupHelper(mUserId));
+        addHelperIfEligibleForUser(NOTIFICATION_HELPER, new NotificationBackupHelper(mUserId));
+        addHelperIfEligibleForUser(PERMISSION_HELPER, new PermissionBackupHelper(mUserId));
+        addHelperIfEligibleForUser(USAGE_STATS_HELPER, new UsageStatsBackupHelper(mUserId));
+        addHelperIfEligibleForUser(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper(mUserId));
+        addHelperIfEligibleForUser(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper(mUserId));
+        addHelperIfEligibleForUser(SLICES_HELPER, new SliceBackupHelper(this));
+        addHelperIfEligibleForUser(PEOPLE_HELPER, new PeopleBackupHelper(mUserId));
+        addHelperIfEligibleForUser(APP_LOCALES_HELPER, new AppSpecificLocalesBackupHelper(mUserId));
+        addHelperIfEligibleForUser(APP_GENDER_HELPER,
+                new AppGrammaticalGenderBackupHelper(mUserId));
     }
 
     @Override
@@ -130,15 +152,6 @@
         super.onRestore(data, appVersionCode, newState);
     }
 
-    @Override
-    public void addHelper(String keyPrefix, BackupHelper helper) {
-        if (mUserId != UserHandle.USER_SYSTEM && !sEligibleForMultiUser.contains(keyPrefix)) {
-            return;
-        }
-
-        super.addHelper(keyPrefix, helper);
-    }
-
     /**
      * Support for 'adb restore' of legacy archives
      */
@@ -189,4 +202,25 @@
             }
         }
     }
+
+    private void addHelperIfEligibleForUser(String keyPrefix, BackupHelper helper) {
+        if (isHelperEligibleForUser(keyPrefix)) {
+            addHelper(keyPrefix, helper);
+        }
+    }
+
+    private boolean isHelperEligibleForUser(String keyPrefix) {
+        // All helpers are eligible for the system user.
+        if (mUserId == UserHandle.USER_SYSTEM) {
+            return true;
+        }
+
+        // Profile users (such as work profile) have their own allow list.
+        if (mIsProfileUser) {
+            return sEligibleHelpersForProfileUser.contains(keyPrefix);
+        }
+
+        // Full, non-system users have their own allow list.
+        return sEligibleHelpersForNonSystemUser.contains(keyPrefix);
+    }
 }
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index c8d43e4..ffa5d20 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -563,6 +563,14 @@
                 }
             }
 
+            // Set the default subtitle if necessary.
+            if (promptInfo.isUseDefaultSubtitle()) {
+                if (TextUtils.isEmpty(promptInfo.getSubtitle())) {
+                    promptInfo.setSubtitle(getContext()
+                            .getString(R.string.biometric_dialog_default_subtitle));
+                }
+            }
+
             final long requestId = mRequestCounter.get();
             mHandler.post(() -> handleAuthenticate(
                     token, requestId, operationId, userId, receiver, opPackageName, promptInfo));
diff --git a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
index 969a174..0b5c1c1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
+++ b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
@@ -150,6 +150,13 @@
     }
 
     /**
+     * Returns if the sensor is side fps.
+     */
+    public boolean isSfps() {
+        return mSidefpsController.isPresent();
+    }
+
+    /**
      * Consumer for a biometric overlay controller.
      *
      * This behaves like a normal {@link Consumer} except that it will trap and log
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index a90679e..932c0b4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -236,8 +236,14 @@
 
     @Override
     public void onError(int errorCode, int vendorCode) {
-        super.onError(errorCode, vendorCode);
-
+        if (errorCode == BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR
+                && vendorCode == BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED
+                && mSensorOverlays.isSfps()) {
+            super.onError(BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED,
+                    0 /* vendorCode */);
+        } else {
+            super.onError(errorCode, vendorCode);
+        }
         if (errorCode == BiometricFingerprintConstants.FINGERPRINT_ERROR_BAD_CALIBRATION) {
             BiometricNotificationUtils.showBadCalibrationNotification(getContext());
         }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 513b3e3..cf54662 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -146,7 +146,14 @@
             }
         });
         mCallback.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
-        super.onAcquired(acquiredInfo, vendorCode);
+        if (acquiredInfo == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR
+                && vendorCode == BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED
+                && mSensorOverlays.isSfps()) {
+            super.onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED,
+                    0 /* vendorCode */);
+        } else {
+            super.onAcquired(acquiredInfo, vendorCode);
+        }
     }
 
     @Override
@@ -274,8 +281,5 @@
     }
 
     @Override
-    public void onPowerPressed() {
-        onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED,
-                0 /* vendorCode */);
-    }
+    public void onPowerPressed() { }
 }
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 0b03005..12134f7 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -247,7 +247,7 @@
         private long mDurationOrStartTimeMs;  // Either start time, or duration once completed
 
         CameraUsageEvent(String cameraId, int facing, String clientName, int apiLevel,
-                boolean isNdk, int action, int latencyMs, int operatingMode) {
+                boolean isNdk, int action, int latencyMs, int operatingMode, boolean deviceError) {
             mCameraId = cameraId;
             mCameraFacing = facing;
             mClientName = clientName;
@@ -258,6 +258,7 @@
             mAction = action;
             mLatencyMs = latencyMs;
             mOperatingMode = operatingMode;
+            mDeviceError = deviceError;
         }
 
         public void markCompleted(int internalReconfigure, long requestCount,
@@ -1108,7 +1109,7 @@
                     CameraUsageEvent openEvent = new CameraUsageEvent(
                             cameraId, facing, clientName, apiLevel, isNdk,
                             FrameworkStatsLog.CAMERA_ACTION_EVENT__ACTION__OPEN,
-                            latencyMs, sessionType);
+                            latencyMs, sessionType, deviceError);
                     mCameraUsageHistory.add(openEvent);
                     break;
                 case CameraSessionStats.CAMERA_STATE_ACTIVE:
@@ -1135,7 +1136,7 @@
                     CameraUsageEvent newEvent = new CameraUsageEvent(
                             cameraId, facing, clientName, apiLevel, isNdk,
                             FrameworkStatsLog.CAMERA_ACTION_EVENT__ACTION__SESSION,
-                            latencyMs, sessionType);
+                            latencyMs, sessionType, deviceError);
                     CameraUsageEvent oldEvent = mActiveCameraUsage.put(cameraId, newEvent);
                     if (oldEvent != null) {
                         Slog.w(TAG, "Camera " + cameraId + " was already marked as active");
@@ -1154,6 +1155,8 @@
                                 resultErrorCount, deviceError, streamStats, userTag,
                                 videoStabilizationMode);
                         mCameraUsageHistory.add(doneEvent);
+                        // Do not double count device error
+                        deviceError = false;
 
                         // Check current active camera IDs to see if this package is still
                         // talking to some camera
@@ -1177,7 +1180,7 @@
                         CameraUsageEvent closeEvent = new CameraUsageEvent(
                                 cameraId, facing, clientName, apiLevel, isNdk,
                                 FrameworkStatsLog.CAMERA_ACTION_EVENT__ACTION__CLOSE,
-                                latencyMs, sessionType);
+                                latencyMs, sessionType, deviceError);
                         mCameraUsageHistory.add(closeEvent);
                     }
 
diff --git a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
index dce1c96..39c649b 100644
--- a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
+++ b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
@@ -111,7 +111,7 @@
         bb.order(ByteOrder.LITTLE_ENDIAN);
         final int msgLen = bb.getInt();
 
-        if (msgLen <= 0 || msgLen > MAX_CLIPBOARD_BYTES) {
+        if (msgLen < 0 || msgLen > MAX_CLIPBOARD_BYTES) {
             throw new ProtocolException("Clipboard message length: " + msgLen + " out of bounds.");
         }
 
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 064cd2d..43ee5e2 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -25,6 +25,7 @@
 import static com.android.server.devicestate.DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
 import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_BASE_STATE;
 import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_EMULATED_STATE;
+import static com.android.server.devicestate.OverrideRequestController.FLAG_THERMAL_CRITICAL;
 import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
 import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
 import static com.android.server.devicestate.OverrideRequestController.STATUS_UNKNOWN;
@@ -33,6 +34,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.app.TaskStackListener;
 import android.content.Context;
 import android.hardware.devicestate.DeviceStateInfo;
@@ -183,6 +185,9 @@
     ActivityTaskManagerInternal.ScreenObserver mOverrideRequestScreenObserver =
             new OverrideRequestScreenObserver();
 
+    @NonNull
+    private final DeviceStateNotificationController mDeviceStateNotificationController;
+
     public DeviceStateManagerService(@NonNull Context context) {
         this(context, DeviceStatePolicy.Provider
                 .fromResources(context.getResources())
@@ -211,6 +216,13 @@
         mDeviceStatePolicy.getDeviceStateProvider().setListener(mDeviceStateProviderListener);
         mBinderService = new BinderService();
         mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
+        mDeviceStateNotificationController = new DeviceStateNotificationController(
+                context, mHandler,
+                () -> {
+                    synchronized (mLock) {
+                        mActiveOverride.ifPresent(mOverrideRequestController::cancelRequest);
+                    }
+                });
     }
 
     @Override
@@ -346,7 +358,8 @@
         return mBinderService;
     }
 
-    private void updateSupportedStates(DeviceState[] supportedDeviceStates) {
+    private void updateSupportedStates(DeviceState[] supportedDeviceStates,
+            @DeviceStateProvider.SupportedStatesUpdatedReason int reason) {
         synchronized (mLock) {
             final int[] oldStateIdentifiers = getSupportedStateIdentifiersLocked();
 
@@ -370,7 +383,7 @@
                 return;
             }
 
-            mOverrideRequestController.handleNewSupportedStates(newStateIdentifiers);
+            mOverrideRequestController.handleNewSupportedStates(newStateIdentifiers, reason);
             updatePendingStateLocked();
 
             setRearDisplayStateLocked();
@@ -596,7 +609,7 @@
 
     @GuardedBy("mLock")
     private void onOverrideRequestStatusChangedLocked(@NonNull OverrideRequest request,
-            @OverrideRequestController.RequestStatus int status) {
+            @OverrideRequestController.RequestStatus int status, int flags) {
         if (request.getRequestType() == OVERRIDE_REQUEST_TYPE_BASE_STATE) {
             switch (status) {
                 case STATUS_ACTIVE:
@@ -616,10 +629,19 @@
             switch (status) {
                 case STATUS_ACTIVE:
                     mActiveOverride = Optional.of(request);
+                    mDeviceStateNotificationController.showStateActiveNotificationIfNeeded(
+                            request.getRequestedState(), request.getUid());
                     break;
                 case STATUS_CANCELED:
                     if (mActiveOverride.isPresent() && mActiveOverride.get() == request) {
                         mActiveOverride = Optional.empty();
+                        mDeviceStateNotificationController.cancelNotification(
+                                request.getRequestedState());
+                        if ((flags & FLAG_THERMAL_CRITICAL) == FLAG_THERMAL_CRITICAL) {
+                            mDeviceStateNotificationController
+                                    .showThermalCriticalNotificationIfNeeded(
+                                            request.getRequestedState());
+                        }
                     }
                     break;
                 case STATUS_UNKNOWN: // same as default
@@ -700,7 +722,7 @@
         }
     }
 
-    private void requestStateInternal(int state, int flags, int callingPid,
+    private void requestStateInternal(int state, int flags, int callingPid, int callingUid,
             @NonNull IBinder token, boolean hasControlDeviceStatePermission) {
         synchronized (mLock) {
             final ProcessRecord processRecord = mProcessRecords.get(callingPid);
@@ -721,8 +743,8 @@
                         + " is not supported.");
             }
 
-            OverrideRequest request = new OverrideRequest(token, callingPid, state, flags,
-                    OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+            OverrideRequest request = new OverrideRequest(token, callingPid, callingUid,
+                    state, flags, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
             // If we don't have the CONTROL_DEVICE_STATE permission, we want to show the overlay
             if (!hasControlDeviceStatePermission && mRearDisplayState != null
@@ -762,7 +784,7 @@
     }
 
     private void requestBaseStateOverrideInternal(int state, int flags, int callingPid,
-            @NonNull IBinder token) {
+            int callingUid, @NonNull IBinder token) {
         synchronized (mLock) {
             final Optional<DeviceState> deviceState = getStateLocked(state);
             if (!deviceState.isPresent()) {
@@ -782,8 +804,8 @@
                         + " token: " + token);
             }
 
-            OverrideRequest request = new OverrideRequest(token, callingPid, state, flags,
-                    OVERRIDE_REQUEST_TYPE_BASE_STATE);
+            OverrideRequest request = new OverrideRequest(token, callingPid, callingUid,
+                    state, flags, OVERRIDE_REQUEST_TYPE_BASE_STATE);
             mOverrideRequestController.addBaseStateRequest(request);
         }
     }
@@ -953,11 +975,12 @@
         @IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int mCurrentBaseState;
 
         @Override
-        public void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates) {
+        public void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates,
+                @DeviceStateProvider.SupportedStatesUpdatedReason int reason) {
             if (newDeviceStates.length == 0) {
                 throw new IllegalArgumentException("Supported device states must not be empty");
             }
-            updateSupportedStates(newDeviceStates);
+            updateSupportedStates(newDeviceStates, reason);
         }
 
         @Override
@@ -1085,6 +1108,7 @@
         @Override // Binder call
         public void requestState(IBinder token, int state, int flags) {
             final int callingPid = Binder.getCallingPid();
+            final int callingUid = Binder.getCallingUid();
             // Allow top processes to request a device state change
             // If the calling process ID is not the top app, then we check if this process
             // holds a permission to CONTROL_DEVICE_STATE
@@ -1099,7 +1123,8 @@
 
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
-                requestStateInternal(state, flags, callingPid, token, hasControlStatePermission);
+                requestStateInternal(state, flags, callingPid, callingUid, token,
+                        hasControlStatePermission);
             } finally {
                 Binder.restoreCallingIdentity(callingIdentity);
             }
@@ -1124,6 +1149,7 @@
         @Override // Binder call
         public void requestBaseStateOverride(IBinder token, int state, int flags) {
             final int callingPid = Binder.getCallingPid();
+            final int callingUid = Binder.getCallingUid();
             getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
                     "Permission required to control base state of device.");
 
@@ -1133,7 +1159,7 @@
 
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
-                requestBaseStateOverrideInternal(state, flags, callingPid, token);
+                requestBaseStateOverrideInternal(state, flags, callingPid, callingUid, token);
             } finally {
                 Binder.restoreCallingIdentity(callingIdentity);
             }
@@ -1210,7 +1236,8 @@
 
     private class OverrideRequestTaskStackListener extends TaskStackListener {
         @Override
-        public void onTaskStackChanged() throws RemoteException {
+        public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
+                throws RemoteException {
             synchronized (mLock) {
                 if (!shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
                     return;
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateNotificationController.java b/services/core/java/com/android/server/devicestate/DeviceStateNotificationController.java
new file mode 100644
index 0000000..9008740
--- /dev/null
+++ b/services/core/java/com/android/server/devicestate/DeviceStateNotificationController.java
@@ -0,0 +1,296 @@
+/*
+ * 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.devicestate;
+
+import android.annotation.DrawableRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.hardware.devicestate.DeviceStateManager;
+import android.os.Handler;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Manages the user-visible device state notifications.
+ */
+class DeviceStateNotificationController extends BroadcastReceiver {
+    private static final String TAG = "DeviceStateNotificationController";
+
+    @VisibleForTesting static final String INTENT_ACTION_CANCEL_STATE =
+            "com.android.server.devicestate.INTENT_ACTION_CANCEL_STATE";
+    @VisibleForTesting static final int NOTIFICATION_ID = 1;
+    @VisibleForTesting static final String CHANNEL_ID = "DeviceStateManager";
+    @VisibleForTesting static final String NOTIFICATION_TAG = "DeviceStateManager";
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final NotificationManager mNotificationManager;
+    private final PackageManager mPackageManager;
+
+    // Stores the notification title and content indexed with the device state identifier.
+    private final SparseArray<NotificationInfo> mNotificationInfos;
+
+    // The callback when a device state is requested to be canceled.
+    private final Runnable mCancelStateRunnable;
+
+    DeviceStateNotificationController(@NonNull Context context, @NonNull Handler handler,
+            @NonNull Runnable cancelStateRunnable) {
+        this(context, handler, cancelStateRunnable, getNotificationInfos(context),
+                context.getPackageManager(), context.getSystemService(NotificationManager.class));
+    }
+
+    @VisibleForTesting
+    DeviceStateNotificationController(
+            @NonNull Context context, @NonNull Handler handler,
+            @NonNull Runnable cancelStateRunnable,
+            @NonNull SparseArray<NotificationInfo> notificationInfos,
+            @NonNull PackageManager packageManager,
+            @NonNull NotificationManager notificationManager) {
+        mContext = context;
+        mHandler = handler;
+        mCancelStateRunnable = cancelStateRunnable;
+        mNotificationInfos = notificationInfos;
+        mPackageManager = packageManager;
+        mNotificationManager = notificationManager;
+        mContext.registerReceiver(
+                this,
+                new IntentFilter(INTENT_ACTION_CANCEL_STATE),
+                android.Manifest.permission.CONTROL_DEVICE_STATE,
+                mHandler,
+                Context.RECEIVER_NOT_EXPORTED);
+    }
+
+    /**
+     * Displays the ongoing notification indicating that the device state is active. Does nothing if
+     * the state does not have an active notification.
+     *
+     * @param state the active device state identifier.
+     * @param requestingAppUid the uid of the requesting app used to retrieve the app name.
+     */
+    void showStateActiveNotificationIfNeeded(int state, int requestingAppUid) {
+        NotificationInfo info = mNotificationInfos.get(state);
+        if (info == null || !info.hasActiveNotification()) {
+            return;
+        }
+        String requesterApplicationLabel = getApplicationLabel(requestingAppUid);
+        if (requesterApplicationLabel != null) {
+            showNotification(
+                    info.name, info.activeNotificationTitle,
+                    String.format(info.activeNotificationContent, requesterApplicationLabel),
+                    true /* ongoing */, R.drawable.ic_dual_screen
+            );
+        } else {
+            Slog.e(TAG, "Cannot determine the requesting app name when showing state active "
+                    + "notification. uid=" + requestingAppUid + ", state=" + state);
+        }
+    }
+
+    /**
+     * Displays the notification indicating that the device state is canceled due to thermal
+     * critical condition. Does nothing if the state does not have a thermal critical notification.
+     *
+     * @param state the identifier of the device state being canceled.
+     */
+    void showThermalCriticalNotificationIfNeeded(int state) {
+        NotificationInfo info = mNotificationInfos.get(state);
+        if (info == null || !info.hasThermalCriticalNotification()) {
+            return;
+        }
+        showNotification(
+                info.name, info.thermalCriticalNotificationTitle,
+                info.thermalCriticalNotificationContent, false /* ongoing */,
+                R.drawable.ic_thermostat
+        );
+    }
+
+    /**
+     * Cancels the notification of the corresponding device state.
+     *
+     * @param state the device state identifier.
+     */
+    void cancelNotification(int state) {
+        if (!mNotificationInfos.contains(state)) {
+            return;
+        }
+        mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
+    }
+
+    @Override
+    public void onReceive(@NonNull Context context, @Nullable Intent intent) {
+        if (intent != null) {
+            if (INTENT_ACTION_CANCEL_STATE.equals(intent.getAction())) {
+                mCancelStateRunnable.run();
+            }
+        }
+    }
+
+    /**
+     * Displays a notification with the specified name, title, and content.
+     *
+     * @param name the name of the notification.
+     * @param title the title of the notification.
+     * @param content the content of the notification.
+     * @param ongoing if true, display an ongoing (sticky) notification with a turn off button.
+     */
+    private void showNotification(
+            @NonNull String name, @NonNull String title, @NonNull String content, boolean ongoing,
+            @DrawableRes int iconRes) {
+        final NotificationChannel channel = new NotificationChannel(
+                CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH);
+        final Notification.Builder builder = new Notification.Builder(mContext, CHANNEL_ID)
+                .setSmallIcon(iconRes)
+                .setContentTitle(title)
+                .setContentText(content)
+                .setSubText(name)
+                .setLocalOnly(true)
+                .setOngoing(ongoing)
+                .setCategory(Notification.CATEGORY_SYSTEM);
+
+        if (ongoing) {
+            final Intent intent = new Intent(INTENT_ACTION_CANCEL_STATE)
+                    .setPackage(mContext.getPackageName());
+            final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                    mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE);
+            final Notification.Action action = new Notification.Action.Builder(
+                    null /* icon */,
+                    mContext.getString(R.string.device_state_notification_turn_off_button),
+                    pendingIntent)
+                    .build();
+            builder.addAction(action);
+        }
+
+        mNotificationManager.createNotificationChannel(channel);
+        mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_ID, builder.build());
+    }
+
+    /**
+     * Loads the resources for the notifications. The device state identifiers and strings are
+     * stored in arrays. All the string arrays must have the same length and same order as the
+     * identifier array.
+     */
+    private static SparseArray<NotificationInfo> getNotificationInfos(Context context) {
+        final SparseArray<NotificationInfo> notificationInfos = new SparseArray<>();
+
+        final int[] stateIdentifiers =
+                context.getResources().getIntArray(
+                        R.array.device_state_notification_state_identifiers);
+        final String[] names =
+                context.getResources().getStringArray(R.array.device_state_notification_names);
+        final String[] activeNotificationTitles =
+                context.getResources().getStringArray(
+                        R.array.device_state_notification_active_titles);
+        final String[] activeNotificationContents =
+                context.getResources().getStringArray(
+                        R.array.device_state_notification_active_contents);
+        final String[] thermalCriticalNotificationTitles =
+                context.getResources().getStringArray(
+                        R.array.device_state_notification_thermal_titles);
+        final String[] thermalCriticalNotificationContents =
+                context.getResources().getStringArray(
+                        R.array.device_state_notification_thermal_contents);
+
+        if (stateIdentifiers.length != names.length
+                || stateIdentifiers.length != activeNotificationTitles.length
+                || stateIdentifiers.length != activeNotificationContents.length
+                || stateIdentifiers.length != thermalCriticalNotificationTitles.length
+                || stateIdentifiers.length != thermalCriticalNotificationContents.length
+        ) {
+            throw new IllegalStateException(
+                    "The length of state identifiers and notification texts must match!");
+        }
+
+        for (int i = 0; i < stateIdentifiers.length; i++) {
+            int identifier = stateIdentifiers[i];
+            if (identifier == DeviceStateManager.INVALID_DEVICE_STATE) {
+                continue;
+            }
+
+            notificationInfos.put(
+                    identifier,
+                    new NotificationInfo(
+                            names[i], activeNotificationTitles[i], activeNotificationContents[i],
+                            thermalCriticalNotificationTitles[i],
+                            thermalCriticalNotificationContents[i])
+            );
+        }
+
+        return notificationInfos;
+    }
+
+    /**
+     * A helper function to get app name (label) using the app uid.
+     *
+     * @param uid the uid of the app.
+     * @return app name (label) if found, or null otherwise.
+     */
+    @Nullable
+    private String getApplicationLabel(int uid) {
+        String packageName = mPackageManager.getNameForUid(uid);
+        try {
+            ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
+                    packageName, PackageManager.ApplicationInfoFlags.of(0));
+            return appInfo.loadLabel(mPackageManager).toString();
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
+        }
+    }
+
+    /**
+     * A data class storing string resources of the notification of a device state.
+     */
+    @VisibleForTesting
+    static class NotificationInfo {
+        public final String name;
+        public final String activeNotificationTitle;
+        public final String activeNotificationContent;
+        public final String thermalCriticalNotificationTitle;
+        public final String thermalCriticalNotificationContent;
+
+        NotificationInfo(String name, String activeNotificationTitle,
+                String activeNotificationContent, String thermalCriticalNotificationTitle,
+                String thermalCriticalNotificationContent) {
+
+            this.name = name;
+            this.activeNotificationTitle = activeNotificationTitle;
+            this.activeNotificationContent = activeNotificationContent;
+            this.thermalCriticalNotificationTitle = thermalCriticalNotificationTitle;
+            this.thermalCriticalNotificationContent = thermalCriticalNotificationContent;
+        }
+
+        boolean hasActiveNotification() {
+            return activeNotificationTitle != null && activeNotificationTitle.length() > 0;
+        }
+
+        boolean hasThermalCriticalNotification() {
+            return thermalCriticalNotificationTitle != null
+                    && thermalCriticalNotificationTitle.length() > 0;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
index 109bf63..fecc13f 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
@@ -19,8 +19,12 @@
 import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STATE;
 import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
 
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Responsible for providing the set of supported {@link DeviceState device states} as well as the
  * current device state.
@@ -28,12 +32,42 @@
  * @see DeviceStatePolicy
  */
 public interface DeviceStateProvider {
+    int SUPPORTED_DEVICE_STATES_CHANGED_DEFAULT = 0;
+
+    /**
+     * Indicating that the supported device states changed callback is trigger for initial listener
+     * registration.
+     */
+    int SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED = 1;
+
+    /**
+     * Indicating that the supported device states have changed because the thermal condition
+     * returned to normal status from critical status.
+     */
+    int SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_NORMAL = 2;
+
+    /**
+     * Indicating that the supported device states have changed because of thermal critical
+     * condition.
+     */
+    int SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_CRITICAL = 3;
+
+    @IntDef(prefix = { "SUPPORTED_DEVICE_STATES_CHANGED_" }, value = {
+            SUPPORTED_DEVICE_STATES_CHANGED_DEFAULT,
+            SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED,
+            SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_NORMAL,
+            SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_CRITICAL
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface SupportedStatesUpdatedReason {}
+
     /**
      * Registers a listener for changes in provider state.
      * <p>
-     * It is <b>required</b> that {@link Listener#onSupportedDeviceStatesChanged(DeviceState[])} be
-     * called followed by {@link Listener#onStateChanged(int)} with the initial values on successful
-     * registration of the listener.
+     * It is <b>required</b> that
+     * {@link Listener#onSupportedDeviceStatesChanged(DeviceState[], int)} be called followed by
+     * {@link Listener#onStateChanged(int)} with the initial values on successful registration of
+     * the listener.
      */
     void setListener(Listener listener);
 
@@ -53,18 +87,20 @@
          * to zero and there must always be at least one supported device state.
          *
          * @param newDeviceStates array of supported device states.
+         * @param reason the reason for the supported device states change.
          *
          * @throws IllegalArgumentException if the list of device states is empty or if one of the
          * provided states contains an invalid identifier.
          */
-        void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates);
+        void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates,
+                @SupportedStatesUpdatedReason int reason);
 
         /**
          * Called to notify the listener of a change in current device state. Required to be called
          * once on successful registration of the listener and then once on every subsequent change
          * in device state. Value must have been included in the set of supported device states
          * provided in the most recent call to
-         * {@link #onSupportedDeviceStatesChanged(DeviceState[])}.
+         * {@link #onSupportedDeviceStatesChanged(DeviceState[], int)}.
          *
          * @param identifier the identifier of the new device state.
          *
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequest.java b/services/core/java/com/android/server/devicestate/OverrideRequest.java
index 325e384..74cf184 100644
--- a/services/core/java/com/android/server/devicestate/OverrideRequest.java
+++ b/services/core/java/com/android/server/devicestate/OverrideRequest.java
@@ -31,6 +31,7 @@
 final class OverrideRequest {
     private final IBinder mToken;
     private final int mPid;
+    private final int mUid;
     private final int mRequestedState;
     @DeviceStateRequest.RequestFlags
     private final int mFlags;
@@ -68,10 +69,11 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface OverrideRequestType {}
 
-    OverrideRequest(IBinder token, int pid, int requestedState,
+    OverrideRequest(IBinder token, int pid, int uid, int requestedState,
             @DeviceStateRequest.RequestFlags int flags, @OverrideRequestType int requestType) {
         mToken = token;
         mPid = pid;
+        mUid = uid;
         mRequestedState = requestedState;
         mFlags = flags;
         mRequestType = requestType;
@@ -85,6 +87,10 @@
         return mPid;
     }
 
+    int getUid() {
+        return mUid;
+    }
+
     int getRequestedState() {
         return mRequestedState;
     }
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequestController.java b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
index e39c732..2ed4765 100644
--- a/services/core/java/com/android/server/devicestate/OverrideRequestController.java
+++ b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
@@ -59,6 +59,11 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface RequestStatus {}
 
+    /**
+     * A flag indicating that the status change was triggered by thermal critical status.
+     */
+    static final int FLAG_THERMAL_CRITICAL = 1 << 0;
+
     static String statusToString(@RequestStatus int status) {
         switch (status) {
             case STATUS_ACTIVE:
@@ -106,7 +111,7 @@
     void addRequest(@NonNull OverrideRequest request) {
         OverrideRequest previousRequest = mRequest;
         mRequest = request;
-        mListener.onStatusChanged(request, STATUS_ACTIVE);
+        mListener.onStatusChanged(request, STATUS_ACTIVE, 0 /* flags */);
 
         if (previousRequest != null) {
             cancelRequestLocked(previousRequest);
@@ -116,7 +121,7 @@
     void addBaseStateRequest(@NonNull OverrideRequest request) {
         OverrideRequest previousRequest = mBaseStateRequest;
         mBaseStateRequest = request;
-        mListener.onStatusChanged(request, STATUS_ACTIVE);
+        mListener.onStatusChanged(request, STATUS_ACTIVE, 0 /* flags */);
 
         if (previousRequest != null) {
             cancelRequestLocked(previousRequest);
@@ -219,14 +224,17 @@
      * Notifies the controller that the set of supported states has changed. The controller will
      * notify the listener of all changes to request status as a result of this change.
      */
-    void handleNewSupportedStates(int[] newSupportedStates) {
+    void handleNewSupportedStates(int[] newSupportedStates,
+            @DeviceStateProvider.SupportedStatesUpdatedReason int reason) {
+        boolean isThermalCritical =
+                reason == DeviceStateProvider.SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_CRITICAL;
         if (mBaseStateRequest != null && !contains(newSupportedStates,
                 mBaseStateRequest.getRequestedState())) {
-            cancelCurrentBaseStateRequestLocked();
+            cancelCurrentBaseStateRequestLocked(isThermalCritical ? FLAG_THERMAL_CRITICAL : 0);
         }
 
         if (mRequest != null && !contains(newSupportedStates, mRequest.getRequestedState())) {
-            cancelCurrentRequestLocked();
+            cancelCurrentRequestLocked(isThermalCritical ? FLAG_THERMAL_CRITICAL : 0);
         }
     }
 
@@ -244,7 +252,11 @@
     }
 
     private void cancelRequestLocked(@NonNull OverrideRequest requestToCancel) {
-        mListener.onStatusChanged(requestToCancel, STATUS_CANCELED);
+        cancelRequestLocked(requestToCancel, 0 /* flags */);
+    }
+
+    private void cancelRequestLocked(@NonNull OverrideRequest requestToCancel, int flags) {
+        mListener.onStatusChanged(requestToCancel, STATUS_CANCELED, flags);
     }
 
     /**
@@ -252,12 +264,16 @@
      * Notifies the listener of the canceled status as well.
      */
     private void cancelCurrentRequestLocked() {
+        cancelCurrentRequestLocked(0 /* flags */);
+    }
+
+    private void cancelCurrentRequestLocked(int flags) {
         if (mRequest == null) {
             Slog.w(TAG, "Attempted to cancel a null OverrideRequest");
             return;
         }
         mStickyRequest = false;
-        cancelRequestLocked(mRequest);
+        cancelRequestLocked(mRequest, flags);
         mRequest = null;
     }
 
@@ -266,11 +282,15 @@
      * Notifies the listener of the canceled status as well.
      */
     private void cancelCurrentBaseStateRequestLocked() {
+        cancelCurrentBaseStateRequestLocked(0 /* flags */);
+    }
+
+    private void cancelCurrentBaseStateRequestLocked(int flags) {
         if (mBaseStateRequest == null) {
             Slog.w(TAG, "Attempted to cancel a null OverrideRequest");
             return;
         }
-        cancelRequestLocked(mBaseStateRequest);
+        cancelRequestLocked(mBaseStateRequest, flags);
         mBaseStateRequest = null;
     }
 
@@ -284,12 +304,14 @@
     }
 
     public interface StatusChangeListener {
+
         /**
          * Notifies the listener of a change in request status. If a change within the controller
          * causes one request to become active and one to become either suspended or cancelled, this
          * method is guaranteed to be called with the active request first before the suspended or
          * cancelled request.
          */
-        void onStatusChanged(@NonNull OverrideRequest request, @RequestStatus int newStatus);
+        void onStatusChanged(@NonNull OverrideRequest request, @RequestStatus int newStatus,
+                int flags);
     }
 }
diff --git a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
index 188672a..7026529 100644
--- a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
+++ b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
@@ -22,6 +22,7 @@
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.Display;
 import android.view.DisplayAddress;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -114,15 +115,19 @@
                 Slog.i(TAG, "Display layout config not found: " + configFile);
                 return;
             }
+            int leadDisplayId = Display.DEFAULT_DISPLAY;
             for (com.android.server.display.config.layout.Layout l : layouts.getLayout()) {
                 final int state = l.getState().intValue();
                 final Layout layout = createLayout(state);
                 for (com.android.server.display.config.layout.Display d: l.getDisplay()) {
+                    assert layout != null;
                     Layout.Display display = layout.createDisplayLocked(
                             DisplayAddress.fromPhysicalDisplayId(d.getAddress().longValue()),
                             d.isDefaultDisplay(),
                             d.isEnabled(),
-                            mIdProducer);
+                            mIdProducer,
+                            d.getBrightnessThrottlingMapId(),
+                            leadDisplayId);
 
                     if (FRONT_STRING.equals(d.getPosition())) {
                         display.setPosition(POSITION_FRONT);
@@ -131,6 +136,7 @@
                     } else {
                         display.setPosition(POSITION_UNKNOWN);
                     }
+                    display.setRefreshRateZoneId(d.getRefreshRateZoneId());
                 }
             }
         } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
diff --git a/services/core/java/com/android/server/display/DisplayControl.java b/services/core/java/com/android/server/display/DisplayControl.java
index fa9a100..f229d0f 100644
--- a/services/core/java/com/android/server/display/DisplayControl.java
+++ b/services/core/java/com/android/server/display/DisplayControl.java
@@ -28,7 +28,8 @@
  * Calls into SurfaceFlinger for Display creation and deletion.
  */
 public class DisplayControl {
-    private static native IBinder nativeCreateDisplay(String name, boolean secure);
+    private static native IBinder nativeCreateDisplay(String name, boolean secure,
+            float requestedRefreshRate);
     private static native void nativeDestroyDisplay(IBinder displayToken);
     private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes);
     private static native long[] nativeGetPhysicalDisplayIds();
@@ -46,7 +47,25 @@
      */
     public static IBinder createDisplay(String name, boolean secure) {
         Objects.requireNonNull(name, "name must not be null");
-        return nativeCreateDisplay(name, secure);
+        return nativeCreateDisplay(name, secure, 0.0f);
+    }
+
+    /**
+     * Create a display in SurfaceFlinger.
+     *
+     * @param name The name of the display
+     * @param secure Whether this display is secure.
+     * @param requestedRefreshRate The requested refresh rate in frames per second.
+     * For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on
+     * 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded
+     * up or down to a divisor of the physical display. If 0 is specified, the virtual
+     * display is refreshed at the physical display refresh rate.
+     * @return The token reference for the display in SurfaceFlinger.
+     */
+    public static IBinder createDisplay(String name, boolean secure,
+            float requestedRefreshRate) {
+        Objects.requireNonNull(name, "name must not be null");
+        return nativeCreateDisplay(name, secure, requestedRefreshRate);
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index e048a0f..a107f33 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -33,6 +33,7 @@
 import android.util.Slog;
 import android.util.Spline;
 import android.view.DisplayAddress;
+import android.view.SurfaceControl;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -53,6 +54,7 @@
 import com.android.server.display.config.Point;
 import com.android.server.display.config.RefreshRateConfigs;
 import com.android.server.display.config.RefreshRateRange;
+import com.android.server.display.config.RefreshRateZone;
 import com.android.server.display.config.SdrHdrRatioMap;
 import com.android.server.display.config.SdrHdrRatioPoint;
 import com.android.server.display.config.SensorDetails;
@@ -74,8 +76,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 import javax.xml.datatype.DatatypeConfigurationException;
 
@@ -411,6 +415,8 @@
 
     public static final String QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC = "canSetBrightnessViaHwc";
 
+    static final String DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID = "default";
+
     private static final float BRIGHTNESS_DEFAULT = 0.5f;
     private static final String ETC_DIR = "etc";
     private static final String DISPLAY_CONFIG_DIR = "displayconfig";
@@ -421,6 +427,8 @@
     private static final String STABLE_ID_SUFFIX_FORMAT = "id_%d";
     private static final String NO_SUFFIX_FORMAT = "%d";
     private static final long STABLE_FLAG = 1L << 62;
+    private static final int DEFAULT_PEAK_REFRESH_RATE = 0;
+    private static final int DEFAULT_REFRESH_RATE = 60;
     private static final int DEFAULT_LOW_REFRESH_RATE = 60;
     private static final int DEFAULT_HIGH_REFRESH_RATE = 0;
     private static final int[] DEFAULT_BRIGHTNESS_THRESHOLDS = new int[]{};
@@ -497,10 +505,10 @@
     /**
      * Array of light sensor lux values to define our levels for auto backlight
      * brightness support.
-
+     *
      * The N + 1 entries of this array define N control points defined in mBrightnessLevelsNits,
      * with first value always being 0 lux
-
+     *
      * The control points must be strictly increasing.  Each control point
      * corresponds to an entry in the brightness backlight values arrays.
      * For example, if lux == level[1] (second element of the levels array)
@@ -509,7 +517,6 @@
      *
      * Spline interpolation is used to determine the auto-brightness
      * backlight values for lux levels between these control points.
-     *
      */
     private float[] mBrightnessLevelsLux;
 
@@ -589,17 +596,33 @@
      * using higher refresh rates, even if display modes with higher refresh rates are available
      * from hardware composer. Only has an effect if the value is non-zero.
      */
-    private int mDefaultHighRefreshRate = DEFAULT_HIGH_REFRESH_RATE;
+    private int mDefaultPeakRefreshRate = DEFAULT_PEAK_REFRESH_RATE;
 
     /**
      * The default refresh rate for a given device. This value sets the higher default
      * refresh rate. If the hardware composer on the device supports display modes with
      * a higher refresh rate than the default value specified here, the framework may use those
      * higher refresh rate modes if an app chooses one by setting preferredDisplayModeId or calling
-     * setFrameRate(). We have historically allowed fallback to mDefaultHighRefreshRate if
-     * mDefaultLowRefreshRate is set to 0, but this is not supported anymore.
+     * setFrameRate(). We have historically allowed fallback to mDefaultPeakRefreshRate if
+     * mDefaultRefreshRate is set to 0, but this is not supported anymore.
      */
-    private int mDefaultLowRefreshRate = DEFAULT_LOW_REFRESH_RATE;
+    private int mDefaultRefreshRate = DEFAULT_REFRESH_RATE;
+
+    /**
+     * Default refresh rate in the high zone defined by brightness and ambient thresholds.
+     * If non-positive, then the refresh rate is unchanged even if thresholds are configured.
+     */
+    private int mDefaultHighBlockingZoneRefreshRate = DEFAULT_HIGH_REFRESH_RATE;
+
+    /**
+     * Default refresh rate in the zone defined by brightness and ambient thresholds.
+     * If non-positive, then the refresh rate is unchanged even if thresholds are configured.
+     */
+    private int mDefaultLowBlockingZoneRefreshRate = DEFAULT_LOW_REFRESH_RATE;
+
+    // Refresh rate profiles, currently only for concurrent mode profile and controlled by Layout
+    private final Map<String, SurfaceControl.RefreshRateRange> mRefreshRateZoneProfiles =
+            new HashMap<>();
 
     /**
      * The display uses different gamma curves for different refresh rates. It's hard for panel
@@ -627,13 +650,7 @@
     private int[] mHighDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS;
     private int[] mHighAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS;
 
-    // Brightness Throttling data may be updated via the DeviceConfig. Here we store the original
-    // data, which comes from the ddc, and the current one, which may be the DeviceConfig
-    // overwritten value.
-    private BrightnessThrottlingData mBrightnessThrottlingData;
-    private BrightnessThrottlingData mOriginalBrightnessThrottlingData;
-    // The concurrent displays mode might need a stricter throttling policy
-    private BrightnessThrottlingData mConcurrentDisplaysBrightnessThrottlingData;
+    private Map<String, BrightnessThrottlingData> mBrightnessThrottlingDataMap = new HashMap();
 
     @Nullable
     private HostUsiVersion mHostUsiVersion;
@@ -779,10 +796,6 @@
         return config;
     }
 
-    void setBrightnessThrottlingData(BrightnessThrottlingData brightnessThrottlingData) {
-        mBrightnessThrottlingData = brightnessThrottlingData;
-    }
-
     /**
      * Return the brightness mapping nits array.
      *
@@ -1282,18 +1295,11 @@
     }
 
     /**
+     * @param id The ID of the throttling data
      * @return brightness throttling configuration data for the display.
      */
-    public BrightnessThrottlingData getBrightnessThrottlingData() {
-        return BrightnessThrottlingData.create(mBrightnessThrottlingData);
-    }
-
-    /**
-     * @return brightness throttling configuration data for the display for the concurrent
-     * displays mode.
-     */
-    public BrightnessThrottlingData getConcurrentDisplaysBrightnessThrottlingData() {
-        return BrightnessThrottlingData.create(mConcurrentDisplaysBrightnessThrottlingData);
+    public BrightnessThrottlingData getBrightnessThrottlingData(String id) {
+        return BrightnessThrottlingData.create(mBrightnessThrottlingDataMap.get(id));
     }
 
     /**
@@ -1327,15 +1333,46 @@
     /**
      * @return Default peak refresh rate of the associated display
      */
-    public int getDefaultHighRefreshRate() {
-        return mDefaultHighRefreshRate;
+    public int getDefaultPeakRefreshRate() {
+        return mDefaultPeakRefreshRate;
     }
 
     /**
      * @return Default refresh rate of the associated display
      */
-    public int getDefaultLowRefreshRate() {
-        return mDefaultLowRefreshRate;
+    public int getDefaultRefreshRate() {
+        return mDefaultRefreshRate;
+    }
+
+    /**
+     * @return Default refresh rate in the higher blocking zone of the associated display
+     */
+    public int getDefaultHighBlockingZoneRefreshRate() {
+        return mDefaultHighBlockingZoneRefreshRate;
+    }
+
+    /**
+     * @return Default refresh rate in the lower blocking zone of the associated display
+     */
+    public int getDefaultLowBlockingZoneRefreshRate() {
+        return mDefaultLowBlockingZoneRefreshRate;
+    }
+
+    /**
+     * @return Refresh rate range for specific profile id or null
+     */
+    @Nullable
+    public SurfaceControl.RefreshRateRange getRefreshRange(@Nullable String id) {
+        if (TextUtils.isEmpty(id)) {
+            return null;
+        }
+        return mRefreshRateZoneProfiles.get(id);
+    }
+
+    @NonNull
+    @VisibleForTesting
+    Map<String, SurfaceControl.RefreshRateRange> getRefreshRangeProfiles() {
+        return mRefreshRateZoneProfiles;
     }
 
     /**
@@ -1411,8 +1448,7 @@
                 + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled
                 + ", mHbmData=" + mHbmData
                 + ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline
-                + ", mBrightnessThrottlingData=" + mBrightnessThrottlingData
-                + ", mOriginalBrightnessThrottlingData=" + mOriginalBrightnessThrottlingData
+                + ", mBrightnessThrottlingData=" + mBrightnessThrottlingDataMap
                 + "\n"
                 + ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
                 + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
@@ -1482,8 +1518,11 @@
                 + ", mDdcAutoBrightnessAvailable= " + mDdcAutoBrightnessAvailable
                 + ", mAutoBrightnessAvailable= " + mAutoBrightnessAvailable
                 + "\n"
-                + ", mDefaultRefreshRate= " + mDefaultLowRefreshRate
-                + ", mDefaultPeakRefreshRate= " + mDefaultHighRefreshRate
+                + ", mDefaultLowBlockingZoneRefreshRate= " + mDefaultLowBlockingZoneRefreshRate
+                + ", mDefaultHighBlockingZoneRefreshRate= " + mDefaultHighBlockingZoneRefreshRate
+                + ", mDefaultPeakRefreshRate= " + mDefaultPeakRefreshRate
+                + ", mDefaultRefreshRate= " + mDefaultRefreshRate
+                + ", mRefreshRateZoneProfiles= " + mRefreshRateZoneProfiles
                 + ", mLowDisplayBrightnessThresholds= "
                 + Arrays.toString(mLowDisplayBrightnessThresholds)
                 + ", mLowAmbientBrightnessThresholds= "
@@ -1545,8 +1584,7 @@
                 loadBrightnessDefaultFromDdcXml(config);
                 loadBrightnessConstraintsFromConfigXml();
                 loadBrightnessMap(config);
-                loadBrightnessThrottlingMap(config);
-                loadConcurrentDisplaysBrightnessThrottlingMap(config);
+                loadBrightnessThrottlingMaps(config);
                 loadHighBrightnessModeData(config);
                 loadQuirks(config);
                 loadBrightnessRamps(config);
@@ -1756,76 +1794,47 @@
         return Spline.createSpline(nits, ratios);
     }
 
-    private void loadBrightnessThrottlingMap(DisplayConfiguration config) {
+    private void loadBrightnessThrottlingMaps(DisplayConfiguration config) {
         final ThermalThrottling throttlingConfig = config.getThermalThrottling();
         if (throttlingConfig == null) {
             Slog.i(TAG, "No thermal throttling config found");
             return;
         }
 
-        final BrightnessThrottlingMap map = throttlingConfig.getBrightnessThrottlingMap();
-        if (map == null) {
+        final List<BrightnessThrottlingMap> maps = throttlingConfig.getBrightnessThrottlingMap();
+        if (maps == null || maps.isEmpty()) {
             Slog.i(TAG, "No brightness throttling map found");
             return;
         }
 
-        final List<BrightnessThrottlingPoint> points = map.getBrightnessThrottlingPoint();
-        // At least 1 point is guaranteed by the display device config schema
-        List<BrightnessThrottlingData.ThrottlingLevel> throttlingLevels =
-                new ArrayList<>(points.size());
+        for (BrightnessThrottlingMap map : maps) {
+            final List<BrightnessThrottlingPoint> points = map.getBrightnessThrottlingPoint();
+            // At least 1 point is guaranteed by the display device config schema
+            List<BrightnessThrottlingData.ThrottlingLevel> throttlingLevels =
+                    new ArrayList<>(points.size());
 
-        boolean badConfig = false;
-        for (BrightnessThrottlingPoint point : points) {
-            ThermalStatus status = point.getThermalStatus();
-            if (!thermalStatusIsValid(status)) {
-                badConfig = true;
-                break;
+            boolean badConfig = false;
+            for (BrightnessThrottlingPoint point : points) {
+                ThermalStatus status = point.getThermalStatus();
+                if (!thermalStatusIsValid(status)) {
+                    badConfig = true;
+                    break;
+                }
+
+                throttlingLevels.add(new BrightnessThrottlingData.ThrottlingLevel(
+                        convertThermalStatus(status), point.getBrightness().floatValue()));
             }
 
-            throttlingLevels.add(new BrightnessThrottlingData.ThrottlingLevel(
-                    convertThermalStatus(status), point.getBrightness().floatValue()));
-        }
-
-        if (!badConfig) {
-            mBrightnessThrottlingData = BrightnessThrottlingData.create(throttlingLevels);
-            mOriginalBrightnessThrottlingData = mBrightnessThrottlingData;
-        }
-    }
-
-    private void loadConcurrentDisplaysBrightnessThrottlingMap(DisplayConfiguration config) {
-        final ThermalThrottling throttlingConfig = config.getThermalThrottling();
-        if (throttlingConfig == null) {
-            Slog.i(TAG, "No concurrent displays thermal throttling config found");
-            return;
-        }
-
-        final BrightnessThrottlingMap map =
-                throttlingConfig.getConcurrentDisplaysBrightnessThrottlingMap();
-        if (map == null) {
-            Slog.i(TAG, "No concurrent displays brightness throttling map found");
-            return;
-        }
-
-        final List<BrightnessThrottlingPoint> points = map.getBrightnessThrottlingPoint();
-        // At least 1 point is guaranteed by the display device config schema
-        List<BrightnessThrottlingData.ThrottlingLevel> throttlingLevels =
-                new ArrayList<>(points.size());
-
-        boolean badConfig = false;
-        for (BrightnessThrottlingPoint point : points) {
-            ThermalStatus status = point.getThermalStatus();
-            if (!thermalStatusIsValid(status)) {
-                badConfig = true;
-                break;
+            if (!badConfig) {
+                String id = map.getId() == null ? DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID
+                        : map.getId();
+                if (mBrightnessThrottlingDataMap.containsKey(id)) {
+                    throw new RuntimeException("Brightness throttling data with ID " + id
+                            + " already exists");
+                }
+                mBrightnessThrottlingDataMap.put(id,
+                        BrightnessThrottlingData.create(throttlingLevels));
             }
-
-            throttlingLevels.add(new BrightnessThrottlingData.ThrottlingLevel(
-                    convertThermalStatus(status), point.getBrightness().floatValue()));
-        }
-
-        if (!badConfig) {
-            mConcurrentDisplaysBrightnessThrottlingData =
-                    BrightnessThrottlingData.create(throttlingLevels);
         }
     }
 
@@ -1838,10 +1847,47 @@
         BlockingZoneConfig higherBlockingZoneConfig =
                 (refreshRateConfigs == null) ? null
                         : refreshRateConfigs.getHigherBlockingZoneConfigs();
+        loadPeakDefaultRefreshRate(refreshRateConfigs);
+        loadDefaultRefreshRate(refreshRateConfigs);
         loadLowerRefreshRateBlockingZones(lowerBlockingZoneConfig);
         loadHigherRefreshRateBlockingZones(higherBlockingZoneConfig);
+        loadRefreshRateZoneProfiles(refreshRateConfigs);
     }
 
+    private void loadPeakDefaultRefreshRate(RefreshRateConfigs refreshRateConfigs) {
+        if (refreshRateConfigs == null || refreshRateConfigs.getDefaultPeakRefreshRate() == null) {
+            mDefaultPeakRefreshRate = mContext.getResources().getInteger(
+                R.integer.config_defaultPeakRefreshRate);
+        } else {
+            mDefaultPeakRefreshRate =
+                refreshRateConfigs.getDefaultPeakRefreshRate().intValue();
+        }
+    }
+
+    private void loadDefaultRefreshRate(RefreshRateConfigs refreshRateConfigs) {
+        if (refreshRateConfigs == null || refreshRateConfigs.getDefaultRefreshRate() == null) {
+            mDefaultRefreshRate = mContext.getResources().getInteger(
+                R.integer.config_defaultRefreshRate);
+        } else {
+            mDefaultRefreshRate =
+                refreshRateConfigs.getDefaultRefreshRate().intValue();
+        }
+    }
+
+    /** Loads the refresh rate profiles. */
+    private void loadRefreshRateZoneProfiles(RefreshRateConfigs refreshRateConfigs) {
+        if (refreshRateConfigs == null) {
+            return;
+        }
+        for (RefreshRateZone zone :
+                refreshRateConfigs.getRefreshRateZoneProfiles().getRefreshRateZoneProfile()) {
+            RefreshRateRange range = zone.getRefreshRateRange();
+            mRefreshRateZoneProfiles.put(
+                    zone.getId(),
+                    new SurfaceControl.RefreshRateRange(
+                            range.getMinimum().floatValue(), range.getMaximum().floatValue()));
+        }
+    }
 
     /**
      * Loads the refresh rate configurations pertaining to the upper blocking zones.
@@ -1866,10 +1912,10 @@
     private void loadHigherBlockingZoneDefaultRefreshRate(
                 BlockingZoneConfig upperBlockingZoneConfig) {
         if (upperBlockingZoneConfig == null) {
-            mDefaultHighRefreshRate = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_defaultPeakRefreshRate);
+            mDefaultHighBlockingZoneRefreshRate = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_fixedRefreshRateInHighZone);
         } else {
-            mDefaultHighRefreshRate =
+            mDefaultHighBlockingZoneRefreshRate =
                 upperBlockingZoneConfig.getDefaultRefreshRate().intValue();
         }
     }
@@ -1881,10 +1927,10 @@
     private void loadLowerBlockingZoneDefaultRefreshRate(
                 BlockingZoneConfig lowerBlockingZoneConfig) {
         if (lowerBlockingZoneConfig == null) {
-            mDefaultLowRefreshRate = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_defaultRefreshRate);
+            mDefaultLowBlockingZoneRefreshRate = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_defaultRefreshRateInZone);
         } else {
-            mDefaultLowRefreshRate =
+            mDefaultLowBlockingZoneRefreshRate =
                 lowerBlockingZoneConfig.getDefaultRefreshRate().intValue();
         }
     }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 3759a8b..237e78b 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -142,6 +142,7 @@
 import com.android.server.UiThread;
 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 import com.android.server.display.DisplayDeviceConfig.SensorData;
+import com.android.server.display.layout.Layout;
 import com.android.server.display.utils.SensorUtils;
 import com.android.server.input.InputManagerInternal;
 import com.android.server.wm.SurfaceAnimationThread;
@@ -245,7 +246,7 @@
     private Display.Mode mUserPreferredMode;
     // HDR conversion mode chosen by user
     @GuardedBy("mSyncRoot")
-    private HdrConversionMode mHdrConversionMode;
+    private HdrConversionMode mHdrConversionMode = null;
 
     // The synchronization root for the display manager.
     // This lock guards most of the display manager's state.
@@ -647,6 +648,7 @@
             updateSettingsLocked();
             updateUserDisabledHdrTypesFromSettingsLocked();
             updateUserPreferredDisplayModeSettingsLocked();
+            updateHdrConversionModeSettingsLocked();
         }
 
         mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
@@ -1664,12 +1666,37 @@
                 return;
             }
 
-            // TODO (b/265793751): Set this DPC as a follower of the default DPC if needed,
-            // clear this DPC's followers if it's not a lead display
+            final int leadDisplayId = display.getLeadDisplayIdLocked();
+            updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
 
             final String uniqueId = device.getUniqueId();
             HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
-            dpc.onDisplayChanged(hbmMetadata);
+            dpc.onDisplayChanged(hbmMetadata, leadDisplayId);
+        }
+    }
+
+    private void updateDisplayPowerControllerLeaderLocked(DisplayPowerControllerInterface dpc,
+            int leadDisplayId) {
+        if (dpc.getLeadDisplayId() == leadDisplayId) {
+            // Lead display hasn't changed, nothing to do.
+            return;
+        }
+
+        // If it has changed, then we need to unregister from the previous leader if there was one.
+        final int prevLeaderId = dpc.getLeadDisplayId();
+        if (prevLeaderId != Layout.NO_LEAD_DISPLAY) {
+            final DisplayPowerControllerInterface prevLeader =
+                    mDisplayPowerControllers.get(prevLeaderId);
+            if (prevLeader != null) {
+                prevLeader.removeDisplayBrightnessFollower(dpc);
+            }
+        }
+
+        // And then, if it's following, register it with the new one.
+        if (leadDisplayId != Layout.NO_LEAD_DISPLAY) {
+            final DisplayPowerControllerInterface newLead =
+                    mDisplayPowerControllers.get(leadDisplayId);
+            newLead.addDisplayBrightnessFollower(dpc);
         }
     }
 
@@ -1733,9 +1760,13 @@
                         + display.getDisplayIdLocked());
                 return;
             }
+
+            final int leadDisplayId = display.getLeadDisplayIdLocked();
+            updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
+
             final String uniqueId = device.getUniqueId();
             HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
-            dpc.onDisplayChanged(hbmMetadata);
+            dpc.onDisplayChanged(hbmMetadata, leadDisplayId);
         }
     }
 
@@ -1806,6 +1837,31 @@
         device.setUserPreferredDisplayModeLocked(modeBuilder.build());
     }
 
+    @GuardedBy("mSyncRoot")
+    private void storeHdrConversionModeLocked(HdrConversionMode hdrConversionMode) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.HDR_CONVERSION_MODE, hdrConversionMode.getConversionMode());
+        final int preferredHdrOutputType =
+                hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_FORCE
+                        ? hdrConversionMode.getPreferredHdrOutputType()
+                        : Display.HdrCapabilities.HDR_TYPE_INVALID;
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.HDR_FORCE_CONVERSION_TYPE, preferredHdrOutputType);
+    }
+
+    @GuardedBy("mSyncRoot")
+    void updateHdrConversionModeSettingsLocked() {
+        final int conversionMode = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.HDR_CONVERSION_MODE, HdrConversionMode.HDR_CONVERSION_SYSTEM);
+        final int preferredHdrOutputType = conversionMode == HdrConversionMode.HDR_CONVERSION_FORCE
+                ? Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.HDR_FORCE_CONVERSION_TYPE,
+                        Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION)
+                : Display.HdrCapabilities.HDR_TYPE_INVALID;
+        mHdrConversionMode = new HdrConversionMode(conversionMode, preferredHdrOutputType);
+        setHdrConversionModeInternal(mHdrConversionMode);
+    }
+
     // If we've never recorded stable device stats for this device before and they aren't
     // explicitly configured, go ahead and record the stable device stats now based on the status
     // of the default display at first boot.
@@ -1962,13 +2018,14 @@
         int[] autoHdrOutputTypes = null;
         synchronized (mSyncRoot) {
             mHdrConversionMode = hdrConversionMode;
+            storeHdrConversionModeLocked(mHdrConversionMode);
 
             // For auto mode, all supported HDR types are allowed except the ones specifically
             // disabled by the user.
             if (hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM) {
                 autoHdrOutputTypes = getEnabledAutoHdrTypesLocked();
             }
-            DisplayControl.setHdrConversionMode(hdrConversionMode.getConversionMode(),
+            mInjector.setHdrConversionMode(hdrConversionMode.getConversionMode(),
                     hdrConversionMode.getPreferredHdrOutputType(), autoHdrOutputTypes);
         }
     }
@@ -1984,7 +2041,7 @@
 
     private @Display.HdrCapabilities.HdrType int[] getSupportedHdrOutputTypesInternal() {
         if (mSupportedHdrOutputType == null) {
-            mSupportedHdrOutputType = DisplayControl.getSupportedHdrOutputTypes();
+            mSupportedHdrOutputType = mInjector.getSupportedHdrOutputTypes();
         }
         return mSupportedHdrOutputType;
     }
@@ -2604,6 +2661,10 @@
                 }
             }
 
+            if (mHdrConversionMode != null) {
+                pw.println("  mHdrConversionMode=" + mHdrConversionMode);
+            }
+
             pw.println();
             final int displayStateCount = mDisplayStates.size();
             pw.println("Display States: size=" + displayStateCount);
@@ -2712,6 +2773,16 @@
         long getDefaultDisplayDelayTimeout() {
             return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
         }
+
+        void setHdrConversionMode(int conversionMode, int preferredHdrOutputType,
+                int[] autoHdrTypes) {
+            DisplayControl.setHdrConversionMode(conversionMode, preferredHdrOutputType,
+                    autoHdrTypes);
+        }
+
+        int[] getSupportedHdrOutputTypes() {
+            return DisplayControl.getSupportedHdrOutputTypes();
+        }
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 52e20d6..91ef167 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -159,7 +159,6 @@
         mSupportedModesByDisplay = new SparseArray<>();
         mDefaultModeByDisplay = new SparseArray<>();
         mAppRequestObserver = new AppRequestObserver();
-        mDisplayObserver = new DisplayObserver(context, handler);
         mDeviceConfig = injector.getDeviceConfig();
         mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
         mSettingsObserver = new SettingsObserver(context, handler);
@@ -170,6 +169,7 @@
                 updateVoteLocked(displayId, priority, vote);
             }
         };
+        mDisplayObserver = new DisplayObserver(context, handler, ballotBox);
         mSensorObserver = new SensorObserver(context, ballotBox, injector);
         mSkinThermalStatusObserver = new SkinThermalStatusObserver(injector, ballotBox);
         mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler(),
@@ -373,9 +373,13 @@
         }
     }
 
-    private void disableRenderRateSwitching(VoteSummary summary) {
+    private void disableRenderRateSwitching(VoteSummary summary, float fps) {
         summary.minRenderFrameRate = summary.maxRenderFrameRate;
 
+        if (!isRenderRateAchievable(fps, summary)) {
+            summary.minRenderFrameRate = summary.maxRenderFrameRate = fps;
+        }
+
         if (mLoggingEnabled) {
             Slog.i(TAG, "Disabled render rate switching on summary: " + summary);
         }
@@ -540,10 +544,10 @@
                 disableModeSwitching(primarySummary, fps);
                 if (modeSwitchingDisabled) {
                     disableModeSwitching(appRequestSummary, fps);
-                    disableRenderRateSwitching(primarySummary);
+                    disableRenderRateSwitching(primarySummary, fps);
 
                     if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE) {
-                        disableRenderRateSwitching(appRequestSummary);
+                        disableRenderRateSwitching(appRequestSummary, fps);
                     }
                 }
             }
@@ -570,6 +574,22 @@
         }
     }
 
+    private boolean isRenderRateAchievable(float physicalRefreshRate, VoteSummary summary) {
+        // Check whether the render frame rate range is achievable by the mode's physical
+        // refresh rate, meaning that if a divisor of the physical refresh rate is in range
+        // of the render frame rate.
+        // For example for the render frame rate [50, 70]:
+        //   - 120Hz is in range as we can render at 60hz by skipping every other frame,
+        //     which is within the render rate range
+        //   - 90hz is not in range as none of the even divisors (i.e. 90, 45, 30)
+        //     fall within the acceptable render range.
+        final int divisor =
+                (int) Math.ceil((physicalRefreshRate / summary.maxRenderFrameRate)
+                        - FLOAT_TOLERANCE);
+        float adjustedPhysicalRefreshRate = physicalRefreshRate / divisor;
+        return adjustedPhysicalRefreshRate >= (summary.minRenderFrameRate - FLOAT_TOLERANCE);
+    }
+
     private ArrayList<Display.Mode> filterModes(Display.Mode[] supportedModes,
             VoteSummary summary) {
         if (summary.minRenderFrameRate > summary.maxRenderFrameRate + FLOAT_TOLERANCE) {
@@ -627,22 +647,9 @@
                 }
             }
 
-            // Check whether the render frame rate range is achievable by the mode's physical
-            // refresh rate, meaning that if a divisor of the physical refresh rate is in range
-            // of the render frame rate.
-            // For example for the render frame rate [50, 70]:
-            //   - 120Hz is in range as we can render at 60hz by skipping every other frame,
-            //     which is within the render rate range
-            //   - 90hz is not in range as none of the even divisors (i.e. 90, 45, 30)
-            //     fall within the acceptable render range.
-            final int divisor =
-                    (int) Math.ceil((physicalRefreshRate / summary.maxRenderFrameRate)
-                            - FLOAT_TOLERANCE);
-            float adjustedPhysicalRefreshRate = physicalRefreshRate / divisor;
-            if (adjustedPhysicalRefreshRate < (summary.minRenderFrameRate - FLOAT_TOLERANCE)) {
+            if (!isRenderRateAchievable(physicalRefreshRate, summary)) {
                 if (mLoggingEnabled) {
                     Slog.w(TAG, "Discarding mode " + mode.getModeId()
-                            + " with adjusted refresh rate: " + adjustedPhysicalRefreshRate
                             + ", outside frame rate bounds"
                             + ": minRenderFrameRate=" + summary.minRenderFrameRate
                             + ", maxRenderFrameRate=" + summary.maxRenderFrameRate
@@ -726,7 +733,7 @@
 
     /**
      * Sets the display mode switching type.
-     * @param newType
+     * @param newType new mode switching type
      */
     public void setModeSwitchingType(@DisplayManager.SwitchingType int newType) {
         synchronized (mLock) {
@@ -843,6 +850,18 @@
         notifyDesiredDisplayModeSpecsChangedLocked();
     }
 
+    @GuardedBy("mLock")
+    private float getMaxRefreshRateLocked(int displayId) {
+        Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
+        float maxRefreshRate = 0f;
+        for (Display.Mode mode : modes) {
+            if (mode.getRefreshRate() > maxRefreshRate) {
+                maxRefreshRate = mode.getRefreshRate();
+            }
+        }
+        return maxRefreshRate;
+    }
+
     private void notifyDesiredDisplayModeSpecsChangedLocked() {
         if (mDesiredDisplayModeSpecsListener != null
                 && !mHandler.hasMessages(MSG_REFRESH_RATE_RANGE_CHANGED)) {
@@ -1179,26 +1198,33 @@
         // rest of low priority voters. It votes [0, max(PEAK, MIN)]
         public static final int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 7;
 
+        // To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh
+        // rate to max value (same as for PRIORITY_UDFPS) on lock screen
+        public static final int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 8;
+
+        // For concurrent displays we want to limit refresh rate on all displays
+        public static final int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 9;
+
         // LOW_POWER_MODE force the render frame rate to [0, 60HZ] if
         // Settings.Global.LOW_POWER_MODE is on.
-        public static final int PRIORITY_LOW_POWER_MODE = 8;
+        public static final int PRIORITY_LOW_POWER_MODE = 10;
 
         // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the
         // higher priority voters' result is a range, it will fix the rate to a single choice.
         // It's used to avoid refresh rate switches in certain conditions which may result in the
         // user seeing the display flickering when the switches occur.
-        public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 9;
+        public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 11;
 
         // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
-        public static final int PRIORITY_SKIN_TEMPERATURE = 10;
+        public static final int PRIORITY_SKIN_TEMPERATURE = 12;
 
         // The proximity sensor needs the refresh rate to be locked in order to function, so this is
         // set to a high priority.
-        public static final int PRIORITY_PROXIMITY = 11;
+        public static final int PRIORITY_PROXIMITY = 13;
 
         // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
         // to function, so this needs to be the highest priority of all votes.
-        public static final int PRIORITY_UDFPS = 12;
+        public static final int PRIORITY_UDFPS = 14;
 
         // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
         // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
@@ -1315,6 +1341,8 @@
                     return "PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE";
                 case PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE:
                     return "PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE";
+                case PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE:
+                    return "PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE";
                 default:
                     return Integer.toString(priority);
             }
@@ -1366,7 +1394,7 @@
             mDefaultRefreshRate =
                     (displayDeviceConfig == null) ? (float) mContext.getResources().getInteger(
                         R.integer.config_defaultRefreshRate)
-                        : (float) displayDeviceConfig.getDefaultLowRefreshRate();
+                        : (float) displayDeviceConfig.getDefaultRefreshRate();
         }
 
         public void observe() {
@@ -1453,7 +1481,7 @@
                 defaultPeakRefreshRate =
                         (displayDeviceConfig == null) ? (float) mContext.getResources().getInteger(
                                 R.integer.config_defaultPeakRefreshRate)
-                                : (float) displayDeviceConfig.getDefaultHighRefreshRate();
+                                : (float) displayDeviceConfig.getDefaultPeakRefreshRate();
             }
             mDefaultPeakRefreshRate = defaultPeakRefreshRate;
         }
@@ -1650,10 +1678,12 @@
         // calling into us already holding its own lock.
         private final Context mContext;
         private final Handler mHandler;
+        private final BallotBox mBallotBox;
 
-        DisplayObserver(Context context, Handler handler) {
+        DisplayObserver(Context context, Handler handler, BallotBox ballotBox) {
             mContext = context;
             mHandler = handler;
+            mBallotBox = ballotBox;
         }
 
         public void observe() {
@@ -1682,7 +1712,9 @@
 
         @Override
         public void onDisplayAdded(int displayId) {
-            updateDisplayModes(displayId);
+            DisplayInfo displayInfo = getDisplayInfo(displayId);
+            updateDisplayModes(displayId, displayInfo);
+            updateLayoutLimitedFrameRate(displayId, displayInfo);
         }
 
         @Override
@@ -1691,23 +1723,41 @@
                 mSupportedModesByDisplay.remove(displayId);
                 mDefaultModeByDisplay.remove(displayId);
             }
+            updateLayoutLimitedFrameRate(displayId, null);
         }
 
         @Override
         public void onDisplayChanged(int displayId) {
-            updateDisplayModes(displayId);
+            DisplayInfo displayInfo = getDisplayInfo(displayId);
+            updateDisplayModes(displayId, displayInfo);
+            updateLayoutLimitedFrameRate(displayId, displayInfo);
         }
 
-        private void updateDisplayModes(int displayId) {
+        @Nullable
+        private DisplayInfo getDisplayInfo(int displayId) {
             Display d = mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
             if (d == null) {
                 // We can occasionally get a display added or changed event for a display that was
                 // subsequently removed, which means this returns null. Check this case and bail
                 // out early; if it gets re-attached we'll eventually get another call back for it.
-                return;
+                return null;
             }
             DisplayInfo info = new DisplayInfo();
             d.getDisplayInfo(info);
+            return info;
+        }
+
+        private void updateLayoutLimitedFrameRate(int displayId, @Nullable DisplayInfo info) {
+            Vote vote = info != null && info.layoutLimitedRefreshRate != null
+                    ? Vote.forPhysicalRefreshRates(info.layoutLimitedRefreshRate.min,
+                    info.layoutLimitedRefreshRate.max) : null;
+            mBallotBox.vote(displayId, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE, vote);
+        }
+
+        private void updateDisplayModes(int displayId, @Nullable DisplayInfo info) {
+            if (info == null) {
+                return;
+            }
             boolean changed = false;
             synchronized (mLock) {
                 if (!Arrays.equals(mSupportedModesByDisplay.get(displayId), info.supportedModes)) {
@@ -1812,8 +1862,26 @@
             return mHighAmbientBrightnessThresholds;
         }
 
+        /**
+         * @return the refresh rate to lock to when in a high brightness zone
+         */
+        @VisibleForTesting
+        int getRefreshRateInHighZone() {
+            return mRefreshRateInHighZone;
+        }
+
+        /**
+         * @return the refresh rate to lock to when in a low brightness zone
+         */
+        @VisibleForTesting
+        int getRefreshRateInLowZone() {
+            return mRefreshRateInLowZone;
+        }
+
         private void loadLowBrightnessThresholds(DisplayDeviceConfig displayDeviceConfig,
                 boolean attemptLoadingFromDeviceConfig) {
+            loadRefreshRateInHighZone(displayDeviceConfig, attemptLoadingFromDeviceConfig);
+            loadRefreshRateInLowZone(displayDeviceConfig, attemptLoadingFromDeviceConfig);
             mLowDisplayBrightnessThresholds = loadBrightnessThresholds(
                     () -> mDeviceConfigDisplaySettings.getLowDisplayBrightnessThresholds(),
                     () -> displayDeviceConfig.getLowDisplayBrightnessThresholds(),
@@ -1834,6 +1902,44 @@
             }
         }
 
+        private void loadRefreshRateInLowZone(DisplayDeviceConfig displayDeviceConfig,
+                boolean attemptLoadingFromDeviceConfig) {
+            int refreshRateInLowZone =
+                    (displayDeviceConfig == null) ? mContext.getResources().getInteger(
+                        R.integer.config_defaultRefreshRateInZone)
+                        : displayDeviceConfig.getDefaultLowBlockingZoneRefreshRate();
+            if (attemptLoadingFromDeviceConfig) {
+                try {
+                    refreshRateInLowZone = mDeviceConfig.getInt(
+                        DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+                        DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE,
+                        refreshRateInLowZone);
+                } catch (Exception exception) {
+                    // Do nothing
+                }
+            }
+            mRefreshRateInLowZone = refreshRateInLowZone;
+        }
+
+        private void loadRefreshRateInHighZone(DisplayDeviceConfig displayDeviceConfig,
+                boolean attemptLoadingFromDeviceConfig) {
+            int refreshRateInHighZone =
+                    (displayDeviceConfig == null) ? mContext.getResources().getInteger(
+                        R.integer.config_fixedRefreshRateInHighZone) : displayDeviceConfig
+                        .getDefaultHighBlockingZoneRefreshRate();
+            if (attemptLoadingFromDeviceConfig) {
+                try {
+                    refreshRateInHighZone = mDeviceConfig.getInt(
+                        DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+                        DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE,
+                        refreshRateInHighZone);
+                } catch (Exception exception) {
+                    // Do nothing
+                }
+            }
+            mRefreshRateInHighZone = refreshRateInHighZone;
+        }
+
         private void loadHighBrightnessThresholds(DisplayDeviceConfig displayDeviceConfig,
                 boolean attemptLoadingFromDeviceConfig) {
             mHighDisplayBrightnessThresholds = loadBrightnessThresholds(
@@ -1887,14 +1993,6 @@
         }
 
         /**
-         * @return the refresh to lock to when in a low brightness zone
-         */
-        @VisibleForTesting
-        int getRefreshRateInLowZone() {
-            return mRefreshRateInLowZone;
-        }
-
-        /**
          * @return the display brightness thresholds for the low brightness zones
          */
         @VisibleForTesting
@@ -1939,8 +2037,17 @@
                 mHighAmbientBrightnessThresholds = highAmbientBrightnessThresholds;
             }
 
-            mRefreshRateInLowZone = mDeviceConfigDisplaySettings.getRefreshRateInLowZone();
-            mRefreshRateInHighZone = mDeviceConfigDisplaySettings.getRefreshRateInHighZone();
+            final int refreshRateInLowZone = mDeviceConfigDisplaySettings
+                    .getRefreshRateInLowZone();
+            if (refreshRateInLowZone != -1) {
+                mRefreshRateInLowZone = refreshRateInLowZone;
+            }
+
+            final int refreshRateInHighZone = mDeviceConfigDisplaySettings
+                    .getRefreshRateInHighZone();
+            if (refreshRateInHighZone != -1) {
+                mRefreshRateInHighZone = refreshRateInHighZone;
+            }
 
             restartObserver();
             mDeviceConfigDisplaySettings.startListening();
@@ -1994,6 +2101,10 @@
             restartObserver();
         }
 
+        /**
+         * Used to reload the lower blocking zone refresh rate in case of changes in the
+         * DeviceConfig properties.
+         */
         public void onDeviceConfigRefreshRateInLowZoneChanged(int refreshRate) {
             if (refreshRate != mRefreshRateInLowZone) {
                 mRefreshRateInLowZone = refreshRate;
@@ -2017,6 +2128,10 @@
             restartObserver();
         }
 
+        /**
+         * Used to reload the higher blocking zone refresh rate in case of changes in the
+         * DeviceConfig properties.
+         */
         public void onDeviceConfigRefreshRateInHighZoneChanged(int refreshRate) {
             if (refreshRate != mRefreshRateInHighZone) {
                 mRefreshRateInHighZone = refreshRate;
@@ -2467,6 +2582,7 @@
 
     private class UdfpsObserver extends IUdfpsRefreshRateRequestCallback.Stub {
         private final SparseBooleanArray mUdfpsRefreshRateEnabled = new SparseBooleanArray();
+        private final SparseBooleanArray mAuthenticationPossible = new SparseBooleanArray();
 
         public void observe() {
             StatusBarManagerInternal statusBar =
@@ -2479,38 +2595,38 @@
         @Override
         public void onRequestEnabled(int displayId) {
             synchronized (mLock) {
-                updateRefreshRateStateLocked(displayId, true /*enabled*/);
+                mUdfpsRefreshRateEnabled.put(displayId, true);
+                updateVoteLocked(displayId, true, Vote.PRIORITY_UDFPS);
             }
         }
 
         @Override
         public void onRequestDisabled(int displayId) {
             synchronized (mLock) {
-                updateRefreshRateStateLocked(displayId, false /*enabled*/);
+                mUdfpsRefreshRateEnabled.put(displayId, false);
+                updateVoteLocked(displayId, false, Vote.PRIORITY_UDFPS);
             }
         }
 
-        private void updateRefreshRateStateLocked(int displayId, boolean enabled) {
-            mUdfpsRefreshRateEnabled.put(displayId, enabled);
-            updateVoteLocked(displayId);
+        @Override
+        public void onAuthenticationPossible(int displayId, boolean isPossible) {
+            synchronized (mLock) {
+                mAuthenticationPossible.put(displayId, isPossible);
+                updateVoteLocked(displayId, isPossible,
+                        Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE);
+            }
         }
 
-        private void updateVoteLocked(int displayId) {
+        @GuardedBy("mLock")
+        private void updateVoteLocked(int displayId, boolean enabled, int votePriority) {
             final Vote vote;
-            if (mUdfpsRefreshRateEnabled.get(displayId)) {
-                Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
-                float maxRefreshRate = 0f;
-                for (Display.Mode mode : modes) {
-                    if (mode.getRefreshRate() > maxRefreshRate) {
-                        maxRefreshRate = mode.getRefreshRate();
-                    }
-                }
+            if (enabled) {
+                float maxRefreshRate = DisplayModeDirector.this.getMaxRefreshRateLocked(displayId);
                 vote = Vote.forPhysicalRefreshRates(maxRefreshRate, maxRefreshRate);
             } else {
                 vote = null;
             }
-
-            DisplayModeDirector.this.updateVoteLocked(displayId, Vote.PRIORITY_UDFPS, vote);
+            DisplayModeDirector.this.updateVoteLocked(displayId, votePriority, vote);
         }
 
         void dumpLocked(PrintWriter pw) {
@@ -2521,6 +2637,13 @@
                 final String enabled = mUdfpsRefreshRateEnabled.valueAt(i) ? "enabled" : "disabled";
                 pw.println("      Display " + displayId + ": " + enabled);
             }
+            pw.println("    mAuthenticationPossible: ");
+            for (int i = 0; i < mAuthenticationPossible.size(); i++) {
+                final int displayId = mAuthenticationPossible.keyAt(i);
+                final String isPossible = mAuthenticationPossible.valueAt(i) ? "possible"
+                        : "impossible";
+                pw.println("      Display " + displayId + ": " + isPossible);
+            }
         }
     }
 
@@ -2867,15 +2990,10 @@
         }
 
         public int getRefreshRateInLowZone() {
-            int defaultRefreshRateInZone = mContext.getResources().getInteger(
-                    R.integer.config_defaultRefreshRateInZone);
-
-            int refreshRate = mDeviceConfig.getInt(
+            return mDeviceConfig.getInt(
                     DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
-                    DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE,
-                    defaultRefreshRateInZone);
+                    DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE, -1);
 
-            return refreshRate;
         }
 
         /*
@@ -2897,15 +3015,10 @@
         }
 
         public int getRefreshRateInHighZone() {
-            int defaultRefreshRateInZone = mContext.getResources().getInteger(
-                    R.integer.config_fixedRefreshRateInHighZone);
-
-            int refreshRate = mDeviceConfig.getInt(
+            return mDeviceConfig.getInt(
                     DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                     DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE,
-                    defaultRefreshRateInZone);
-
-            return refreshRate;
+                    -1);
         }
 
         public int getRefreshRateInHbmSunlight() {
@@ -2953,23 +3066,29 @@
 
             int[] lowDisplayBrightnessThresholds = getLowDisplayBrightnessThresholds();
             int[] lowAmbientBrightnessThresholds = getLowAmbientBrightnessThresholds();
-            int refreshRateInLowZone = getRefreshRateInLowZone();
+            final int refreshRateInLowZone = getRefreshRateInLowZone();
 
             mHandler.obtainMessage(MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED,
                     new Pair<>(lowDisplayBrightnessThresholds, lowAmbientBrightnessThresholds))
                     .sendToTarget();
-            mHandler.obtainMessage(MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED, refreshRateInLowZone, 0)
-                    .sendToTarget();
+
+            if (refreshRateInLowZone != -1) {
+                mHandler.obtainMessage(MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED, refreshRateInLowZone,
+                        0).sendToTarget();
+            }
 
             int[] highDisplayBrightnessThresholds = getHighDisplayBrightnessThresholds();
             int[] highAmbientBrightnessThresholds = getHighAmbientBrightnessThresholds();
-            int refreshRateInHighZone = getRefreshRateInHighZone();
+            final int refreshRateInHighZone = getRefreshRateInHighZone();
 
             mHandler.obtainMessage(MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED,
                     new Pair<>(highDisplayBrightnessThresholds, highAmbientBrightnessThresholds))
                     .sendToTarget();
-            mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone, 0)
-                    .sendToTarget();
+
+            if (refreshRateInHighZone != -1) {
+                mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone,
+                        0).sendToTarget();
+            }
 
             final int refreshRateInHbmSunlight = getRefreshRateInHbmSunlight();
             mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED,
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index abb0ff6..1305d63 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -18,6 +18,7 @@
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
@@ -74,6 +75,7 @@
 import com.android.server.display.brightness.BrightnessReason;
 import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
 import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
+import com.android.server.display.layout.Layout;
 import com.android.server.display.utils.SensorUtils;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
@@ -195,6 +197,9 @@
     // The ID of the LogicalDisplay tied to this DisplayPowerController.
     private final int mDisplayId;
 
+    // The ID of the display which this display follows for brightness purposes.
+    private int mLeadDisplayId = Layout.NO_LEAD_DISPLAY;
+
     // The unique ID of the primary display device currently tied to this logical display
     private String mUniqueDisplayId;
 
@@ -504,11 +509,13 @@
     private boolean mIsEnabled;
     private boolean mIsInTransition;
 
+    private String mBrightnessThrottlingDataId;
+
     // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there
     // is one lead display, the additional displays follow the brightness value of the lead display.
     @GuardedBy("mLock")
-    private SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
-            new SparseArray();
+    private final SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
+            new SparseArray<>();
 
     /**
      * Creates the display power controller.
@@ -539,6 +546,7 @@
         mHandler = new DisplayControllerHandler(handler.getLooper());
         mLastBrightnessEvent = new BrightnessEvent(mDisplayId);
         mTempBrightnessEvent = new BrightnessEvent(mDisplayId);
+        mBrightnessThrottlingDataId = logicalDisplay.getBrightnessThrottlingDataIdLocked();
 
         if (mDisplayId == Display.DEFAULT_DISPLAY) {
             mBatteryStats = BatteryStatsService.getService();
@@ -719,6 +727,11 @@
     }
 
     @Override
+    public int getLeadDisplayId() {
+        return mLeadDisplayId;
+    }
+
+    @Override
     public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) {
         mHbmController.onAmbientLuxChange(ambientLux);
         if (mAutomaticBrightnessController == null || nits < 0) {
@@ -736,24 +749,20 @@
     }
 
     @Override
-    public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
+    public void addDisplayBrightnessFollower(@NonNull DisplayPowerControllerInterface follower) {
         synchronized (mLock) {
             mDisplayBrightnessFollowers.append(follower.getDisplayId(), follower);
+            sendUpdatePowerStateLocked();
         }
-        sendUpdatePowerState();
     }
 
     @Override
-    public void clearDisplayBrightnessFollowers() {
-        SparseArray<DisplayPowerControllerInterface> followers;
+    public void removeDisplayBrightnessFollower(@NonNull DisplayPowerControllerInterface follower) {
         synchronized (mLock) {
-            followers = mDisplayBrightnessFollowers.clone();
-            mDisplayBrightnessFollowers.clear();
-        }
-        for (int i = 0; i < followers.size(); i++) {
-            DisplayPowerControllerInterface follower = followers.valueAt(i);
-            follower.setBrightnessToFollow(PowerManager.BRIGHTNESS_INVALID_FLOAT, /* nits= */ -1,
-                    /* ambientLux= */ 0);
+            mDisplayBrightnessFollowers.remove(follower.getDisplayId());
+            mHandler.postAtTime(() -> follower.setBrightnessToFollow(
+                    PowerManager.BRIGHTNESS_INVALID_FLOAT, /* nits= */ -1,
+                    /* ambientLux= */ 0), mClock.uptimeMillis());
         }
     }
 
@@ -848,7 +857,8 @@
      * Make sure DisplayManagerService.mSyncRoot is held when this is called
      */
     @Override
-    public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) {
+    public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata, int leadDisplayId) {
+        mLeadDisplayId = leadDisplayId;
         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
         if (device == null) {
             Slog.wtf(mTag, "Display Device is null in DisplayPowerController for display: "
@@ -862,6 +872,8 @@
         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         final boolean isEnabled = mLogicalDisplay.isEnabledLocked();
         final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
+        final String brightnessThrottlingDataId =
+                mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
         mHandler.post(() -> {
             boolean changed = false;
             if (mDisplayDevice != device) {
@@ -870,12 +882,19 @@
                 mUniqueDisplayId = uniqueId;
                 mDisplayStatsId = mUniqueDisplayId.hashCode();
                 mDisplayDeviceConfig = config;
+                mBrightnessThrottlingDataId = brightnessThrottlingDataId;
                 loadFromDisplayDeviceConfig(token, info, hbmMetadata);
 
                 /// Since the underlying display-device changed, we really don't know the
                 // last command that was sent to change it's state. Lets assume it is unknown so
                 // that we trigger a change immediately.
                 mPowerState.resetScreenState();
+            } else if (!mBrightnessThrottlingDataId.equals(brightnessThrottlingDataId)) {
+                changed = true;
+                mBrightnessThrottlingDataId = brightnessThrottlingDataId;
+                mBrightnessThrottler.resetThrottlingData(
+                        config.getBrightnessThrottlingData(mBrightnessThrottlingDataId),
+                        mUniqueDisplayId);
             }
             if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) {
                 changed = true;
@@ -887,9 +906,6 @@
                 updatePowerState();
             }
         });
-
-        // TODO (b/265793751): Re-create BrightnessTracker if we're enetering/exiting concurrent
-        // displays mode
     }
 
     /**
@@ -926,7 +942,7 @@
     }
 
     private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info,
-                                             HighBrightnessModeMetadata hbmMetadata) {
+            HighBrightnessModeMetadata hbmMetadata) {
         // All properties that depend on the associated DisplayDevice and the DDC must be
         // updated here.
         loadBrightnessRampRates();
@@ -948,10 +964,9 @@
                         return mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness);
                     }
                 });
-        // TODO (b/265793751): Use the appropriate throttling data if we're in concurrent displays
-        // mode
         mBrightnessThrottler.resetThrottlingData(
-                mDisplayDeviceConfig.getBrightnessThrottlingData(), mUniqueDisplayId);
+                mDisplayDeviceConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId),
+                mUniqueDisplayId);
     }
 
     private void sendUpdatePowerState() {
@@ -1003,7 +1018,7 @@
         }
         mBrightnessSettingListener = brightnessValue -> {
             Message msg = mHandler.obtainMessage(MSG_UPDATE_BRIGHTNESS, brightnessValue);
-            mHandler.sendMessage(msg);
+            mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
         };
 
         mBrightnessSetting.registerListener(mBrightnessSettingListener);
@@ -1032,7 +1047,7 @@
 
         final boolean isIdleScreenBrightnessEnabled = resources.getBoolean(
                 R.bool.config_enableIdleScreenBrightnessMode);
-        mInteractiveModeBrightnessMapper = BrightnessMappingStrategy.create(resources,
+        mInteractiveModeBrightnessMapper = mInjector.getInteractiveModeBrightnessMapper(resources,
                 mDisplayDeviceConfig, mDisplayWhiteBalanceController);
         if (isIdleScreenBrightnessEnabled) {
             mIdleModeBrightnessMapper = BrightnessMappingStrategy.createForIdleMode(resources,
@@ -1057,7 +1072,7 @@
                     mDisplayDeviceConfig.getAmbientLuxDarkeningMinThreshold();
             float ambientBrighteningMinThreshold =
                     mDisplayDeviceConfig.getAmbientLuxBrighteningMinThreshold();
-            HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
+            HysteresisLevels ambientBrightnessThresholds = mInjector.getHysteresisLevels(
                     ambientBrighteningThresholds, ambientDarkeningThresholds,
                     ambientBrighteningLevels, ambientDarkeningLevels, ambientDarkeningMinThreshold,
                     ambientBrighteningMinThreshold);
@@ -1075,7 +1090,7 @@
                     mDisplayDeviceConfig.getScreenDarkeningMinThreshold();
             float screenBrighteningMinThreshold =
                     mDisplayDeviceConfig.getScreenBrighteningMinThreshold();
-            HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
+            HysteresisLevels screenBrightnessThresholds = mInjector.getHysteresisLevels(
                     screenBrighteningThresholds, screenDarkeningThresholds,
                     screenBrighteningLevels, screenDarkeningLevels, screenDarkeningMinThreshold,
                     screenBrighteningMinThreshold, true);
@@ -1093,7 +1108,7 @@
                     mDisplayDeviceConfig.getAmbientBrighteningLevelsIdle();
             float[] ambientDarkeningLevelsIdle =
                     mDisplayDeviceConfig.getAmbientDarkeningLevelsIdle();
-            HysteresisLevels ambientBrightnessThresholdsIdle = new HysteresisLevels(
+            HysteresisLevels ambientBrightnessThresholdsIdle = mInjector.getHysteresisLevels(
                     ambientBrighteningThresholdsIdle, ambientDarkeningThresholdsIdle,
                     ambientBrighteningLevelsIdle, ambientDarkeningLevelsIdle,
                     ambientDarkeningMinThresholdIdle, ambientBrighteningMinThresholdIdle);
@@ -1111,7 +1126,7 @@
                     mDisplayDeviceConfig.getScreenBrighteningLevelsIdle();
             float[] screenDarkeningLevelsIdle =
                     mDisplayDeviceConfig.getScreenDarkeningLevelsIdle();
-            HysteresisLevels screenBrightnessThresholdsIdle = new HysteresisLevels(
+            HysteresisLevels screenBrightnessThresholdsIdle = mInjector.getHysteresisLevels(
                     screenBrighteningThresholdsIdle, screenDarkeningThresholdsIdle,
                     screenBrighteningLevelsIdle, screenDarkeningLevelsIdle,
                     screenDarkeningMinThresholdIdle, screenBrighteningMinThresholdIdle);
@@ -1147,8 +1162,8 @@
             if (mAutomaticBrightnessController != null) {
                 mAutomaticBrightnessController.stop();
             }
-            mAutomaticBrightnessController = new AutomaticBrightnessController(this,
-                    handler.getLooper(), mSensorManager, mLightSensor,
+            mAutomaticBrightnessController = mInjector.getAutomaticBrightnessController(
+                    this, handler.getLooper(), mSensorManager, mLightSensor,
                     mInteractiveModeBrightnessMapper, lightSensorWarmUpTimeConfig,
                     PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, dozeScaleFactor,
                     lightSensorRate, initialLightSensorRate, brighteningLightDebounce,
@@ -1249,7 +1264,7 @@
         public void onAnimationEnd() {
             sendUpdatePowerState();
             Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_RAMP_DONE);
-            mHandler.sendMessage(msg);
+            mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
         }
     };
 
@@ -2061,11 +2076,8 @@
     private BrightnessThrottler createBrightnessThrottlerLocked() {
         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
         final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
-        // TODO (b/265793751): Use the appropriate throttling data if we're in concurrent displays
-        // mode
-        final DisplayDeviceConfig.BrightnessThrottlingData data =
-                ddConfig != null ? ddConfig.getBrightnessThrottlingData() : null;
-        return new BrightnessThrottler(mHandler, data,
+        return new BrightnessThrottler(mHandler,
+                ddConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId),
                 () -> {
                     sendUpdatePowerState();
                     postBrightnessChangeRunnable();
@@ -2200,15 +2212,13 @@
     }
 
     private void loadProximitySensor() {
-        if (DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
+        if (DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT || mDisplayId != Display.DEFAULT_DISPLAY) {
             return;
         }
         final DisplayDeviceConfig.SensorData proxSensor =
                 mDisplayDeviceConfig.getProximitySensor();
-        final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY
-                ? Sensor.TYPE_PROXIMITY : SensorUtils.NO_FALLBACK;
         mProximitySensor = SensorUtils.findSensor(mSensorManager, proxSensor.type, proxSensor.name,
-                fallbackType);
+                Sensor.TYPE_PROXIMITY);
         if (mProximitySensor != null) {
             mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
                     TYPICAL_PROXIMITY_THRESHOLD);
@@ -2698,6 +2708,7 @@
             pw.println();
             pw.println("Display Power Controller:");
             pw.println("  mDisplayId=" + mDisplayId);
+            pw.println("  mLeadDisplayId=" + mLeadDisplayId);
             pw.println("  mLightSensor=" + mLightSensor);
 
             pw.println();
@@ -2946,7 +2957,8 @@
                 msg.what = MSG_STATSD_HBM_BRIGHTNESS;
                 msg.arg1 = Float.floatToIntBits(brightness);
                 msg.arg2 = mDisplayStatsId;
-                mHandler.sendMessageDelayed(msg, BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
+                mHandler.sendMessageAtTime(msg, mClock.uptimeMillis()
+                        + BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
             }
         }
     }
@@ -3102,7 +3114,7 @@
         @Override
         public void onScreenOn() {
             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
-            mHandler.sendMessage(msg);
+            mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
         }
     }
 
@@ -3110,7 +3122,7 @@
         @Override
         public void onScreenOff() {
             Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this);
-            mHandler.sendMessage(msg);
+            mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
         }
     }
 
@@ -3192,6 +3204,58 @@
                 FloatProperty<DisplayPowerState> secondProperty) {
             return new DualRampAnimator(dps, firstProperty, secondProperty);
         }
+
+        AutomaticBrightnessController getAutomaticBrightnessController(
+                AutomaticBrightnessController.Callbacks callbacks, Looper looper,
+                SensorManager sensorManager, Sensor lightSensor,
+                BrightnessMappingStrategy interactiveModeBrightnessMapper,
+                int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
+                float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
+                long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
+                boolean resetAmbientLuxAfterWarmUpConfig,
+                HysteresisLevels ambientBrightnessThresholds,
+                HysteresisLevels screenBrightnessThresholds,
+                HysteresisLevels ambientBrightnessThresholdsIdle,
+                HysteresisLevels screenBrightnessThresholdsIdle, Context context,
+                HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
+                BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
+                int ambientLightHorizonLong, float userLux, float userBrightness) {
+            return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor,
+                    interactiveModeBrightnessMapper, lightSensorWarmUpTime, brightnessMin,
+                    brightnessMax, dozeScaleFactor, lightSensorRate, initialLightSensorRate,
+                    brighteningLightDebounceConfig, darkeningLightDebounceConfig,
+                    resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds,
+                    screenBrightnessThresholds, ambientBrightnessThresholdsIdle,
+                    screenBrightnessThresholdsIdle, context, hbmController, brightnessThrottler,
+                    idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong,
+                    userLux, userBrightness);
+        }
+
+        BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
+                DisplayDeviceConfig displayDeviceConfig,
+                DisplayWhiteBalanceController displayWhiteBalanceController) {
+            return BrightnessMappingStrategy.create(resources,
+                    displayDeviceConfig, displayWhiteBalanceController);
+        }
+
+        HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
+                float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
+                float[] darkeningThresholdLevels, float minDarkeningThreshold,
+                float minBrighteningThreshold) {
+            return new HysteresisLevels(brighteningThresholdsPercentages,
+                    darkeningThresholdsPercentages, brighteningThresholdLevels,
+                    darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold);
+        }
+
+        HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
+                float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
+                float[] darkeningThresholdLevels, float minDarkeningThreshold,
+                float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
+            return new HysteresisLevels(brighteningThresholdsPercentages,
+                    darkeningThresholdsPercentages, brighteningThresholdLevels,
+                    darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold,
+                    potentialOldBrightnessRange);
+        }
     }
 
     static class CachedBrightnessInfo {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 2e91bdb..82faa12 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -73,6 +73,7 @@
 import com.android.server.display.brightness.DisplayBrightnessController;
 import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
 import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
+import com.android.server.display.layout.Layout;
 import com.android.server.display.state.DisplayStateController;
 import com.android.server.display.utils.SensorUtils;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
@@ -179,6 +180,9 @@
     // The ID of the LogicalDisplay tied to this DisplayPowerController2.
     private final int mDisplayId;
 
+    // The ID of the display which this display follows for brightness purposes.
+    private int mLeadDisplayId = Layout.NO_LEAD_DISPLAY;
+
     // The unique ID of the primary display device currently tied to this logical display
     private String mUniqueDisplayId;
 
@@ -411,6 +415,8 @@
     private boolean mIsEnabled;
     private boolean mIsInTransition;
 
+    private String mBrightnessThrottlingDataId;
+
     // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there
     // is one lead display, the additional displays follow the brightness value of the lead display.
     @GuardedBy("mLock")
@@ -443,6 +449,7 @@
         mHighBrightnessModeMetadata = hbmMetadata;
         mDisplayStateController = new DisplayStateController(mDisplayPowerProximityStateController);
         mTag = "DisplayPowerController2[" + mDisplayId + "]";
+        mBrightnessThrottlingDataId = logicalDisplay.getBrightnessThrottlingDataIdLocked();
 
         mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
         mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
@@ -691,7 +698,8 @@
      * Make sure DisplayManagerService.mSyncRoot lock is held when this is called
      */
     @Override
-    public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) {
+    public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata, int leadDisplayId) {
+        mLeadDisplayId = leadDisplayId;
         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
         if (device == null) {
             Slog.wtf(mTag, "Display Device is null in DisplayPowerController2 for display: "
@@ -705,6 +713,8 @@
         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         final boolean isEnabled = mLogicalDisplay.isEnabledLocked();
         final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
+        final String brightnessThrottlingDataId =
+                mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
 
         mHandler.post(() -> {
             boolean changed = false;
@@ -714,6 +724,7 @@
                 mUniqueDisplayId = uniqueId;
                 mDisplayStatsId = mUniqueDisplayId.hashCode();
                 mDisplayDeviceConfig = config;
+                mBrightnessThrottlingDataId = brightnessThrottlingDataId;
                 loadFromDisplayDeviceConfig(token, info, hbmMetadata);
                 mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config);
 
@@ -721,6 +732,12 @@
                 // last command that was sent to change it's state. Lets assume it is unknown so
                 // that we trigger a change immediately.
                 mPowerState.resetScreenState();
+            } else if (!mBrightnessThrottlingDataId.equals(brightnessThrottlingDataId)) {
+                changed = true;
+                mBrightnessThrottlingDataId = brightnessThrottlingDataId;
+                mBrightnessThrottler.resetThrottlingData(
+                        config.getBrightnessThrottlingData(mBrightnessThrottlingDataId),
+                        mUniqueDisplayId);
             }
             if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) {
                 changed = true;
@@ -732,9 +749,6 @@
                 updatePowerState();
             }
         });
-
-        // TODO (b/265793751): Re-create BrightnessTracker if we're enetering/exiting concurrent
-        // displays mode
     }
 
     /**
@@ -765,7 +779,7 @@
     }
 
     private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info,
-                                             HighBrightnessModeMetadata hbmMetadata) {
+            HighBrightnessModeMetadata hbmMetadata) {
         // All properties that depend on the associated DisplayDevice and the DDC must be
         // updated here.
         loadBrightnessRampRates();
@@ -786,10 +800,9 @@
                         return mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness);
                     }
                 });
-        // TODO (b/265793751): Use the appropriate throttling data if we're in concurrent displays
-        // mode
         mBrightnessThrottler.resetThrottlingData(
-                mDisplayDeviceConfig.getBrightnessThrottlingData(), mUniqueDisplayId);
+                mDisplayDeviceConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId),
+                mUniqueDisplayId);
     }
 
     private void sendUpdatePowerState() {
@@ -842,7 +855,7 @@
 
         BrightnessSetting.BrightnessSettingListener brightnessSettingListener = brightnessValue -> {
             Message msg = mHandler.obtainMessage(MSG_UPDATE_BRIGHTNESS, brightnessValue);
-            mHandler.sendMessage(msg);
+            mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
         };
         mDisplayBrightnessController
                 .registerBrightnessSettingChangeListener(brightnessSettingListener);
@@ -872,7 +885,7 @@
 
         final boolean isIdleScreenBrightnessEnabled = resources.getBoolean(
                 R.bool.config_enableIdleScreenBrightnessMode);
-        mInteractiveModeBrightnessMapper = BrightnessMappingStrategy.create(resources,
+        mInteractiveModeBrightnessMapper = mInjector.getInteractiveModeBrightnessMapper(resources,
                 mDisplayDeviceConfig, mDisplayWhiteBalanceController);
         if (isIdleScreenBrightnessEnabled) {
             mIdleModeBrightnessMapper = BrightnessMappingStrategy.createForIdleMode(resources,
@@ -897,7 +910,7 @@
                     mDisplayDeviceConfig.getAmbientLuxDarkeningMinThreshold();
             float ambientBrighteningMinThreshold =
                     mDisplayDeviceConfig.getAmbientLuxBrighteningMinThreshold();
-            HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
+            HysteresisLevels ambientBrightnessThresholds = mInjector.getHysteresisLevels(
                     ambientBrighteningThresholds, ambientDarkeningThresholds,
                     ambientBrighteningLevels, ambientDarkeningLevels, ambientDarkeningMinThreshold,
                     ambientBrighteningMinThreshold);
@@ -915,7 +928,7 @@
                     mDisplayDeviceConfig.getScreenDarkeningMinThreshold();
             float screenBrighteningMinThreshold =
                     mDisplayDeviceConfig.getScreenBrighteningMinThreshold();
-            HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
+            HysteresisLevels screenBrightnessThresholds = mInjector.getHysteresisLevels(
                     screenBrighteningThresholds, screenDarkeningThresholds,
                     screenBrighteningLevels, screenDarkeningLevels, screenDarkeningMinThreshold,
                     screenBrighteningMinThreshold, true);
@@ -933,7 +946,7 @@
                     mDisplayDeviceConfig.getAmbientBrighteningLevelsIdle();
             float[] ambientDarkeningLevelsIdle =
                     mDisplayDeviceConfig.getAmbientDarkeningLevelsIdle();
-            HysteresisLevels ambientBrightnessThresholdsIdle = new HysteresisLevels(
+            HysteresisLevels ambientBrightnessThresholdsIdle = mInjector.getHysteresisLevels(
                     ambientBrighteningThresholdsIdle, ambientDarkeningThresholdsIdle,
                     ambientBrighteningLevelsIdle, ambientDarkeningLevelsIdle,
                     ambientDarkeningMinThresholdIdle, ambientBrighteningMinThresholdIdle);
@@ -951,7 +964,7 @@
                     mDisplayDeviceConfig.getScreenBrighteningLevelsIdle();
             float[] screenDarkeningLevelsIdle =
                     mDisplayDeviceConfig.getScreenDarkeningLevelsIdle();
-            HysteresisLevels screenBrightnessThresholdsIdle = new HysteresisLevels(
+            HysteresisLevels screenBrightnessThresholdsIdle = mInjector.getHysteresisLevels(
                     screenBrighteningThresholdsIdle, screenDarkeningThresholdsIdle,
                     screenBrighteningLevelsIdle, screenDarkeningLevelsIdle,
                     screenDarkeningMinThresholdIdle, screenBrighteningMinThresholdIdle);
@@ -987,8 +1000,8 @@
             if (mAutomaticBrightnessController != null) {
                 mAutomaticBrightnessController.stop();
             }
-            mAutomaticBrightnessController = new AutomaticBrightnessController(this,
-                    handler.getLooper(), mSensorManager, mLightSensor,
+            mAutomaticBrightnessController = mInjector.getAutomaticBrightnessController(
+                    this, handler.getLooper(), mSensorManager, mLightSensor,
                     mInteractiveModeBrightnessMapper, lightSensorWarmUpTimeConfig,
                     PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, dozeScaleFactor,
                     lightSensorRate, initialLightSensorRate, brighteningLightDebounce,
@@ -1086,7 +1099,7 @@
         public void onAnimationEnd() {
             sendUpdatePowerState();
             Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_RAMP_DONE);
-            mHandler.sendMessage(msg);
+            mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
         }
     };
 
@@ -1768,11 +1781,8 @@
     private BrightnessThrottler createBrightnessThrottlerLocked() {
         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
         final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
-        // TODO (b/265793751): Use the appropriate throttling data if we're in concurrent displays
-        // mode
-        final DisplayDeviceConfig.BrightnessThrottlingData data =
-                ddConfig != null ? ddConfig.getBrightnessThrottlingData() : null;
-        return new BrightnessThrottler(mHandler, data,
+        return new BrightnessThrottler(mHandler,
+                ddConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId),
                 () -> {
                     sendUpdatePowerState();
                     postBrightnessChangeRunnable();
@@ -2144,6 +2154,11 @@
     }
 
     @Override
+    public int getLeadDisplayId() {
+        return mLeadDisplayId;
+    }
+
+    @Override
     public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) {
         mHbmController.onAmbientLuxChange(ambientLux);
         if (mAutomaticBrightnessController == null || nits < 0) {
@@ -2213,21 +2228,17 @@
     public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
         synchronized (mLock) {
             mDisplayBrightnessFollowers.append(follower.getDisplayId(), follower);
+            sendUpdatePowerStateLocked();
         }
-        sendUpdatePowerState();
     }
 
     @Override
-    public void clearDisplayBrightnessFollowers() {
-        SparseArray<DisplayPowerControllerInterface> followers;
+    public void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
         synchronized (mLock) {
-            followers = mDisplayBrightnessFollowers.clone();
-            mDisplayBrightnessFollowers.clear();
-        }
-        for (int i = 0; i < followers.size(); i++) {
-            DisplayPowerControllerInterface follower = followers.valueAt(i);
-            follower.setBrightnessToFollow(PowerManager.BRIGHTNESS_INVALID_FLOAT, /* nits= */ -1,
-                    /* ambientLux= */ 0);
+            mDisplayBrightnessFollowers.remove(follower.getDisplayId());
+            mHandler.postAtTime(() -> follower.setBrightnessToFollow(
+                    PowerManager.BRIGHTNESS_INVALID_FLOAT, /* nits= */ -1,
+                    /* ambientLux= */ 0), mClock.uptimeMillis());
         }
     }
 
@@ -2237,6 +2248,7 @@
             pw.println();
             pw.println("Display Power Controller:");
             pw.println("  mDisplayId=" + mDisplayId);
+            pw.println("  mLeadDisplayId=" + mLeadDisplayId);
             pw.println("  mLightSensor=" + mLightSensor);
 
             pw.println();
@@ -2453,7 +2465,8 @@
                 msg.what = MSG_STATSD_HBM_BRIGHTNESS;
                 msg.arg1 = Float.floatToIntBits(brightness);
                 msg.arg2 = mDisplayStatsId;
-                mHandler.sendMessageDelayed(msg, BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
+                mHandler.sendMessageAtTime(msg, mClock.uptimeMillis()
+                        + BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
             }
         }
     }
@@ -2584,7 +2597,7 @@
         @Override
         public void onScreenOn() {
             Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
-            mHandler.sendMessage(msg);
+            mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
         }
     }
 
@@ -2592,7 +2605,7 @@
         @Override
         public void onScreenOff() {
             Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this);
-            mHandler.sendMessage(msg);
+            mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
         }
     }
 
@@ -2666,6 +2679,58 @@
                     looper, nudgeUpdatePowerState,
                     displayId, sensorManager, /* injector= */ null);
         }
+
+        AutomaticBrightnessController getAutomaticBrightnessController(
+                AutomaticBrightnessController.Callbacks callbacks, Looper looper,
+                SensorManager sensorManager, Sensor lightSensor,
+                BrightnessMappingStrategy interactiveModeBrightnessMapper,
+                int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
+                float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
+                long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
+                boolean resetAmbientLuxAfterWarmUpConfig,
+                HysteresisLevels ambientBrightnessThresholds,
+                HysteresisLevels screenBrightnessThresholds,
+                HysteresisLevels ambientBrightnessThresholdsIdle,
+                HysteresisLevels screenBrightnessThresholdsIdle, Context context,
+                HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler,
+                BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort,
+                int ambientLightHorizonLong, float userLux, float userBrightness) {
+            return new AutomaticBrightnessController(callbacks, looper, sensorManager, lightSensor,
+                    interactiveModeBrightnessMapper, lightSensorWarmUpTime, brightnessMin,
+                    brightnessMax, dozeScaleFactor, lightSensorRate, initialLightSensorRate,
+                    brighteningLightDebounceConfig, darkeningLightDebounceConfig,
+                    resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds,
+                    screenBrightnessThresholds, ambientBrightnessThresholdsIdle,
+                    screenBrightnessThresholdsIdle, context, hbmController, brightnessThrottler,
+                    idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong,
+                    userLux, userBrightness);
+        }
+
+        BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
+                DisplayDeviceConfig displayDeviceConfig,
+                DisplayWhiteBalanceController displayWhiteBalanceController) {
+            return BrightnessMappingStrategy.create(resources,
+                    displayDeviceConfig, displayWhiteBalanceController);
+        }
+
+        HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
+                float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
+                float[] darkeningThresholdLevels, float minDarkeningThreshold,
+                float minBrighteningThreshold) {
+            return new HysteresisLevels(brighteningThresholdsPercentages,
+                    darkeningThresholdsPercentages, brighteningThresholdLevels,
+                    darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold);
+        }
+
+        HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
+                float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
+                float[] darkeningThresholdLevels, float minDarkeningThreshold,
+                float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
+            return new HysteresisLevels(brighteningThresholdsPercentages,
+                    darkeningThresholdsPercentages, brighteningThresholdLevels,
+                    darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold,
+                    potentialOldBrightnessRange);
+        }
     }
 
     static class CachedBrightnessInfo {
diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
index 4612ec9..0bc8154 100644
--- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
+++ b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
@@ -32,13 +32,18 @@
 
     /**
      * Notified when the display is changed.
-     * We use this to apply any changes that might be needed
-     * when displays get swapped on foldable devices.
-     * We also pass the High brightness mode metadata like
-     * remaining time and hbm events for the corresponding
-     * physical display, to update the values correctly.
+     *
+     * We use this to apply any changes that might be needed when displays get swapped on foldable
+     * devices, when layouts change, etc.
+     *
+     * Must be called while holding the SyncRoot lock.
+     *
+     * @param hbmInfo The high brightness mode metadata, like
+     *                remaining time and hbm events, for the corresponding
+     *                physical display, to make sure we stay within the safety margins.
+     * @param leadDisplayId The display who is considered our "leader" for things like brightness.
      */
-    void onDisplayChanged(HighBrightnessModeMetadata hbmInfo);
+    void onDisplayChanged(HighBrightnessModeMetadata hbmInfo, int leadDisplayId);
 
     /**
      * Unregisters all listeners and interrupts all running threads; halting future work.
@@ -169,6 +174,16 @@
     int getDisplayId();
 
     /**
+     * Get the ID of the display that is the leader of this DPC.
+     *
+     * Note that this is different than the display associated with the DPC. The leader is another
+     * display which we follow for things like brightness.
+     *
+     * Must be called while holding the SyncRoot lock.
+     */
+    int getLeadDisplayId();
+
+    /**
      * Set the brightness to follow if this is an additional display in a set of concurrent
      * displays.
      * @param leadDisplayBrightness The brightness of the lead display in the set of concurrent
@@ -187,7 +202,8 @@
     void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
 
     /**
-     * Clear all the additional displays following the brightness value of this display.
+     * Removes the given display from the list of brightness followers.
+     * @param follower The DPC to remove from the followers list
      */
-    void clearDisplayBrightnessFollowers();
+    void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
 }
diff --git a/services/core/java/com/android/server/display/DisplayPowerProximityStateController.java b/services/core/java/com/android/server/display/DisplayPowerProximityStateController.java
index a3433d9..5bb3e6b 100644
--- a/services/core/java/com/android/server/display/DisplayPowerProximityStateController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerProximityStateController.java
@@ -346,15 +346,13 @@
     }
 
     private void loadProximitySensor() {
-        if (DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
+        if (DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT || mDisplayId != Display.DEFAULT_DISPLAY) {
             return;
         }
         final DisplayDeviceConfig.SensorData proxSensor =
                 mDisplayDeviceConfig.getProximitySensor();
-        final int fallbackType = mDisplayId == Display.DEFAULT_DISPLAY
-                ? Sensor.TYPE_PROXIMITY : SensorUtils.NO_FALLBACK;
         mProximitySensor = SensorUtils.findSensor(mSensorManager, proxSensor.type, proxSensor.name,
-                fallbackType);
+                Sensor.TYPE_PROXIMITY);
         if (mProximitySensor != null) {
             mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
                     TYPICAL_PROXIMITY_THRESHOLD);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index dfdbce5..1086c55 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -31,6 +31,7 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 
+import com.android.server.display.layout.Layout;
 import com.android.server.wm.utils.InsetUtils;
 
 import java.io.PrintWriter;
@@ -76,6 +77,12 @@
     private final int mDisplayId;
     private final int mLayerStack;
 
+    // Indicates which display leads this logical display, in terms of brightness or other
+    // properties.
+    // {@link Layout.NO_LEAD_DISPLAY} means that this display is not lead by any others, and could
+    // be a leader itself.
+    private int mLeadDisplayId = Layout.NO_LEAD_DISPLAY;
+
     private int mDisplayGroupId = Display.INVALID_DISPLAY_GROUP;
 
     /**
@@ -149,9 +156,24 @@
 
     // Indicates the display is part of a transition from one device-state ({@link
     // DeviceStateManager}) to another. Being a "part" of a transition means that either
-    // the {@link mIsEnabled} is changing, or the underlying mPrimiaryDisplayDevice is changing.
+    // the {@link mIsEnabled} is changing, or the underlying mPrimaryDisplayDevice is changing.
     private boolean mIsInTransition;
 
+    // Indicates the position of the display, POSITION_UNKNOWN could mean it hasn't been specified,
+    // or this is a virtual display etc.
+    private int mDevicePosition = Layout.Display.POSITION_UNKNOWN;
+
+    // Indicates that something other than the primary display device info has changed and needs to
+    // be handled in the next update.
+    private boolean mDirty = false;
+
+    /**
+     * The ID of the brightness throttling data that should be used. This can change e.g. in
+     * concurrent displays mode in which a stricter brightness throttling policy might need to be
+     * used.
+     */
+    private String mBrightnessThrottlingDataId;
+
     public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) {
         mDisplayId = displayId;
         mLayerStack = layerStack;
@@ -160,6 +182,17 @@
         mTempFrameRateOverride = new SparseArray<>();
         mIsEnabled = true;
         mIsInTransition = false;
+        mBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID;
+    }
+
+    public void setDevicePositionLocked(int position) {
+        if (mDevicePosition != position) {
+            mDevicePosition = position;
+            mDirty = true;
+        }
+    }
+    public int getDevicePositionLocked() {
+        return mDevicePosition;
     }
 
     /**
@@ -317,9 +350,11 @@
         // logical display that they are sharing.  (eg. Adjust size for pixel-perfect
         // mirroring over HDMI.)
         DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked();
-        if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo)) {
+        if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo) || mDirty) {
             mBaseDisplayInfo.layerStack = mLayerStack;
             mBaseDisplayInfo.flags = 0;
+            // Displays default to moving content to the primary display when removed
+            mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
                 mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS;
             }
@@ -416,8 +451,21 @@
             mBaseDisplayInfo.roundedCorners = deviceInfo.roundedCorners;
             mBaseDisplayInfo.installOrientation = deviceInfo.installOrientation;
             mBaseDisplayInfo.displayShape = deviceInfo.displayShape;
+
+            if (mDevicePosition == Layout.Display.POSITION_REAR) {
+                // A rear display is meant to host a specific experience that is essentially
+                // a presentation to another user or users other than the main user since they
+                // can't actually see that display. Given that, it's a suitable display for
+                // presentations but the content should be destroyed rather than moved to a non-rear
+                // display when the rear display is removed.
+                mBaseDisplayInfo.flags |= Display.FLAG_REAR;
+                mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION;
+                mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT;
+            }
+
             mPrimaryDisplayDeviceInfo = deviceInfo;
             mInfo.set(null);
+            mDirty = false;
         }
     }
 
@@ -762,7 +810,7 @@
     /**
      * Sets the display as enabled.
      *
-     * @param enable True if enabled, false otherwise.
+     * @param enabled True if enabled, false otherwise.
      */
     public void setEnabledLocked(boolean enabled) {
         mIsEnabled = enabled;
@@ -785,11 +833,48 @@
         mIsInTransition = isInTransition;
     }
 
+    /**
+     * @return The ID of the brightness throttling data that this display should use.
+     */
+    public String getBrightnessThrottlingDataIdLocked() {
+        return mBrightnessThrottlingDataId;
+    }
+
+    /**
+     * @param brightnessThrottlingDataId The ID of the brightness throttling data that this
+     *                                  display should use.
+     */
+    public void setBrightnessThrottlingDataIdLocked(String brightnessThrottlingDataId) {
+        mBrightnessThrottlingDataId =
+                brightnessThrottlingDataId;
+    }
+
+    /**
+     * Sets the display of which this display is a follower, regarding brightness or other
+     * properties. If set to {@link Layout#NO_LEAD_DISPLAY}, this display does not follow any
+     * others, and has the potential to be a lead display to others.
+     *
+     * A display cannot be a leader or follower of itself, and there cannot be cycles.
+     * A display cannot be both a leader and a follower, ie, there must not be any chains.
+     *
+     * @param displayId logical display id
+     */
+    public void setLeadDisplayLocked(int displayId) {
+        if (mDisplayId != mLeadDisplayId && mDisplayId != displayId) {
+            mLeadDisplayId = displayId;
+        }
+    }
+
+    public int getLeadDisplayIdLocked() {
+        return mLeadDisplayId;
+    }
+
     public void dumpLocked(PrintWriter pw) {
         pw.println("mDisplayId=" + mDisplayId);
         pw.println("mIsEnabled=" + mIsEnabled);
         pw.println("mIsInTransition=" + mIsInTransition);
         pw.println("mLayerStack=" + mLayerStack);
+        pw.println("mPosition=" + mDevicePosition);
         pw.println("mHasContent=" + mHasContent);
         pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}");
         pw.println("mRequestedColorMode=" + mRequestedColorMode);
@@ -802,6 +887,8 @@
         pw.println("mRequestedMinimalPostProcessing=" + mRequestedMinimalPostProcessing);
         pw.println("mFrameRateOverrides=" + Arrays.toString(mFrameRateOverrides));
         pw.println("mPendingFrameRateOverrideUids=" + mPendingFrameRateOverrideUids);
+        pw.println("mBrightnessThrottlingDataId=" + mBrightnessThrottlingDataId);
+        pw.println("mLeadDisplayId=" + mLeadDisplayId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 5087caa..c695862 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -18,6 +18,8 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.android.server.display.layout.Layout.NO_LEAD_DISPLAY;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -638,7 +640,8 @@
                         & DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0
                         && !nextDeviceInfo.address.equals(deviceInfo.address)) {
                     layout.createDisplayLocked(nextDeviceInfo.address,
-                            /* isDefault= */ true, /* isEnabled= */ true, mIdProducer);
+                            /* isDefault= */ true, /* isEnabled= */ true, mIdProducer,
+                            /* brightnessThrottlingMapId= */ null, DEFAULT_DISPLAY);
                     applyLayoutLocked();
                     return;
                 }
@@ -976,6 +979,7 @@
             // Now that we have a display-device, we need a LogicalDisplay to map it to. Find the
             // right one, if it doesn't exist, create a new one.
             final int logicalDisplayId = displayLayout.getLogicalDisplayId();
+
             LogicalDisplay newDisplay = getDisplayLocked(logicalDisplayId);
             if (newDisplay == null) {
                 newDisplay = createNewLogicalDisplayLocked(
@@ -988,11 +992,23 @@
                 newDisplay.swapDisplaysLocked(oldDisplay);
             }
 
+            newDisplay.setDevicePositionLocked(displayLayout.getPosition());
+            newDisplay.setLeadDisplayLocked(displayLayout.getLeadDisplayId());
+            setLayoutLimitedRefreshRate(newDisplay, device, displayLayout);
             setEnabledLocked(newDisplay, displayLayout.isEnabled());
+            newDisplay.setBrightnessThrottlingDataIdLocked(
+                    displayLayout.getBrightnessThrottlingMapId() == null
+                            ? DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID
+                            : displayLayout.getBrightnessThrottlingMapId());
         }
-
     }
 
+    private void setLayoutLimitedRefreshRate(@NonNull LogicalDisplay logicalDisplay,
+            @NonNull DisplayDevice device, @NonNull Layout.Display display) {
+        DisplayDeviceConfig config = device.getDisplayDeviceConfig();
+        DisplayInfo info = logicalDisplay.getDisplayInfoLocked();
+        info.layoutLimitedRefreshRate = config.getRefreshRange(display.getRefreshRateZoneId());
+    }
 
     /**
      * Creates a new logical display for the specified device and display Id and adds it to the list
@@ -1063,7 +1079,7 @@
         }
         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         layout.createDisplayLocked(info.address, /* isDefault= */ true, /* isEnabled= */ true,
-                mIdProducer);
+                mIdProducer, /* brightnessThrottlingMapId= */ null, NO_LEAD_DISPLAY);
     }
 
     private int assignLayerStackLocked(int displayId) {
diff --git a/services/core/java/com/android/server/display/TEST_MAPPING b/services/core/java/com/android/server/display/TEST_MAPPING
index 57c2e01..c4a566f 100644
--- a/services/core/java/com/android/server/display/TEST_MAPPING
+++ b/services/core/java/com/android/server/display/TEST_MAPPING
@@ -16,6 +16,20 @@
                 {"exclude-annotation": "androidx.test.filters.FlakyTest"},
                 {"exclude-annotation": "org.junit.Ignore"}
             ]
+        },
+        {
+            "name": "CtsMediaProjectionTestCases",
+            "options": [
+                {
+                    "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+                },
+                {
+                    "exclude-annotation": "androidx.test.filters.FlakyTest"
+                },
+                {
+                    "exclude-annotation": "org.junit.Ignore"
+                }
+            ]
         }
     ]
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index ddeaa1b..364d53b 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -106,7 +106,8 @@
         String name = virtualDisplayConfig.getName();
         boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
         IBinder appToken = callback.asBinder();
-        IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure);
+        IBinder displayToken = mSurfaceControlDisplayFactory.createDisplay(name, secure,
+                virtualDisplayConfig.getRequestedRefreshRate());
         final String baseUniqueId =
                 UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ",";
         final int uniqueIndex = getNextUniqueIndex(baseUniqueId);
@@ -247,6 +248,7 @@
         private int mWidth;
         private int mHeight;
         private int mDensityDpi;
+        private float mRequestedRefreshRate;
         private Surface mSurface;
         private DisplayDeviceInfo mInfo;
         private int mDisplayState;
@@ -270,8 +272,9 @@
             mName = virtualDisplayConfig.getName();
             mWidth = virtualDisplayConfig.getWidth();
             mHeight = virtualDisplayConfig.getHeight();
-            mMode = createMode(mWidth, mHeight, REFRESH_RATE);
             mDensityDpi = virtualDisplayConfig.getDensityDpi();
+            mRequestedRefreshRate = virtualDisplayConfig.getRequestedRefreshRate();
+            mMode = createMode(mWidth, mHeight, getRefreshRate());
             mSurface = surface;
             mFlags = flags;
             mCallback = callback;
@@ -410,7 +413,7 @@
                 sendTraversalRequestLocked();
                 mWidth = width;
                 mHeight = height;
-                mMode = createMode(width, height, REFRESH_RATE);
+                mMode = createMode(width, height, getRefreshRate());
                 mDensityDpi = densityDpi;
                 mInfo = null;
                 mPendingChanges |= PENDING_RESIZE;
@@ -438,9 +441,9 @@
             pw.println("mStopped=" + mStopped);
             pw.println("mDisplayIdToMirror=" + mDisplayIdToMirror);
             pw.println("mWindowManagerMirroring=" + mIsWindowManagerMirroring);
+            pw.println("mRequestedRefreshRate=" + mRequestedRefreshRate);
         }
 
-
         @Override
         public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
             if (mInfo == null) {
@@ -456,7 +459,7 @@
                 mInfo.densityDpi = mDensityDpi;
                 mInfo.xDpi = mDensityDpi;
                 mInfo.yDpi = mDensityDpi;
-                mInfo.presentationDeadlineNanos = 1000000000L / (int) REFRESH_RATE; // 1 frame
+                mInfo.presentationDeadlineNanos = 1000000000L / (int) getRefreshRate(); // 1 frame
                 mInfo.flags = 0;
                 if ((mFlags & VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) {
                     mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE
@@ -554,6 +557,10 @@
             }
             return mInfo;
         }
+
+        private float getRefreshRate() {
+            return (mRequestedRefreshRate != 0.0f) ? mRequestedRefreshRate : REFRESH_RATE;
+        }
     }
 
     private static class Callback extends Handler {
@@ -632,6 +639,19 @@
 
     @VisibleForTesting
     public interface SurfaceControlDisplayFactory {
-        public IBinder createDisplay(String name, boolean secure);
+        /**
+         * Create a virtual display in SurfaceFlinger.
+         *
+         * @param name The name of the display
+         * @param secure Whether this display is secure.
+         * @param requestedRefreshRate
+         *     The refresh rate, frames per second, to request on the virtual display.
+         *     It should be a divisor of refresh rate of the leader physical display
+         *     that drives VSYNC, e.g. 30/60fps on 120fps display. If an arbitrary refresh
+         *     rate is specified, SurfaceFlinger rounds up or down to match a divisor of
+         *     the refresh rate of the leader physical display.
+         * @return The token reference for the display in SurfaceFlinger.
+         */
+        IBinder createDisplay(String name, boolean secure, float requestedRefreshRate);
     }
 }
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index 13fcff3..e3d92a7 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -92,9 +92,9 @@
         // TODO: b/186428377 update brightness setting when display changes
         mBrightnessSetting = brightnessSetting;
         mPendingScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        mScreenBrightnessDefault = BrightnessUtils.clampAbsoluteBrightness(defaultScreenBrightness);
         mCurrentScreenBrightness = getScreenBrightnessSetting();
         mOnBrightnessChangeRunnable = onBrightnessChangeRunnable;
-        mScreenBrightnessDefault = BrightnessUtils.clampAbsoluteBrightness(defaultScreenBrightness);
         mDisplayBrightnessStrategySelector = injector.getDisplayBrightnessStrategySelector(context,
                 displayId);
     }
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 5824887..0284d9c 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -108,11 +108,6 @@
         Matrix.setIdentityM(MATRIX_IDENTITY, 0);
     }
 
-    /**
-     * The transition time, in milliseconds, for Night Display to turn on/off.
-     */
-    private static final long TRANSITION_DURATION = 3000L;
-
     private static final int MSG_USER_CHANGED = 0;
     private static final int MSG_SET_UP = 1;
     private static final int MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE = 2;
@@ -663,7 +658,7 @@
             TintValueAnimator valueAnimator = TintValueAnimator.ofMatrix(COLOR_MATRIX_EVALUATOR,
                     from == null ? MATRIX_IDENTITY : from, to);
             tintController.setAnimator(valueAnimator);
-            valueAnimator.setDuration(TRANSITION_DURATION);
+            valueAnimator.setDuration(tintController.getTransitionDurationMilliseconds());
             valueAnimator.setInterpolator(AnimationUtils.loadInterpolator(
                     getContext(), android.R.interpolator.fast_out_slow_in));
             valueAnimator.addUpdateListener((ValueAnimator animator) -> {
diff --git a/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java b/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
index c5dd6ac..106ac0c 100644
--- a/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
+++ b/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
@@ -60,7 +60,8 @@
     private float[] mCurrentColorTemperatureXYZ;
     @VisibleForTesting
     boolean mSetUp = false;
-    private float[] mMatrixDisplayWhiteBalance = new float[16];
+    private final float[] mMatrixDisplayWhiteBalance = new float[16];
+    private long mTransitionDuration;
     private Boolean mIsAvailable;
     // This feature becomes disallowed if the device is in an unsupported strong/light state.
     private boolean mIsAllowed = true;
@@ -126,6 +127,9 @@
         final int colorTemperature = res.getInteger(
                 R.integer.config_displayWhiteBalanceColorTemperatureDefault);
 
+        mTransitionDuration = res.getInteger(
+                R.integer.config_displayWhiteBalanceTransitionTime);
+
         synchronized (mLock) {
             mDisplayColorSpaceRGB = displayColorSpaceRGB;
             mDisplayNominalWhiteXYZ = displayNominalWhiteXYZ;
@@ -239,6 +243,11 @@
     }
 
     @Override
+    public long getTransitionDurationMilliseconds() {
+        return mTransitionDuration;
+    }
+
+    @Override
     public void dump(PrintWriter pw) {
         synchronized (mLock) {
             pw.println("    mSetUp = " + mSetUp);
diff --git a/services/core/java/com/android/server/display/color/TintController.java b/services/core/java/com/android/server/display/color/TintController.java
index 422dd32..c53ac06 100644
--- a/services/core/java/com/android/server/display/color/TintController.java
+++ b/services/core/java/com/android/server/display/color/TintController.java
@@ -16,7 +16,6 @@
 
 package com.android.server.display.color;
 
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.util.Slog;
 
@@ -24,6 +23,11 @@
 
 abstract class TintController {
 
+    /**
+     * The default transition time, in milliseconds, for color transforms to turn on/off.
+     */
+    private static final long TRANSITION_DURATION = 3000L;
+
     private ColorDisplayService.TintValueAnimator mAnimator;
     private Boolean mIsActivated;
 
@@ -66,6 +70,10 @@
         return mIsActivated == null;
     }
 
+    public long getTransitionDurationMilliseconds() {
+        return TRANSITION_DURATION;
+    }
+
     /**
      * Dump debug information.
      */
diff --git a/services/core/java/com/android/server/display/layout/Layout.java b/services/core/java/com/android/server/display/layout/Layout.java
index 4a466fd..59d95a6 100644
--- a/services/core/java/com/android/server/display/layout/Layout.java
+++ b/services/core/java/com/android/server/display/layout/Layout.java
@@ -18,6 +18,8 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.android.server.display.layout.Layout.Display.POSITION_UNKNOWN;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.Slog;
@@ -25,6 +27,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Holds a collection of {@link Display}s. A single instance of this class describes
@@ -36,6 +39,10 @@
     private static final String TAG = "Layout";
     private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;
 
+    // Lead display Id is set to this if this is not a follower display, and therefore
+    // has no lead.
+    public static final int NO_LEAD_DISPLAY = -1;
+
     private final List<Display> mDisplays = new ArrayList<>(2);
 
     /**
@@ -72,11 +79,34 @@
      * @param address Address of the device.
      * @param isDefault Indicates if the device is meant to be the default display.
      * @param isEnabled Indicates if this display is usable and can be switched on
-     * @return The new layout.
+     * @param idProducer Produces the logical display id.
+     * @param brightnessThrottlingMapId Name of which throttling policy should be used.
+     * @param leadDisplayId Display that this one follows (-1 if none).
+     * @return The new Display.
      */
     public Display createDisplayLocked(
             @NonNull DisplayAddress address, boolean isDefault, boolean isEnabled,
-            DisplayIdProducer idProducer) {
+            DisplayIdProducer idProducer, String brightnessThrottlingMapId, int leadDisplayId) {
+        return createDisplayLocked(address, isDefault, isEnabled, idProducer,
+                brightnessThrottlingMapId, POSITION_UNKNOWN, leadDisplayId);
+    }
+
+    /**
+     * Creates a simple 1:1 LogicalDisplay mapping for the specified DisplayDevice.
+     *
+     * @param address Address of the device.
+     * @param isDefault Indicates if the device is meant to be the default display.
+     * @param isEnabled Indicates if this display is usable and can be switched on
+     * @param idProducer Produces the logical display id.
+     * @param brightnessThrottlingMapId Name of which throttling policy should be used.
+     * @param position Indicates the position this display is facing in this layout.
+     * @param leadDisplayId Display that this one follows (-1 if none).
+     * @return The new Display.
+     */
+    public Display createDisplayLocked(
+            @NonNull DisplayAddress address, boolean isDefault, boolean isEnabled,
+            DisplayIdProducer idProducer, String brightnessThrottlingMapId, int position,
+            int leadDisplayId) {
         if (contains(address)) {
             Slog.w(TAG, "Attempting to add second definition for display-device: " + address);
             return null;
@@ -93,7 +123,8 @@
         // different layouts, a logical display can be destroyed and later recreated with the
         // same logical display ID.
         final int logicalDisplayId = idProducer.getId(isDefault);
-        final Display display = new Display(address, logicalDisplayId, isEnabled);
+        final Display display = new Display(address, logicalDisplayId, isEnabled,
+                brightnessThrottlingMapId, position, leadDisplayId);
 
         mDisplays.add(display);
         return display;
@@ -195,11 +226,33 @@
         // {@link DeviceStateToLayoutMap.POSITION_UNKNOWN} is unspecified.
         private int mPosition;
 
-        Display(@NonNull DisplayAddress address, int logicalDisplayId, boolean isEnabled) {
+        // The ID of the brightness throttling map that should be used. This can change e.g. in
+        // concurrent displays mode in which a stricter brightness throttling policy might need to
+        // be used.
+        @Nullable
+        private final String mBrightnessThrottlingMapId;
+
+        // The ID of the lead display that this display will follow in a layout. -1 means no lead.
+        private int mLeadDisplayId;
+
+        // Refresh rate zone id for specific layout
+        @Nullable
+        private String mRefreshRateZoneId;
+
+        Display(@NonNull DisplayAddress address, int logicalDisplayId, boolean isEnabled,
+                String brightnessThrottlingMapId, int position, int leadDisplayId) {
             mAddress = address;
             mLogicalDisplayId = logicalDisplayId;
             mIsEnabled = isEnabled;
-            mPosition = POSITION_UNKNOWN;
+            mPosition = position;
+            mBrightnessThrottlingMapId = brightnessThrottlingMapId;
+
+            if (leadDisplayId == mLogicalDisplayId) {
+                mLeadDisplayId = NO_LEAD_DISPLAY;
+            } else {
+                mLeadDisplayId = leadDisplayId;
+            }
+
         }
 
         @Override
@@ -209,6 +262,9 @@
                     + "(" + (mIsEnabled ? "ON" : "OFF") + ")"
                     + ", addr: " + mAddress
                     +  ((mPosition == POSITION_UNKNOWN) ? "" : ", position: " + mPosition)
+                    + ", brightnessThrottlingMapId: " + mBrightnessThrottlingMapId
+                    + ", mRefreshRateZoneId: " + mRefreshRateZoneId
+                    + ", mLeadDisplayId: " + mLeadDisplayId
                     + "}";
         }
 
@@ -223,7 +279,11 @@
             return otherDisplay.mIsEnabled == this.mIsEnabled
                     && otherDisplay.mPosition == this.mPosition
                     && otherDisplay.mLogicalDisplayId == this.mLogicalDisplayId
-                    && this.mAddress.equals(otherDisplay.mAddress);
+                    && this.mAddress.equals(otherDisplay.mAddress)
+                    && Objects.equals(mBrightnessThrottlingMapId,
+                    otherDisplay.mBrightnessThrottlingMapId)
+                    && Objects.equals(otherDisplay.mRefreshRateZoneId, this.mRefreshRateZoneId)
+                    && this.mLeadDisplayId == otherDisplay.mLeadDisplayId;
         }
 
         @Override
@@ -233,6 +293,9 @@
             result = 31 * result + mPosition;
             result = 31 * result + mLogicalDisplayId;
             result = 31 * result + mAddress.hashCode();
+            result = 31 * result + mBrightnessThrottlingMapId.hashCode();
+            result = 31 * result + Objects.hashCode(mRefreshRateZoneId);
+            result = 31 * result + mLeadDisplayId;
             return result;
         }
 
@@ -248,8 +311,56 @@
             return mIsEnabled;
         }
 
+
+        public void setRefreshRateZoneId(@Nullable String refreshRateZoneId) {
+            mRefreshRateZoneId = refreshRateZoneId;
+        }
+
+        @Nullable
+        public String getRefreshRateZoneId() {
+            return mRefreshRateZoneId;
+        }
+
+        /**
+         * Sets the position that this display is facing.
+         * @param position the display is facing.
+         */
         public void setPosition(int position) {
             mPosition = position;
         }
+
+        /**
+         * @return The ID of the brightness throttling map that this display should use.
+         */
+        public String getBrightnessThrottlingMapId() {
+            return mBrightnessThrottlingMapId;
+        }
+
+        /**
+         *
+         * @return the position that this display is facing.
+         */
+        public int getPosition() {
+            return mPosition;
+        }
+
+        /**
+         * Set the display that this display should follow certain properties of, for example,
+         * brightness
+         * @param displayId of the lead display.
+         */
+        public void setLeadDisplay(int displayId) {
+            if (displayId != mLogicalDisplayId) {
+                mLeadDisplayId = displayId;
+            }
+        }
+
+        /**
+         *
+         * @return logical displayId of the display that this one follows.
+         */
+        public int getLeadDisplayId() {
+            return mLeadDisplayId;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index 85d5b4f..5b772fc 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -419,16 +419,16 @@
         float ambientBrightness = mBrightnessFilter.getEstimate(time);
         mLatestAmbientBrightness = ambientBrightness;
 
-        if (ambientColorTemperature != -1.0f &&
-                mLowLightAmbientBrightnessToBiasSpline != null) {
+        if (ambientColorTemperature != -1.0f && ambientBrightness != -1.0f
+                && mLowLightAmbientBrightnessToBiasSpline != null) {
             float bias = mLowLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
             ambientColorTemperature =
                     bias * ambientColorTemperature + (1.0f - bias)
                     * mLowLightAmbientColorTemperature;
             mLatestLowLightBias = bias;
         }
-        if (ambientColorTemperature != -1.0f &&
-                mHighLightAmbientBrightnessToBiasSpline != null) {
+        if (ambientColorTemperature != -1.0f && ambientBrightness != -1.0f
+                && mHighLightAmbientBrightnessToBiasSpline != null) {
             float bias = mHighLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
             ambientColorTemperature =
                     (1.0f - bias) * ambientColorTemperature + bias
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index d7306b7..66fe019 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -294,8 +294,6 @@
                         new int[] {ACTIVITY_TYPE_DREAM});
 
                 mListener.onDreamStopped(dream.mToken);
-            } else if (dream.mCanDoze && !mCurrentDream.mCanDoze) {
-                mListener.stopDozing(dream.mToken);
             }
 
         } finally {
@@ -343,7 +341,6 @@
      */
     public interface Listener {
         void onDreamStopped(Binder token);
-        void stopDozing(Binder token);
     }
 
     private final class DreamRecord implements DeathRecipient, ServiceConnection {
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index d9cdba7..7802b9d 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -72,6 +72,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.input.InputManagerInternal;
+import com.android.server.pm.UserManagerInternal;
 import com.android.server.wm.ActivityInterceptorCallback;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
@@ -499,12 +500,7 @@
         }
 
         synchronized (mLock) {
-            if (mCurrentDream == null) {
-                return;
-            }
-
-            final boolean sameDream = mCurrentDream.token == token;
-            if ((sameDream && mCurrentDream.isDozing) || (!sameDream && !mCurrentDream.isDozing)) {
+            if (mCurrentDream != null && mCurrentDream.token == token && mCurrentDream.isDozing) {
                 mCurrentDream.isDozing = false;
                 mDozeWakeLock.release();
                 mPowerManagerInternal.setDozeOverrideFromDreamManager(
@@ -639,8 +635,10 @@
     }
 
     private boolean dreamsEnabledForUser(int userId) {
-        // TODO(b/257333623): Support non-system Dock Users in HSUM.
-        return !mDreamsOnlyEnabledForDockUser || (userId == UserHandle.USER_SYSTEM);
+        if (!mDreamsOnlyEnabledForDockUser) return true;
+        if (userId < 0) return false;
+        final int mainUserId = LocalServices.getService(UserManagerInternal.class).getMainUserId();
+        return userId == mainUserId;
     }
 
     private ServiceInfo getServiceInfo(ComponentName name) {
@@ -668,6 +666,10 @@
 
         Slog.i(TAG, "Entering dreamland.");
 
+        if (mCurrentDream != null && mCurrentDream.isDozing) {
+            stopDozingInternal(mCurrentDream.token);
+        }
+
         mCurrentDream = new DreamRecord(name, userId, isPreviewMode, canDoze);
 
         if (!mCurrentDream.name.equals(mAmbientDisplayComponent)) {
@@ -773,11 +775,6 @@
                 }
             }
         }
-
-        @Override
-        public void stopDozing(Binder token) {
-            stopDozingInternal(token);
-        }
     };
 
     private final ContentObserver mDozeEnabledObserver = new ContentObserver(null) {
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
index 1a357ee..41053e9 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
@@ -21,11 +21,14 @@
 import android.annotation.Nullable;
 import android.app.IGrammaticalInflectionManager;
 import android.content.Context;
+import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.SystemProperties;
+import android.util.Log;
 
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -36,9 +39,10 @@
  * <p>This service is API entry point for storing app-specific grammatical inflection.
  */
 public class GrammaticalInflectionService extends SystemService {
-
+    private final String TAG = "GrammaticalInflection";
     private final GrammaticalInflectionBackupHelper mBackupHelper;
     private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
+    private PackageManagerInternal mPackageManagerInternal;
     private static final String GRAMMATICAL_INFLECTION_ENABLED =
             "i18n.grammatical_Inflection.enabled";
 
@@ -55,6 +59,7 @@
     public GrammaticalInflectionService(Context context) {
         super(context);
         mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mBackupHelper = new GrammaticalInflectionBackupHelper(
                 this, context.getPackageManager());
     }
@@ -110,14 +115,26 @@
 
     protected void setRequestedApplicationGrammaticalGender(
             String appPackageName, int userId, int gender) {
-        if (!SystemProperties.getBoolean(GRAMMATICAL_INFLECTION_ENABLED, true)) {
-            return;
-        }
-
+        int preValue = getApplicationGrammaticalGender(appPackageName, userId);
         final ActivityTaskManagerInternal.PackageConfigurationUpdater updater =
                 mActivityTaskManagerInternal.createPackageConfigurationUpdater(appPackageName,
                         userId);
 
+        if (!SystemProperties.getBoolean(GRAMMATICAL_INFLECTION_ENABLED, true)) {
+            if (preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED) {
+                Log.d(TAG, "Clearing the user's grammatical gender setting");
+                updater.setGrammaticalGender(GRAMMATICAL_GENDER_NOT_SPECIFIED).commit();
+            }
+            return;
+        }
+
+        final int uid = mPackageManagerInternal.getPackageUid(appPackageName, 0, userId);
+        FrameworkStatsLog.write(FrameworkStatsLog.GRAMMATICAL_INFLECTION_CHANGED,
+                FrameworkStatsLog.APPLICATION_GRAMMATICAL_INFLECTION_CHANGED__SOURCE_ID__OTHERS,
+                uid,
+                gender != GRAMMATICAL_GENDER_NOT_SPECIFIED,
+                preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED);
+
         updater.setGrammaticalGender(gender).commit();
     }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 6303bdc..9eedc4e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1261,7 +1261,8 @@
     void launchRoutingControl(boolean routingForBootup) {
         assertRunOnServiceThread();
         // Seq #24
-        if (getActivePortId() != Constants.INVALID_PORT_ID) {
+        if (getActivePortId() != Constants.INVALID_PORT_ID
+                && getActivePortId() != Constants.CEC_SWITCH_HOME) {
             if (!routingForBootup && !isProhibitMode()) {
                 int newPath = mService.portIdToPath(getActivePortId());
                 setActivePath(newPath);
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 14b9121..740d2a3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -2481,6 +2481,7 @@
                         Slog.w(TAG, "Local tv device not available to change arc mode.");
                         return;
                     }
+                    tv.startArcAction(enabled);
                 }
             });
         }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index e2caeec..172aa20 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -32,7 +32,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.database.ContentObserver;
 import android.graphics.PointF;
 import android.hardware.SensorPrivacyManager;
 import android.hardware.SensorPrivacyManager.Sensors;
@@ -78,8 +77,6 @@
 import android.os.vibrator.StepSegment;
 import android.os.vibrator.VibrationEffectSegment;
 import android.provider.DeviceConfig;
-import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.IndentingPrintWriter;
@@ -147,8 +144,6 @@
     private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
     private static final String PORT_ASSOCIATIONS_PATH = "etc/input-port-associations.xml";
 
-    // Feature flag name for the deep press feature
-    private static final String DEEP_PRESS_ENABLED = "deep_press_enabled";
     // Feature flag name for the strategy to be used in VelocityTracker
     private static final String VELOCITYTRACKER_STRATEGY_PROPERTY = "velocitytracker_strategy";
 
@@ -307,6 +302,9 @@
     @GuardedBy("mInputMonitors")
     final Map<IBinder, GestureMonitorSpyWindow> mInputMonitors = new HashMap<>();
 
+    // Watches for settings changes and updates the native side appropriately.
+    private final InputSettingsObserver mSettingsObserver;
+
     // Manages Keyboard layouts for Physical keyboards
     private final KeyboardLayoutManager mKeyboardLayoutManager;
 
@@ -428,6 +426,7 @@
         mContext = injector.getContext();
         mHandler = new InputManagerHandler(injector.getLooper());
         mNative = injector.getNativeService(this);
+        mSettingsObserver = new InputSettingsObserver(mContext, mHandler, mNative);
         mKeyboardLayoutManager = new KeyboardLayoutManager(mContext, mNative, mDataStore,
                 injector.getLooper());
         mBatteryController = new BatteryController(mContext, mNative, injector.getLooper());
@@ -493,39 +492,7 @@
         // Add ourselves to the Watchdog monitors.
         Watchdog.getInstance().addMonitor(this);
 
-        registerMousePointerSpeedSettingObserver();
-        registerTouchpadPointerSpeedSettingObserver();
-        registerTouchpadNaturalScrollingEnabledObserver();
-        registerTouchpadTapToClickEnabledObserver();
-        registerTouchpadRightClickZoneEnabledObserver();
-        registerShowTouchesSettingObserver();
-        registerAccessibilityLargePointerSettingObserver();
-        registerLongPressTimeoutObserver();
-        registerMaximumObscuringOpacityForTouchSettingObserver();
-
-        mContext.registerReceiver(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                updateMousePointerSpeedFromSettings();
-                updateTouchpadPointerSpeedFromSettings();
-                updateTouchpadNaturalScrollingEnabledFromSettings();
-                updateTouchpadTapToClickEnabledFromSettings();
-                updateTouchpadRightClickZoneEnabledFromSettings();
-                updateShowTouchesFromSettings();
-                updateAccessibilityLargePointerFromSettings();
-                updateDeepPressStatusFromSettings("user switched");
-            }
-        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
-
-        updateMousePointerSpeedFromSettings();
-        updateTouchpadPointerSpeedFromSettings();
-        updateTouchpadNaturalScrollingEnabledFromSettings();
-        updateTouchpadTapToClickEnabledFromSettings();
-        updateTouchpadRightClickZoneEnabledFromSettings();
-        updateShowTouchesFromSettings();
-        updateAccessibilityLargePointerFromSettings();
-        updateDeepPressStatusFromSettings("just booted");
-        updateMaximumObscuringOpacityForTouchFromSettings();
+        mSettingsObserver.registerAndUpdate();
     }
 
     // TODO(BT) Pass in parameter for bluetooth system
@@ -1349,11 +1316,6 @@
         setPointerSpeedUnchecked(speed);
     }
 
-    private void updateMousePointerSpeedFromSettings() {
-        int speed = getMousePointerSpeedSetting();
-        setPointerSpeedUnchecked(speed);
-    }
-
     private void setPointerSpeedUnchecked(int speed) {
         speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
                 InputManager.MAX_POINTER_SPEED);
@@ -1370,194 +1332,6 @@
                 properties -> properties.pointerIconVisible = visible);
     }
 
-    private void registerMousePointerSpeedSettingObserver() {
-        mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateMousePointerSpeedFromSettings();
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private int getMousePointerSpeedSetting() {
-        int speed = InputManager.DEFAULT_POINTER_SPEED;
-        try {
-            speed = Settings.System.getIntForUser(mContext.getContentResolver(),
-                    Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT);
-        } catch (SettingNotFoundException ignored) {
-        }
-        return speed;
-    }
-
-    private void registerTouchpadPointerSpeedSettingObserver() {
-        mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.TOUCHPAD_POINTER_SPEED), true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateTouchpadPointerSpeedFromSettings();
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private void updateTouchpadPointerSpeedFromSettings() {
-        int speed = Settings.System.getIntForUser(mContext.getContentResolver(),
-                Settings.System.TOUCHPAD_POINTER_SPEED, InputManager.DEFAULT_POINTER_SPEED,
-                UserHandle.USER_CURRENT);
-        speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
-                InputManager.MAX_POINTER_SPEED);
-        mNative.setTouchpadPointerSpeed(speed);
-    }
-
-    private void registerTouchpadNaturalScrollingEnabledObserver() {
-        mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.TOUCHPAD_NATURAL_SCROLLING), true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateTouchpadNaturalScrollingEnabledFromSettings();
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private void updateTouchpadNaturalScrollingEnabledFromSettings() {
-        int setting = Settings.System.getIntForUser(mContext.getContentResolver(),
-                Settings.System.TOUCHPAD_NATURAL_SCROLLING, 0, UserHandle.USER_CURRENT);
-        mNative.setTouchpadNaturalScrollingEnabled(setting != 0);
-    }
-
-    private void registerTouchpadTapToClickEnabledObserver() {
-        mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.TOUCHPAD_TAP_TO_CLICK), true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateTouchpadTapToClickEnabledFromSettings();
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private void updateTouchpadTapToClickEnabledFromSettings() {
-        int setting = Settings.System.getIntForUser(mContext.getContentResolver(),
-                Settings.System.TOUCHPAD_TAP_TO_CLICK, 0, UserHandle.USER_CURRENT);
-        mNative.setTouchpadTapToClickEnabled(setting != 0);
-    }
-
-    private void registerTouchpadRightClickZoneEnabledObserver() {
-        mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE), true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateTouchpadRightClickZoneEnabledFromSettings();
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private void updateTouchpadRightClickZoneEnabledFromSettings() {
-        int setting = Settings.System.getIntForUser(mContext.getContentResolver(),
-                Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, 0, UserHandle.USER_CURRENT);
-        mNative.setTouchpadRightClickZoneEnabled(setting != 0);
-    }
-
-    private void updateShowTouchesFromSettings() {
-        int setting = getShowTouchesSetting(0);
-        mNative.setShowTouches(setting != 0);
-    }
-
-    private void registerShowTouchesSettingObserver() {
-        mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateShowTouchesFromSettings();
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private void updateAccessibilityLargePointerFromSettings() {
-        final int accessibilityConfig = Settings.Secure.getIntForUser(
-                mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
-                0, UserHandle.USER_CURRENT);
-        PointerIcon.setUseLargeIcons(accessibilityConfig == 1);
-        mNative.reloadPointerIcons();
-    }
-
-    private void registerAccessibilityLargePointerSettingObserver() {
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON), true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateAccessibilityLargePointerFromSettings();
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private void updateDeepPressStatusFromSettings(String reason) {
-        // Not using ViewConfiguration.getLongPressTimeout here because it may return a stale value
-        final int timeout = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.LONG_PRESS_TIMEOUT, ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT,
-                UserHandle.USER_CURRENT);
-        final boolean featureEnabledFlag =
-                DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
-                        DEEP_PRESS_ENABLED, true /* default */);
-        final boolean enabled =
-                featureEnabledFlag && timeout <= ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT;
-        Log.i(TAG,
-                (enabled ? "Enabling" : "Disabling") + " motion classifier because " + reason
-                + ": feature " + (featureEnabledFlag ? "enabled" : "disabled")
-                + ", long press timeout = " + timeout);
-        mNative.setMotionClassifierEnabled(enabled);
-    }
-
-    private void registerLongPressTimeoutObserver() {
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.LONG_PRESS_TIMEOUT), true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateDeepPressStatusFromSettings("timeout changed");
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private void registerMaximumObscuringOpacityForTouchSettingObserver() {
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH),
-                /* notifyForDescendants */ true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateMaximumObscuringOpacityForTouchFromSettings();
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private void updateMaximumObscuringOpacityForTouchFromSettings() {
-        InputManager im = Objects.requireNonNull(mContext.getSystemService(InputManager.class));
-        final float opacity = im.getMaximumObscuringOpacityForTouch();
-        if (opacity < 0 || opacity > 1) {
-            Log.e(TAG, "Invalid maximum obscuring opacity " + opacity
-                    + ", it should be >= 0 and <= 1, rejecting update.");
-            return;
-        }
-        mNative.setMaximumObscuringOpacityForTouch(opacity);
-    }
-
-    private int getShowTouchesSetting(int defaultValue) {
-        int result = defaultValue;
-        try {
-            result = Settings.System.getIntForUser(mContext.getContentResolver(),
-                    Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT);
-        } catch (SettingNotFoundException snfe) {
-        }
-        return result;
-    }
-
     /**
      * Update the display on which the mouse pointer is shown.
      *
@@ -2974,6 +2748,13 @@
         return null;
     }
 
+    // Native callback.
+    @SuppressWarnings("unused")
+    private boolean isStylusPointerIconEnabled() {
+        return Objects.requireNonNull(mContext.getSystemService(InputManager.class))
+                .isStylusPointerIconEnabled();
+    }
+
     private static class PointerDisplayIdChangedArgs {
         final int mPointerDisplayId;
         final float mXPosition;
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
new file mode 100644
index 0000000..a113d01
--- /dev/null
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -0,0 +1,182 @@
+/*
+ * 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.input;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.hardware.input.InputManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.PointerIcon;
+import android.view.ViewConfiguration;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/** Observes settings changes and propagates them to the native side. */
+class InputSettingsObserver extends ContentObserver {
+    static final String TAG = "InputManager";
+
+    /** Feature flag name for the deep press feature */
+    private static final String DEEP_PRESS_ENABLED = "deep_press_enabled";
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final NativeInputManagerService mNative;
+    private final Map<Uri, Consumer<String /* reason*/>> mObservers;
+
+    InputSettingsObserver(Context context, Handler handler, NativeInputManagerService nativeIms) {
+        super(handler);
+        mContext = context;
+        mHandler = handler;
+        mNative = nativeIms;
+        mObservers = Map.ofEntries(
+            Map.entry(Settings.System.getUriFor(Settings.System.POINTER_SPEED),
+                    (reason) -> updateMousePointerSpeed()),
+            Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_POINTER_SPEED),
+                    (reason) -> updateTouchpadPointerSpeed()),
+            Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_NATURAL_SCROLLING),
+                    (reason) -> updateTouchpadNaturalScrollingEnabled()),
+            Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_TAP_TO_CLICK),
+                    (reason) -> updateTouchpadTapToClickEnabled()),
+            Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE),
+                    (reason) -> updateTouchpadRightClickZoneEnabled()),
+            Map.entry(Settings.System.getUriFor(Settings.System.SHOW_TOUCHES),
+                    (reason) -> updateShowTouches()),
+            Map.entry(Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON),
+                    (reason) -> updateAccessibilityLargePointer()),
+            Map.entry(Settings.Secure.getUriFor(Settings.Secure.LONG_PRESS_TIMEOUT),
+                    (reason) -> updateDeepPressStatus(reason)),
+            Map.entry(
+                    Settings.Global.getUriFor(Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH),
+                    (reason) -> updateMaximumObscuringOpacityForTouch()));
+    }
+
+    /**
+     * Registers observers for input-related settings and updates the input subsystem with their
+     * current values.
+     */
+    public void registerAndUpdate() {
+        for (Uri uri : mObservers.keySet()) {
+            mContext.getContentResolver().registerContentObserver(
+                    uri, true /* notifyForDescendants */, this, UserHandle.USER_ALL);
+        }
+
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                for (Consumer<String> observer : mObservers.values()) {
+                    observer.accept("user switched");
+                }
+            }
+        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
+
+        for (Consumer<String> observer : mObservers.values()) {
+            observer.accept("just booted");
+        }
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        mObservers.get(uri).accept("setting changed");
+    }
+
+    private boolean getBoolean(String settingName, boolean defaultValue) {
+        final int setting = Settings.System.getIntForUser(mContext.getContentResolver(),
+                settingName, defaultValue ? 1 : 0, UserHandle.USER_CURRENT);
+        return setting != 0;
+    }
+
+    private int getPointerSpeedValue(String settingName) {
+        int speed = Settings.System.getIntForUser(mContext.getContentResolver(),
+                settingName, InputManager.DEFAULT_POINTER_SPEED, UserHandle.USER_CURRENT);
+        return Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
+                InputManager.MAX_POINTER_SPEED);
+    }
+
+    private void updateMousePointerSpeed() {
+        mNative.setPointerSpeed(getPointerSpeedValue(Settings.System.POINTER_SPEED));
+    }
+
+    private void updateTouchpadPointerSpeed() {
+        mNative.setTouchpadPointerSpeed(
+                getPointerSpeedValue(Settings.System.TOUCHPAD_POINTER_SPEED));
+    }
+
+    private void updateTouchpadNaturalScrollingEnabled() {
+        mNative.setTouchpadNaturalScrollingEnabled(
+                getBoolean(Settings.System.TOUCHPAD_NATURAL_SCROLLING, true));
+    }
+
+    private void updateTouchpadTapToClickEnabled() {
+        mNative.setTouchpadTapToClickEnabled(
+                getBoolean(Settings.System.TOUCHPAD_TAP_TO_CLICK, true));
+    }
+
+    private void updateTouchpadRightClickZoneEnabled() {
+        mNative.setTouchpadRightClickZoneEnabled(
+                getBoolean(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, false));
+    }
+
+    private void updateShowTouches() {
+        mNative.setShowTouches(getBoolean(Settings.System.SHOW_TOUCHES, false));
+    }
+
+    private void updateAccessibilityLargePointer() {
+        final int accessibilityConfig = Settings.Secure.getIntForUser(
+                mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
+                0, UserHandle.USER_CURRENT);
+        PointerIcon.setUseLargeIcons(accessibilityConfig == 1);
+        mNative.reloadPointerIcons();
+    }
+
+    private void updateDeepPressStatus(String reason) {
+        // Not using ViewConfiguration.getLongPressTimeout here because it may return a stale value
+        final int timeout = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.LONG_PRESS_TIMEOUT, ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT,
+                UserHandle.USER_CURRENT);
+        final boolean featureEnabledFlag =
+                DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
+                        DEEP_PRESS_ENABLED, true /* default */);
+        final boolean enabled =
+                featureEnabledFlag && timeout <= ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT;
+        Log.i(TAG,
+                (enabled ? "Enabling" : "Disabling") + " motion classifier because " + reason
+                + ": feature " + (featureEnabledFlag ? "enabled" : "disabled")
+                + ", long press timeout = " + timeout);
+        mNative.setMotionClassifierEnabled(enabled);
+    }
+
+    private void updateMaximumObscuringOpacityForTouch() {
+        InputManager im = Objects.requireNonNull(mContext.getSystemService(InputManager.class));
+        final float opacity = im.getMaximumObscuringOpacityForTouch();
+        if (opacity < 0 || opacity > 1) {
+            Log.e(TAG, "Invalid maximum obscuring opacity " + opacity
+                    + ", it should be >= 0 and <= 1, rejecting update.");
+            return;
+        }
+        mNative.setMaximumObscuringOpacityForTouch(opacity);
+    }
+}
diff --git a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
index e21895a..9f7ff31 100644
--- a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
+++ b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
@@ -27,7 +27,6 @@
 import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME_IMPLICIT;
 
 import android.annotation.Nullable;
-import android.os.Binder;
 import android.os.IBinder;
 import android.os.ResultReceiver;
 import android.util.EventLog;
@@ -65,13 +64,10 @@
 
     @GuardedBy("ImfLock.class")
     @Override
-    public void performShowIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+    public void performShowIme(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
             int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
         final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
         if (curMethod != null) {
-            // create a placeholder token for IMS so that IMS cannot inject windows into client app.
-            final IBinder showInputToken = new Binder();
-            mService.setRequestImeTokenToWindow(windowToken, showInputToken);
             if (DEBUG) {
                 Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken
                         + ", " + showFlags + ", " + resultReceiver + ") for reason: "
@@ -86,7 +82,7 @@
                             InputMethodDebug.softInputModeToString(
                                     mService.mCurFocusedWindowSoftInputMode));
                 }
-                mService.onShowHideSoftInputRequested(true /* show */, windowToken, reason,
+                mService.onShowHideSoftInputRequested(true /* show */, showInputToken, reason,
                         statsToken);
             }
         }
@@ -94,12 +90,10 @@
 
     @GuardedBy("ImfLock.class")
     @Override
-    public void performHideIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+    public void performHideIme(IBinder hideInputToken, @Nullable ImeTracker.Token statsToken,
             ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
         final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
         if (curMethod != null) {
-            final Binder hideInputToken = new Binder();
-            mService.setRequestImeTokenToWindow(windowToken, hideInputToken);
             // The IME will report its visible state again after the following message finally
             // delivered to the IME process as an IPC.  Hence the inconsistency between
             // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
@@ -118,7 +112,7 @@
                             InputMethodDebug.softInputModeToString(
                                     mService.mCurFocusedWindowSoftInputMode));
                 }
-                mService.onShowHideSoftInputRequested(false /* show */, windowToken, reason,
+                mService.onShowHideSoftInputRequested(false /* show */, hideInputToken, reason,
                         statsToken);
             }
         }
@@ -136,14 +130,14 @@
             @ImeVisibilityStateComputer.VisibilityState int state, int reason) {
         switch (state) {
             case STATE_SHOW_IME:
-                ImeTracker.get().onProgress(statsToken,
+                ImeTracker.forLogging().onProgress(statsToken,
                         ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
                 // Send to window manager to show IME after IME layout finishes.
                 mWindowManagerInternal.showImePostLayout(windowToken, statsToken);
                 break;
             case STATE_HIDE_IME:
                 if (mService.mCurFocusedWindowClient != null) {
-                    ImeTracker.get().onProgress(statsToken,
+                    ImeTracker.forLogging().onProgress(statsToken,
                             ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
                     // IMMS only knows of focused window, not the actual IME target.
                     // e.g. it isn't aware of any window that has both
@@ -154,7 +148,7 @@
                     mWindowManagerInternal.hideIme(windowToken,
                             mService.mCurFocusedWindowClient.mSelfReportedDisplayId, statsToken);
                 } else {
-                    ImeTracker.get().onFailed(statsToken,
+                    ImeTracker.forLogging().onFailed(statsToken,
                             ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
                 }
                 break;
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
index e97ec93..f03e985 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
@@ -31,26 +31,26 @@
     /**
      * Performs showing IME on top of the given window.
      *
-     * @param windowToken    The token of a window that currently has focus.
+     * @param showInputToken A token that represents the requester to show IME.
      * @param statsToken     A token that tracks the progress of an IME request.
      * @param showFlags      Provides additional operating flags to show IME.
      * @param resultReceiver If non-null, this will be called back to the caller when
      *                       it has processed request to tell what it has done.
      * @param reason         The reason for requesting to show IME.
      */
-    default void performShowIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+    default void performShowIme(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
             int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {}
 
     /**
      * Performs hiding IME to the given window
      *
-     * @param windowToken    The token of a window that currently has focus.
+     * @param hideInputToken A token that represents the requester to hide IME.
      * @param statsToken     A token that tracks the progress of an IME request.
      * @param resultReceiver If non-null, this will be called back to the caller when
      *                       it has processed request to tell what it has done.
      * @param reason         The reason for requesting to hide IME.
      */
-    default void performHideIme(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
+    default void performHideIme(IBinder hideInputToken, @Nullable ImeTracker.Token statsToken,
             ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {}
 
     /**
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
index db61e954..ceb9706 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
@@ -35,6 +35,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.content.res.Configuration;
+import android.os.Binder;
 import android.os.IBinder;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
@@ -182,10 +183,10 @@
      */
     boolean onImeShowFlags(@NonNull ImeTracker.Token statsToken, int showFlags) {
         if (mPolicy.mA11yRequestingNoSoftKeyboard || mPolicy.mImeHiddenByDisplayPolicy) {
-            ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
+            ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
             return false;
         }
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
+        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
         if ((showFlags & InputMethodManager.SHOW_FORCED) != 0) {
             mRequestedShowExplicitly = true;
             mShowForced = true;
@@ -206,15 +207,15 @@
         if ((hideFlags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
                 && (mRequestedShowExplicitly || mShowForced)) {
             if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
-            ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
+            ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
             return false;
         }
         if (mShowForced && (hideFlags & InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
             if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
-            ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
+            ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
             return false;
         }
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
+        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
         return true;
     }
 
@@ -263,6 +264,8 @@
             // policy.
             mPolicy.mPendingA11yRequestingHideKeyboard = false;
         }
+        // create a placeholder token for IMS so that IMS cannot inject windows into client app.
+        state.setRequestImeToken(new Binder());
         setWindowStateInner(windowToken, state);
     }
 
@@ -279,14 +282,6 @@
         return state;
     }
 
-    void setRequestImeTokenToWindow(IBinder windowToken, IBinder token) {
-        ImeTargetWindowState state = getWindowStateOrNull(windowToken);
-        if (state != null) {
-            state.setRequestImeToken(token);
-            setWindowStateInner(windowToken, state);
-        }
-    }
-
     void setWindowState(IBinder windowToken, @NonNull ImeTargetWindowState newState) {
         final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
         if (state != null && newState.hasEdiorFocused()) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 2ced988..233e285 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2293,7 +2293,7 @@
             mCurClient.mSessionRequestedForAccessibility = false;
             mCurClient = null;
             mCurVirtualDisplayToScreenMatrix = null;
-            ImeTracker.get().onFailed(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+            ImeTracker.forLogging().onFailed(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
             mCurStatsToken = null;
 
             mMenuController.hideInputMethodMenuLocked();
@@ -3279,7 +3279,8 @@
                 "InputMethodManagerService#showSoftInput");
         synchronized (ImfLock.class) {
             if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken)) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+                ImeTracker.forLogging().onFailed(
+                        statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
                 return false;
             }
             final long ident = Binder.clearCallingIdentity();
@@ -3344,11 +3345,6 @@
         }
     }
 
-    @GuardedBy("ImfLock.class")
-    void setRequestImeTokenToWindow(IBinder windowToken, IBinder token) {
-        mVisibilityStateComputer.setRequestImeTokenToWindow(windowToken, token);
-    }
-
     @BinderThread
     @Override
     public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
@@ -3380,7 +3376,7 @@
             // TODO(b/261565259): to avoid using null, add package name in ClientState
             final String packageName = (mCurEditorInfo != null) ? mCurEditorInfo.packageName : null;
             final int uid = mCurClient != null ? mCurClient.mUid : -1;
-            statsToken = ImeTracker.get().onRequestShow(packageName, uid,
+            statsToken = ImeTracker.forLogging().onRequestShow(packageName, uid,
                     ImeTracker.ORIGIN_SERVER_START_INPUT, reason);
         }
 
@@ -3389,19 +3385,19 @@
         }
 
         if (!mSystemReady) {
-            ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
+            ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
             return false;
         }
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
+        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
 
         mVisibilityStateComputer.requestImeVisibility(windowToken, true);
 
         // Ensure binding the connection when IME is going to show.
         mBindingController.setCurrentMethodVisible();
         final IInputMethodInvoker curMethod = getCurMethodLocked();
-        ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+        ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
         if (curMethod != null) {
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HAS_IME);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_HAS_IME);
             mCurStatsToken = null;
 
             if (lastClickToolType != MotionEvent.TOOL_TYPE_UNKNOWN) {
@@ -3412,7 +3408,7 @@
             mVisibilityStateComputer.setInputShown(true);
             return true;
         } else {
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
             mCurStatsToken = statsToken;
         }
         return false;
@@ -3428,9 +3424,10 @@
         synchronized (ImfLock.class) {
             if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken)) {
                 if (isInputShown()) {
-                    ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+                    ImeTracker.forLogging().onFailed(
+                            statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
                 } else {
-                    ImeTracker.get().onCancelled(statsToken,
+                    ImeTracker.forLogging().onCancelled(statsToken,
                             ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
                 }
                 return false;
@@ -3463,7 +3460,7 @@
             } else {
                 uid = -1;
             }
-            statsToken = ImeTracker.get().onRequestHide(packageName, uid,
+            statsToken = ImeTracker.forLogging().onRequestHide(packageName, uid,
                     ImeTracker.ORIGIN_SERVER_HIDE_INPUT, reason);
         }
 
@@ -3489,15 +3486,15 @@
             // delivered to the IME process as an IPC.  Hence the inconsistency between
             // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
             // the final state.
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
             mVisibilityApplier.performHideIme(windowToken, statsToken, resultReceiver, reason);
         } else {
-            ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
+            ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
         }
         mBindingController.setCurrentMethodNotVisible();
         mVisibilityStateComputer.clearImeShowFlags();
         // Cancel existing statsToken for show IME as we got a hide request.
-        ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+        ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
         mCurStatsToken = null;
         return shouldHideSoftInput;
     }
@@ -3769,16 +3766,16 @@
             // be made before input is started in it.
             final ClientState cs = mClients.get(client.asBinder());
             if (cs == null) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
+                ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
                 throw new IllegalArgumentException("unknown client " + client.asBinder());
             }
-            ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
+            ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
             if (!isImeClientFocused(mCurFocusedWindow, cs)) {
                 Slog.w(TAG, String.format("Ignoring %s of uid %d : %s", methodName, uid, client));
                 return false;
             }
         }
-        ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+        ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
         return true;
     }
 
@@ -4555,7 +4552,8 @@
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.applyImeVisibility");
         synchronized (ImfLock.class) {
             if (!calledWithValidTokenLocked(token)) {
-                ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
+                ImeTracker.forLogging().onFailed(statsToken,
+                        ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
                 return;
             }
             final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(windowToken);
@@ -4603,10 +4601,13 @@
         }
     }
 
-    /** Called right after {@link com.android.internal.inputmethod.IInputMethod#showSoftInput}. */
+    /**
+     * Called right after {@link IInputMethod#showSoftInput} or {@link IInputMethod#hideSoftInput}.
+     */
     @GuardedBy("ImfLock.class")
-    void onShowHideSoftInputRequested(boolean show, IBinder requestToken,
+    void onShowHideSoftInputRequested(boolean show, IBinder requestImeToken,
             @SoftInputShowHideReason int reason, @Nullable ImeTracker.Token statsToken) {
+        final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(requestImeToken);
         final WindowManagerInternal.ImeTargetInfo info =
                 mWindowManagerInternal.onToggleImeRequested(
                         show, mCurFocusedWindow, requestToken, mCurTokenDisplayId);
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index ffdb531..925ab65 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -305,6 +305,7 @@
         public void deliverOnFlushComplete(int requestCode) throws PendingIntent.CanceledException {
             BroadcastOptions options = BroadcastOptions.makeBasic();
             options.setDontSendToRestrictedApps(true);
+            options.setPendingIntentBackgroundActivityLaunchAllowed(false);
 
             mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_FLUSH_COMPLETE, requestCode),
                     null, null, null, options.toBundle());
@@ -2104,6 +2105,11 @@
     @Override
     protected boolean registerWithService(ProviderRequest request,
             Collection<Registration> registrations) {
+        if (!request.isActive()) {
+            // the default request is already an empty request, no need to register this
+            return true;
+        }
+
         return reregisterWithService(ProviderRequest.EMPTY_REQUEST, request, registrations);
     }
 
@@ -2178,6 +2184,9 @@
         }
 
         EVENT_LOG.logProviderUpdateRequest(mName, request);
+        if (D) {
+            Log.d(TAG, mName + " provider request changed to " + request);
+        }
         mProvider.getController().setRequest(request);
 
         FgThread.getHandler().post(() -> {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index ebc18bc..1457bff 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -18,7 +18,6 @@
 
 import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
 import static android.Manifest.permission.MANAGE_BIOMETRIC;
-import static android.Manifest.permission.READ_CONTACTS;
 import static android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS;
 import static android.Manifest.permission.SET_INITIAL_LOCK;
 import static android.app.admin.DevicePolicyManager.DEPRECATE_USERMANAGERINTERNAL_DEVICEPOLICY_DEFAULT;
@@ -29,7 +28,7 @@
 import static android.content.Context.KEYGUARD_SERVICE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.UserHandle.USER_ALL;
-import static android.provider.DeviceConfig.NAMESPACE_AUTO_PIN_CONFIRMATION;
+import static android.os.UserHandle.USER_SYSTEM;
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
@@ -57,6 +56,8 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.RemoteLockscreenValidationResult;
+import android.app.StartLockscreenValidationRequest;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.DeviceStateCache;
@@ -70,6 +71,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.database.sqlite.SQLiteDatabase;
 import android.hardware.authsecret.IAuthSecret;
@@ -96,7 +98,6 @@
 import android.os.storage.StorageManager;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
-import android.provider.Settings.Secure;
 import android.security.AndroidKeyStoreMaintenance;
 import android.security.Authorization;
 import android.security.KeyStore;
@@ -110,12 +111,12 @@
 import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
 import android.security.keystore2.AndroidKeyStoreProvider;
 import android.service.gatekeeper.IGateKeeperService;
+import android.service.notification.StatusBarNotification;
 import android.system.keystore2.Domain;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.EventLog;
-import android.util.FeatureFlagUtils;
 import android.util.LongSparseArray;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -218,6 +219,8 @@
     private static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
     private static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
 
+    private static final int HEADLESS_VENDOR_AUTH_SECRET_LENGTH = 32;
+
     // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this
     // Do not call into ActivityManager while holding mSpManager lock.
     private final Object mSeparateChallengeLock = new Object();
@@ -266,6 +269,13 @@
     @VisibleForTesting
     protected boolean mHasSecureLockScreen;
 
+    @VisibleForTesting
+    protected final Object mHeadlessAuthSecretLock = new Object();
+
+    @VisibleForTesting
+    @GuardedBy("mHeadlessAuthSecretLock")
+    protected byte[] mAuthSecret;
+
     protected IGateKeeperService mGateKeeperService;
     protected IAuthSecret mAuthSecretService;
 
@@ -562,6 +572,15 @@
                 java.security.KeyStore ks) {
             return new ManagedProfilePasswordCache(ks, getUserManager());
         }
+
+        public boolean isHeadlessSystemUserMode() {
+            return UserManager.isHeadlessSystemUserMode();
+        }
+
+        public boolean isMainUserPermanentAdmin() {
+            return Resources.getSystem()
+                    .getBoolean(com.android.internal.R.bool.config_isMainUserPermanentAdmin);
+        }
     }
 
     public LockSettingsService(Context context) {
@@ -581,6 +600,7 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_USER_ADDED);
         filter.addAction(Intent.ACTION_USER_STARTING);
+        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
         injector.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter,
                 null, null);
 
@@ -602,6 +622,20 @@
         LocalServices.addService(LockSettingsInternal.class, new LocalService());
     }
 
+    private void updateActivatedEncryptionNotifications(String reason) {
+        for (UserInfo userInfo : mUserManager.getUsers()) {
+            Context userContext = mContext.createContextAsUser(UserHandle.of(userInfo.id), 0);
+            NotificationManager nm = (NotificationManager)
+                    userContext.getSystemService(Context.NOTIFICATION_SERVICE);
+            for (StatusBarNotification notification : nm.getActiveNotifications()) {
+                if (notification.getId() == SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION) {
+                    maybeShowEncryptionNotificationForUser(userInfo.id, reason);
+                    break;
+                }
+            }
+        }
+    }
+
     /**
      * If the account is credential-encrypted, show notification requesting the user to unlock the
      * device.
@@ -799,6 +833,8 @@
             } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 mStorage.prefetchUser(userHandle);
+            } else if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
+                updateActivatedEncryptionNotifications("locale changed");
             }
         }
     };
@@ -814,7 +850,6 @@
                 .hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN);
         migrateOldData();
         getGateKeeperService();
-        mSpManager.initWeaverService();
         getAuthSecretHal();
         mDeviceProvisionedObserver.onSystemReady();
 
@@ -1048,27 +1083,21 @@
         mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave");
     }
 
-    private final void checkReadPermission(String requestedKey, int userId) {
-        final int callingUid = Binder.getCallingUid();
+    private static final String[] UNPROTECTED_SETTINGS = {
+        // These three LOCK_PATTERN_* settings have traditionally been readable via the public API
+        // android.provider.Settings.{System,Secure}.getString() without any permission.
+        Settings.Secure.LOCK_PATTERN_ENABLED,
+        Settings.Secure.LOCK_PATTERN_VISIBLE,
+        Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
+    };
 
-        for (int i = 0; i < READ_CONTACTS_PROTECTED_SETTINGS.length; i++) {
-            String key = READ_CONTACTS_PROTECTED_SETTINGS[i];
-            if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_CONTACTS)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("uid=" + callingUid
-                        + " needs permission " + READ_CONTACTS + " to read "
-                        + requestedKey + " for user " + userId);
-            }
+    private final void checkDatabaseReadPermission(String requestedKey, int userId) {
+        if (ArrayUtils.contains(UNPROTECTED_SETTINGS, requestedKey)) {
+            return;
         }
-
-        for (int i = 0; i < READ_PASSWORD_PROTECTED_SETTINGS.length; i++) {
-            String key = READ_PASSWORD_PROTECTED_SETTINGS[i];
-            if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(PERMISSION)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("uid=" + callingUid
-                        + " needs permission " + PERMISSION + " to read "
-                        + requestedKey + " for user " + userId);
-            }
+        if (!hasPermission(PERMISSION)) {
+            throw new SecurityException("uid=" + getCallingUid() + " needs permission "
+                    + PERMISSION + " to read " + requestedKey + " for user " + userId);
         }
     }
 
@@ -1097,7 +1126,7 @@
 
     @Override
     public boolean getSeparateProfileChallengeEnabled(int userId) {
-        checkReadPermission(SEPARATE_PROFILE_CHALLENGE_KEY, userId);
+        checkDatabaseReadPermission(SEPARATE_PROFILE_CHALLENGE_KEY, userId);
         return getSeparateProfileChallengeEnabledInternal(userId);
     }
 
@@ -1178,7 +1207,7 @@
 
     @Override
     public boolean getBoolean(String key, boolean defaultValue, int userId) {
-        checkReadPermission(key, userId);
+        checkDatabaseReadPermission(key, userId);
         if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
             return getCredentialTypeInternal(userId) == CREDENTIAL_TYPE_PATTERN;
         }
@@ -1187,13 +1216,13 @@
 
     @Override
     public long getLong(String key, long defaultValue, int userId) {
-        checkReadPermission(key, userId);
+        checkDatabaseReadPermission(key, userId);
         return mStorage.getLong(key, defaultValue, userId);
     }
 
     @Override
     public String getString(String key, String defaultValue, int userId) {
-        checkReadPermission(key, userId);
+        checkDatabaseReadPermission(key, userId);
         return mStorage.getString(key, defaultValue, userId);
     }
 
@@ -1679,7 +1708,7 @@
                 throw new IllegalStateException("password change failed");
             }
 
-            onSyntheticPasswordKnown(userId, sp);
+            onSyntheticPasswordUnlocked(userId, sp);
             setLockCredentialWithSpLocked(credential, sp, userId);
             sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
             return true;
@@ -1690,8 +1719,7 @@
         if (newCredential.isPattern()) {
             setBoolean(LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, true, userHandle);
         }
-        if (DeviceConfig.getBoolean(NAMESPACE_AUTO_PIN_CONFIRMATION,
-                "enable_auto_pin_confirmation", /* defaultValue= */ false)) {
+        if (LockPatternUtils.isAutoPinConfirmFeatureAvailable()) {
             if (newCredential.isPin()) {
                 setLong(LockPatternUtils.PIN_LENGTH, newCredential.size(), userHandle);
             }
@@ -1991,7 +2019,7 @@
                 Slogf.wtf(TAG, "Failed to unwrap synthetic password for unsecured user %d", userId);
                 return;
             }
-            onSyntheticPasswordKnown(userId, result.syntheticPassword);
+            onSyntheticPasswordUnlocked(userId, result.syntheticPassword);
             unlockUserKey(userId, result.syntheticPassword);
         }
     }
@@ -2515,39 +2543,20 @@
     /**
      * Starts a session to verify lock screen credentials provided by a remote device.
      */
-    public void startRemoteLockscreenValidation() {
-        if (!FeatureFlagUtils.isEnabled(mContext,
-                FeatureFlagUtils.SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API)) {
-            throw new UnsupportedOperationException("Under development");
-        }
-        mRecoverableKeyStoreManager.startRemoteLockscreenValidation();
+    @NonNull
+    public StartLockscreenValidationRequest startRemoteLockscreenValidation() {
+        return mRecoverableKeyStoreManager.startRemoteLockscreenValidation(this);
     }
 
     /**
-     * Verifies credentials guess from a remote device.
+     * Verifies encrypted credentials guess from a remote device.
      */
-    public void validateRemoteLockscreen(@NonNull byte[] encryptedCredential) {
-        if (!FeatureFlagUtils.isEnabled(mContext,
-                FeatureFlagUtils.SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API)) {
-            throw new UnsupportedOperationException("Under development");
-        }
-        mRecoverableKeyStoreManager.validateRemoteLockscreen(encryptedCredential);
+    @NonNull
+    public RemoteLockscreenValidationResult
+            validateRemoteLockScreen2(@NonNull byte[] encryptedCredential) {
+        return mRecoverableKeyStoreManager.validateRemoteLockscreen(encryptedCredential, this);
     }
 
-    // Reading these settings needs the contacts permission
-    private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] {
-            Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
-            Secure.LOCK_SCREEN_OWNER_INFO
-    };
-
-    // Reading these settings needs the same permission as checking the password
-    private static final String[] READ_PASSWORD_PROTECTED_SETTINGS = new String[] {
-            LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
-            LockPatternUtils.PASSWORD_HISTORY_KEY,
-            LockPatternUtils.PASSWORD_TYPE_KEY,
-            SEPARATE_PROFILE_CHALLENGE_KEY
-    };
-
     private class GateKeeperDiedRecipient implements IBinder.DeathRecipient {
         @Override
         public void binderDied() {
@@ -2584,43 +2593,112 @@
         }
     }
 
-    private void onSyntheticPasswordKnown(@UserIdInt int userId, SyntheticPassword sp) {
+    private void onSyntheticPasswordCreated(@UserIdInt int userId, SyntheticPassword sp) {
+        onSyntheticPasswordKnown(userId, sp, true);
+    }
+
+    private void onSyntheticPasswordUnlocked(@UserIdInt int userId, SyntheticPassword sp) {
+        onSyntheticPasswordKnown(userId, sp, false);
+    }
+
+    private void onSyntheticPasswordKnown(
+            @UserIdInt int userId, SyntheticPassword sp, boolean justCreated) {
         if (mInjector.isGsiRunning()) {
             Slog.w(TAG, "Running in GSI; skipping calls to AuthSecret and RebootEscrow");
             return;
         }
 
-        mRebootEscrowManager.callToRebootEscrowIfNeeded(userId, sp.getVersion(),
-                sp.getSyntheticPassword());
-
-        callToAuthSecretIfNeeded(userId, sp);
+        mRebootEscrowManager.callToRebootEscrowIfNeeded(
+                userId, sp.getVersion(), sp.getSyntheticPassword());
+        callToAuthSecretIfNeeded(userId, sp, justCreated);
     }
 
-    private void callToAuthSecretIfNeeded(@UserIdInt int userId, SyntheticPassword sp) {
-        // If the given user is the primary user, pass the auth secret to the HAL.  Only the system
-        // user can be primary.  Check for the system user ID before calling getUserInfo(), as other
-        // users may still be under construction.
+    /**
+     * Handles generation, storage, and sending of the vendor auth secret. Here we try to retrieve
+     * the auth secret to send it to the auth secret HAL, generate a fresh secret if need be, store
+     * it encrypted on disk so that the given user can unlock it in future, and stash it in memory
+     * so that when future users are created they can also unlock it.
+     *
+     * <p>Called whenever the SP of a user is available, except in GSI.
+     */
+    private void callToAuthSecretIfNeeded(
+            @UserIdInt int userId, SyntheticPassword sp, boolean justCreated) {
         if (mAuthSecretService == null) {
+            // If there's no IAuthSecret service, we don't need to maintain a auth secret
             return;
         }
-        if (userId == UserHandle.USER_SYSTEM &&
-                mUserManager.getUserInfo(userId).isPrimary()) {
-            final byte[] secret = sp.deriveVendorAuthSecret();
-            try {
-                mAuthSecretService.setPrimaryUserCredential(secret);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Failed to pass primary user secret to AuthSecret HAL", e);
+        // User may be partially created, so use the internal user manager interface
+        final UserManagerInternal userManagerInternal = mInjector.getUserManagerInternal();
+        final UserInfo userInfo = userManagerInternal.getUserInfo(userId);
+        if (userInfo == null) {
+            // User may be partially deleted, skip this.
+            return;
+        }
+        final byte[] authSecret;
+        if (!mInjector.isHeadlessSystemUserMode()) {
+            // On non-headless systems, the auth secret is derived from user 0's
+            // SP, and only user 0 passes it to the HAL.
+            if (userId != USER_SYSTEM) {
+                return;
             }
+            authSecret = sp.deriveVendorAuthSecret();
+        } else if (!mInjector.isMainUserPermanentAdmin() || !userInfo.isFull()) {
+            // Only full users can receive or pass on the auth secret.
+            // If there is no main permanent admin user, we don't try to create or send
+            // an auth secret, since there may sometimes be no full users.
+            return;
+        } else if (justCreated) {
+            if (userInfo.isMain()) {
+                // The first user is just being created, so we create a new auth secret
+                // at the same time.
+                Slog.i(TAG, "Generating new vendor auth secret and storing for user: " + userId);
+                authSecret = SecureRandomUtils.randomBytes(HEADLESS_VENDOR_AUTH_SECRET_LENGTH);
+                // Store it in memory, for when new users are created.
+                synchronized (mHeadlessAuthSecretLock) {
+                    mAuthSecret = authSecret;
+                }
+            } else {
+                // A new user is being created. Another user should already have logged in at
+                // this point, and therefore the auth secret should be stored in memory.
+                synchronized (mHeadlessAuthSecretLock) {
+                    authSecret = mAuthSecret;
+                }
+                if (authSecret == null) {
+                    Slog.e(TAG, "Creating non-main user " + userId
+                            + " but vendor auth secret is not in memory");
+                    return;
+                }
+            }
+            // Store the auth secret encrypted using the user's SP (which was just created).
+            mSpManager.writeVendorAuthSecret(authSecret, sp, userId);
+        } else {
+            // The user already exists, so the auth secret should be stored encrypted
+            // with that user's SP.
+            authSecret = mSpManager.readVendorAuthSecret(sp, userId);
+            if (authSecret == null) {
+                Slog.e(TAG, "Unable to read vendor auth secret for user: " + userId);
+                return;
+            }
+            // Store it in memory, for when new users are created.
+            synchronized (mHeadlessAuthSecretLock) {
+                mAuthSecret = authSecret;
+            }
+        }
+        Slog.i(TAG, "Sending vendor auth secret to IAuthSecret HAL as user: " + userId);
+        try {
+            mAuthSecretService.setPrimaryUserCredential(authSecret);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Failed to send vendor auth secret to IAuthSecret HAL", e);
         }
     }
 
     /**
      * Creates the synthetic password (SP) for the given user, protects it with an empty LSKF, and
      * protects the user's CE key with a key derived from the SP.
-     * <p>
-     * This is called just once in the lifetime of the user: at user creation time (possibly delayed
-     * until the time when Weaver is guaranteed to be available), or when upgrading from Android 13
-     * or earlier where users with no LSKF didn't necessarily have an SP.
+     *
+     * <p>This is called just once in the lifetime of the user: at user creation time (possibly
+     * delayed until the time when Weaver is guaranteed to be available), or when upgrading from
+     * Android 13 or earlier where users with no LSKF didn't necessarily have an SP.
      */
     @VisibleForTesting
     SyntheticPassword initializeSyntheticPassword(int userId) {
@@ -2635,7 +2713,7 @@
                     LockscreenCredential.createNone(), sp, userId);
             setCurrentLskfBasedProtectorId(protectorId, userId);
             setUserKeyProtection(userId, sp.deriveFileBasedEncryptionKey());
-            onSyntheticPasswordKnown(userId, sp);
+            onSyntheticPasswordCreated(userId, sp);
             return sp;
         }
     }
@@ -2702,7 +2780,7 @@
         }
         mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
 
-        onSyntheticPasswordKnown(userId, sp);
+        onSyntheticPasswordUnlocked(userId, sp);
     }
 
     private void setDeviceUnlockedForUser(int userId) {
@@ -2990,7 +3068,7 @@
                     + "verification.");
             return false;
         }
-        onSyntheticPasswordKnown(userId, result.syntheticPassword);
+        onSyntheticPasswordUnlocked(userId, result.syntheticPassword);
         setLockCredentialWithSpLocked(credential, result.syntheticPassword, userId);
         return true;
     }
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index cd972dc..dee26e38 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.admin.PasswordMetrics;
 import android.content.Context;
 import android.content.pm.UserInfo;
@@ -93,6 +94,9 @@
  *                     while the LSKF is nonempty.
  *     SP_E0_NAME, SP_P1_NAME: Information needed to create and use escrow token-based protectors.
  *                             Deleted when escrow token support is disabled for the user.
+ *     VENDOR_AUTH_SECRET_NAME: A copy of the secret passed using the IAuthSecret interface,
+ *                              encrypted using a secret derived from the SP using
+ *                              PERSONALIZATION_AUTHSECRET_ENCRYPTION_KEY.
  *
  *     For each protector, stored under the corresponding protector ID:
  *       SP_BLOB_NAME: The encrypted SP secret (the SP itself or the P0 value).  Always exists.
@@ -120,6 +124,7 @@
     private static final String PASSWORD_DATA_NAME = "pwd";
     private static final String WEAVER_SLOT_NAME = "weaver";
     private static final String PASSWORD_METRICS_NAME = "metrics";
+    private static final String VENDOR_AUTH_SECRET_NAME = "vendor_auth_secret";
 
     // used for files associated with the SP itself, not with a particular protector
     public static final long NULL_PROTECTOR_ID = 0L;
@@ -158,6 +163,8 @@
     private static final byte[] PERSONALIZATION_SP_GK_AUTH = "sp-gk-authentication".getBytes();
     private static final byte[] PERSONALIZATION_FBE_KEY = "fbe-key".getBytes();
     private static final byte[] PERSONALIZATION_AUTHSECRET_KEY = "authsecret-hal".getBytes();
+    private static final byte[] PERSONALIZATION_AUTHSECRET_ENCRYPTION_KEY =
+            "vendor-authsecret-encryption-key".getBytes();
     private static final byte[] PERSONALIZATION_SP_SPLIT = "sp-split".getBytes();
     private static final byte[] PERSONALIZATION_PASSWORD_HASH = "pw-hash".getBytes();
     private static final byte[] PERSONALIZATION_E0 = "e0-encryption".getBytes();
@@ -249,6 +256,10 @@
             return deriveSubkey(PERSONALIZATION_PASSWORD_METRICS);
         }
 
+        public byte[] deriveVendorAuthSecretEncryptionKey() {
+            return deriveSubkey(PERSONALIZATION_AUTHSECRET_ENCRYPTION_KEY);
+        }
+
         /**
          * Assigns escrow data to this synthetic password. This is a prerequisite to call
          * {@link SyntheticPassword#recreateFromEscrow}.
@@ -499,40 +510,35 @@
         return null;
     }
 
-    public synchronized void initWeaverService() {
+    private synchronized boolean isWeaverAvailable() {
         if (mWeaver != null) {
-            return;
+            return true;
         }
 
+        // Re-initialize weaver in case there was a transient error preventing access to it.
         IWeaver weaver = getWeaverService();
         if (weaver == null) {
-            return;
+            return false;
         }
 
-        // Get the config
-        WeaverConfig weaverConfig = null;
+        final WeaverConfig weaverConfig;
         try {
             weaverConfig = weaver.getConfig();
-        } catch (RemoteException e) {
+        } catch (RemoteException | ServiceSpecificException e) {
             Slog.e(TAG, "Failed to get weaver config", e);
+            return false;
         }
         if (weaverConfig == null || weaverConfig.slots <= 0) {
-            Slog.e(TAG, "Failed to initialize weaver config");
-            return;
+            Slog.e(TAG, "Invalid weaver config");
+            return false;
         }
 
         mWeaver = weaver;
         mWeaverConfig = weaverConfig;
         mPasswordSlotManager.refreshActiveSlots(getUsedWeaverSlots());
         Slog.i(TAG, "Weaver service initialized");
-    }
 
-    private synchronized boolean isWeaverAvailable() {
-        if (mWeaver == null) {
-            //Re-initializing weaver in case there was a transient error preventing access to it.
-            initWeaverService();
-        }
-        return mWeaver != null && mWeaverConfig.slots > 0;
+        return true;
     }
 
     /**
@@ -1737,4 +1743,25 @@
             mListeners.finishBroadcast();
         }
     }
+
+    public void writeVendorAuthSecret(
+            @NonNull final byte[] vendorAuthSecret,
+            @NonNull final SyntheticPassword sp,
+            @UserIdInt final int userId) {
+        final byte[] encrypted =
+                SyntheticPasswordCrypto.encrypt(
+                        sp.deriveVendorAuthSecretEncryptionKey(), new byte[0], vendorAuthSecret);
+        saveState(VENDOR_AUTH_SECRET_NAME, encrypted, NULL_PROTECTOR_ID, userId);
+        syncState(userId);
+    }
+
+    public @Nullable byte[] readVendorAuthSecret(
+            @NonNull final SyntheticPassword sp, @UserIdInt final int userId) {
+        final byte[] encrypted = loadState(VENDOR_AUTH_SECRET_NAME, NULL_PROTECTOR_ID, userId);
+        if (encrypted == null) {
+            return null;
+        }
+        return SyntheticPasswordCrypto.decrypt(
+                sp.deriveVendorAuthSecretEncryptionKey(), new byte[0], encrypted);
+    }
 }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index b437421..33dc7ef 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -28,7 +28,10 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.KeyguardManager;
 import android.app.PendingIntent;
+import android.app.RemoteLockscreenValidationResult;
+import android.app.StartLockscreenValidationRequest;
 import android.content.Context;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -40,11 +43,17 @@
 import android.security.keystore.recovery.RecoveryController;
 import android.security.keystore.recovery.WrappedApplicationKey;
 import android.util.ArrayMap;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.HexDump;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockscreenCredential;
+import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.security.SecureBox;
+import com.android.server.locksettings.LockSettingsService;
 import com.android.server.locksettings.recoverablekeystore.certificate.CertParsingException;
 import com.android.server.locksettings.recoverablekeystore.certificate.CertUtils;
 import com.android.server.locksettings.recoverablekeystore.certificate.CertValidationException;
@@ -55,8 +64,11 @@
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
+import com.android.server.locksettings.recoverablekeystore.storage.RemoteLockscreenValidationSessionStorage;
+import com.android.server.locksettings.recoverablekeystore.storage.RemoteLockscreenValidationSessionStorage.LockscreenVerificationSession;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
@@ -89,6 +101,9 @@
 public class RecoverableKeyStoreManager {
     private static final String TAG = "RecoverableKeyStoreMgr";
     private static final long SYNC_DELAY_MILLIS = 2000;
+    private static final int INVALID_REMOTE_GUESS_LIMIT = 5;
+    public static final byte[] ENCRYPTED_REMOTE_CREDENTIALS_HEADER =
+            "encrypted_remote_credentials".getBytes(StandardCharsets.UTF_8);
 
     private static RecoverableKeyStoreManager mInstance;
 
@@ -103,6 +118,9 @@
     private final ApplicationKeyStorage mApplicationKeyStorage;
     private final TestOnlyInsecureCertificateHelper mTestCertHelper;
     private final CleanupManager mCleanupManager;
+    // only set if SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API is enabled.
+    @Nullable private final RemoteLockscreenValidationSessionStorage
+            mRemoteLockscreenValidationSessionStorage;
 
     /**
      * Returns a new or existing instance.
@@ -112,7 +130,18 @@
     public static synchronized RecoverableKeyStoreManager
             getInstance(Context context) {
         if (mInstance == null) {
-            RecoverableKeyStoreDb db = RecoverableKeyStoreDb.newInstance(context);
+            RecoverableKeyStoreDb db;
+            RemoteLockscreenValidationSessionStorage lockscreenCheckSessions;
+            if (FeatureFlagUtils.isEnabled(context,
+                    FeatureFlagUtils.SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API)) {
+                // TODO(b/254335492): Remove flag check when feature is launched.
+                db = RecoverableKeyStoreDb.newInstance(context, 7);
+                lockscreenCheckSessions = new RemoteLockscreenValidationSessionStorage();
+            } else {
+                db = RecoverableKeyStoreDb.newInstance(context);
+                lockscreenCheckSessions = null;
+            }
+
             PlatformKeyManager platformKeyManager;
             ApplicationKeyStorage applicationKeyStorage;
             try {
@@ -142,7 +171,8 @@
                     platformKeyManager,
                     applicationKeyStorage,
                     new TestOnlyInsecureCertificateHelper(),
-                    cleanupManager);
+                    cleanupManager,
+                    lockscreenCheckSessions);
         }
         return mInstance;
     }
@@ -158,7 +188,8 @@
             PlatformKeyManager platformKeyManager,
             ApplicationKeyStorage applicationKeyStorage,
             TestOnlyInsecureCertificateHelper testOnlyInsecureCertificateHelper,
-            CleanupManager cleanupManager) {
+            CleanupManager cleanupManager,
+            RemoteLockscreenValidationSessionStorage remoteLockscreenValidationSessionStorage) {
         mContext = context;
         mDatabase = recoverableKeyStoreDb;
         mRecoverySessionStorage = recoverySessionStorage;
@@ -177,6 +208,7 @@
             Log.wtf(TAG, "AES keygen algorithm not available. AOSP must support this.", e);
             throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
         }
+        mRemoteLockscreenValidationSessionStorage = remoteLockscreenValidationSessionStorage;
     }
 
     /**
@@ -969,19 +1001,128 @@
     /**
      * Starts a session to verify lock screen credentials provided by a remote device.
      */
-    public void startRemoteLockscreenValidation() {
+    public StartLockscreenValidationRequest startRemoteLockscreenValidation(
+            LockSettingsService lockSettingsService) {
+        if (mRemoteLockscreenValidationSessionStorage == null) {
+            throw new UnsupportedOperationException("Under development");
+        }
         checkVerifyRemoteLockscreenPermission();
-        // TODO(b/254335492): Create session in memory
-        return;
+        int userId = UserHandle.getCallingUserId();
+        int savedCredentialType;
+        final long token = Binder.clearCallingIdentity();
+        try {
+            savedCredentialType = lockSettingsService.getCredentialType(userId);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        int keyguardCredentialsType = lockPatternUtilsToKeyguardType(savedCredentialType);
+        LockscreenVerificationSession session =
+                mRemoteLockscreenValidationSessionStorage.startSession(userId);
+        PublicKey publicKey = session.getKeyPair().getPublic();
+        byte[] encodedPublicKey = SecureBox.encodePublicKey(publicKey);
+        int badGuesses = mDatabase.getBadRemoteGuessCounter(userId);
+        int remainingAttempts = Math.max(INVALID_REMOTE_GUESS_LIMIT - badGuesses, 0);
+        // TODO(b/254335492): Schedule task to remove inactive session
+        return new StartLockscreenValidationRequest.Builder()
+                .setLockscreenUiType(keyguardCredentialsType)
+                .setRemainingAttempts(remainingAttempts)
+                .setSourcePublicKey(encodedPublicKey)
+                .build();
     }
 
     /**
      * Verifies encrypted credentials guess from a remote device.
      */
-    public void validateRemoteLockscreen(@NonNull byte[] encryptedCredential) {
+    public synchronized RemoteLockscreenValidationResult validateRemoteLockscreen(
+            @NonNull byte[] encryptedCredential,
+            LockSettingsService lockSettingsService) {
         checkVerifyRemoteLockscreenPermission();
-        // TODO(b/254335492): Decrypt and verify credentials
-        return;
+        int userId = UserHandle.getCallingUserId();
+        LockscreenVerificationSession session =
+                mRemoteLockscreenValidationSessionStorage.get(userId);
+        int badGuesses = mDatabase.getBadRemoteGuessCounter(userId);
+        int remainingAttempts = INVALID_REMOTE_GUESS_LIMIT - badGuesses;
+        if (remainingAttempts <= 0) {
+            return new RemoteLockscreenValidationResult.Builder()
+                .setResultCode(RemoteLockscreenValidationResult.RESULT_NO_REMAINING_ATTEMPTS)
+                .build();
+        }
+        if (session == null) {
+            throw new IllegalStateException("There is no active lock screen check session");
+        }
+        byte[] decryptedCredentials;
+        try {
+            decryptedCredentials = SecureBox.decrypt(
+                session.getKeyPair().getPrivate(),
+                /* sharedSecret= */ null,
+                ENCRYPTED_REMOTE_CREDENTIALS_HEADER,
+                encryptedCredential);
+        } catch (NoSuchAlgorithmException e) {
+            Log.wtf(TAG, "Missing SecureBox algorithm. AOSP required to support this.", e);
+            throw new IllegalStateException(e);
+        } catch (InvalidKeyException e) {
+            Log.e(TAG, "Got InvalidKeyException during lock screen credentials decryption");
+            throw new IllegalStateException(e);
+        } catch (AEADBadTagException e) {
+            throw new IllegalStateException("Could not decrypt credentials guess", e);
+        }
+        int savedCredentialType;
+        final long token = Binder.clearCallingIdentity();
+        try {
+            savedCredentialType = lockSettingsService.getCredentialType(userId);
+            int keyguardCredentialsType = lockPatternUtilsToKeyguardType(savedCredentialType);
+            try (LockscreenCredential credential =
+                    createLockscreenCredential(keyguardCredentialsType, decryptedCredentials)) {
+                // TODO(b/254335492): remove decryptedCredentials
+                VerifyCredentialResponse verifyResponse =
+                        lockSettingsService.verifyCredential(credential, userId, 0);
+                return handleVerifyCredentialResponse(verifyResponse, userId);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private RemoteLockscreenValidationResult handleVerifyCredentialResponse(
+            VerifyCredentialResponse response, int userId) {
+        if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+            mDatabase.setBadRemoteGuessCounter(userId, 0);
+            mRemoteLockscreenValidationSessionStorage.finishSession(userId);
+            return new RemoteLockscreenValidationResult.Builder()
+                    .setResultCode(RemoteLockscreenValidationResult.RESULT_GUESS_VALID)
+                    .build();
+        }
+        if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
+            long timeout = (long) response.getTimeout();
+            return new RemoteLockscreenValidationResult.Builder()
+                    .setResultCode(RemoteLockscreenValidationResult.RESULT_LOCKOUT)
+                    .setTimeoutMillis(timeout)
+                    .build();
+        }
+        // Invalid guess
+        int badGuesses = mDatabase.getBadRemoteGuessCounter(userId);
+        mDatabase.setBadRemoteGuessCounter(userId, badGuesses + 1);
+        return new RemoteLockscreenValidationResult.Builder()
+                .setResultCode(RemoteLockscreenValidationResult.RESULT_GUESS_INVALID)
+                .build();
+    }
+
+    private LockscreenCredential createLockscreenCredential(
+            int lockType, byte[] password) {
+        switch (lockType) {
+            case KeyguardManager.PASSWORD:
+                CharSequence passwordStr = new String(password, StandardCharsets.UTF_8);
+                return LockscreenCredential.createPassword(passwordStr);
+            case KeyguardManager.PIN:
+                CharSequence pinStr = new String(password);
+                return LockscreenCredential.createPin(pinStr);
+            case KeyguardManager.PATTERN:
+                List<LockPatternView.Cell> pattern =
+                        LockPatternUtils.byteArrayToPattern(password);
+                return LockscreenCredential.createPattern(pattern);
+            default:
+                throw new IllegalStateException("Lockscreen is not set");
+        }
     }
 
     private void checkVerifyRemoteLockscreenPermission() {
@@ -995,6 +1136,21 @@
         mCleanupManager.registerRecoveryAgent(userId, uid);
     }
 
+    private int lockPatternUtilsToKeyguardType(int credentialsType) {
+        switch(credentialsType) {
+            case LockPatternUtils.CREDENTIAL_TYPE_NONE:
+                throw new IllegalStateException("Screen lock is not set");
+            case LockPatternUtils.CREDENTIAL_TYPE_PATTERN:
+                return KeyguardManager.PATTERN;
+            case LockPatternUtils.CREDENTIAL_TYPE_PIN:
+                return KeyguardManager.PIN;
+            case LockPatternUtils.CREDENTIAL_TYPE_PASSWORD:
+                return KeyguardManager.PASSWORD;
+            default:
+                throw new IllegalStateException("Screen lock is not set");
+        }
+    }
+
     private void checkRecoverKeyStorePermission() {
         mContext.enforceCallingOrSelfPermission(
                 Manifest.permission.RECOVER_KEYSTORE,
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index ffc309e..3c97aaf8 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -280,13 +280,13 @@
     public void setRouteListingPreference(
             @NonNull IMediaRouter2 router,
             @Nullable RouteListingPreference routeListingPreference) {
-        ComponentName inAppOnlyItemRoutingReceiver =
+        ComponentName linkedItemLandingComponent =
                 routeListingPreference != null
-                        ? routeListingPreference.getInAppOnlyItemRoutingReceiver()
+                        ? routeListingPreference.getLinkedItemComponentName()
                         : null;
-        if (inAppOnlyItemRoutingReceiver != null) {
+        if (linkedItemLandingComponent != null) {
             MediaServerUtils.enforcePackageName(
-                    inAppOnlyItemRoutingReceiver.getPackageName(), Binder.getCallingUid());
+                    linkedItemLandingComponent.getPackageName(), Binder.getCallingUid());
         }
 
         final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index f2a39b8..26e8fe6 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -21,11 +21,11 @@
 import android.media.Session2Token;
 import android.media.session.MediaSession;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseArray;
 
-import com.android.server.utils.EventLogger;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -61,8 +61,6 @@
     private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
     private final OnMediaButtonSessionChangedListener mOnMediaButtonSessionChangedListener;
 
-    private final EventLogger mEventLogger = new EventLogger(DUMP_EVENTS_MAX_COUNT, TAG);
-
     /**
      * The media button session which receives media key events.
      * It could be null if the previous media button session is released.
@@ -86,9 +84,8 @@
      * @param record The record to add.
      */
     public void addSession(MediaSessionRecordImpl record) {
-        mEventLogger.enqueue(EventLogger.StringEvent.from(
-                "addSession() (to bottom of stack)",
-                "record: %s",
+        Slog.i(TAG, TextUtils.formatSimple(
+                "addSession to bottom of stack | record: %s",
                 record
         ));
         mSessions.add(record);
@@ -106,9 +103,8 @@
      * @param record The record to remove.
      */
     public void removeSession(MediaSessionRecordImpl record) {
-        mEventLogger.enqueue(EventLogger.StringEvent.from(
-                "removeSession()",
-                "record: %s",
+        Slog.i(TAG, TextUtils.formatSimple(
+                "removeSession | record: %s",
                 record
         ));
         mSessions.remove(record);
@@ -156,9 +152,8 @@
     public void onPlaybackStateChanged(
             MediaSessionRecordImpl record, boolean shouldUpdatePriority) {
         if (shouldUpdatePriority) {
-            mEventLogger.enqueue(EventLogger.StringEvent.from(
-                    "onPlaybackStateChanged() - Pushing session to top",
-                    "record: %s",
+            Slog.i(TAG, TextUtils.formatSimple(
+                    "onPlaybackStateChanged - Pushing session to top | record: %s",
                     record
             ));
             mSessions.remove(record);
@@ -365,8 +360,6 @@
         for (MediaSessionRecordImpl record : mSessions) {
             record.dump(pw, indent);
         }
-        pw.println(prefix + "Session stack events:");
-        mEventLogger.dump(pw, indent);
     }
 
     /**
diff --git a/services/core/java/com/android/server/media/projection/TEST_MAPPING b/services/core/java/com/android/server/media/projection/TEST_MAPPING
index a792498..4324930 100644
--- a/services/core/java/com/android/server/media/projection/TEST_MAPPING
+++ b/services/core/java/com/android/server/media/projection/TEST_MAPPING
@@ -13,6 +13,20 @@
           "exclude-annotation": "org.junit.Ignore"
         }
       ]
+    },
+    {
+      "name": "CtsMediaProjectionTestCases",
+      "options": [
+        {
+          "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
     }
   ]
 }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 03e4f09..82625e4 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -132,6 +132,7 @@
 
     // contains connections to all connected services, including app services
     // and system services
+    @GuardedBy("mMutex")
     private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>();
     /**
      * The services that have been bound by us. If the service is also connected, it will also
@@ -157,7 +158,8 @@
     // List of approved packages or components (by user, then by primary/secondary) that are
     // allowed to be bound as managed services. A package or component appearing in this list does
     // not mean that we are currently bound to said package/component.
-    protected ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved = new ArrayMap<>();
+    protected final ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved =
+            new ArrayMap<>();
 
     // List of packages or components (by user) that are configured to be enabled/disabled
     // explicitly by the user
@@ -316,6 +318,7 @@
         return changes;
     }
 
+    @GuardedBy("mApproved")
     private boolean clearUserSetFlagLocked(ComponentName component, int userId) {
         String approvedValue = getApprovedValue(component.flattenToString());
         ArraySet<String> userSet = mUserSetServices.get(userId);
@@ -376,8 +379,8 @@
             pw.println("      " + cmpt);
         }
 
-        pw.println("    Live " + getCaption() + "s (" + mServices.size() + "):");
         synchronized (mMutex) {
+            pw.println("    Live " + getCaption() + "s (" + mServices.size() + "):");
             for (ManagedServiceInfo info : mServices) {
                 if (filter != null && !filter.matches(info.component)) continue;
                 pw.println("      " + info.component
@@ -1011,10 +1014,12 @@
             return null;
         }
         final IBinder token = service.asBinder();
-        final int N = mServices.size();
-        for (int i = 0; i < N; i++) {
-            final ManagedServiceInfo info = mServices.get(i);
-            if (info.service.asBinder() == token) return info;
+        synchronized (mMutex) {
+            final int nServices = mServices.size();
+            for (int i = 0; i < nServices; i++) {
+                final ManagedServiceInfo info = mServices.get(i);
+                if (info.service.asBinder() == token) return info;
+            }
         }
         return null;
     }
@@ -1488,10 +1493,12 @@
         }
     }
 
+    @GuardedBy("mMutex")
     private void registerServiceLocked(final ComponentName name, final int userid) {
         registerServiceLocked(name, userid, false /* isSystem */);
     }
 
+    @GuardedBy("mMutex")
     private void registerServiceLocked(final ComponentName name, final int userid,
             final boolean isSystem) {
         if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
@@ -1622,6 +1629,7 @@
         }
     }
 
+    @GuardedBy("mMutex")
     private void unregisterServiceLocked(ComponentName name, int userid) {
         final int N = mServices.size();
         for (int i = N - 1; i >= 0; i--) {
@@ -1656,6 +1664,7 @@
         return serviceInfo;
     }
 
+    @GuardedBy("mMutex")
     private ManagedServiceInfo removeServiceLocked(int i) {
         final ManagedServiceInfo info = mServices.remove(i);
         onServiceRemovedLocked(info);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5ab4a42..0aa822b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -24,6 +24,7 @@
 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
 import static android.app.Notification.FLAG_INSISTENT;
 import static android.app.Notification.FLAG_NO_CLEAR;
+import static android.app.Notification.FLAG_NO_DISMISS;
 import static android.app.Notification.FLAG_ONGOING_EVENT;
 import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
 import static android.app.NotificationChannel.CONVERSATION_CHANNEL_ID_FORMAT;
@@ -521,8 +522,6 @@
     private PackageManager mPackageManagerClient;
     PackageManagerInternal mPackageManagerInternal;
     private PermissionPolicyInternal mPermissionPolicyInternal;
-
-    private PermissionManagerServiceInternal mPermissionInternal;
     AudioManager mAudioManager;
     AudioManagerInternal mAudioManagerInternal;
     // Can be null for wear
@@ -578,6 +577,11 @@
     private float mInCallNotificationVolume;
     private Binder mCallNotificationToken = null;
 
+    private static final boolean ONGOING_DISMISSAL = SystemProperties.getBoolean(
+            "persist.sysui.notification.ongoing_dismissal", true);
+    @VisibleForTesting
+    protected boolean mSystemExemptFromDismissal = false;
+
     // used as a mutex for access to all active notifications & listeners
     final Object mNotificationLock = new Object();
     @GuardedBy("mNotificationLock")
@@ -1203,10 +1207,13 @@
                     id = r.getSbn().getId();
                 }
             }
-            int mustNotHaveFlags = FLAG_ONGOING_EVENT;
-            cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
-                    mustNotHaveFlags,
-                    true, userId, REASON_CANCEL, nv.rank, nv.count,null);
+
+            int mustNotHaveFlags = ONGOING_DISMISSAL ? FLAG_NO_DISMISS : FLAG_ONGOING_EVENT;
+            cancelNotification(callingUid, callingPid, pkg, tag, id,
+                    /* mustHaveFlags= */ 0,
+                    /* mustNotHaveFlags= */ mustNotHaveFlags,
+                    /* sendDelete= */ true,
+                    userId, REASON_CANCEL, nv.rank, nv.count, /* listener= */ null);
             nv.recycle();
         }
 
@@ -2212,8 +2219,7 @@
             TelephonyManager telephonyManager, ActivityManagerInternal ami,
             MultiRateLimiter toastRateLimiter, PermissionHelper permissionHelper,
             UsageStatsManagerInternal usageStatsManagerInternal,
-            TelecomManager telecomManager, NotificationChannelLogger channelLogger,
-            PermissionManagerServiceInternal permInternal) {
+            TelecomManager telecomManager, NotificationChannelLogger channelLogger) {
         mHandler = handler;
         Resources resources = getContext().getResources();
         mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
@@ -2231,7 +2237,6 @@
         mPackageManagerClient = packageManagerClient;
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
-        mPermissionInternal = permInternal;
         mUmInternal = LocalServices.getService(UserManagerInternal.class);
         mUsageStatsManagerInternal = usageStatsManagerInternal;
         mAppOps = appOps;
@@ -2543,8 +2548,7 @@
                         AppGlobals.getPermissionManager()),
                 LocalServices.getService(UsageStatsManagerInternal.class),
                 getContext().getSystemService(TelecomManager.class),
-                new NotificationChannelLoggerImpl(),
-                LocalServices.getService(PermissionManagerServiceInternal.class));
+                new NotificationChannelLoggerImpl());
 
         publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false,
                 DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL);
@@ -2593,6 +2597,8 @@
         mAllowFgsDismissal = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED, true);
+        mSystemExemptFromDismissal =
+                mDpm.isApplicationExemptionsFlagEnabled();
         DeviceConfig.addOnPropertiesChangedListener(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 new HandlerExecutor(mHandler),
@@ -6694,30 +6700,27 @@
                 (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
         Notification.addFieldsFromContext(ai, notification);
 
-        int canColorize = mPermissionInternal.checkPermission(
-                android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, pkg, userId);
+        // Only notifications that can be non-dismissible can have the flag FLAG_NO_DISMISS
+        if (ONGOING_DISMISSAL) {
+            if (((notification.flags & FLAG_ONGOING_EVENT) > 0)
+                    && canBeNonDismissible(ai, notification)) {
+                notification.flags |= FLAG_NO_DISMISS;
+            } else {
+                notification.flags &= ~FLAG_NO_DISMISS;
+            }
+        }
+
+        int canColorize = mPackageManagerClient.checkPermission(
+                android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, pkg);
         if (canColorize == PERMISSION_GRANTED) {
             notification.flags |= Notification.FLAG_CAN_COLORIZE;
         } else {
             notification.flags &= ~Notification.FLAG_CAN_COLORIZE;
         }
 
-        if (notification.extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, false)) {
-            int hasShowDuringSetupPerm = mPermissionInternal.checkPermission(
-                    android.Manifest.permission.NOTIFICATION_DURING_SETUP, pkg, userId);
-            if (hasShowDuringSetupPerm != PERMISSION_GRANTED) {
-                notification.extras.remove(Notification.EXTRA_ALLOW_DURING_SETUP);
-                if (DBG) {
-                    Slog.w(TAG, "warning: pkg " + pkg + " attempting to show during setup"
-                            + " without holding perm "
-                            + Manifest.permission.NOTIFICATION_DURING_SETUP);
-                }
-            }
-        }
-
         if (notification.fullScreenIntent != null && ai.targetSdkVersion >= Build.VERSION_CODES.Q) {
-            int fullscreenIntentPermission = mPermissionInternal.checkPermission(
-                    android.Manifest.permission.USE_FULL_SCREEN_INTENT, pkg, userId);
+            int fullscreenIntentPermission = mPackageManagerClient.checkPermission(
+                    android.Manifest.permission.USE_FULL_SCREEN_INTENT, pkg);
             if (fullscreenIntentPermission != PERMISSION_GRANTED) {
                 notification.fullScreenIntent = null;
                 Slog.w(TAG, "Package " + pkg +
@@ -6725,6 +6728,31 @@
             }
         }
 
+        // Ensure all actions are present
+        if (notification.actions != null) {
+            boolean hasNullActions = false;
+            int nActions = notification.actions.length;
+            for (int i = 0; i < nActions; i++) {
+                if (notification.actions[i] == null) {
+                    hasNullActions = true;
+                    break;
+                }
+            }
+            if (hasNullActions) {
+                ArrayList<Notification.Action> nonNullActions = new ArrayList<>();
+                for (int i = 0; i < nActions; i++) {
+                    if (notification.actions[i] != null) {
+                        nonNullActions.add(notification.actions[i]);
+                    }
+                }
+                if (nonNullActions.size() != 0) {
+                    notification.actions = nonNullActions.toArray(new Notification.Action[0]);
+                } else {
+                    notification.actions = null;
+                }
+            }
+        }
+
         // Ensure CallStyle has all the correct actions
         if (notification.isStyle(Notification.CallStyle.class)) {
             Notification.Builder builder =
@@ -6737,7 +6765,7 @@
 
         // Ensure MediaStyle has correct permissions for remote device extras
         if (notification.isStyle(Notification.MediaStyle.class)) {
-            int hasMediaContentControlPermission = mPermissionInternal.checkPermission(
+            int hasMediaContentControlPermission = mPackageManager.checkPermission(
                     android.Manifest.permission.MEDIA_CONTENT_CONTROL, pkg, userId);
             if (hasMediaContentControlPermission != PERMISSION_GRANTED) {
                 notification.extras.remove(Notification.EXTRA_MEDIA_REMOTE_DEVICE);
@@ -6752,7 +6780,7 @@
 
         // Ensure only allowed packages have a substitute app name
         if (notification.extras.containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)) {
-            int hasSubstituteAppNamePermission = mPermissionInternal.checkPermission(
+            int hasSubstituteAppNamePermission = mPackageManager.checkPermission(
                     permission.SUBSTITUTE_NOTIFICATION_APP_NAME, pkg, userId);
             if (hasSubstituteAppNamePermission != PERMISSION_GRANTED) {
                 notification.extras.remove(Notification.EXTRA_SUBSTITUTE_APP_NAME);
@@ -6768,6 +6796,31 @@
         checkRemoteViews(pkg, tag, id, notification);
     }
 
+    /**
+     * Whether a notification can be non-dismissible.
+     * A notification should be dismissible, unless it's exempted for some reason.
+     */
+    private boolean canBeNonDismissible(ApplicationInfo ai, Notification notification) {
+        // Check if the app is on the system partition, or an update to an app on the system
+        // partition.
+        boolean isSystemAppExempt = (ai.flags
+                & (ApplicationInfo.FLAG_UPDATED_SYSTEM_APP | ApplicationInfo.FLAG_SYSTEM)) > 0;
+        return isSystemAppExempt || notification.isMediaNotification() || isEnterpriseExempted(ai);
+    }
+
+    private boolean isEnterpriseExempted(ApplicationInfo ai) {
+        // Check if the app is an organization admin app
+        // TODO(b/234609037): Replace with new DPM APIs to check if organization admin
+        if (mDpm != null && (mDpm.isActiveProfileOwner(ai.uid)
+                || mDpm.isActiveDeviceOwner(ai.uid))) {
+            return true;
+        }
+        // Check if an app has been given system exemption
+        return mSystemExemptFromDismissal && mAppOps.checkOpNoThrow(
+                AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
+                ai.packageName) == AppOpsManager.MODE_ALLOWED;
+    }
+
     private void checkRemoteViews(String pkg, String tag, int id, Notification notification) {
         if (removeRemoteView(pkg, tag, id, notification.contentView)) {
             notification.contentView = null;
@@ -7996,6 +8049,13 @@
                             }
                         }
                     }
+
+                    // Try to start flash notification event whenever an audible and non-suppressed
+                    // notification is received
+                    mAccessibilityManager.startFlashNotificationEvent(getContext(),
+                            AccessibilityManager.FLASH_REASON_NOTIFICATION,
+                            record.getSbn().getPackageName());
+
                 } else if ((record.getFlags() & Notification.FLAG_INSISTENT) != 0) {
                     hasValidSound = false;
                 }
@@ -8356,9 +8416,15 @@
     }
 
     private boolean isExemptFromRateLimiting(String pkg, int userId) {
-        return mPermissionInternal.checkPermission(
-                android.Manifest.permission.UNLIMITED_TOASTS, pkg, userId)
-                == PackageManager.PERMISSION_GRANTED;
+        boolean isExemptFromRateLimiting = false;
+        try {
+            isExemptFromRateLimiting = mPackageManager.checkPermission(
+                    android.Manifest.permission.UNLIMITED_TOASTS, pkg, userId)
+                    == PackageManager.PERMISSION_GRANTED;
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to connect with package manager");
+        }
+        return isExemptFromRateLimiting;
     }
 
     /** Reports rate limiting toasts compat change (used when the toast was blocked). */
@@ -10005,9 +10071,13 @@
     boolean canUseManagedServices(String pkg, Integer userId, String requiredPermission) {
         boolean canUseManagedServices = true;
         if (requiredPermission != null) {
-            if (mPermissionInternal.checkPermission(requiredPermission, pkg, userId)
-                    != PackageManager.PERMISSION_GRANTED) {
-                canUseManagedServices = false;
+            try {
+                if (mPackageManager.checkPermission(requiredPermission, pkg, userId)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    canUseManagedServices = false;
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "can't talk to pm", e);
             }
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
index 4031c83..25d619d 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLogger.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
@@ -473,4 +473,15 @@
         }
         return (r.getSbn().getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
     }
+
+    /**
+     * @param r NotificationRecord
+     * @return Whether the notification is a non-dismissible notification.
+     */
+    static boolean isNonDismissible(@NonNull NotificationRecord r) {
+        if (r.getSbn() == null || r.getSbn().getNotification() == null) {
+            return false;
+        }
+        return (r.getNotification().flags & Notification.FLAG_NO_DISMISS) != 0;
+    }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
index 17c6c46..9a1f19d 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
@@ -86,7 +86,9 @@
                 /* bool is_foreground_service = 23 */
                 NotificationRecordLogger.isForegroundService(p.r),
                 /* optional int64 timeout_millis = 24 */
-                p.r.getSbn().getNotification().getTimeoutAfter()
+                p.r.getSbn().getNotification().getTimeoutAfter(),
+                /* bool is_nondismissible = 25 */
+                NotificationRecordLogger.isNonDismissible(p.r)
         );
     }
 
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 2fdc4cd..e698c4b 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.os;
 
+import android.Manifest;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.app.ActivityManager;
@@ -25,6 +26,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.os.Binder;
+import android.os.BugreportManager.BugreportCallback;
 import android.os.BugreportParams;
 import android.os.IDumpstate;
 import android.os.IDumpstateListener;
@@ -35,10 +37,13 @@
 import android.os.UserHandle;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Pair;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.SystemConfig;
 
 import java.io.FileDescriptor;
@@ -60,18 +65,105 @@
     private final AppOpsManager mAppOps;
     private final TelephonyManager mTelephonyManager;
     private final ArraySet<String> mBugreportWhitelistedPackages;
+    private final BugreportFileManager mBugreportFileManager;
 
     @GuardedBy("mLock")
     private OptionalInt mPreDumpedDataUid = OptionalInt.empty();
 
-    BugreportManagerServiceImpl(Context context) {
-        mContext = context;
-        mAppOps = context.getSystemService(AppOpsManager.class);
-        mTelephonyManager = context.getSystemService(TelephonyManager.class);
-        mBugreportWhitelistedPackages =
-                SystemConfig.getInstance().getBugreportWhitelistedPackages();
+    /** Helper class for associating previously generated bugreports with their callers. */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    static class BugreportFileManager {
+
+        private final Object mLock = new Object();
+
+        @GuardedBy("mLock")
+        private final ArrayMap<Pair<Integer, String>, ArraySet<String>> mBugreportFiles;
+
+        BugreportFileManager() {
+            mBugreportFiles = new ArrayMap<>();
+        }
+
+        /**
+         * Checks that a given file was generated on behalf of the given caller. If the file was
+         * generated on behalf of the caller, it is removed from the bugreport mapping so that it
+         * may not be retrieved again. If the file was not generated on behalf of the caller, an
+         * {@link IllegalArgumentException} is thrown.
+         *
+         * @param callingInfo a (uid, package name) pair identifying the caller
+         * @param bugreportFile the file name which was previously given to the caller in the
+         *                      {@link BugreportCallback#onFinished(String)} callback.
+         *
+         * @throws IllegalArgumentException if {@code bugreportFile} is not associated with
+         *                                  {@code callingInfo}.
+         */
+        void ensureCallerPreviouslyGeneratedFile(
+                Pair<Integer, String> callingInfo, String bugreportFile) {
+            synchronized (mLock) {
+                ArraySet<String> bugreportFilesForCaller = mBugreportFiles.get(callingInfo);
+                if (bugreportFilesForCaller != null
+                        && bugreportFilesForCaller.contains(bugreportFile)) {
+                    bugreportFilesForCaller.remove(bugreportFile);
+                    if (bugreportFilesForCaller.isEmpty()) {
+                        mBugreportFiles.remove(callingInfo);
+                    }
+                } else {
+                    throw new IllegalArgumentException(
+                            "File " + bugreportFile + " was not generated"
+                                    + " on behalf of calling package " + callingInfo.second);
+                }
+            }
+        }
+
+        /**
+         * Associates a bugreport file with a caller, which is identified as a
+         * (uid, package name) pair.
+         */
+        void addBugreportFileForCaller(Pair<Integer, String> caller, String bugreportFile) {
+            synchronized (mLock) {
+                if (!mBugreportFiles.containsKey(caller)) {
+                    mBugreportFiles.put(caller, new ArraySet<>());
+                }
+                ArraySet<String> bugreportFilesForCaller = mBugreportFiles.get(caller);
+                bugreportFilesForCaller.add(bugreportFile);
+            }
+        }
     }
 
+    static class Injector {
+        Context mContext;
+        ArraySet<String> mAllowlistedPackages;
+
+        Injector(Context context, ArraySet<String> allowlistedPackages) {
+            mContext = context;
+            mAllowlistedPackages = allowlistedPackages;
+        }
+
+        Context getContext() {
+            return mContext;
+        }
+
+        ArraySet<String> getAllowlistedPackages() {
+            return mAllowlistedPackages;
+        }
+
+    }
+
+    BugreportManagerServiceImpl(Context context) {
+        this(new Injector(context, SystemConfig.getInstance().getBugreportWhitelistedPackages()));
+
+    }
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    BugreportManagerServiceImpl(Injector injector) {
+        mContext = injector.getContext();
+        mAppOps = mContext.getSystemService(AppOpsManager.class);
+        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+        mBugreportFileManager = new BugreportFileManager();
+        mBugreportWhitelistedPackages =
+                injector.getAllowlistedPackages();
+    }
+
+
     @Override
     @RequiresPermission(android.Manifest.permission.DUMP)
     public void preDumpUiData(String callingPackage) {
@@ -135,6 +227,50 @@
         }
     }
 
+    @Override
+    @RequiresPermission(Manifest.permission.DUMP)
+    public void retrieveBugreport(int callingUidUnused, String callingPackage,
+            FileDescriptor bugreportFd, String bugreportFile, IDumpstateListener listener) {
+        int callingUid = Binder.getCallingUid();
+        enforcePermission(callingPackage, callingUid, false);
+
+        try {
+            mBugreportFileManager.ensureCallerPreviouslyGeneratedFile(
+                    new Pair<>(callingUid, callingPackage), bugreportFile);
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, e.getMessage());
+            reportError(listener, IDumpstateListener.BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE);
+            return;
+        }
+
+        synchronized (mLock) {
+            if (isDumpstateBinderServiceRunningLocked()) {
+                Slog.w(TAG, "'dumpstate' is already running. Cannot retrieve a bugreport"
+                        + " while another one is currently in progress.");
+                reportError(listener,
+                        IDumpstateListener.BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS);
+                return;
+            }
+
+            IDumpstate ds = startAndGetDumpstateBinderServiceLocked();
+            if (ds == null) {
+                Slog.w(TAG, "Unable to get bugreport service");
+                reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
+                return;
+            }
+
+            // Wrap the listener so we can intercept binder events directly.
+            IDumpstateListener myListener = new DumpstateListener(listener, ds,
+                    new Pair<>(callingUid, callingPackage));
+            try {
+                ds.retrieveBugreport(callingUid, callingPackage, bugreportFd,
+                        bugreportFile, myListener);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "RemoteException in retrieveBugreport", e);
+            }
+        }
+    }
+
     private void validateBugreportMode(@BugreportParams.BugreportMode int mode) {
         if (mode != BugreportParams.BUGREPORT_MODE_FULL
                 && mode != BugreportParams.BUGREPORT_MODE_INTERACTIVE
@@ -148,7 +284,9 @@
     }
 
     private void validateBugreportFlags(int flags) {
-        flags = clearBugreportFlag(flags, BugreportParams.BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA);
+        flags = clearBugreportFlag(flags,
+                BugreportParams.BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA
+                        | BugreportParams.BUGREPORT_FLAG_DEFER_CONSENT);
         if (flags != 0) {
             Slog.w(TAG, "Unknown bugreport flags: " + flags);
             throw new IllegalArgumentException("Unknown bugreport flags: " + flags);
@@ -298,6 +436,9 @@
             }
         }
 
+        boolean isConsentDeferred =
+                (bugreportFlags & BugreportParams.BUGREPORT_FLAG_DEFER_CONSENT) != 0;
+
         IDumpstate ds = startAndGetDumpstateBinderServiceLocked();
         if (ds == null) {
             Slog.w(TAG, "Unable to get bugreport service");
@@ -306,7 +447,8 @@
         }
 
         // Wrap the listener so we can intercept binder events directly.
-        IDumpstateListener myListener = new DumpstateListener(listener, ds);
+        IDumpstateListener myListener = new DumpstateListener(listener, ds,
+                isConsentDeferred ? new Pair<>(callingUid, callingPackage) : null);
         try {
             ds.startBugreport(callingUid, callingPackage, bugreportFd, screenshotFd, bugreportMode,
                     bugreportFlags, myListener, isScreenshotRequested);
@@ -405,10 +547,13 @@
         private final IDumpstateListener mListener;
         private final IDumpstate mDs;
         private boolean mDone = false;
+        private final Pair<Integer, String> mCaller;
 
-        DumpstateListener(IDumpstateListener listener, IDumpstate ds) {
+        DumpstateListener(IDumpstateListener listener, IDumpstate ds,
+                @Nullable Pair<Integer, String> caller) {
             mListener = listener;
             mDs = ds;
+            mCaller = caller;
             try {
                 mDs.asBinder().linkToDeath(this, 0);
             } catch (RemoteException e) {
@@ -430,11 +575,14 @@
         }
 
         @Override
-        public void onFinished() throws RemoteException {
+        public void onFinished(String bugreportFile) throws RemoteException {
             synchronized (mLock) {
                 mDone = true;
             }
-            mListener.onFinished();
+            if (mCaller != null) {
+                mBugreportFileManager.addBugreportFileForCaller(mCaller, bugreportFile);
+            }
+            mListener.onFinished(bugreportFile);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
index 69436da..8d40adf 100644
--- a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
+++ b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
@@ -27,12 +27,15 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
+import android.os.Build;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.Slog;
@@ -51,6 +54,7 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Set;
@@ -122,7 +126,18 @@
         @Override
         public ParceledListSlice<PackageInfo> getBackgroundInstalledPackages(
                 @PackageManager.PackageInfoFlagsBits long flags, int userId) {
-            return mService.getBackgroundInstalledPackages(flags, userId);
+            if (!Build.IS_DEBUGGABLE) {
+                return mService.getBackgroundInstalledPackages(flags, userId);
+            }
+            // The debug.transparency.bg-install-apps (only works for debuggable builds)
+            // is used to set mock list of background installed apps for testing.
+            // The list of apps' names is delimited by ",".
+            String propertyString = SystemProperties.get("debug.transparency.bg-install-apps");
+            if (TextUtils.isEmpty(propertyString)) {
+                return mService.getBackgroundInstalledPackages(flags, userId);
+            } else {
+                return mService.getMockBackgroundInstalledPackages(propertyString);
+            }
         }
     }
 
@@ -145,6 +160,27 @@
         return new ParceledListSlice<>(packages);
     }
 
+    /**
+     * Mock a list of background installed packages based on the property string.
+     */
+    @NonNull
+    ParceledListSlice<PackageInfo> getMockBackgroundInstalledPackages(
+            @NonNull String propertyString) {
+        String[] mockPackageNames = propertyString.split(",");
+        List<PackageInfo> mockPackages = new ArrayList<>();
+        for (String name : mockPackageNames) {
+            try {
+                PackageInfo packageInfo = mPackageManager.getPackageInfo(name,
+                        PackageManager.PackageInfoFlags.of(PackageManager.MATCH_ALL));
+                mockPackages.add(packageInfo);
+            } catch (PackageManager.NameNotFoundException e) {
+                Slog.w(TAG, "Package's PackageInfo not found " + name);
+                continue;
+            }
+        }
+        return new ParceledListSlice<>(mockPackages);
+    }
+
     private static class EventHandler extends Handler {
         private final BackgroundInstallControlService mService;
 
diff --git a/services/core/java/com/android/server/pm/BroadcastHelper.java b/services/core/java/com/android/server/pm/BroadcastHelper.java
index 98d6081..1823a39 100644
--- a/services/core/java/com/android/server/pm/BroadcastHelper.java
+++ b/services/core/java/com/android/server/pm/BroadcastHelper.java
@@ -18,6 +18,8 @@
 
 import static android.os.PowerExemptionManager.REASON_LOCKED_BOOT_COMPLETED;
 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.safetylabel.SafetyLabelConstants.PERMISSION_RATIONALE_ENABLED;
+import static android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED;
 
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
 import static com.android.server.pm.PackageManagerService.PACKAGE_SCHEME;
@@ -42,6 +44,7 @@
 import android.os.PowerExemptionManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.DeviceConfig;
 import android.util.IntArray;
 import android.util.Log;
 import android.util.Pair;
@@ -335,11 +338,13 @@
                 broadcastAllowlist, null /* filterExtrasForReceiver */, null);
         // Send to PermissionController for all new users, even if it may not be running for some
         // users
-        sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
-                packageName, extras, 0,
-                mContext.getPackageManager().getPermissionControllerPackageName(),
-                null, userIds, instantUserIds,
-                broadcastAllowlist, null /* filterExtrasForReceiver */, null);
+        if (isPrivacySafetyLabelChangeNotificationsEnabled()) {
+            sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
+                    packageName, extras, 0,
+                    mContext.getPackageManager().getPermissionControllerPackageName(),
+                    null, userIds, instantUserIds,
+                    broadcastAllowlist, null /* filterExtrasForReceiver */, null);
+        }
     }
 
     public void sendFirstLaunchBroadcast(String pkgName, String installerPkg,
@@ -384,6 +389,13 @@
         return filteredExtras;
     }
 
+    /** Returns whether the Safety Label Change notification, a privacy feature, is enabled. */
+    public static boolean isPrivacySafetyLabelChangeNotificationsEnabled() {
+        return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+                SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, false) && DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_PRIVACY, PERMISSION_RATIONALE_ENABLED, false);
+    }
+
     @NonNull
     private static Pair<String[], int[]> filterPackages(@NonNull Computer snapshot,
             @NonNull String[] pkgs, @Nullable int[] uids, int callingUid, int userId) {
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 094b182..58a609e 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -1856,8 +1856,7 @@
         // Figure out which lib versions the caller can see
         LongSparseLongArray versionsCallerCanSee = null;
         final int callingAppId = UserHandle.getAppId(callingUid);
-        if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.SHELL_UID
-                && callingAppId != Process.ROOT_UID) {
+        if (!PackageManagerServiceUtils.isSystemOrRootOrShell(callingAppId)) {
             versionsCallerCanSee = new LongSparseLongArray();
             String libName = versionedLib.valueAt(0).getName();
             String[] uidPackages = getPackagesForUidInternal(callingUid, callingUid);
@@ -2034,8 +2033,7 @@
         if ((flags & PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES) != 0) {
             // System/shell/root get to see all static libs
             final int appId = UserHandle.getAppId(uid);
-            if (appId == Process.SYSTEM_UID || appId == Process.SHELL_UID
-                    || appId == Process.ROOT_UID) {
+            if (PackageManagerServiceUtils.isSystemOrRootOrShell(appId)) {
                 return false;
             }
             // Installer gets to see all static libs.
@@ -2091,8 +2089,7 @@
         if ((flags & PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES) != 0) {
             // System/shell/root get to see all SDK libs.
             final int appId = UserHandle.getAppId(uid);
-            if (appId == Process.SYSTEM_UID || appId == Process.SHELL_UID
-                    || appId == Process.ROOT_UID) {
+            if (PackageManagerServiceUtils.isSystemOrRootOrShell(appId)) {
                 return false;
             }
             // Installer gets to see all SDK libs.
@@ -2152,7 +2149,7 @@
         if (!requirePermissionWhenSameUser && userId == callingUserId) {
             return true;
         }
-        if (callingUid == Process.SYSTEM_UID || callingUid == Process.ROOT_UID) {
+        if (PackageManagerServiceUtils.isSystemOrRoot(callingUid)) {
             return true;
         }
         if (requireFullPermission) {
@@ -3813,8 +3810,7 @@
     public boolean canRequestPackageInstalls(@NonNull String packageName, int callingUid,
             int userId, boolean throwIfPermNotDeclared) {
         int uid = getPackageUidInternal(packageName, 0, userId, callingUid);
-        if (callingUid != uid && callingUid != Process.ROOT_UID
-                && callingUid != Process.SYSTEM_UID) {
+        if (callingUid != uid && !PackageManagerServiceUtils.isSystemOrRoot(callingUid)) {
             throw new SecurityException(
                     "Caller uid " + callingUid + " does not own package " + packageName);
         }
@@ -5540,8 +5536,8 @@
         enforceCrossUserPermission(callingUid, userId, true /*requireFullPermission*/,
                 true /*checkShell*/, "getHarmfulAppInfo");
 
-        if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.ROOT_UID &&
-                checkUidPermission(SET_HARMFUL_APP_WARNINGS, callingUid) != PERMISSION_GRANTED) {
+        if (!PackageManagerServiceUtils.isSystemOrRoot(callingAppId)
+                && checkUidPermission(SET_HARMFUL_APP_WARNINGS, callingUid) != PERMISSION_GRANTED) {
             throw new SecurityException("Caller must have the "
                     + SET_HARMFUL_APP_WARNINGS + " permission.");
         }
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java
index e149b04..b5c0417 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java
@@ -37,6 +37,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 
+import com.android.internal.config.appcloning.AppCloningDeviceConfigHelper;
 import com.android.server.LocalServices;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
@@ -61,6 +62,8 @@
     private final Context mContext;
     private final UserManagerInternal mUserManagerInternal;
 
+    private AppCloningDeviceConfigHelper mAppCloningDeviceConfigHelper;
+
     public CrossProfileIntentResolverEngine(UserManagerService userManager,
             DomainVerificationManagerInternal domainVerificationManager,
             DefaultAppProvider defaultAppProvider, Context context) {
@@ -250,7 +253,12 @@
          * We would return NoFilteringResolver only if it is allowed(feature flag is set).
          */
         if (shouldUseNoFilteringResolver(sourceUserId, targetUserId)) {
-            if (NoFilteringResolver.isIntentRedirectionAllowed(mContext, resolveForStart, flags)) {
+            if (mAppCloningDeviceConfigHelper == null) {
+                //lazy initialization of helper till required, to improve performance.
+                mAppCloningDeviceConfigHelper = AppCloningDeviceConfigHelper.getInstance(mContext);
+            }
+            if (NoFilteringResolver.isIntentRedirectionAllowed(mContext,
+                    mAppCloningDeviceConfigHelper, resolveForStart, flags)) {
                 return new NoFilteringResolver(computer.getComponentResolver(),
                         mUserManager);
             } else {
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index e0de294..a119a3c 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -35,6 +35,7 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ApplicationExitInfo;
 import android.app.ApplicationPackageManager;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -237,7 +238,7 @@
         synchronized (mPm.mInstallLock) {
             if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
             try (PackageFreezer freezer = mPm.freezePackageForDelete(packageName, freezeUser,
-                    deleteFlags, "deletePackageX")) {
+                    deleteFlags, "deletePackageX", ApplicationExitInfo.REASON_OTHER)) {
                 res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
                         deleteFlags | PackageManager.DELETE_CHATTY, info, true);
             }
@@ -262,7 +263,7 @@
             final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0;
             info.sendPackageRemovedBroadcasts(killApp, removedBySystem);
             info.sendSystemPackageUpdatedBroadcasts();
-            PackageMetrics.onUninstallSucceeded(info, deleteFlags, userId);
+            PackageMetrics.onUninstallSucceeded(info, deleteFlags, removeUser);
         }
 
         // Force a gc to clear up things.
@@ -840,7 +841,7 @@
 
     private boolean isCallerAllowedToSilentlyUninstall(@NonNull Computer snapshot, int callingUid,
             String pkgName, int userId) {
-        if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID
+        if (PackageManagerServiceUtils.isRootOrShell(callingUid)
                 || UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
             return true;
         }
diff --git a/services/core/java/com/android/server/pm/GentleUpdateHelper.java b/services/core/java/com/android/server/pm/GentleUpdateHelper.java
index ae80bab..babcd33 100644
--- a/services/core/java/com/android/server/pm/GentleUpdateHelper.java
+++ b/services/core/java/com/android/server/pm/GentleUpdateHelper.java
@@ -145,7 +145,7 @@
         mHandler.post(() -> {
             var pendingCheck = new PendingInstallConstraintsCheck(
                     packageNames, constraints, resultFuture, timeoutMillis);
-            var deviceIdleFuture = constraints.isRequireDeviceIdle()
+            var deviceIdleFuture = constraints.isDeviceIdleRequired()
                     ? checkDeviceIdle() : CompletableFuture.completedFuture(false);
             deviceIdleFuture.thenAccept(isIdle -> {
                 Preconditions.checkState(mHandler.getLooper().isCurrentThread());
@@ -217,14 +217,14 @@
     @WorkerThread
     private boolean areConstraintsSatisfied(List<String> packageNames,
             InstallConstraints constraints, boolean isIdle) {
-        return (!constraints.isRequireDeviceIdle() || isIdle)
-                && (!constraints.isRequireAppNotForeground()
+        return (!constraints.isDeviceIdleRequired() || isIdle)
+                && (!constraints.isAppNotForegroundRequired()
                 || !mAppStateHelper.hasForegroundApp(packageNames))
-                && (!constraints.isRequireAppNotInteracting()
+                && (!constraints.isAppNotInteractingRequired()
                 || !mAppStateHelper.hasInteractingApp(packageNames))
-                && (!constraints.isRequireAppNotTopVisible()
+                && (!constraints.isAppNotTopVisibleRequired()
                 || !mAppStateHelper.hasTopVisibleApp(packageNames))
-                && (!constraints.isRequireNotInCall()
+                && (!constraints.isNotInCallRequired()
                 || !mAppStateHelper.isInCall());
     }
 
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index a4c9baa..3dbbfa0 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -70,6 +70,7 @@
 import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT;
+import static com.android.server.pm.PackageManagerService.SCAN_AS_STOPPED_SYSTEM_APP;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR;
@@ -99,7 +100,9 @@
 import android.annotation.UserIdInt;
 import android.apex.ApexInfo;
 import android.app.AppOpsManager;
+import android.app.ApplicationExitInfo;
 import android.app.ApplicationPackageManager;
+import android.app.BroadcastOptions;
 import android.app.backup.IBackupManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -488,8 +491,10 @@
             if (pkg.getStaticSharedLibraryName() == null || isReplace) {
                 for (int i = 0; i < clientLibPkgs.size(); i++) {
                     AndroidPackage clientPkg = clientLibPkgs.get(i);
-                    mPm.killApplication(clientPkg.getPackageName(),
-                            clientPkg.getUid(), "update lib");
+                    String packageName = clientPkg.getPackageName();
+                    mPm.killApplication(packageName,
+                            clientPkg.getUid(), "update lib",
+                            ApplicationExitInfo.REASON_DEPENDENCY_DIED);
                 }
             }
         }
@@ -686,7 +691,10 @@
         fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
                 PackageManager.installStatusToPublicStatus(returnCode));
         try {
-            target.sendIntent(context, 0, fillIn, null, null);
+            final BroadcastOptions options = BroadcastOptions.makeBasic();
+            options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+            target.sendIntent(context, 0, fillIn, null /* onFinished*/, null /* handler */,
+                    null /* requiredPermission */, options.toBundle());
         } catch (IntentSender.SendIntentException ignored) {
         }
     }
@@ -1171,7 +1179,8 @@
         request.setName(pkgName);
         if (parsedPackage.isTestOnly()) {
             if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) {
-                throw new PrepareFailure(INSTALL_FAILED_TEST_ONLY, "installPackageLI");
+                throw new PrepareFailure(INSTALL_FAILED_TEST_ONLY,
+                        "Failed to install test-only apk. Did you forget to add -t?");
             }
         }
 
@@ -1536,7 +1545,8 @@
         }
 
         final PackageFreezer freezer =
-                freezePackageForInstall(pkgName, installFlags, "installPackageLI");
+                freezePackageForInstall(pkgName, UserHandle.USER_ALL, installFlags,
+                        "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED);
         boolean shouldCloseFreezerBeforeReturn = true;
         try {
             final PackageState oldPackageState;
@@ -1985,17 +1995,12 @@
         }
     }
 
-    private PackageFreezer freezePackageForInstall(String packageName, int installFlags,
-            String killReason) {
-        return freezePackageForInstall(packageName, UserHandle.USER_ALL, installFlags, killReason);
-    }
-
     private PackageFreezer freezePackageForInstall(String packageName, int userId, int installFlags,
-            String killReason) {
+            String killReason, int exitInfoReason) {
         if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
             return new PackageFreezer(mPm);
         } else {
-            return mPm.freezePackage(packageName, userId, killReason);
+            return mPm.freezePackage(packageName, userId, killReason, exitInfoReason);
         }
     }
 
@@ -2516,10 +2521,10 @@
             // will be null whereas dataOwnerPkg will contain information about the package
             // which was uninstalled while keeping its data.
             AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName);
+            PackageSetting dataOwnerPs = mPm.mSettings.getPackageLPr(packageName);
             if (dataOwnerPkg  == null) {
-                PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
-                if (ps != null) {
-                    dataOwnerPkg = ps.getPkg();
+                if (dataOwnerPs != null) {
+                    dataOwnerPkg = dataOwnerPs.getPkg();
                 }
             }
 
@@ -2547,6 +2552,7 @@
             if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) {
                 if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
                         dataOwnerPkg.isDebuggable())) {
+                    // Downgrade is not permitted; a lower version of the app will not be allowed
                     try {
                         PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
                     } catch (PackageManagerException e) {
@@ -2555,6 +2561,28 @@
                         return Pair.create(
                                 PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
                     }
+                } else if (dataOwnerPs.isSystem()) {
+                    // Downgrade is permitted, but system apps can't be downgraded below
+                    // the version preloaded onto the system image
+                    final PackageSetting disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(
+                            dataOwnerPs);
+                    if (disabledPs != null) {
+                        dataOwnerPkg = disabledPs.getPkg();
+                    }
+                    if (!Build.IS_DEBUGGABLE && !dataOwnerPkg.isDebuggable()) {
+                        // Only restrict non-debuggable builds and non-debuggable version of the app
+                        try {
+                            PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
+                        } catch (PackageManagerException e) {
+                            String errorMsg =
+                                    "System app: " + packageName + " cannot be downgraded to"
+                                            + " older than its preloaded version on the system"
+                                            + " image. " + e.getMessage();
+                            Slog.w(TAG, errorMsg);
+                            return Pair.create(
+                                    PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
+                        }
+                    }
                 }
             }
         }
@@ -2838,10 +2866,12 @@
                 }
                 // Send to PermissionController for all update users, even if it may not be running
                 // for some users
-                mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
-                        extras, 0 /*flags*/,
-                        mPm.mRequiredPermissionControllerPackage, null /*finishedReceiver*/,
-                        updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
+                if (BroadcastHelper.isPrivacySafetyLabelChangeNotificationsEnabled()) {
+                    mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+                            extras, 0 /*flags*/,
+                            mPm.mRequiredPermissionControllerPackage, null /*finishedReceiver*/,
+                            updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
+                }
                 // Notify required verifier(s) that are not the installer of record for the package.
                 for (String verifierPackageName : mPm.mRequiredVerifierPackages) {
                     if (verifierPackageName != null && !verifierPackageName.equals(
@@ -3102,7 +3132,9 @@
         synchronized (mPm.mInstallLock) {
             final AndroidPackage pkg;
             try (PackageFreezer freezer =
-                         mPm.freezePackage(stubPkg.getPackageName(), "setEnabledSetting")) {
+                         mPm.freezePackage(stubPkg.getPackageName(), UserHandle.USER_ALL,
+                                 "setEnabledSetting",
+                                 ApplicationExitInfo.REASON_PACKAGE_UPDATED)) {
                 pkg = installStubPackageLI(stubPkg, parseFlags, 0 /*scanFlags*/);
                 mAppDataHelper.prepareAppDataAfterInstallLIF(pkg);
                 synchronized (mPm.mLock) {
@@ -3124,7 +3156,9 @@
             } catch (PackageManagerException e) {
                 // Whoops! Something went very wrong; roll back to the stub and disable the package
                 try (PackageFreezer freezer =
-                             mPm.freezePackage(stubPkg.getPackageName(), "setEnabledSetting")) {
+                             mPm.freezePackage(stubPkg.getPackageName(), UserHandle.USER_ALL,
+                                     "setEnabledSetting",
+                                     ApplicationExitInfo.REASON_PACKAGE_UPDATED)) {
                     synchronized (mPm.mLock) {
                         // NOTE: Ensure the system package is enabled; even for a compressed stub.
                         // If we don't, installing the system package fails during scan
@@ -4180,8 +4214,8 @@
                         "System package signature mismatch;"
                                 + " name: " + pkgSetting.getPackageName());
                 try (@SuppressWarnings("unused") PackageFreezer freezer = mPm.freezePackage(
-                        parsedPackage.getPackageName(),
-                        "scanPackageInternalLI")) {
+                        parsedPackage.getPackageName(), UserHandle.USER_ALL,
+                        "scanPackageInternalLI", ApplicationExitInfo.REASON_OTHER)) {
                     DeletePackageHelper deletePackageHelper = new DeletePackageHelper(mPm);
                     deletePackageHelper.deletePackageLIF(parsedPackage.getPackageName(), null, true,
                             mPm.mUserManager.getUserIds(), 0, null, false);
@@ -4215,6 +4249,18 @@
             }
         }
 
+        // A new application appeared on /system, and we are seeing it for the first time.
+        // Its also not updated as we don't have a copy of it on /data. So, scan it in a
+        // STOPPED state. Ignore if it's an APEX package since stopped state does not affect them.
+        final boolean isApexPkg = (scanFlags & SCAN_AS_APEX) != 0;
+        if (mPm.mShouldStopSystemPackagesByDefault && scanSystemPartition
+                && !pkgAlreadyExists && !isApexPkg) {
+            String packageName = parsedPackage.getPackageName();
+            if (!mPm.mInitialNonStoppedSystemPackages.contains(packageName)) {
+                scanFlags |= SCAN_AS_STOPPED_SYSTEM_APP;
+            }
+        }
+
         final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags,
                 scanFlags | SCAN_UPDATE_SIGNATURE, 0 /* currentTime */, user, null);
         return new Pair<>(scanResult, shouldHideSystemApp);
diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java
index 7b759e3..43c0e05 100644
--- a/services/core/java/com/android/server/pm/InstallingSession.java
+++ b/services/core/java/com/android/server/pm/InstallingSession.java
@@ -525,13 +525,13 @@
     }
 
     private void processApkInstallRequests(boolean success, List<InstallRequest> installRequests) {
-        if (success) {
+        if (!success) {
             for (InstallRequest request : installRequests) {
                 if (request.getReturnCode() != PackageManager.INSTALL_SUCCEEDED) {
                     cleanUpForFailedInstall(request);
                 }
             }
-
+        } else {
             mInstallPackageHelper.installPackagesTraced(installRequests);
 
             for (InstallRequest request : installRequests) {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index c5bcddc..6b9be25 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -1116,12 +1116,16 @@
 
             // Flag for bubble
             ActivityOptions options = ActivityOptions.fromBundle(startActivityOptions);
-            if (options != null && options.isApplyActivityFlagsForBubbles()) {
-                // Flag for bubble to make behaviour match documentLaunchMode=always.
-                intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
-                intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+            if (options != null) {
+                if (options.isApplyActivityFlagsForBubbles()) {
+                    // Flag for bubble to make behaviour match documentLaunchMode=always.
+                    intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
+                    intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+                }
+                if (options.isApplyMultipleTaskFlagForShortcut()) {
+                    intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+                }
             }
-
             intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             intents[0].setSourceBounds(sourceBounds);
 
diff --git a/services/core/java/com/android/server/pm/MovePackageHelper.java b/services/core/java/com/android/server/pm/MovePackageHelper.java
index 52adc0d..bec5a9a 100644
--- a/services/core/java/com/android/server/pm/MovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/MovePackageHelper.java
@@ -28,6 +28,7 @@
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
 import static com.android.server.pm.PackageManagerService.TAG;
 
+import android.app.ApplicationExitInfo;
 import android.content.Intent;
 import android.content.pm.IPackageInstallObserver2;
 import android.content.pm.IPackageMoveObserver;
@@ -145,7 +146,8 @@
 
         final PackageFreezer freezer;
         synchronized (mPm.mLock) {
-            freezer = mPm.freezePackage(packageName, "movePackageInternal");
+            freezer = mPm.freezePackage(packageName, UserHandle.USER_ALL,
+                    "movePackageInternal", ApplicationExitInfo.REASON_USER_REQUESTED);
         }
 
         final Bundle extras = new Bundle();
diff --git a/services/core/java/com/android/server/pm/NoFilteringResolver.java b/services/core/java/com/android/server/pm/NoFilteringResolver.java
index 999706a..3923890 100644
--- a/services/core/java/com/android/server/pm/NoFilteringResolver.java
+++ b/services/core/java/com/android/server/pm/NoFilteringResolver.java
@@ -22,8 +22,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Binder;
-import android.provider.DeviceConfig;
 
+import com.android.internal.config.appcloning.AppCloningDeviceConfigHelper;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.resolution.ComponentResolverApi;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
@@ -49,18 +49,19 @@
             "allow_intent_redirection_for_clone_profile";
 
     /**
-     * Returns true if intent redirection for clone profile feature flag is set
-     * and if its query, then check if calling user have necessary permission
+     * Returns true if intent redirection for clone profile feature flag
+     * (enable_app_cloning_building_blocks) is set and if its query,
+     * then check if calling user have necessary permission
      * (android.permission.QUERY_CLONED_APPS) as well as required flag
      * (PackageManager.MATCH_CLONE_PROFILE) bit set.
      * @return true if resolver would be used for cross profile resolution.
      */
     public static boolean isIntentRedirectionAllowed(Context context,
-            boolean resolveForStart, long flags) {
+            AppCloningDeviceConfigHelper appCloningDeviceConfigHelper, boolean resolveForStart,
+            long flags) {
         final long token = Binder.clearCallingIdentity();
         try {
-            return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_APP_CLONING,
-                    FLAG_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE, false /* defaultValue */)
+            return appCloningDeviceConfigHelper.getEnableAppCloningBuildingBlocks()
                     && (resolveForStart || (((flags & PackageManager.MATCH_CLONE_PROFILE) != 0)
                     && hasPermission(context, Manifest.permission.QUERY_CLONED_APPS)));
         } finally {
diff --git a/services/core/java/com/android/server/pm/PackageFreezer.java b/services/core/java/com/android/server/pm/PackageFreezer.java
index 1e0a1f2..841b66e 100644
--- a/services/core/java/com/android/server/pm/PackageFreezer.java
+++ b/services/core/java/com/android/server/pm/PackageFreezer.java
@@ -51,7 +51,7 @@
     }
 
     PackageFreezer(String packageName, int userId, String killReason,
-            PackageManagerService pm) {
+            PackageManagerService pm, int exitInfoReason) {
         mPm = pm;
         mPackageName = packageName;
         final PackageSetting ps;
@@ -62,7 +62,8 @@
             ps = mPm.mSettings.getPackageLPr(mPackageName);
         }
         if (ps != null) {
-            mPm.killApplication(ps.getPackageName(), ps.getAppId(), userId, killReason);
+            mPm.killApplication(ps.getPackageName(), ps.getAppId(), userId, killReason,
+                    exitInfoReason);
         }
         mCloseGuard.open("close");
     }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 239853c..8823714 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -28,6 +28,7 @@
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PackageDeleteObserver;
@@ -184,6 +185,7 @@
     private volatile boolean mOkToSendBroadcasts = false;
     private volatile boolean mBypassNextStagedInstallerCheck = false;
     private volatile boolean mBypassNextAllowedApexUpdateCheck = false;
+    private volatile int mDisableVerificationForUid = INVALID_UID;
 
     /**
      * File storing persisted {@link #mSessions} metadata.
@@ -662,7 +664,7 @@
                 && params.installerPackageName.length() < SessionParams.MAX_PACKAGE_NAME_LENGTH)
                 ? params.installerPackageName : installerPackageName;
 
-        if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)
+        if (PackageManagerServiceUtils.isRootOrShell(callingUid)
                 || PackageInstallerSession.isSystemDataLoaderInstallation(params)) {
             params.installFlags |= PackageManager.INSTALL_FROM_ADB;
             // adb installs can override the installingPackageName, but not the
@@ -705,14 +707,23 @@
             }
         }
 
-        if (Build.IS_DEBUGGABLE || isCalledBySystemOrShell(callingUid)) {
+        if (Build.IS_DEBUGGABLE || PackageManagerServiceUtils.isSystemOrRoot(callingUid)) {
             params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
         } else {
             params.installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE;
             params.installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
         }
 
-        if ((params.installFlags & ADB_DEV_MODE) != ADB_DEV_MODE) {
+        if (mDisableVerificationForUid != INVALID_UID) {
+            if (callingUid == mDisableVerificationForUid) {
+                params.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
+            } else {
+                // Clear the flag if current calling uid doesn't match the requested uid.
+                params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION;
+            }
+            // Reset the field as this is a one-off request.
+            mDisableVerificationForUid = INVALID_UID;
+        } else if ((params.installFlags & ADB_DEV_MODE) != ADB_DEV_MODE) {
             // Only tools under specific conditions (test app installed through ADB, and
             // verification disabled flag specified) can disable verification.
             params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION;
@@ -738,7 +749,8 @@
             if (params.isMultiPackage) {
                 throw new IllegalArgumentException("A multi-session can't be set as APEX.");
             }
-            if (isCalledBySystemOrShell(callingUid) || mBypassNextAllowedApexUpdateCheck) {
+            if (PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)
+                    || mBypassNextAllowedApexUpdateCheck) {
                 params.installFlags |= PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK;
             } else {
                 // Only specific APEX updates (installed through ADB, or for CTS tests) can disable
@@ -748,20 +760,20 @@
         }
 
         if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0
-                && !isCalledBySystemOrShell(callingUid)
+                && !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)
                 && (snapshot.getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM)
                 == 0) {
             throw new SecurityException(
                     "Only system apps could use the PackageManager.INSTALL_INSTANT_APP flag.");
         }
 
-        if (params.isStaged && !isCalledBySystemOrShell(callingUid)) {
+        if (params.isStaged && !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)) {
             if (!mBypassNextStagedInstallerCheck
                     && !isStagedInstallerAllowed(requestedInstallerPackageName)) {
                 throw new SecurityException("Installer not allowed to commit staged install");
             }
         }
-        if (isApex && !isCalledBySystemOrShell(callingUid)) {
+        if (isApex && !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)) {
             if (!mBypassNextStagedInstallerCheck
                     && !isStagedInstallerAllowed(requestedInstallerPackageName)) {
                 throw new SecurityException(
@@ -864,7 +876,7 @@
 
         // reset the force queryable param if it's not called by an approved caller.
         if (params.forceQueryableOverride) {
-            if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
+            if (!PackageManagerServiceUtils.isRootOrShell(callingUid)) {
                 params.forceQueryableOverride = false;
             }
         }
@@ -906,11 +918,6 @@
         return sessionId;
     }
 
-    private boolean isCalledBySystemOrShell(int callingUid) {
-        return callingUid == Process.SYSTEM_UID || callingUid == Process.ROOT_UID
-                || callingUid == Process.SHELL_UID;
-    }
-
     private boolean isStagedInstallerAllowed(String installerName) {
         return SystemConfig.getInstance().getWhitelistedStagedInstallers().contains(installerName);
     }
@@ -1175,7 +1182,7 @@
         final Computer snapshot = mPm.snapshotComputer();
         final int callingUid = Binder.getCallingUid();
         snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
-        if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) {
+        if (!PackageManagerServiceUtils.isRootOrShell(callingUid)) {
             mAppOps.checkPackage(callingUid, callerPackageName);
         }
 
@@ -1229,7 +1236,7 @@
         mContext.enforceCallingOrSelfPermission(Manifest.permission.DELETE_PACKAGES, null);
         final Computer snapshot = mPm.snapshotComputer();
         snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
-        if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) {
+        if (!PackageManagerServiceUtils.isRootOrShell(callingUid)) {
             mAppOps.checkPackage(callingUid, callerPackageName);
         }
 
@@ -1266,7 +1273,7 @@
 
         final var snapshot = mPm.snapshotComputer();
         final int callingUid = Binder.getCallingUid();
-        if (!isCalledBySystemOrShell(callingUid)) {
+        if (!PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)) {
             for (var packageName : packageNames) {
                 var ps = snapshot.getPackageStateInternal(packageName);
                 if (ps == null || !TextUtils.equals(
@@ -1308,7 +1315,10 @@
             intent.putExtra(PackageInstaller.EXTRA_INSTALL_CONSTRAINTS, constraints);
             intent.putExtra(PackageInstaller.EXTRA_INSTALL_CONSTRAINTS_RESULT, result);
             try {
-                callback.sendIntent(mContext, 0, intent, null, null);
+                final BroadcastOptions options = BroadcastOptions.makeBasic();
+                options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+                callback.sendIntent(mContext, 0, intent, null /* onFinished*/,
+                        null /* handler */, null /* requiredPermission */, options.toBundle());
             } catch (SendIntentException ignore) {
             }
         });
@@ -1353,7 +1363,7 @@
 
     @Override
     public void bypassNextStagedInstallerCheck(boolean value) {
-        if (!isCalledBySystemOrShell(Binder.getCallingUid())) {
+        if (!PackageManagerServiceUtils.isSystemOrRootOrShell(Binder.getCallingUid())) {
             throw new SecurityException("Caller not allowed to bypass staged installer check");
         }
         mBypassNextStagedInstallerCheck = value;
@@ -1361,18 +1371,26 @@
 
     @Override
     public void bypassNextAllowedApexUpdateCheck(boolean value) {
-        if (!isCalledBySystemOrShell(Binder.getCallingUid())) {
+        if (!PackageManagerServiceUtils.isSystemOrRootOrShell(Binder.getCallingUid())) {
             throw new SecurityException("Caller not allowed to bypass allowed apex update check");
         }
         mBypassNextAllowedApexUpdateCheck = value;
     }
 
+    @Override
+    public void disableVerificationForUid(int uid) {
+        if (!PackageManagerServiceUtils.isSystemOrRootOrShell(Binder.getCallingUid())) {
+            throw new SecurityException("Operation not allowed for caller");
+        }
+        mDisableVerificationForUid = uid;
+    }
+
     /**
      * Set an installer to allow for the unlimited silent updates.
      */
     @Override
     public void setAllowUnlimitedSilentUpdates(@Nullable String installerPackageName) {
-        if (!isCalledBySystemOrShell(Binder.getCallingUid())) {
+        if (!PackageManagerServiceUtils.isSystemOrRootOrShell(Binder.getCallingUid())) {
             throw new SecurityException("Caller not allowed to unlimite silent updates");
         }
         mSilentUpdatePolicy.setAllowUnlimitedSilentUpdates(installerPackageName);
@@ -1383,7 +1401,7 @@
      */
     @Override
     public void setSilentUpdatesThrottleTime(long throttleTimeInSeconds) {
-        if (!isCalledBySystemOrShell(Binder.getCallingUid())) {
+        if (!PackageManagerServiceUtils.isSystemOrRootOrShell(Binder.getCallingUid())) {
             throw new SecurityException("Caller not allowed to set silent updates throttle time");
         }
         mSilentUpdatePolicy.setSilentUpdatesThrottleTime(throttleTimeInSeconds);
@@ -1463,7 +1481,10 @@
                     PackageInstaller.STATUS_PENDING_USER_ACTION);
             fillIn.putExtra(Intent.EXTRA_INTENT, intent);
             try {
-                mTarget.sendIntent(mContext, 0, fillIn, null, null);
+                final BroadcastOptions options = BroadcastOptions.makeBasic();
+                options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+                mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/,
+                        null /* handler */, null /* requiredPermission */, options.toBundle());
             } catch (SendIntentException ignored) {
             }
         }
@@ -1488,7 +1509,10 @@
                     PackageManager.deleteStatusToString(returnCode, msg));
             fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
             try {
-                mTarget.sendIntent(mContext, 0, fillIn, null, null);
+                final BroadcastOptions options = BroadcastOptions.makeBasic();
+                options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+                mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/,
+                        null /* handler */, null /* requiredPermission */, options.toBundle());
             } catch (SendIntentException ignored) {
             }
         }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 47e18f1..e5e87af 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -59,6 +59,7 @@
 import android.annotation.Nullable;
 import android.annotation.WorkerThread;
 import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.admin.DevicePolicyEventLogger;
@@ -1520,7 +1521,10 @@
     public ParcelFileDescriptor getAppMetadataFd() {
         assertCallerIsOwnerOrRoot();
         synchronized (mLock) {
-            assertPreparedAndNotCommittedOrDestroyedLocked("openRead");
+            assertPreparedAndNotCommittedOrDestroyedLocked("getAppMetadataFd");
+            if (getStagedAppMetadataFile() == null) {
+                return null;
+            }
             try {
                 return openReadInternalLocked(APP_METADATA_FILE_NAME);
             } catch (IOException e) {
@@ -1529,6 +1533,14 @@
         }
     }
 
+    @Override
+    public void removeAppMetadata() {
+        File file = getStagedAppMetadataFile();
+        if (file != null) {
+            file.delete();
+        }
+    }
+
     private static long getAppMetadataSizeLimit() {
         final long token = Binder.clearCallingIdentity();
         try {
@@ -3995,7 +4007,14 @@
                 return;
             }
         }
-        r.run();
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            // This will call into StagingManager which might trigger external callbacks
+            r.run();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -4495,8 +4514,10 @@
         intent.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_SUCCESS);
         intent.putExtra(PackageInstaller.EXTRA_PRE_APPROVAL, true);
         try {
+            final BroadcastOptions options = BroadcastOptions.makeBasic();
+            options.setPendingIntentBackgroundActivityLaunchAllowed(false);
             target.sendIntent(mContext, 0 /* code */, intent, null /* onFinished */,
-                    null /* handler */);
+                    null /* handler */, null /* requiredPermission */, options.toBundle());
         } catch (IntentSender.SendIntentException ignored) {
         }
     }
@@ -4763,7 +4784,10 @@
                 PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL.equals(intent.getAction()));
         fillIn.putExtra(Intent.EXTRA_INTENT, intent);
         try {
-            target.sendIntent(context, 0, fillIn, null, null);
+            final BroadcastOptions options = BroadcastOptions.makeBasic();
+            options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+            target.sendIntent(context, 0, fillIn, null /* onFinished */,
+                    null /* handler */, null /* requiredPermission */, options.toBundle());
         } catch (IntentSender.SendIntentException ignored) {
         }
     }
@@ -4805,7 +4829,10 @@
             }
         }
         try {
-            target.sendIntent(context, 0, fillIn, null, null);
+            final BroadcastOptions options = BroadcastOptions.makeBasic();
+            options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+            target.sendIntent(context, 0, fillIn, null /* onFinished */,
+                    null /* handler */, null /* requiredPermission */, options.toBundle());
         } catch (IntentSender.SendIntentException ignored) {
         }
     }
@@ -4839,7 +4866,10 @@
             intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready");
         }
         try {
-            target.sendIntent(context, 0, intent, null, null);
+            final BroadcastOptions options = BroadcastOptions.makeBasic();
+            options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+            target.sendIntent(context, 0, intent, null /* onFinished */,
+                    null /* handler */, null /* requiredPermission */, options.toBundle());
         } catch (IntentSender.SendIntentException ignored) {
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 620ee37..97ee3c5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -55,7 +55,9 @@
 import android.annotation.WorkerThread;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
+import android.app.ApplicationExitInfo;
 import android.app.ApplicationPackageManager;
+import android.app.BroadcastOptions;
 import android.app.IActivityManager;
 import android.app.admin.IDevicePolicyManager;
 import android.app.admin.SecurityLog;
@@ -387,6 +389,7 @@
     static final int SCAN_DROP_CACHE = 1 << 24;
     static final int SCAN_AS_FACTORY = 1 << 25;
     static final int SCAN_AS_APEX = 1 << 26;
+    static final int SCAN_AS_STOPPED_SYSTEM_APP = 1 << 27;
 
     @IntDef(flag = true, prefix = { "SCAN_" }, value = {
             SCAN_NO_DEX,
@@ -403,6 +406,7 @@
             SCAN_AS_INSTANT_APP,
             SCAN_AS_FULL_APP,
             SCAN_AS_VIRTUAL_PRELOAD,
+            SCAN_AS_STOPPED_SYSTEM_APP,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ScanFlags {}
@@ -964,6 +968,8 @@
     final @Nullable String mRecentsPackage;
     final @Nullable String mAmbientContextDetectionPackage;
     final @Nullable String mWearableSensingPackage;
+    final @NonNull Set<String> mInitialNonStoppedSystemPackages;
+    final boolean mShouldStopSystemPackagesByDefault;
     private final @NonNull String mRequiredSdkSandboxPackage;
 
     @GuardedBy("mLock")
@@ -1771,6 +1777,8 @@
         mOverlayConfigSignaturePackage = testParams.overlayConfigSignaturePackage;
         mResolveComponentName = testParams.resolveComponentName;
         mRequiredSdkSandboxPackage = testParams.requiredSdkSandboxPackage;
+        mInitialNonStoppedSystemPackages = testParams.initialNonStoppedSystemPackages;
+        mShouldStopSystemPackagesByDefault = testParams.shouldStopSystemPackagesByDefault;
 
         mLiveComputer = createLiveComputer();
         mSnapshotStatistics = null;
@@ -2097,6 +2105,11 @@
             mCacheDir = PackageManagerServiceUtils.preparePackageParserCache(
                     mIsEngBuild, mIsUserDebugBuild, mIncrementalVersion);
 
+            mInitialNonStoppedSystemPackages = mInjector.getSystemConfig()
+                    .getInitialNonStoppedSystemPackages();
+            mShouldStopSystemPackagesByDefault = mContext.getResources()
+                    .getBoolean(R.bool.config_stopSystemPackagesByDefault);
+
             final int[] userIds = mUserManager.getUserIds();
             PackageParser2 packageParser = mInjector.getScanningCachingPackageParser();
             mOverlayConfig = mInitAppsHelper.initSystemApps(packageParser, packageSettings, userIds,
@@ -3038,12 +3051,12 @@
         onChanged();
     }
 
-    void killApplication(String pkgName, @AppIdInt int appId, String reason) {
-        killApplication(pkgName, appId, UserHandle.USER_ALL, reason);
+    void killApplication(String pkgName, @AppIdInt int appId, String reason, int exitInfoReason) {
+        killApplication(pkgName, appId, UserHandle.USER_ALL, reason, exitInfoReason);
     }
 
     void killApplication(String pkgName, @AppIdInt int appId,
-            @UserIdInt int userId, String reason) {
+            @UserIdInt int userId, String reason, int exitInfoReason) {
         // Request the ActivityManager to kill the process(only for existing packages)
         // so that we do not end up in a confused state while the user is still using the older
         // version of the application while the new one gets installed.
@@ -3052,7 +3065,7 @@
             IActivityManager am = ActivityManager.getService();
             if (am != null) {
                 try {
-                    am.killApplication(pkgName, appId, userId, reason);
+                    am.killApplication(pkgName, appId, userId, reason, exitInfoReason);
                 } catch (RemoteException e) {
                 }
             }
@@ -3201,7 +3214,7 @@
         mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
                 callingMethod);
 
-        if (callingUid != Process.ROOT_UID && callingUid != Process.SYSTEM_UID
+        if (!PackageManagerServiceUtils.isSystemOrRoot(callingUid)
                 && UserHandle.getUserId(callingUid) != userId) {
             throw new SecurityException("Calling uid " + callingUid + " cannot call for user "
                     + userId);
@@ -4326,25 +4339,17 @@
         }
     }
 
-    public PackageFreezer freezePackage(String packageName, String killReason) {
-        return freezePackage(packageName, UserHandle.USER_ALL, killReason);
-    }
-
-    public PackageFreezer freezePackage(String packageName, int userId, String killReason) {
-        return new PackageFreezer(packageName, userId, killReason, this);
-    }
-
-    public PackageFreezer freezePackageForDelete(String packageName, int deleteFlags,
-            String killReason) {
-        return freezePackageForDelete(packageName, UserHandle.USER_ALL, deleteFlags, killReason);
+    public PackageFreezer freezePackage(String packageName, int userId, String killReason,
+            int exitInfoReason) {
+        return new PackageFreezer(packageName, userId, killReason, this, exitInfoReason);
     }
 
     public PackageFreezer freezePackageForDelete(String packageName, int userId, int deleteFlags,
-            String killReason) {
+            String killReason, int exitInfoReason) {
         if ((deleteFlags & PackageManager.DELETE_DONT_KILL_APP) != 0) {
             return new PackageFreezer(this);
         } else {
-            return freezePackage(packageName, userId, killReason);
+            return freezePackage(packageName, userId, killReason, exitInfoReason);
         }
     }
 
@@ -4648,7 +4653,9 @@
             final Computer snapshot = snapshotComputer();
             final AndroidPackage pkg = snapshot.getPackage(packageName);
             try (PackageFreezer ignored =
-                            freezePackage(packageName, "clearApplicationProfileData")) {
+                            freezePackage(packageName, UserHandle.USER_ALL,
+                                    "clearApplicationProfileData",
+                                    ApplicationExitInfo.REASON_OTHER)) {
                 synchronized (mInstallLock) {
                     mAppDataHelper.clearAppProfilesLIF(pkg);
                 }
@@ -4689,8 +4696,9 @@
                 public void run() {
                     mHandler.removeCallbacks(this);
                     final boolean succeeded;
-                    try (PackageFreezer freezer = freezePackage(packageName,
-                            "clearApplicationUserData")) {
+                    try (PackageFreezer freezer = freezePackage(packageName, UserHandle.USER_ALL,
+                            "clearApplicationUserData",
+                            ApplicationExitInfo.REASON_USER_REQUESTED)) {
                         synchronized (mInstallLock) {
                             succeeded = clearApplicationUserDataLIF(snapshotComputer(), packageName,
                                     userId);
@@ -4937,7 +4945,11 @@
                 }
                 if (pi != null) {
                     try {
-                        pi.sendIntent(null, success ? 1 : 0, null, null, null);
+                        final BroadcastOptions options = BroadcastOptions.makeBasic();
+                        options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+                        pi.sendIntent(null, success ? 1 : 0, null /* intent */,
+                                null /* onFinished*/, null /* handler */,
+                                null /* requiredPermission */, options.toBundle());
                     } catch (SendIntentException e) {
                         Slog.w(TAG, e);
                     }
@@ -5312,7 +5324,7 @@
             snapshot.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
                     true /*checkShell*/, "isPackageStateProtected");
 
-            if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.ROOT_UID
+            if (!PackageManagerServiceUtils.isSystemOrRoot(callingAppId)
                     && snapshot.checkUidPermission(MANAGE_DEVICE_ADMINS, callingUid)
                     != PERMISSION_GRANTED) {
                 throw new SecurityException("Caller must have the "
@@ -5760,7 +5772,8 @@
                         newSnapshot.getPackageStateInternal(packageName);
 
                 if (hidden) {
-                    killApplication(packageName, newPackageState.getAppId(), userId, "hiding pkg");
+                    killApplication(packageName, newPackageState.getAppId(), userId, "hiding pkg",
+                            ApplicationExitInfo.REASON_OTHER);
                     sendApplicationHiddenForUser(packageName, newPackageState, userId);
                 } else {
                     sendPackageAddedForUser(newSnapshot, packageName, newPackageState, userId,
@@ -5847,8 +5860,8 @@
             snapshot.enforceCrossUserPermission(callingUid, userId, true /*requireFullPermission*/,
                     true /*checkShell*/, "setHarmfulAppInfo");
 
-            if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.ROOT_UID &&
-                    snapshot.checkUidPermission(SET_HARMFUL_APP_WARNINGS, callingUid)
+            if (!PackageManagerServiceUtils.isSystemOrRoot(callingAppId)
+                    && snapshot.checkUidPermission(SET_HARMFUL_APP_WARNINGS, callingUid)
                             != PERMISSION_GRANTED) {
                 throw new SecurityException("Caller must have the "
                         + SET_HARMFUL_APP_WARNINGS + " permission.");
@@ -6205,8 +6218,12 @@
             mHandler.post(() -> {
                 final int id = verificationId >= 0 ? verificationId : -verificationId;
                 final PackageVerificationState state = mPendingVerification.get(id);
-                if (state == null || !state.checkRequiredVerifierUid(callingUid)) {
-                    // Only allow calls from required verifiers.
+                if (state == null) {
+                    return;
+                }
+                if (!state.checkRequiredVerifierUid(callingUid)
+                        && !state.checkSufficientVerifierUid(callingUid)) {
+                    // Only allow calls from verifiers.
                     return;
                 }
 
@@ -6598,7 +6615,7 @@
         public void uninstallApex(String packageName, long versionCode, int userId,
                 IntentSender intentSender, int flags) {
             final int callerUid = Binder.getCallingUid();
-            if (callerUid != Process.ROOT_UID && callerUid != Process.SHELL_UID) {
+            if (!PackageManagerServiceUtils.isRootOrShell(callerUid)) {
                 throw new SecurityException("Not allowed to uninstall apexes");
             }
             PackageInstallerService.PackageDeleteObserverAdapter adapter =
@@ -6643,7 +6660,7 @@
             final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
             final String[] callerPackageNames = snapshot.getPackagesForUid(callingUid);
-            if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID
+            if (!PackageManagerServiceUtils.isRootOrShell(callingUid)
                     && !ArrayUtils.contains(callerPackageNames, packageName)) {
                 throw new SecurityException("dumpProfiles");
             }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index e5cfa67..0ed90e4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -26,6 +26,7 @@
 import android.os.Handler;
 import android.os.incremental.IncrementalManager;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.DisplayMetrics;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -40,6 +41,7 @@
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
 public final class PackageManagerServiceTestParams {
@@ -119,4 +121,6 @@
     public SuspendPackageHelper suspendPackageHelper;
     public DistractingPackageHelper distractingPackageHelper;
     public StorageEventHelper storageEventHelper;
+    public Set<String> initialNonStoppedSystemPackages = new ArraySet<>();
+    public boolean shouldStopSystemPackagesByDefault;
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index b919330..928ffa7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -1372,10 +1372,24 @@
      */
     public static boolean isSystemOrRoot() {
         final int uid = Binder.getCallingUid();
+        return isSystemOrRoot(uid);
+    }
+
+    /**
+     * Check if a UID is system UID or root's UID.
+     */
+    public static boolean isSystemOrRoot(int uid) {
         return uid == Process.SYSTEM_UID || uid == Process.ROOT_UID;
     }
 
     /**
+     * Check if a UID is system UID or shell's UID.
+     */
+    public static boolean isRootOrShell(int uid) {
+        return uid == Process.ROOT_UID || uid == Process.SHELL_UID;
+    }
+
+    /**
      * Enforces that only the system UID or root's UID can call a method exposed
      * via Binder.
      *
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 4263791..5cfe6de 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -344,6 +344,8 @@
                     return runBypassStagedInstallerCheck();
                 case "bypass-allowed-apex-update-check":
                     return runBypassAllowedApexUpdateCheck();
+                case "disable-verification-for-uid":
+                    return runDisableVerificationForUid();
                 case "set-silent-updates-policy":
                     return runSetSilentUpdatesPolicy();
                 default: {
@@ -516,6 +518,29 @@
         }
     }
 
+    private int runDisableVerificationForUid() {
+        final PrintWriter pw = getOutPrintWriter();
+        try {
+            int uid = Integer.parseInt(getNextArgRequired());
+            var amInternal = LocalServices.getService(ActivityManagerInternal.class);
+            boolean isInstrumented =
+                    amInternal.getInstrumentationSourceUid(uid) != Process.INVALID_UID;
+            if (isInstrumented) {
+                mInterface.getPackageInstaller().disableVerificationForUid(uid);
+                return 0;
+            } else {
+                // Only available for testing
+                pw.println("Error: must specify an instrumented uid");
+                return -1;
+            }
+        } catch (RemoteException e) {
+            pw.println("Failure ["
+                    + e.getClass().getName() + " - "
+                    + e.getMessage() + "]");
+            return -1;
+        }
+    }
+
     private int uninstallSystemUpdates(String packageName) {
         final PrintWriter pw = getOutPrintWriter();
         boolean failedUninstalls = false;
@@ -3044,7 +3069,7 @@
                 getOutPrintWriter().printf("Success: user %d is already being removed\n", userId);
                 return 0;
             case UserManager.REMOVE_RESULT_ERROR_MAIN_USER_PERMANENT_ADMIN:
-                getOutPrintWriter().printf("Error: user %d is a permanent admin main user\n",
+                getErrPrintWriter().printf("Error: user %d is a permanent admin main user\n",
                         userId);
                 return 1;
             default:
@@ -3098,12 +3123,7 @@
                 translateUserId(userId, UserHandle.USER_NULL, "runSetUserRestriction");
         final IUserManager um = IUserManager.Stub.asInterface(
                 ServiceManager.getService(Context.USER_SERVICE));
-        try {
-            um.setUserRestriction(restriction, value, translatedUserId);
-        } catch (IllegalArgumentException e) {
-            getErrPrintWriter().println(e.getMessage());
-            return 1;
-        }
+        um.setUserRestriction(restriction, value, translatedUserId);
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index d4c1256..c4ad20e 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -41,7 +41,7 @@
 import java.util.stream.Stream;
 
 /**
- * Metrics class for reporting stats to logging infrastructures like Westworld
+ * Metrics class for reporting stats to logging infrastructures like statsd
  */
 final class PackageMetrics {
     public static final int STEP_PREPARE = 1;
diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java
index 8acdb0e..929bc1e 100644
--- a/services/core/java/com/android/server/pm/PackageVerificationState.java
+++ b/services/core/java/com/android/server/pm/PackageVerificationState.java
@@ -83,6 +83,11 @@
         mSufficientVerifierUids.put(uid, true);
     }
 
+    /** Returns true if the uid a sufficient verifier. */
+    boolean checkSufficientVerifierUid(int uid) {
+        return mSufficientVerifierUids.get(uid, false);
+    }
+
     /**
      * Should be called when a verification is received from an agent so the state of the package
      * verification can be tracked.
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index 830b096c..2538871 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -31,6 +31,7 @@
 import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT;
+import static com.android.server.pm.PackageManagerService.SCAN_AS_STOPPED_SYSTEM_APP;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR;
@@ -198,6 +199,7 @@
         if (createNewPackage) {
             final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
             final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0;
+            final boolean isStoppedSystemApp = (scanFlags & SCAN_AS_STOPPED_SYSTEM_APP) != 0;
 
             // Flags contain system values stored in the server variant of AndroidPackage,
             // and so the server-side PackageInfoUtils is still called, even without a
@@ -212,7 +214,7 @@
                     AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),
                     AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
                     parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user,
-                    true /*allowInstall*/, instantApp, virtualPreload,
+                    true /*allowInstall*/, instantApp, virtualPreload, isStoppedSystemApp,
                     UserManagerService.getInstance(), usesSdkLibraries,
                     parsedPackage.getUsesSdkLibrariesVersionsMajor(), usesStaticLibraries,
                     parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 165e476..7e7205d 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -89,7 +89,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BackgroundThread;
-import com.android.internal.security.VerityUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.IndentingPrintWriter;
@@ -121,6 +120,7 @@
 import com.android.server.pm.verify.domain.DomainVerificationLegacySettings;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 import com.android.server.pm.verify.domain.DomainVerificationPersistence;
+import com.android.server.security.FileIntegrity;
 import com.android.server.utils.Slogf;
 import com.android.server.utils.Snappable;
 import com.android.server.utils.SnapshotCache;
@@ -1041,7 +1041,7 @@
             File codePath, String legacyNativeLibraryPath, String primaryCpuAbi,
             String secondaryCpuAbi, long versionCode, int pkgFlags, int pkgPrivateFlags,
             UserHandle installUser, boolean allowInstall, boolean instantApp,
-            boolean virtualPreload, UserManagerService userManager,
+            boolean virtualPreload, boolean isStoppedSystemApp, UserManagerService userManager,
             String[] usesSdkLibraries, long[] usesSdkLibrariesVersions,
             String[] usesStaticLibraries, long[] usesStaticLibrariesVersions,
             Set<String> mimeGroupNames, @NonNull UUID domainSetId) {
@@ -1068,6 +1068,9 @@
             pkgSetting.setFlags(pkgFlags)
                     .setPrivateFlags(pkgPrivateFlags);
         } else {
+            int installUserId = installUser != null ? installUser.getIdentifier()
+                    : UserHandle.USER_SYSTEM;
+
             pkgSetting = new PackageSetting(pkgName, realPkgName, codePath,
                     legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
                     null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
@@ -1086,8 +1089,6 @@
                     Slog.i(PackageManagerService.TAG, "Stopping package " + pkgName, e);
                 }
                 List<UserInfo> users = getAllUsers(userManager);
-                int installUserId = installUser != null ? installUser.getIdentifier()
-                        : UserHandle.USER_SYSTEM;
                 if (users != null && allowInstall) {
                     for (UserInfo user : users) {
                         // By default we consider this app to be installed
@@ -1126,6 +1127,13 @@
                         );
                     }
                 }
+            } else if (isStoppedSystemApp) {
+                if (DEBUG_STOPPED) {
+                    RuntimeException e = new RuntimeException("here");
+                    e.fillInStackTrace();
+                    Slog.i(PackageManagerService.TAG, "Stopping system package " + pkgName, e);
+                }
+                pkgSetting.setStopped(true, installUserId);
             }
             if (sharedUser != null) {
                 pkgSetting.setAppId(sharedUser.mAppId);
@@ -2706,8 +2714,8 @@
             }
 
             try {
-                VerityUtils.setUpFsverity(mSettingsFilename.getAbsolutePath());
-                VerityUtils.setUpFsverity(mSettingsReserveCopyFilename.getAbsolutePath());
+                FileIntegrity.setUpFsVerity(mSettingsFilename);
+                FileIntegrity.setUpFsVerity(mSettingsReserveCopyFilename);
             } catch (IOException e) {
                 Slog.e(TAG, "Failed to verity-protect settings", e);
             }
@@ -4422,6 +4430,15 @@
                                 ps.getPackageName()));
                 // Only system apps are initially installed.
                 ps.setInstalled(shouldReallyInstall, userHandle);
+
+                // Non-Apex system apps, that are not included in the allowlist in
+                // initialNonStoppedSystemPackages, should be marked as stopped by default.
+                final boolean shouldBeStopped = service.mShouldStopSystemPackagesByDefault
+                        && ps.isSystem()
+                        && !ps.isApex()
+                        && !service.mInitialNonStoppedSystemPackages.contains(ps.getPackageName());
+                ps.setStopped(shouldBeStopped, userHandle);
+
                 // If userTypeInstallablePackages is the *only* reason why we're not installing,
                 // then uninstallReason is USER_TYPE. If there's a different reason, or if we
                 // actually are installing, put UNKNOWN.
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 0362ddd..6d5e2b0 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -885,7 +885,12 @@
      * available ShareTarget definitions in this package.
      */
     public List<ShortcutManager.ShareShortcutInfo> getMatchingShareTargets(
-            @NonNull IntentFilter filter) {
+            @NonNull final IntentFilter filter) {
+        return getMatchingShareTargets(filter, null);
+    }
+
+    List<ShortcutManager.ShareShortcutInfo> getMatchingShareTargets(
+            @NonNull final IntentFilter filter, @Nullable final String pkgName) {
         synchronized (mLock) {
             final List<ShareTargetInfo> matchedTargets = new ArrayList<>();
             for (int i = 0; i < mShareTargets.size(); i++) {
@@ -909,8 +914,7 @@
             // included in the result
             findAll(shortcuts, ShortcutInfo::isNonManifestVisible,
                     ShortcutInfo.CLONE_REMOVE_FOR_APP_PREDICTION,
-                    mShortcutUser.mService.mContext.getPackageName(),
-                    0, /*getPinnedByAnyLauncher=*/ false);
+                    pkgName, 0, /*getPinnedByAnyLauncher=*/ false);
 
             final List<ShortcutManager.ShareShortcutInfo> result = new ArrayList<>();
             for (int i = 0; i < shortcuts.size(); i++) {
@@ -1108,7 +1112,7 @@
 
         // Now prepare to publish manifest shortcuts.
         List<ShortcutInfo> newManifestShortcutList = null;
-        final int shareTargetSize;
+        int shareTargetSize = 0;
         synchronized (mLock) {
             try {
                 shareTargetSize = mShareTargets.size();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 83720f1..1cd9ec6 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2512,11 +2512,17 @@
         }
         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();
         synchronized (mLock) {
             throwIfUserLockedL(userId);
             final List<ShortcutManager.ShareShortcutInfo> shortcutInfoList = new ArrayList<>();
             final ShortcutUser user = getUserShortcutsLocked(userId);
-            user.forAllPackages(p -> shortcutInfoList.addAll(p.getMatchingShareTargets(filter)));
+            user.forAllPackages(p -> shortcutInfoList.addAll(
+                    p.getMatchingShareTargets(filter, pkg)));
             return new ParceledListSlice<>(shortcutInfoList);
         }
     }
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index 23156d1..7684a49 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -27,6 +27,7 @@
 import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
 
 import android.annotation.NonNull;
+import android.app.ApplicationExitInfo;
 import android.app.ResourcesManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackagePartitions;
@@ -153,7 +154,8 @@
         }
 
         for (PackageStateInternal ps : packages) {
-            freezers.add(mPm.freezePackage(ps.getPackageName(), "loadPrivatePackagesInner"));
+            freezers.add(mPm.freezePackage(ps.getPackageName(), UserHandle.USER_ALL,
+                    "loadPrivatePackagesInner", ApplicationExitInfo.REASON_OTHER));
             synchronized (mPm.mInstallLock) {
                 final AndroidPackage pkg;
                 try {
@@ -256,7 +258,8 @@
                     final PackageRemovedInfo outInfo = new PackageRemovedInfo(mPm);
 
                     try (PackageFreezer freezer = mPm.freezePackageForDelete(ps.getPackageName(),
-                            deleteFlags, "unloadPrivatePackagesInner")) {
+                             UserHandle.USER_ALL, deleteFlags,
+                            "unloadPrivatePackagesInner", ApplicationExitInfo.REASON_OTHER)) {
                         if (mDeletePackageHelper.deletePackageLIF(ps.getPackageName(), null, false,
                                 userIds, deleteFlags, outInfo, false)) {
                             unloaded.add(pkg);
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 3c5f309..3cbaebe 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -52,12 +52,14 @@
     // TODO(b/248408342): Move keep annotation to the method referencing these fields reflectively.
     @Keep public static final int USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE = 1;
     @Keep public static final int USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE = 2;
+    @Keep public static final int USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE = 3;
     @Keep public static final int USER_ASSIGNMENT_RESULT_FAILURE = -1;
 
     private static final String PREFIX_USER_ASSIGNMENT_RESULT = "USER_ASSIGNMENT_RESULT_";
     @IntDef(flag = false, prefix = {PREFIX_USER_ASSIGNMENT_RESULT}, value = {
             USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE,
             USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE,
+            USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE,
             USER_ASSIGNMENT_RESULT_FAILURE
     })
     public @interface UserAssignmentResult {}
@@ -526,11 +528,12 @@
      * switched to.
      *
      * <p>Otherwise, in {@link UserManager#isHeadlessSystemUserMode() headless system user mode},
-     * this will be the user who was last in the foreground on this device. If there is no
-     * switchable user on the device, a new user will be created and its id will be returned.
+     * this will be the user who was last in the foreground on this device.
      *
-     * <p>In non-headless system user mode, the return value will be {@link UserHandle#USER_SYSTEM}.
+     * <p>In non-headless system user mode, the return value will be
+     * {@link android.os.UserHandle#USER_SYSTEM}.
+
+     * @throws UserManager.CheckedUserOperationException if no switchable user can be found
      */
-    public abstract @UserIdInt int getBootUser()
-            throws UserManager.CheckedUserOperationException;
+    public abstract @UserIdInt int getBootUser() throws UserManager.CheckedUserOperationException;
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 762d1f6..372b580 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2810,8 +2810,9 @@
         }
 
         if (!userExists(userId)) {
-            throw new IllegalArgumentException("Cannot set user restriction. "
-                    + "User with this id does not exist");
+            Slogf.w(LOG_TAG, "Cannot set user restriction %s. User with id %d does not exist",
+                    key, userId);
+            return;
         }
         synchronized (mRestrictionsLock) {
             // Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create
@@ -5049,6 +5050,8 @@
         //...then external ones
         Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
         addedIntent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        // In HSUM, MainUser might be created before PHASE_ACTIVITY_MANAGER_READY has been sent.
+        addedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
         // Also, add the UserHandle for mainline modules which can't use the @hide
         // EXTRA_USER_HANDLE.
@@ -6758,18 +6761,6 @@
         return mLocalService.isUserInitialized(userId);
     }
 
-    /**
-     * Creates a new user, intended to be the initial user on a device in headless system user mode.
-     */
-    private UserInfo createInitialUserForHsum() throws UserManager.CheckedUserOperationException {
-        final int flags = UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN;
-
-        // Null name will be replaced with "Owner" on-demand to allow for localisation.
-        return createUserInternalUnchecked(/* name= */ null, UserManager.USER_TYPE_FULL_SECONDARY,
-                flags, UserHandle.USER_NULL, /* preCreate= */ false,
-                /* disallowedPackages= */ null, /* token= */ null);
-    }
-
     private class LocalService extends UserManagerInternal {
         @Override
         public void setDevicePolicyUserRestrictions(@UserIdInt int originatingUserId,
@@ -7249,15 +7240,9 @@
                         }
                     }
                 }
-                // No switchable users. Create the initial user.
-                final UserInfo newInitialUser = createInitialUserForHsum();
-                if (newInitialUser == null) {
-                    throw new UserManager.CheckedUserOperationException(
-                            "Initial user creation failed", USER_OPERATION_ERROR_UNKNOWN);
-                }
-                Slogf.i(LOG_TAG,
-                        "No switchable users. Boot user is new user %d", newInitialUser.id);
-                return newInitialUser.id;
+                // No switchable users found. Uh oh!
+                throw new UserManager.CheckedUserOperationException(
+                        "No switchable users found", USER_OPERATION_ERROR_UNKNOWN);
             }
             // Not HSUM, return system user.
             return UserHandle.USER_SYSTEM;
@@ -7437,14 +7422,14 @@
 
     /**
      * Returns true, when user has {@link UserInfo#FLAG_MAIN} and system property
-     * {@link com.android.internal.R.bool.isMainUserPermanentAdmin} is true.
+     * {@link com.android.internal.R.bool#config_isMainUserPermanentAdmin} is true.
      */
     private boolean isNonRemovableMainUser(UserInfo userInfo) {
         return userInfo.isMain() && isMainUserPermanentAdmin();
     }
 
     /**
-     * Returns true, when {@link com.android.internal.R.bool.isMainUserPermanentAdmin} is true.
+     * Returns true if {@link com.android.internal.R.bool#config_isMainUserPermanentAdmin} is true.
      * If the main user is a permanent admin user it can't be deleted
      * or downgraded to non-admin status.
      */
diff --git a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
index 5bdcbb9..eed2a78 100644
--- a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
+++ b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserInfo;
+import android.content.res.Resources;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Process;
@@ -36,6 +37,7 @@
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
 
+import com.android.internal.R;
 import com.android.internal.os.RoSystemProperties;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
@@ -103,6 +105,14 @@
         pw.println();
         pw.println("  is-headless-system-user-mode [-v | --verbose]");
         pw.println("    Checks whether the device uses headless system user mode.");
+        pw.println("  is-visible-background-users-on-default-display-supported [-v | --verbose]");
+        pw.println("    Checks whether the device allows users to be start visible on background "
+                + "in the default display.");
+        pw.println("    It returns the effective mode, even when using emulation");
+        pw.println("    (to get the real mode as well, use -v or --verbose)");
+        pw.println();
+        pw.println("  is-visible-background-users-supported [-v | --verbose]");
+        pw.println("    Checks whether the device allows users to be start visible on background.");
         pw.println("    It returns the effective mode, even when using emulation");
         pw.println("    (to get the real mode as well, use -v or --verbose)");
         pw.println();
@@ -111,6 +121,9 @@
         pw.println("    If the display option is not set, it uses the user's context to check");
         pw.println("    (so it emulates what apps would get from UserManager.isUserVisible())");
         pw.println();
+        pw.println("  get-main-user ");
+        pw.println("    Displays main user id or message if there is no main user");
+        pw.println();
     }
 
     @Override
@@ -129,8 +142,14 @@
                     return runSetSystemUserModeEmulation();
                 case "is-headless-system-user-mode":
                     return runIsHeadlessSystemUserMode();
+                case "is-visible-background-users-supported":
+                    return runIsVisibleBackgroundUserSupported();
+                case "is-visible-background-users-on-default-display-supported":
+                    return runIsVisibleBackgroundUserOnDefaultDisplaySupported();
                 case "is-user-visible":
                     return runIsUserVisible();
+                case "get-main-user":
+                    return runGetMainUserId();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -411,6 +430,7 @@
         } else {
             isVisible = getUserManagerForUser(userId).isUserVisible();
         }
+        // NOTE: do not change output below (or command name / args), as it's used by ITestDevice
         pw.println(isVisible);
         return 0;
     }
@@ -431,19 +451,87 @@
                     return -1;
             }
         }
-
-        boolean isHsum = mService.isHeadlessSystemUserMode();
+        boolean effective = mService.isHeadlessSystemUserMode();
         if (!verbose) {
             // NOTE: do not change output below, as it's used by ITestDevice
             // (it's ok to change the verbose option though)
-            pw.println(isHsum);
+            pw.println(effective);
         } else {
-            pw.printf("effective=%b real=%b\n", isHsum,
+            pw.printf("effective=%b real=%b\n", effective,
                     RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER);
         }
         return 0;
     }
 
+    private int runIsVisibleBackgroundUserSupported() {
+        PrintWriter pw = getOutPrintWriter();
+
+        boolean verbose = false;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-v":
+                case "--verbose":
+                    verbose = true;
+                    break;
+                default:
+                    pw.println("Invalid option: " + opt);
+                    return -1;
+            }
+        }
+
+        boolean effective = UserManager.isVisibleBackgroundUsersEnabled();
+        if (!verbose) {
+            // NOTE: do not change output below, as it's used by ITestDevice
+            // (it's ok to change the verbose option though)
+            pw.println(effective);
+        } else {
+            pw.printf("effective=%b real=%b\n", effective, Resources.getSystem()
+                    .getBoolean(R.bool.config_multiuserVisibleBackgroundUsers));
+        }
+        return 0;
+    }
+
+    private int runIsVisibleBackgroundUserOnDefaultDisplaySupported() {
+        PrintWriter pw = getOutPrintWriter();
+
+        boolean verbose = false;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-v":
+                case "--verbose":
+                    verbose = true;
+                    break;
+                default:
+                    pw.println("Invalid option: " + opt);
+                    return -1;
+            }
+        }
+
+        boolean effective = UserManager.isVisibleBackgroundUsersOnDefaultDisplayEnabled();
+        if (!verbose) {
+            // NOTE: do not change output below, as it's used by ITestDevice
+            // (it's ok to change the verbose option though)
+            pw.println(effective);
+        } else {
+            pw.printf("effective=%b real=%b\n", effective, Resources.getSystem()
+                    .getBoolean(R.bool.config_multiuserVisibleBackgroundUsersOnDefaultDisplay));
+        }
+        return 0;
+    }
+
+    private int runGetMainUserId() {
+        PrintWriter pw = getOutPrintWriter();
+        final int mainUserId = mService.getMainUserId();
+        if (mainUserId == UserHandle.USER_NULL) {
+            pw.println("Couldn't get main user.");
+            return 1;
+        }
+        pw.println("Main user id: " + mainUserId);
+        return 0;
+    }
+
     /**
      * Gets the {@link UserManager} associated with the context of the given user.
      */
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index 77c32ae..4cf8c09 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -121,6 +121,16 @@
                 .setBaseType(FLAG_PROFILE)
                 .setMaxAllowedPerParent(1)
                 .setLabel(0)
+                .setIconBadge(com.android.internal.R.drawable.ic_clone_icon_badge)
+                .setBadgePlain(com.android.internal.R.drawable.ic_clone_badge)
+                // Clone doesn't use BadgeNoBackground, so just set to BadgePlain as a placeholder.
+                .setBadgeNoBackground(com.android.internal.R.drawable.ic_clone_badge)
+                .setBadgeLabels(
+                        com.android.internal.R.string.clone_profile_label_badge)
+                .setBadgeColors(
+                        com.android.internal.R.color.system_neutral2_800)
+                .setDarkThemeBadgeColors(
+                        com.android.internal.R.color.system_neutral2_900)
                 .setDefaultRestrictions(null)
                 .setDefaultCrossProfileIntentFilters(getDefaultCloneCrossProfileIntentFilter())
                 .setDefaultUserProperties(new UserProperties.Builder()
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index 1f935f90..d5cc7ca 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -22,6 +22,7 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
+import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE;
 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
 import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND;
@@ -147,8 +148,7 @@
 
     UserVisibilityMediator(Handler handler) {
         this(UserManager.isVisibleBackgroundUsersEnabled(),
-                // TODO(b/261538232): get visibleBackgroundUserOnDefaultDisplayAllowed from UM
-                /* visibleBackgroundUserOnDefaultDisplayAllowed= */ false, handler);
+                UserManager.isVisibleBackgroundUsersOnDefaultDisplayEnabled(), handler);
     }
 
     @VisibleForTesting
@@ -207,7 +207,8 @@
                 Slogf.d(TAG, "result of getUserVisibilityOnStartLocked(%s)",
                         userAssignmentResultToString(result));
             }
-            if (result == USER_ASSIGNMENT_RESULT_FAILURE) {
+            if (result == USER_ASSIGNMENT_RESULT_FAILURE
+                    || result == USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE) {
                 return result;
             }
 
@@ -278,11 +279,19 @@
         }
 
         boolean visibleBackground = userStartMode == USER_START_MODE_BACKGROUND_VISIBLE;
-        if (displayId == DEFAULT_DISPLAY && visibleBackground
-                && !mVisibleBackgroundUserOnDefaultDisplayAllowed
-                && !isProfile(userId, profileGroupId)) {
-            Slogf.wtf(TAG, "cannot start full user (%d) visible on default display", userId);
-            return USER_ASSIGNMENT_RESULT_FAILURE;
+        if (displayId == DEFAULT_DISPLAY && visibleBackground) {
+            if (mVisibleBackgroundUserOnDefaultDisplayAllowed && isCurrentUserLocked(userId)) {
+                // Shouldn't happen - UserController returns before calling this method
+                Slogf.wtf(TAG, "trying to start current user (%d) visible in background on default"
+                        + " display", userId);
+                return USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE;
+
+            }
+            if (!mVisibleBackgroundUserOnDefaultDisplayAllowed
+                    && !isProfile(userId, profileGroupId)) {
+                Slogf.wtf(TAG, "cannot start full user (%d) visible on default display", userId);
+                return USER_ASSIGNMENT_RESULT_FAILURE;
+            }
         }
 
         boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;
@@ -360,7 +369,7 @@
                 // parent is the current user, as the current user is always assigned to the
                 // DEFAULT_DISPLAY).
                 if (DBG) {
-                    Slogf.d(TAG, "ignoring mapping for default display for user %d starting as %s",
+                    Slogf.d(TAG, "Ignoring mapping for default display for user %d starting as %s",
                             userId, userStartModeToString(userStartMode));
                 }
                 return SECONDARY_DISPLAY_MAPPING_NOT_NEEDED;
@@ -924,6 +933,15 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private boolean isCurrentUserLocked(@UserIdInt int userId) {
+        // Special case as NO_PROFILE_GROUP_ID == USER_NULL
+        if (userId == USER_NULL || mCurrentUserId == USER_NULL) {
+            return false;
+        }
+        return mCurrentUserId == userId;
+    }
+
     private boolean isCurrentUserOrRunningProfileOfCurrentUser(@UserIdInt int userId) {
         synchronized (mLock) {
             // Special case as NO_PROFILE_GROUP_ID == USER_NULL
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index 8ec6241..5b967ec 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -681,12 +681,15 @@
         }
 
         final int installerUid = mVerificationInfo == null ? -1 : mVerificationInfo.mInstallerUid;
+        final boolean requestedDisableVerification =
+                (mInstallFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0;
 
         // Check if installing from ADB
         if ((mInstallFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
-            boolean requestedDisableVerification =
-                    (mInstallFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0;
             return isAdbVerificationEnabled(pkgInfoLite, userId, requestedDisableVerification);
+        } else if (requestedDisableVerification) {
+            // Skip verification for non-adb installs
+            return false;
         }
 
         // only when not installed from ADB, skip verification for instant apps when
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 59256d3..a3be8d3 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -212,7 +212,7 @@
                 }
             }
         }
-        if ((flags & PackageManager.GET_ATTRIBUTIONS) != 0) {
+        if ((flags & PackageManager.GET_ATTRIBUTIONS_LONG) != 0) {
             int size = ArrayUtils.size(pkg.getAttributions());
             if (size > 0) {
                 info.attributions = new Attribution[size];
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 287cc29..42a8cb1 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -51,7 +51,7 @@
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.permission.SplitPermissionInfoParcelable;
-import android.healthconnect.HealthConnectManager;
+import android.health.connect.HealthConnectManager;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Process;
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
index 35c42a3..fac681a 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -943,11 +943,7 @@
                 return false;
             }
 
-            // System apps are never considered stopped for purposes of
-            // filtering, because there may be no way for the user to
-            // actually re-launch them.
-            return !packageState.isSystem()
-                    && packageState.getUserStateOrDefault(userId).isStopped();
+            return packageState.getUserStateOrDefault(userId).isStopped();
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
index 7f733ef..8d7f782 100644
--- a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
+++ b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
@@ -366,12 +366,12 @@
             }
             mListener = listener;
         }
-        notifySupportedStatesChanged();
+        notifySupportedStatesChanged(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED);
         notifyDeviceStateChangedIfNeeded();
     }
 
     /** Notifies the listener that the set of supported device states has changed. */
-    private void notifySupportedStatesChanged() {
+    private void notifySupportedStatesChanged(@SupportedStatesUpdatedReason int reason) {
         List<DeviceState> supportedStates = new ArrayList<>();
         Listener listener;
         synchronized (mLock) {
@@ -390,7 +390,7 @@
         }
 
         listener.onSupportedDeviceStatesChanged(
-                supportedStates.toArray(new DeviceState[supportedStates.size()]));
+                supportedStates.toArray(new DeviceState[supportedStates.size()]), reason);
     }
 
     /** Computes the current device state and notifies the listener of a change, if needed. */
@@ -688,7 +688,10 @@
         if (isThermalStatusCriticalOrAbove != isPreviousThermalStatusCriticalOrAbove) {
             Slog.i(TAG, "Updating supported device states due to thermal status change."
                     + " isThermalStatusCriticalOrAbove: " + isThermalStatusCriticalOrAbove);
-            notifySupportedStatesChanged();
+            notifySupportedStatesChanged(
+                    isThermalStatusCriticalOrAbove
+                            ? SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_CRITICAL
+                            : SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_NORMAL);
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index db939d9..c5258b24 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -334,6 +334,8 @@
     static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
     static public final String SYSTEM_DIALOG_REASON_GESTURE_NAV = "gestureNav";
 
+    public static final String TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD = "waitForAllWindowsDrawn";
+
     private static final String TALKBACK_LABEL = "TalkBack";
 
     private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800;
@@ -522,7 +524,7 @@
     int mDoublePressOnStemPrimaryBehavior;
     int mTriplePressOnStemPrimaryBehavior;
     int mLongPressOnStemPrimaryBehavior;
-    boolean mStylusButtonsDisabled = false;
+    boolean mStylusButtonsEnabled = true;
     boolean mHasSoftInput = false;
     boolean mHapticTextHandleEnabled;
     boolean mUseTvRouting;
@@ -781,7 +783,7 @@
                     Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.STYLUS_BUTTONS_DISABLED), false, this,
+                    Settings.Secure.STYLUS_BUTTONS_ENABLED), false, this,
                     UserHandle.USER_ALL);
             updateSettings();
         }
@@ -2601,9 +2603,9 @@
                     mContext.getResources().getInteger(
                             com.android.internal.R.integer.config_keyChordPowerVolumeUp));
 
-            mStylusButtonsDisabled = Settings.Secure.getIntForUser(resolver,
-                    Secure.STYLUS_BUTTONS_DISABLED, 0, UserHandle.USER_CURRENT) == 1;
-            mInputManagerInternal.setStylusButtonMotionEventsEnabled(!mStylusButtonsDisabled);
+            mStylusButtonsEnabled = Settings.Secure.getIntForUser(resolver,
+                    Secure.STYLUS_BUTTONS_ENABLED, 1, UserHandle.USER_CURRENT) == 1;
+            mInputManagerInternal.setStylusButtonMotionEventsEnabled(mStylusButtonsEnabled);
         }
         if (updateRotation) {
             updateRotation(true);
@@ -4315,7 +4317,7 @@
             case KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY:
             case KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY:
             case KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL: {
-                if (down && !mStylusButtonsDisabled) {
+                if (down && mStylusButtonsEnabled) {
                     sendSystemKeyToStatusBarAsync(keyCode);
                 }
                 result &= ~ACTION_PASS_TO_USER;
@@ -4902,10 +4904,15 @@
 
         // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
         // as well as enabling the orientation change logic/sensor.
+        Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
+                TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, /* cookie= */ 0);
         mWindowManagerInternal.waitForAllWindowsDrawn(() -> {
             if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for every display");
             mHandler.sendMessage(mHandler.obtainMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE,
                     INVALID_DISPLAY, 0));
+
+            Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER,
+                    TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, /* cookie= */ 0);
             }, WAITING_FOR_DRAWN_TIMEOUT, INVALID_DISPLAY);
     }
 
@@ -4961,10 +4968,16 @@
             }
         } else {
             mScreenOnListeners.put(displayId, screenOnListener);
+
+            Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
+                    TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, /* cookie= */ 0);
             mWindowManagerInternal.waitForAllWindowsDrawn(() -> {
                 if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display: " + displayId);
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE,
                         displayId, 0));
+
+                Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER,
+                        TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD, /* cookie= */ 0);
             }, WAITING_FOR_DRAWN_TIMEOUT, displayId);
         }
     }
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 514caf2..58c814a 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -129,6 +129,9 @@
     ThermalManagerService(Context context, @Nullable ThermalHalWrapper halWrapper) {
         super(context);
         mHalWrapper = halWrapper;
+        if (halWrapper != null) {
+            halWrapper.setCallback(this::onTemperatureChangedCallback);
+        }
         mStatus = Temperature.THROTTLING_NONE;
     }
 
@@ -149,22 +152,21 @@
             // Connect to HAL and post to listeners.
             boolean halConnected = (mHalWrapper != null);
             if (!halConnected) {
-                mHalWrapper = new ThermalHalAidlWrapper();
+                mHalWrapper = new ThermalHalAidlWrapper(this::onTemperatureChangedCallback);
                 halConnected = mHalWrapper.connectToHal();
             }
             if (!halConnected) {
-                mHalWrapper = new ThermalHal20Wrapper();
+                mHalWrapper = new ThermalHal20Wrapper(this::onTemperatureChangedCallback);
                 halConnected = mHalWrapper.connectToHal();
             }
             if (!halConnected) {
-                mHalWrapper = new ThermalHal11Wrapper();
+                mHalWrapper = new ThermalHal11Wrapper(this::onTemperatureChangedCallback);
                 halConnected = mHalWrapper.connectToHal();
             }
             if (!halConnected) {
-                mHalWrapper = new ThermalHal10Wrapper();
+                mHalWrapper = new ThermalHal10Wrapper(this::onTemperatureChangedCallback);
                 halConnected = mHalWrapper.connectToHal();
             }
-            mHalWrapper.setCallback(this::onTemperatureChangedCallback);
             if (!halConnected) {
                 Slog.w(TAG, "No Thermal HAL service on this device");
                 return;
@@ -723,6 +725,10 @@
             }
         };
 
+        ThermalHalAidlWrapper(TemperatureChangedCallback callback) {
+            mCallback = callback;
+        }
+
         @Override
         protected List<Temperature> getCurrentTemperatures(boolean shouldFilter,
                 int type) {
@@ -832,9 +838,10 @@
                         binder.linkToDeath(this, 0);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "Unable to connect IThermal AIDL instance", e);
-                        mInstance = null;
+                        connectToHal();
                     }
                     if (mInstance != null) {
+                        Slog.i(TAG, "Thermal HAL AIDL service connected.");
                         registerThermalChangedCallback();
                     }
                 }
@@ -850,7 +857,7 @@
                         e);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Unable to connect IThermal AIDL instance", e);
-                mInstance = null;
+                connectToHal();
             }
         }
 
@@ -866,8 +873,8 @@
 
         @Override
         public synchronized void binderDied() {
-            Slog.w(TAG, "IThermal HAL instance died");
-            mInstance = null;
+            Slog.w(TAG, "Thermal AIDL HAL died, reconnecting...");
+            connectToHal();
         }
     }
 
@@ -876,6 +883,10 @@
         @GuardedBy("mHalLock")
         private android.hardware.thermal.V1_0.IThermal mThermalHal10 = null;
 
+        ThermalHal10Wrapper(TemperatureChangedCallback callback) {
+            mCallback = callback;
+        }
+
         @Override
         protected List<Temperature> getCurrentTemperatures(boolean shouldFilter,
                 int type) {
@@ -1011,6 +1022,10 @@
                     }
                 };
 
+        ThermalHal11Wrapper(TemperatureChangedCallback callback) {
+            mCallback = callback;
+        }
+
         @Override
         protected List<Temperature> getCurrentTemperatures(boolean shouldFilter,
                 int type) {
@@ -1145,6 +1160,10 @@
                     }
                 };
 
+        ThermalHal20Wrapper(TemperatureChangedCallback callback) {
+            mCallback = callback;
+        }
+
         @Override
         protected List<Temperature> getCurrentTemperatures(boolean shouldFilter,
                 int type) {
diff --git a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
index 2fbf3fb..751f535 100644
--- a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
@@ -79,7 +79,12 @@
     private static final long MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS = 750;
 
     // Delay for clearing out battery stats for UIDs corresponding to a removed user
-    public static final int UID_REMOVAL_AFTER_USER_REMOVAL_DELAY_MILLIS = 10_000;
+    public static final int UID_QUICK_REMOVAL_AFTER_USER_REMOVAL_DELAY_MILLIS = 2_000;
+
+    // Delay for the _final_ clean-up of battery stats after a user removal - just in case
+    // some UIDs took longer than UID_QUICK_REMOVAL_AFTER_USER_REMOVAL_DELAY_MILLIS to
+    // stop running.
+    public static final int UID_FINAL_REMOVAL_AFTER_USER_REMOVAL_DELAY_MILLIS = 10_000;
 
     private final ScheduledExecutorService mExecutorService =
             Executors.newSingleThreadScheduledExecutor(
@@ -336,11 +341,20 @@
     @Override
     public Future<?> scheduleCleanupDueToRemovedUser(int userId) {
         synchronized (BatteryExternalStatsWorker.this) {
+            // Initial quick clean-up after a user removal
+            mExecutorService.schedule(() -> {
+                synchronized (mStats) {
+                    mStats.clearRemovedUserUidsLocked(userId);
+                }
+            }, UID_QUICK_REMOVAL_AFTER_USER_REMOVAL_DELAY_MILLIS, TimeUnit.MILLISECONDS);
+
+            // Final clean-up after a user removal, to take care of UIDs that were running longer
+            // than expected
             return mExecutorService.schedule(() -> {
                 synchronized (mStats) {
                     mStats.clearRemovedUserUidsLocked(userId);
                 }
-            }, UID_REMOVAL_AFTER_USER_REMOVAL_DELAY_MILLIS, TimeUnit.MILLISECONDS);
+            }, UID_FINAL_REMOVAL_AFTER_USER_REMOVAL_DELAY_MILLIS, TimeUnit.MILLISECONDS);
         }
     }
 
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index bc90c89..add4a89 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -12084,11 +12084,16 @@
             final SparseDoubleArray uidEstimatedConsumptionMah;
             final long dataConsumedChargeUC;
             if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) {
-                // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
-                // numerator for long rounding.
-                final long phoneConsumedChargeUC =
-                        (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
-                                / totalRadioDurationMs;
+                final long phoneConsumedChargeUC;
+                if (totalRadioDurationMs == 0) {
+                    phoneConsumedChargeUC = 0;
+                } else {
+                    // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
+                    // numerator for long rounding.
+                    phoneConsumedChargeUC =
+                            (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
+                                    / totalRadioDurationMs;
+                }
                 dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC;
 
                 mGlobalEnergyConsumerStats.updateStandardBucket(
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java b/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java
index 3226260..aba8e5f 100644
--- a/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java
+++ b/services/core/java/com/android/server/power/stats/MobileRadioPowerCalculator.java
@@ -264,8 +264,10 @@
             if (total.remainingPowerMah < 0) total.remainingPowerMah = 0;
         } else {
             // Smear unattributed active time and add it to the remaining power consumption.
-            total.remainingPowerMah +=
-                    (totalActivePowerMah * total.remainingDurationMs) / totalActiveDurationMs;
+            if (totalActiveDurationMs != 0) {
+                total.remainingPowerMah +=
+                        (totalActivePowerMah * total.remainingDurationMs) / totalActiveDurationMs;
+            }
 
             // Calculate the inactive modem power consumption.
             final BatteryStats.ControllerActivityCounter modemActivity =
diff --git a/services/core/java/com/android/server/security/FileIntegrity.java b/services/core/java/com/android/server/security/FileIntegrity.java
new file mode 100644
index 0000000..7b87d99
--- /dev/null
+++ b/services/core/java/com/android/server/security/FileIntegrity.java
@@ -0,0 +1,58 @@
+/*
+ * 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.security;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.ParcelFileDescriptor;
+
+import com.android.internal.security.VerityUtils;
+
+import java.io.File;
+import java.io.IOException;
+
+
+/**
+ * In-process API for server side FileIntegrity related infrastructure.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public final class FileIntegrity {
+    private FileIntegrity() {}
+
+    /**
+     * Enables fs-verity, if supported by the filesystem.
+     * @see <a href="https://www.kernel.org/doc/html/latest/filesystems/fsverity.html">
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    public static void setUpFsVerity(@NonNull File file) throws IOException {
+        VerityUtils.setUpFsverity(file.getAbsolutePath());
+    }
+
+    /**
+     * Enables fs-verity, if supported by the filesystem.
+     * @see <a href="https://www.kernel.org/doc/html/latest/filesystems/fsverity.html">
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+    public static void setUpFsVerity(@NonNull ParcelFileDescriptor parcelFileDescriptor)
+            throws IOException {
+        VerityUtils.setUpFsverity(parcelFileDescriptor.getFd());
+    }
+}
diff --git a/services/core/java/com/android/server/security/KeyChainSystemService.java b/services/core/java/com/android/server/security/KeyChainSystemService.java
index edd4a3d..da1ff73 100644
--- a/services/core/java/com/android/server/security/KeyChainSystemService.java
+++ b/services/core/java/com/android/server/security/KeyChainSystemService.java
@@ -45,6 +45,7 @@
  * <p>
  * TODO (b/35968281): take a more sophisticated look at what bits of KeyChain should be inside the
  *                    system server and which make sense inside a system app.
+ * @hide
  */
 public class KeyChainSystemService extends SystemService {
 
diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java
index 0e92709..2d3ede0 100644
--- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java
+++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java
@@ -24,6 +24,7 @@
 import android.security.rkp.IStoreUpgradedKeyCallback;
 import android.security.rkp.service.RegistrationProxy;
 import android.security.rkp.service.RemotelyProvisionedKey;
+import android.security.rkp.service.RkpProxyException;
 import android.util.Log;
 
 import java.util.Set;
@@ -68,13 +69,35 @@
             if (e instanceof OperationCanceledException) {
                 Log.i(TAG, "Operation cancelled for client " + mCallback.hashCode());
                 wrapCallback(mCallback::onCancel);
+            } else if (e instanceof RkpProxyException) {
+                Log.e(TAG, "RKP error fetching key for client " + mCallback.hashCode(), e);
+                RkpProxyException rkpException = (RkpProxyException) e;
+                wrapCallback(() -> mCallback.onError(toGetKeyError(rkpException),
+                        e.getMessage()));
             } else {
                 Log.e(TAG, "Error fetching key for client " + mCallback.hashCode(), e);
-                wrapCallback(() -> mCallback.onError(e.getMessage()));
+                wrapCallback(() -> mCallback.onError(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN,
+                        e.getMessage()));
             }
         }
     }
 
+    private byte toGetKeyError(RkpProxyException exception) {
+        switch (exception.getError()) {
+            case RkpProxyException.ERROR_UNKNOWN:
+                return IGetKeyCallback.ErrorCode.ERROR_UNKNOWN;
+            case RkpProxyException.ERROR_REQUIRES_SECURITY_PATCH:
+                return IGetKeyCallback.ErrorCode.ERROR_REQUIRES_SECURITY_PATCH;
+            case RkpProxyException.ERROR_PENDING_INTERNET_CONNECTIVITY:
+                return IGetKeyCallback.ErrorCode.ERROR_PENDING_INTERNET_CONNECTIVITY;
+            case RkpProxyException.ERROR_PERMANENT:
+                return IGetKeyCallback.ErrorCode.ERROR_PERMANENT;
+            default:
+                Log.e(TAG, "Unexpected error code in RkpProxyException", exception);
+                return IGetKeyCallback.ErrorCode.ERROR_UNKNOWN;
+        }
+    }
+
     RemoteProvisioningRegistration(RegistrationProxy registration, Executor executor) {
         mRegistration = registration;
         mExecutor = executor;
@@ -97,7 +120,8 @@
         } catch (Exception e) {
             Log.e(TAG, "getKeyAsync threw an exception for client " + callback.hashCode(), e);
             mGetKeyOperations.remove(callback);
-            wrapCallback(() -> callback.onError(e.getMessage()));
+            wrapCallback(() -> callback.onError(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN,
+                    e.getMessage()));
         }
     }
 
diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
index 6d39177..a694f5f 100644
--- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
@@ -863,8 +863,9 @@
          */
         private void enforceObserveSensorPrivacyPermission() {
             String systemUIPackage = mContext.getString(R.string.config_systemUi);
-            if (Binder.getCallingUid() == mPackageManagerInternal
-                    .getPackageUid(systemUIPackage, MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM)) {
+            int systemUIAppId = UserHandle.getAppId(mPackageManagerInternal
+                    .getPackageUid(systemUIPackage, MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM));
+            if (UserHandle.getCallingAppId() == systemUIAppId) {
                 // b/221782106, possible race condition with role grant might bootloop device.
                 return;
             }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 5521384..ec052ec 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -21,7 +21,6 @@
 import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsController.Appearance;
 import android.view.WindowInsetsController.Behavior;
@@ -162,11 +161,10 @@
             LetterboxDetails[] letterboxDetails);
 
     /** @see com.android.internal.statusbar.IStatusBar#showTransient */
-    void showTransient(int displayId, @InternalInsetsType int[] types,
-            boolean isGestureOnSystemBar);
+    void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar);
 
     /** @see com.android.internal.statusbar.IStatusBar#abortTransient */
-    void abortTransient(int displayId, @InternalInsetsType int[] types);
+    void abortTransient(int displayId, @InsetsType int types);
 
     /**
      * @see com.android.internal.statusbar.IStatusBar#showToast(String, IBinder, CharSequence,
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 83f4805..4489ba9 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -79,12 +79,10 @@
 import android.service.quicksettings.TileService;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.IndentingPrintWriter;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.WindowInsets;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsController.Appearance;
@@ -645,7 +643,7 @@
         }
 
         @Override
-        public void showTransient(int displayId, @InternalInsetsType int[] types,
+        public void showTransient(int displayId, @InsetsType int types,
                 boolean isGestureOnSystemBar) {
             getUiState(displayId).showTransient(types);
             if (mBar != null) {
@@ -656,7 +654,7 @@
         }
 
         @Override
-        public void abortTransient(int displayId, @InternalInsetsType int[] types) {
+        public void abortTransient(int displayId, @InsetsType int types) {
             getUiState(displayId).clearTransient(types);
             if (mBar != null) {
                 try {
@@ -1258,7 +1256,7 @@
     private static class UiState {
         private @Appearance int mAppearance = 0;
         private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
-        private final ArraySet<Integer> mTransientBarTypes = new ArraySet<>();
+        private @InsetsType int mTransientBarTypes;
         private boolean mNavbarColorManagedByIme = false;
         private @Behavior int mBehavior;
         private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();
@@ -1285,16 +1283,12 @@
             mLetterboxDetails = letterboxDetails;
         }
 
-        private void showTransient(@InternalInsetsType int[] types) {
-            for (int type : types) {
-                mTransientBarTypes.add(type);
-            }
+        private void showTransient(@InsetsType int types) {
+            mTransientBarTypes |= types;
         }
 
-        private void clearTransient(@InternalInsetsType int[] types) {
-            for (int type : types) {
-                mTransientBarTypes.remove(type);
-            }
+        private void clearTransient(@InsetsType int types) {
+            mTransientBarTypes &= ~types;
         }
 
         private int getDisabled1() {
@@ -1410,16 +1404,12 @@
             // TODO(b/118592525): Currently, status bar only works on the default display.
             // Make it aware of multi-display if needed.
             final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
-            final int[] transientBarTypes = new int[state.mTransientBarTypes.size()];
-            for (int i = 0; i < transientBarTypes.length; i++) {
-                transientBarTypes[i] = state.mTransientBarTypes.valueAt(i);
-            }
             return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
                     state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis,
                     state.mImeBackDisposition, state.mShowImeSwitcher,
                     gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken,
                     state.mNavbarColorManagedByIme, state.mBehavior, state.mRequestedVisibleTypes,
-                    state.mPackageName, transientBarTypes, state.mLetterboxDetails);
+                    state.mPackageName, state.mTransientBarTypes, state.mLetterboxDetails);
         }
     }
 
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 9faf7a9..4ebd402 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -19,6 +19,7 @@
 import android.Manifest;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ApplicationExitInfo;
 import android.app.IActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -444,7 +445,7 @@
         IActivityManager am = ActivityManager.getService();
         try {
             am.killApplication(mExternalStorageServicePackageName, mExternalStorageServiceAppId,
-                    userId, "storage_session_controller reset");
+                    userId, "storage_session_controller reset", ApplicationExitInfo.REASON_OTHER);
         } catch (RemoteException e) {
             Slog.i(TAG, "Failed to kill the ExtenalStorageService for user " + userId);
         }
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
index 111b4f6..5fd70a8 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
@@ -243,6 +243,8 @@
         }
         builder.setConfigureAutoDetectionEnabledCapability(configureAutoDetectionEnabledCapability);
 
+        builder.setUseLocationEnabled(mLocationEnabledSetting);
+
         boolean deviceHasLocationTimeZoneDetection = isGeoDetectionSupported();
         boolean deviceHasTelephonyDetection = isTelephonyDetectionSupported();
 
diff --git a/services/core/java/com/android/server/tracing/OWNERS b/services/core/java/com/android/server/tracing/OWNERS
index f5de4eb..079d4c5 100644
--- a/services/core/java/com/android/server/tracing/OWNERS
+++ b/services/core/java/com/android/server/tracing/OWNERS
@@ -1,2 +1,3 @@
-cfijalkovich@google.com
 carmenjackson@google.com
+kevinjeon@google.com
+include platform/external/perfetto:/OWNERS
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 0928bef..404ca01 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -93,6 +93,7 @@
 import android.util.SparseArray;
 import android.view.InputChannel;
 import android.view.Surface;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
@@ -103,7 +104,9 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.IoThread;
 import com.android.server.SystemService;
+
 import dalvik.annotation.optimization.NeverCompile;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
@@ -2081,6 +2084,26 @@
         }
 
         @Override
+        public void timeShiftSetMode(IBinder sessionToken, int mode, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "timeShiftSetMode");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .timeShiftSetMode(mode);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in timeShiftSetMode", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void timeShiftEnablePositionTracking(IBinder sessionToken, boolean enable,
                 int userId) {
             final int callingUid = Binder.getCallingUid();
@@ -3654,6 +3677,57 @@
         }
 
         @Override
+        public void onCueingMessageAvailability(boolean available) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onCueingMessageAvailability(" + available + ")");
+                }
+                if (mSessionState.session == null || mSessionState.client == null) {
+                    return;
+                }
+                try {
+                    mSessionState.client.onCueingMessageAvailability(available, mSessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onCueingMessageAvailability", e);
+                }
+            }
+        }
+
+        @Override
+        public void onTimeShiftMode(int mode) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onTimeShiftMode(" + mode + ")");
+                }
+                if (mSessionState.session == null || mSessionState.client == null) {
+                    return;
+                }
+                try {
+                    mSessionState.client.onTimeShiftMode(mode, mSessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onTimeShiftMode", e);
+                }
+            }
+        }
+
+        @Override
+        public void onAvailableSpeeds(float[] speeds) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onAvailableSpeeds(" + Arrays.toString(speeds) + ")");
+                }
+                if (mSessionState.session == null || mSessionState.client == null) {
+                    return;
+                }
+                try {
+                    mSessionState.client.onAvailableSpeeds(speeds, mSessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onAvailableSpeeds", e);
+                }
+            }
+        }
+
+        @Override
         public void onTuned(Uri channelUri) {
             synchronized (mLock) {
                 if (DEBUG) {
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index d4f2f2d..f829449 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -1486,6 +1486,56 @@
         }
 
         @Override
+        public void sendTimeShiftMode(IBinder sessionToken, int mode, int userId) {
+            if (DEBUG) {
+                Slogf.d(TAG, "sendTimeShiftMode(mode=%d)", mode);
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "sendTimeShiftMode");
+            SessionState sessionState = null;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        sessionState = getSessionStateLocked(sessionToken, callingUid,
+                                resolvedUserId);
+                        getSessionLocked(sessionState).sendTimeShiftMode(mode);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slogf.e(TAG, "error in sendTimeShiftMode", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void sendAvailableSpeeds(IBinder sessionToken, float[] speeds, int userId) {
+            if (DEBUG) {
+                Slogf.d(TAG, "sendAvailableSpeeds(speeds=%s)", Arrays.toString(speeds));
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "sendAvailableSpeeds");
+            SessionState sessionState = null;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        sessionState = getSessionStateLocked(sessionToken, callingUid,
+                                resolvedUserId);
+                        getSessionLocked(sessionState).sendAvailableSpeeds(speeds);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slogf.e(TAG, "error in sendAvailableSpeeds", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void sendTvRecordingInfo(IBinder sessionToken, TvRecordingInfo recordingInfo,
                 int userId) {
             if (DEBUG) {
@@ -1701,6 +1751,151 @@
         }
 
         @Override
+        public void notifyRecordingConnectionFailed(
+                IBinder sessionToken, String recordingId, String inputId, int userId) {
+            if (DEBUG) {
+                Slogf.d(TAG, "notifyRecordingConnectionFailed(recordingId=%s, inputId=%s)",
+                        recordingId, inputId);
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(
+                    Binder.getCallingPid(), callingUid, userId,
+                    "notifyRecordingConnectionFailed");
+            SessionState sessionState = null;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        sessionState =
+                                getSessionStateLocked(sessionToken, callingUid, resolvedUserId);
+                        getSessionLocked(sessionState).notifyRecordingConnectionFailed(
+                                recordingId, inputId);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slogf.e(TAG, "error in notifyRecordingConnectionFailed", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void notifyRecordingDisconnected(
+                IBinder sessionToken, String recordingId, String inputId, int userId) {
+            if (DEBUG) {
+                Slogf.d(TAG, "notifyRecordingDisconnected(recordingId=%s, inputId=%s)",
+                        recordingId, inputId);
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(
+                    Binder.getCallingPid(), callingUid, userId,
+                    "notifyRecordingDisconnected");
+            SessionState sessionState = null;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        sessionState =
+                                getSessionStateLocked(sessionToken, callingUid, resolvedUserId);
+                        getSessionLocked(sessionState).notifyRecordingDisconnected(
+                                recordingId, inputId);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slogf.e(TAG, "error in notifyRecordingDisconnected", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void notifyRecordingTuned(
+                IBinder sessionToken, String recordingId, Uri channelUri, int userId) {
+            if (DEBUG) {
+                Slogf.d(TAG, "notifyRecordingTuned(recordingId=%s, channelUri=%s)",
+                        recordingId, channelUri.toString());
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(
+                    Binder.getCallingPid(), callingUid, userId,
+                    "notifyRecordingTuned");
+            SessionState sessionState = null;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        sessionState =
+                                getSessionStateLocked(sessionToken, callingUid, resolvedUserId);
+                        getSessionLocked(sessionState).notifyRecordingTuned(
+                                recordingId, channelUri);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slogf.e(TAG, "error in notifyRecordingTuned", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void notifyRecordingError(
+                IBinder sessionToken, String recordingId, int err, int userId) {
+            if (DEBUG) {
+                Slogf.d(TAG, "notifyRecordingError(recordingId=%s, err=%d)",
+                        recordingId, err);
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(
+                    Binder.getCallingPid(), callingUid, userId,
+                    "notifyRecordingError");
+            SessionState sessionState = null;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        sessionState =
+                                getSessionStateLocked(sessionToken, callingUid, resolvedUserId);
+                        getSessionLocked(sessionState).notifyRecordingError(
+                                recordingId, err);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slogf.e(TAG, "error in notifyRecordingError", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void notifyRecordingScheduled(
+                IBinder sessionToken, String recordingId, String requestId, int userId) {
+            if (DEBUG) {
+                Slogf.d(TAG, "notifyRecordingScheduled(recordingId=%s, requestId=%s)",
+                        recordingId, requestId);
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(
+                    Binder.getCallingPid(), callingUid, userId,
+                    "notifyRecordingScheduled");
+            SessionState sessionState = null;
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        sessionState =
+                                getSessionStateLocked(sessionToken, callingUid, resolvedUserId);
+                        getSessionLocked(sessionState).notifyRecordingScheduled(
+                                recordingId, requestId);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slogf.e(TAG, "error in notifyRecordingScheduled", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void setSurface(IBinder sessionToken, Surface surface, int userId) {
             final int callingUid = Binder.getCallingUid();
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
@@ -2602,6 +2797,40 @@
         }
 
         @Override
+        public void onRequestTimeShiftMode() {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slogf.d(TAG, "onRequestTimeShiftMode");
+                }
+                if (mSessionState.mSession == null || mSessionState.mClient == null) {
+                    return;
+                }
+                try {
+                    mSessionState.mClient.onRequestTimeShiftMode(mSessionState.mSeq);
+                } catch (RemoteException e) {
+                    Slogf.e(TAG, "error in onRequestTimeShiftMode", e);
+                }
+            }
+        }
+
+        @Override
+        public void onRequestAvailableSpeeds() {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slogf.d(TAG, "onRequestAvailableSpeeds");
+                }
+                if (mSessionState.mSession == null || mSessionState.mClient == null) {
+                    return;
+                }
+                try {
+                    mSessionState.mClient.onRequestAvailableSpeeds(mSessionState.mSeq);
+                } catch (RemoteException e) {
+                    Slogf.e(TAG, "error in onRequestAvailableSpeeds", e);
+                }
+            }
+        }
+
+        @Override
         public void onRequestStartRecording(Uri programUri) {
             synchronized (mLock) {
                 if (DEBUG) {
@@ -2636,6 +2865,44 @@
         }
 
         @Override
+        public void onRequestScheduleRecording(
+                String inputId, Uri channelUri, Uri programUri, Bundle params) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slogf.d(TAG, "onRequestScheduleRecording");
+                }
+                if (mSessionState.mSession == null || mSessionState.mClient == null) {
+                    return;
+                }
+                try {
+                    mSessionState.mClient.onRequestScheduleRecording(
+                            inputId, channelUri, programUri, params, mSessionState.mSeq);
+                } catch (RemoteException e) {
+                    Slogf.e(TAG, "error in onRequestScheduleRecording", e);
+                }
+            }
+        }
+
+        @Override
+        public void onRequestScheduleRecording2(String inputId, Uri channelUri, long start,
+                long duration, int repeat, Bundle params) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slogf.d(TAG, "onRequestScheduleRecording2");
+                }
+                if (mSessionState.mSession == null || mSessionState.mClient == null) {
+                    return;
+                }
+                try {
+                    mSessionState.mClient.onRequestScheduleRecording2(inputId, channelUri, start,
+                            duration, repeat, params, mSessionState.mSeq);
+                } catch (RemoteException e) {
+                    Slogf.e(TAG, "error in onRequestScheduleRecording2", e);
+                }
+            }
+        }
+
+        @Override
         public void onSetTvRecordingInfo(String recordingId, TvRecordingInfo recordingInfo) {
             synchronized (mLock) {
                 if (DEBUG) {
diff --git a/services/core/java/com/android/server/vibrator/HalVibration.java b/services/core/java/com/android/server/vibrator/HalVibration.java
new file mode 100644
index 0000000..53f04d7
--- /dev/null
+++ b/services/core/java/com/android/server/vibrator/HalVibration.java
@@ -0,0 +1,219 @@
+/*
+ * 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.vibrator;
+
+import android.annotation.Nullable;
+import android.os.CombinedVibration;
+import android.os.IBinder;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
+import android.util.SparseArray;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.function.Function;
+
+/**
+ * Represents a vibration defined by a {@link CombinedVibration} that will be performed by
+ * the IVibrator HAL.
+ */
+final class HalVibration extends Vibration {
+
+    public final VibrationAttributes attrs;
+    public final long id;
+    public final int uid;
+    public final int displayId;
+    public final String opPkg;
+    public final String reason;
+    public final IBinder token;
+    public final SparseArray<VibrationEffect> mFallbacks = new SparseArray<>();
+
+    /** The actual effect to be played. */
+    @Nullable
+    private CombinedVibration mEffect;
+
+    /**
+     * The original effect that was requested. Typically these two things differ because the effect
+     * was scaled based on the users vibration intensity settings.
+     */
+    @Nullable
+    private CombinedVibration mOriginalEffect;
+
+    /** Vibration status. */
+    private Vibration.Status mStatus;
+
+    /** Vibration runtime stats. */
+    private final VibrationStats mStats = new VibrationStats();
+
+    /** A {@link CountDownLatch} to enable waiting for completion. */
+    private final CountDownLatch mCompletionLatch = new CountDownLatch(1);
+
+    HalVibration(IBinder token, int id, CombinedVibration effect,
+            VibrationAttributes attrs, int uid, int displayId, String opPkg, String reason) {
+        this.token = token;
+        this.mEffect = effect;
+        this.id = id;
+        this.attrs = attrs;
+        this.uid = uid;
+        this.displayId = displayId;
+        this.opPkg = opPkg;
+        this.reason = reason;
+        mStatus = Vibration.Status.RUNNING;
+    }
+
+    VibrationStats stats() {
+        return mStats;
+    }
+
+    /**
+     * Set the {@link Status} of this vibration and reports the current system time as this
+     * vibration end time, for debugging purposes.
+     *
+     * <p>This method will only accept given value if the current status is {@link
+     * Status#RUNNING}.
+     */
+    public void end(EndInfo info) {
+        if (hasEnded()) {
+            // Vibration already ended, keep first ending status set and ignore this one.
+            return;
+        }
+        mStatus = info.status;
+        mStats.reportEnded(info.endedByUid, info.endedByUsage);
+        mCompletionLatch.countDown();
+    }
+
+    /** Waits indefinitely until another thread calls {@link #end} on this vibration. */
+    public void waitForEnd() throws InterruptedException {
+        mCompletionLatch.await();
+    }
+
+    /**
+     * Return the effect to be played when given prebaked effect id is not supported by the
+     * vibrator.
+     */
+    @Nullable
+    public VibrationEffect getFallback(int effectId) {
+        return mFallbacks.get(effectId);
+    }
+
+    /**
+     * Add a fallback {@link VibrationEffect} to be played when given effect id is not supported,
+     * which might be necessary for replacement in realtime.
+     */
+    public void addFallback(int effectId, VibrationEffect effect) {
+        mFallbacks.put(effectId, effect);
+    }
+
+    /**
+     * Applied update function to the current effect held by this vibration, and to each fallback
+     * effect added.
+     */
+    public void updateEffects(Function<VibrationEffect, VibrationEffect> updateFn) {
+        CombinedVibration newEffect = transformCombinedEffect(mEffect, updateFn);
+        if (!newEffect.equals(mEffect)) {
+            if (mOriginalEffect == null) {
+                mOriginalEffect = mEffect;
+            }
+            mEffect = newEffect;
+        }
+        for (int i = 0; i < mFallbacks.size(); i++) {
+            mFallbacks.setValueAt(i, updateFn.apply(mFallbacks.valueAt(i)));
+        }
+    }
+
+    /**
+     * Creates a new {@link CombinedVibration} by applying the given transformation function
+     * to each {@link VibrationEffect}.
+     */
+    private static CombinedVibration transformCombinedEffect(
+            CombinedVibration combinedEffect, Function<VibrationEffect, VibrationEffect> fn) {
+        if (combinedEffect instanceof CombinedVibration.Mono) {
+            VibrationEffect effect = ((CombinedVibration.Mono) combinedEffect).getEffect();
+            return CombinedVibration.createParallel(fn.apply(effect));
+        } else if (combinedEffect instanceof CombinedVibration.Stereo) {
+            SparseArray<VibrationEffect> effects =
+                    ((CombinedVibration.Stereo) combinedEffect).getEffects();
+            CombinedVibration.ParallelCombination combination =
+                    CombinedVibration.startParallel();
+            for (int i = 0; i < effects.size(); i++) {
+                combination.addVibrator(effects.keyAt(i), fn.apply(effects.valueAt(i)));
+            }
+            return combination.combine();
+        } else if (combinedEffect instanceof CombinedVibration.Sequential) {
+            List<CombinedVibration> effects =
+                    ((CombinedVibration.Sequential) combinedEffect).getEffects();
+            CombinedVibration.SequentialCombination combination =
+                    CombinedVibration.startSequential();
+            for (CombinedVibration effect : effects) {
+                combination.addNext(transformCombinedEffect(effect, fn));
+            }
+            return combination.combine();
+        } else {
+            // Unknown combination, return same effect.
+            return combinedEffect;
+        }
+    }
+
+    /** Return true is current status is different from {@link Status#RUNNING}. */
+    public boolean hasEnded() {
+        return mStatus != Status.RUNNING;
+    }
+
+    /** Return true is effect is a repeating vibration. */
+    public boolean isRepeating() {
+        return mEffect.getDuration() == Long.MAX_VALUE;
+    }
+
+    /** Return the effect that should be played by this vibration. */
+    @Nullable
+    public CombinedVibration getEffect() {
+        return mEffect;
+    }
+
+    /**
+     * Return {@link Vibration.DebugInfo} with read-only debug information about this vibration.
+     */
+    public Vibration.DebugInfo getDebugInfo() {
+        return new Vibration.DebugInfo(mStatus, mStats, mEffect, mOriginalEffect, /* scale= */ 0,
+                attrs, uid, displayId, opPkg, reason);
+    }
+
+    /** Return {@link VibrationStats.StatsInfo} with read-only metrics about this vibration. */
+    public VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis) {
+        int vibrationType = isRepeating()
+                ? FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__REPEATED
+                : FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE;
+        return new VibrationStats.StatsInfo(
+                uid, vibrationType, attrs.getUsage(), mStatus, mStats, completionUptimeMillis);
+    }
+
+    /**
+     * Returns true if this vibration can pipeline with the specified one.
+     *
+     * <p>Note that currently, repeating vibrations can't pipeline with following vibrations,
+     * because the cancel() call to stop the repetition will cancel a pending vibration too. This
+     * can be changed if we have a use-case to reason around behavior for. It may also be nice to
+     * pipeline very short vibrations together, regardless of the flag.
+     */
+    public boolean canPipelineWith(HalVibration vib) {
+        return uid == vib.uid && attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT)
+                && vib.attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT)
+                && !isRepeating();
+    }
+}
diff --git a/services/core/java/com/android/server/vibrator/Step.java b/services/core/java/com/android/server/vibrator/Step.java
index 042e8a0..5faa516 100644
--- a/services/core/java/com/android/server/vibrator/Step.java
+++ b/services/core/java/com/android/server/vibrator/Step.java
@@ -38,7 +38,7 @@
         this.startTime = startTime;
     }
 
-    protected Vibration getVibration() {
+    protected HalVibration getVibration() {
         return conductor.getVibration();
     }
 
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index a451ee2..5667c72 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.CombinedVibration;
-import android.os.IBinder;
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.vibrator.PrebakedSegment;
@@ -27,20 +26,16 @@
 import android.os.vibrator.RampSegment;
 import android.os.vibrator.StepSegment;
 import android.os.vibrator.VibrationEffectSegment;
-import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.internal.util.FrameworkStatsLog;
-
 import java.text.SimpleDateFormat;
 import java.util.Date;
-import java.util.List;
 import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.function.Function;
 
-/** Represents a vibration request to the vibrator service. */
-final class Vibration {
+/**
+ * The base class for all vibrations.
+ */
+class Vibration {
     private static final SimpleDateFormat DEBUG_DATE_FORMAT =
             new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
@@ -85,186 +80,6 @@
         }
     }
 
-    public final VibrationAttributes attrs;
-    public final long id;
-    public final int uid;
-    public final int displayId;
-    public final String opPkg;
-    public final String reason;
-    public final IBinder token;
-    public final SparseArray<VibrationEffect> mFallbacks = new SparseArray<>();
-
-    /** The actual effect to be played. */
-    @Nullable
-    private CombinedVibration mEffect;
-
-    /**
-     * The original effect that was requested. Typically these two things differ because the effect
-     * was scaled based on the users vibration intensity settings.
-     */
-    @Nullable
-    private CombinedVibration mOriginalEffect;
-
-    /** Vibration status. */
-    private Vibration.Status mStatus;
-
-    /** Vibration runtime stats. */
-    private final VibrationStats mStats = new VibrationStats();
-
-    /** A {@link CountDownLatch} to enable waiting for completion. */
-    private final CountDownLatch mCompletionLatch = new CountDownLatch(1);
-
-    Vibration(IBinder token, int id, CombinedVibration effect,
-            VibrationAttributes attrs, int uid, int displayId, String opPkg, String reason) {
-        this.token = token;
-        this.mEffect = effect;
-        this.id = id;
-        this.attrs = attrs;
-        this.uid = uid;
-        this.displayId = displayId;
-        this.opPkg = opPkg;
-        this.reason = reason;
-        mStatus = Vibration.Status.RUNNING;
-    }
-
-    VibrationStats stats() {
-        return mStats;
-    }
-
-    /**
-     * Set the {@link Status} of this vibration and reports the current system time as this
-     * vibration end time, for debugging purposes.
-     *
-     * <p>This method will only accept given value if the current status is {@link
-     * Status#RUNNING}.
-     */
-    public void end(EndInfo info) {
-        if (hasEnded()) {
-            // Vibration already ended, keep first ending status set and ignore this one.
-            return;
-        }
-        mStatus = info.status;
-        mStats.reportEnded(info.endedByUid, info.endedByUsage);
-        mCompletionLatch.countDown();
-    }
-
-    /** Waits indefinitely until another thread calls {@link #end} on this vibration. */
-    public void waitForEnd() throws InterruptedException {
-        mCompletionLatch.await();
-    }
-
-    /**
-     * Return the effect to be played when given prebaked effect id is not supported by the
-     * vibrator.
-     */
-    @Nullable
-    public VibrationEffect getFallback(int effectId) {
-        return mFallbacks.get(effectId);
-    }
-
-    /**
-     * Add a fallback {@link VibrationEffect} to be played when given effect id is not supported,
-     * which might be necessary for replacement in realtime.
-     */
-    public void addFallback(int effectId, VibrationEffect effect) {
-        mFallbacks.put(effectId, effect);
-    }
-
-    /**
-     * Applied update function to the current effect held by this vibration, and to each fallback
-     * effect added.
-     */
-    public void updateEffects(Function<VibrationEffect, VibrationEffect> updateFn) {
-        CombinedVibration newEffect = transformCombinedEffect(mEffect, updateFn);
-        if (!newEffect.equals(mEffect)) {
-            if (mOriginalEffect == null) {
-                mOriginalEffect = mEffect;
-            }
-            mEffect = newEffect;
-        }
-        for (int i = 0; i < mFallbacks.size(); i++) {
-            mFallbacks.setValueAt(i, updateFn.apply(mFallbacks.valueAt(i)));
-        }
-    }
-
-    /**
-     * Creates a new {@link CombinedVibration} by applying the given transformation function
-     * to each {@link VibrationEffect}.
-     */
-    private static CombinedVibration transformCombinedEffect(
-            CombinedVibration combinedEffect, Function<VibrationEffect, VibrationEffect> fn) {
-        if (combinedEffect instanceof CombinedVibration.Mono) {
-            VibrationEffect effect = ((CombinedVibration.Mono) combinedEffect).getEffect();
-            return CombinedVibration.createParallel(fn.apply(effect));
-        } else if (combinedEffect instanceof CombinedVibration.Stereo) {
-            SparseArray<VibrationEffect> effects =
-                    ((CombinedVibration.Stereo) combinedEffect).getEffects();
-            CombinedVibration.ParallelCombination combination =
-                    CombinedVibration.startParallel();
-            for (int i = 0; i < effects.size(); i++) {
-                combination.addVibrator(effects.keyAt(i), fn.apply(effects.valueAt(i)));
-            }
-            return combination.combine();
-        } else if (combinedEffect instanceof CombinedVibration.Sequential) {
-            List<CombinedVibration> effects =
-                    ((CombinedVibration.Sequential) combinedEffect).getEffects();
-            CombinedVibration.SequentialCombination combination =
-                    CombinedVibration.startSequential();
-            for (CombinedVibration effect : effects) {
-                combination.addNext(transformCombinedEffect(effect, fn));
-            }
-            return combination.combine();
-        } else {
-            // Unknown combination, return same effect.
-            return combinedEffect;
-        }
-    }
-
-    /** Return true is current status is different from {@link Status#RUNNING}. */
-    public boolean hasEnded() {
-        return mStatus != Status.RUNNING;
-    }
-
-    /** Return true is effect is a repeating vibration. */
-    public boolean isRepeating() {
-        return mEffect.getDuration() == Long.MAX_VALUE;
-    }
-
-    /** Return the effect that should be played by this vibration. */
-    @Nullable
-    public CombinedVibration getEffect() {
-        return mEffect;
-    }
-
-    /** Return {@link Vibration.DebugInfo} with read-only debug information about this vibration. */
-    public Vibration.DebugInfo getDebugInfo() {
-        return new Vibration.DebugInfo(mStatus, mStats, mEffect, mOriginalEffect, /* scale= */ 0,
-                attrs, uid, displayId, opPkg, reason);
-    }
-
-    /** Return {@link VibrationStats.StatsInfo} with read-only metrics about this vibration. */
-    public VibrationStats.StatsInfo getStatsInfo(long completionUptimeMillis) {
-        int vibrationType = isRepeating()
-                ? FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__REPEATED
-                : FrameworkStatsLog.VIBRATION_REPORTED__VIBRATION_TYPE__SINGLE;
-        return new VibrationStats.StatsInfo(
-                uid, vibrationType, attrs.getUsage(), mStatus, mStats, completionUptimeMillis);
-    }
-
-    /**
-     * Returns true if this vibration can pipeline with the specified one.
-     *
-     * <p>Note that currently, repeating vibrations can't pipeline with following vibrations,
-     * because the cancel() call to stop the repetition will cancel a pending vibration too. This
-     * can be changed if we have a use-case to reason around behavior for. It may also be nice to
-     * pipeline very short vibrations together, regardless of the flag.
-     */
-    public boolean canPipelineWith(Vibration vib) {
-        return uid == vib.uid && attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT)
-                && vib.attrs.isFlagSet(VibrationAttributes.FLAG_PIPELINED_EFFECT)
-                && !isRepeating();
-    }
-
     /** Immutable info passed as a signal to end a vibration. */
     static final class EndInfo {
         /** The {@link Status} to be set to the vibration when it ends with this info. */
@@ -505,5 +320,4 @@
             proto.end(token);
         }
     }
-
 }
diff --git a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
index 141be70..11cab4b 100644
--- a/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
+++ b/services/core/java/com/android/server/vibrator/VibrationStepConductor.java
@@ -68,7 +68,7 @@
     // Not guarded by lock because they're not modified by this conductor, it's used here only to
     // check immutable attributes. The status and other mutable states are changed by the service or
     // by the vibrator steps.
-    private final Vibration mVibration;
+    private final HalVibration mVibration;
     private final SparseArray<VibratorController> mVibrators = new SparseArray<>();
 
     private final PriorityQueue<Step> mNextSteps = new PriorityQueue<>();
@@ -95,7 +95,7 @@
     private int mRemainingStartSequentialEffectSteps;
     private int mSuccessfulVibratorOnSteps;
 
-    VibrationStepConductor(Vibration vib, VibrationSettings vibrationSettings,
+    VibrationStepConductor(HalVibration vib, VibrationSettings vibrationSettings,
             DeviceVibrationEffectAdapter effectAdapter,
             SparseArray<VibratorController> availableVibrators,
             VibrationThread.VibratorManagerHooks vibratorManagerHooks) {
@@ -160,7 +160,7 @@
         mVibration.stats().reportStarted();
     }
 
-    public Vibration getVibration() {
+    public HalVibration getVibration() {
         // No thread assertion: immutable
         return mVibration;
     }
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index 3fd9594..d2dc43c 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -33,12 +33,12 @@
 import java.util.NoSuchElementException;
 import java.util.Objects;
 
-/** Plays a {@link Vibration} in dedicated thread. */
+/** Plays a {@link HalVibration} in dedicated thread. */
 final class VibrationThread extends Thread {
     static final String TAG = "VibrationThread";
     static final boolean DEBUG = false;
 
-    /** Calls into VibratorManager functionality needed for playing a {@link Vibration}. */
+    /** Calls into VibratorManager functionality needed for playing a {@link HalVibration}. */
     interface VibratorManagerHooks {
 
         /**
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 966329e..c87332d 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -385,12 +385,13 @@
     }
 
     /**
-     * An internal-only version of vibrate that allows the caller access to the {@link Vibration}.
+     * An internal-only version of vibrate that allows the caller access to the
+     * {@link HalVibration}.
      * The Vibration is only returned if it is ongoing after this method returns.
      */
     @VisibleForTesting
     @Nullable
-    Vibration vibrateInternal(int uid, int displayId, String opPkg,
+    HalVibration vibrateInternal(int uid, int displayId, String opPkg,
             @NonNull CombinedVibration effect, @Nullable VibrationAttributes attrs,
             String reason, IBinder token) {
         Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason = " + reason);
@@ -407,8 +408,8 @@
             }
             attrs = fixupVibrationAttributes(attrs, effect);
             // Create Vibration.Stats as close to the received request as possible, for tracking.
-            Vibration vib = new Vibration(token, mNextVibrationId.getAndIncrement(), effect, attrs,
-                    uid, displayId, opPkg, reason);
+            HalVibration vib = new HalVibration(token, mNextVibrationId.getAndIncrement(), effect,
+                    attrs, uid, displayId, opPkg, reason);
             fillVibrationFallbacks(vib, effect);
 
             if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
@@ -639,7 +640,7 @@
                 return;
             }
 
-            Vibration vib = mCurrentVibration.getVibration();
+            HalVibration vib = mCurrentVibration.getVibration();
             Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(
                     vib.uid, vib.displayId, vib.opPkg, vib.attrs);
 
@@ -683,7 +684,7 @@
     }
 
     @GuardedBy("mLock")
-    private Vibration.Status startVibrationLocked(Vibration vib) {
+    private Vibration.Status startVibrationLocked(HalVibration vib) {
         Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationLocked");
         try {
             vib.updateEffects(effect -> mVibrationScaler.scale(effect, vib.attrs.getUsage()));
@@ -716,7 +717,7 @@
     private Vibration.Status startVibrationOnThreadLocked(VibrationStepConductor conductor) {
         Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationThreadLocked");
         try {
-            Vibration vib = conductor.getVibration();
+            HalVibration vib = conductor.getVibration();
             int mode = startAppOpModeLocked(vib.uid, vib.opPkg, vib.attrs);
             switch (mode) {
                 case AppOpsManager.MODE_ALLOWED:
@@ -741,7 +742,7 @@
     }
 
     @GuardedBy("mLock")
-    private void endVibrationLocked(Vibration vib, Vibration.EndInfo vibrationEndInfo,
+    private void endVibrationLocked(HalVibration vib, Vibration.EndInfo vibrationEndInfo,
             boolean shouldWriteStats) {
         vib.end(vibrationEndInfo);
         logVibrationStatus(vib.uid, vib.attrs, vibrationEndInfo.status);
@@ -763,7 +764,8 @@
                 vib.getStatsInfo(/* completionUptimeMillis= */ SystemClock.uptimeMillis()));
     }
 
-    private void logVibrationStatus(int uid, VibrationAttributes attrs, Vibration.Status status) {
+    private void logVibrationStatus(int uid, VibrationAttributes attrs,
+            Vibration.Status status) {
         switch (status) {
             case IGNORED_BACKGROUND:
                 Slog.e(TAG, "Ignoring incoming vibration as process with"
@@ -813,7 +815,7 @@
         Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "reportFinishVibrationLocked");
         Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
         try {
-            Vibration vib = mCurrentVibration.getVibration();
+            HalVibration vib = mCurrentVibration.getVibration();
             if (DEBUG) {
                 Slog.d(TAG, "Reporting vibration " + vib.id + " finished with " + vibrationEndInfo);
             }
@@ -857,13 +859,13 @@
      */
     @GuardedBy("mLock")
     @Nullable
-    private Vibration.Status shouldIgnoreVibrationForOngoingLocked(Vibration vib) {
+    private Vibration.Status shouldIgnoreVibrationForOngoingLocked(HalVibration vib) {
         if (mCurrentVibration == null || vib.isRepeating()) {
             // Incoming repeating vibrations always take precedence over ongoing vibrations.
             return null;
         }
 
-        Vibration currentVibration = mCurrentVibration.getVibration();
+        HalVibration currentVibration = mCurrentVibration.getVibration();
         if (currentVibration.hasEnded() || mCurrentVibration.wasNotifiedToCancel()) {
             // Current vibration has ended or is cancelling, should not block incoming vibrations.
             return null;
@@ -945,7 +947,7 @@
      * @param token       The binder token to identify the vibration origin. Only vibrations
      *                    started with the same token can be cancelled with it.
      */
-    private boolean shouldCancelVibration(Vibration vib, int usageFilter, IBinder token) {
+    private boolean shouldCancelVibration(HalVibration vib, int usageFilter, IBinder token) {
         return (vib.token == token) && shouldCancelVibration(vib.attrs, usageFilter);
     }
 
@@ -1041,7 +1043,7 @@
      * Sets fallback effects to all prebaked ones in given combination of effects, based on {@link
      * VibrationSettings#getFallbackEffect}.
      */
-    private void fillVibrationFallbacks(Vibration vib, CombinedVibration effect) {
+    private void fillVibrationFallbacks(HalVibration vib, CombinedVibration effect) {
         if (effect instanceof CombinedVibration.Mono) {
             fillVibrationFallbacks(vib, ((CombinedVibration.Mono) effect).getEffect());
         } else if (effect instanceof CombinedVibration.Stereo) {
@@ -1059,7 +1061,7 @@
         }
     }
 
-    private void fillVibrationFallbacks(Vibration vib, VibrationEffect effect) {
+    private void fillVibrationFallbacks(HalVibration vib, VibrationEffect effect) {
         VibrationEffect.Composed composed = (VibrationEffect.Composed) effect;
         int segmentCount = composed.getSegments().size();
         for (int i = 0; i < segmentCount; i++) {
@@ -1183,7 +1185,7 @@
         if (conductor == null) {
             return false;
         }
-        Vibration vib = conductor.getVibration();
+        HalVibration vib = conductor.getVibration();
         return mVibrationSettings.shouldCancelVibrationOnScreenOff(
                 vib.uid, vib.opPkg, vib.attrs.getUsage(), vib.stats().getCreateUptimeMillis());
     }
@@ -1535,7 +1537,7 @@
             mPreviousVibrationsLimit = limit;
         }
 
-        synchronized void record(Vibration vib) {
+        synchronized void record(HalVibration vib) {
             int usage = vib.attrs.getUsage();
             if (!mPreviousVibrations.contains(usage)) {
                 mPreviousVibrations.put(usage, new LinkedList<>());
@@ -1870,7 +1872,7 @@
             // only cancel background vibrations.
             IBinder deathBinder = commonOptions.background ? VibratorManagerService.this
                     : mShellCallbacksToken;
-            Vibration vib = vibrateInternal(Binder.getCallingUid(), Display.DEFAULT_DISPLAY,
+            HalVibration vib = vibrateInternal(Binder.getCallingUid(), Display.DEFAULT_DISPLAY,
                     SHELL_PACKAGE_NAME, combined, attrs, commonOptions.description, deathBinder);
             if (vib != null && !commonOptions.background) {
                 try {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperData.java b/services/core/java/com/android/server/wallpaper/WallpaperData.java
index 625e7d9..6763514 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperData.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperData.java
@@ -30,7 +30,7 @@
 import android.content.ComponentName;
 import android.graphics.Rect;
 import android.os.RemoteCallbackList;
-import android.util.ArrayMap;
+import android.util.SparseArray;
 
 import java.io.File;
 
@@ -115,7 +115,7 @@
      * A map to keep track of the dimming set by different applications. The key is the calling
      * UID and the value is the dim amount.
      */
-    ArrayMap<Integer, Float> mUidToDimAmount = new ArrayMap<>();
+    SparseArray<Float> mUidToDimAmount = new SparseArray<>();
 
     /**
      * Whether we need to extract the wallpaper colors again to calculate the dark hints
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
new file mode 100644
index 0000000..07a7837
--- /dev/null
+++ b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
@@ -0,0 +1,550 @@
+/*
+ * 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.wallpaper;
+
+import static android.app.WallpaperManager.FLAG_LOCK;
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.server.wallpaper.WallpaperDisplayHelper.DisplayData;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_CROP;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_INFO;
+import static com.android.server.wallpaper.WallpaperUtils.getWallpaperDir;
+import static com.android.server.wallpaper.WallpaperUtils.makeWallpaperIdLocked;
+
+import android.annotation.Nullable;
+import android.app.WallpaperColors;
+import android.app.backup.WallpaperBackupHelper;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.os.FileUtils;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.Xml;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.JournaledFile;
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Helper for the wallpaper loading / saving / xml parsing
+ * Only meant to be used lock held by WallpaperManagerService
+ * Only meant to be instantiated once by WallpaperManagerService
+ */
+class WallpaperDataParser {
+
+    private static final String TAG = WallpaperDataParser.class.getSimpleName();
+    private static final boolean DEBUG = false;
+    private final ComponentName mImageWallpaper;
+    private final WallpaperDisplayHelper mWallpaperDisplayHelper;
+    private final WallpaperCropper mWallpaperCropper;
+    private final Context mContext;
+
+    WallpaperDataParser(Context context, WallpaperDisplayHelper wallpaperDisplayHelper,
+            WallpaperCropper wallpaperCropper) {
+        mContext = context;
+        mWallpaperDisplayHelper = wallpaperDisplayHelper;
+        mWallpaperCropper = wallpaperCropper;
+        mImageWallpaper = ComponentName.unflattenFromString(
+                context.getResources().getString(R.string.image_wallpaper_component));
+    }
+
+    private JournaledFile makeJournaledFile(int userId) {
+        final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
+        return new JournaledFile(new File(base), new File(base + ".tmp"));
+    }
+
+    static class WallpaperLoadingResult {
+
+        private final WallpaperData mSystemWallpaperData;
+
+        @Nullable
+        private final WallpaperData mLockWallpaperData;
+
+        private final boolean mSuccess;
+
+        private WallpaperLoadingResult(
+                WallpaperData systemWallpaperData,
+                WallpaperData lockWallpaperData,
+                boolean success) {
+            mSystemWallpaperData = systemWallpaperData;
+            mLockWallpaperData = lockWallpaperData;
+            mSuccess = success;
+        }
+
+        public WallpaperData getSystemWallpaperData() {
+            return mSystemWallpaperData;
+        }
+
+        public WallpaperData getLockWallpaperData() {
+            return mLockWallpaperData;
+        }
+
+        public boolean success() {
+            return mSuccess;
+        }
+    }
+
+    /**
+     * Load the system wallpaper (and the lock wallpaper, if it exists) from disk
+     * @param userId the id of the user for which the wallpaper should be loaded
+     * @param keepDimensionHints if false, parse and set the
+     *                      {@link DisplayData} width and height for the specified userId
+     * @param wallpaper the wallpaper object to reuse to do the modifications.
+     *                      If null, a new object will be created.
+     * @param lockWallpaper the lock wallpaper object to reuse to do the modifications.
+     *                      If null, a new object will be created.
+     * @return a {@link WallpaperLoadingResult} object containing the wallpaper data.
+     *                      This object will contain the {@code wallpaper} and
+     *                      {@code lockWallpaper} provided as parameters, if they are not null.
+     */
+    public WallpaperLoadingResult loadSettingsLocked(int userId, boolean keepDimensionHints,
+            WallpaperData wallpaper, WallpaperData lockWallpaper) {
+        JournaledFile journal = makeJournaledFile(userId);
+        FileInputStream stream = null;
+        File file = journal.chooseForRead();
+
+        if (wallpaper == null) {
+            // Do this once per boot
+            migrateFromOld();
+            wallpaper = new WallpaperData(userId, FLAG_SYSTEM);
+            wallpaper.allowBackup = true;
+            if (!wallpaper.cropExists()) {
+                if (wallpaper.sourceExists()) {
+                    mWallpaperCropper.generateCrop(wallpaper);
+                } else {
+                    Slog.i(TAG, "No static wallpaper imagery; defaults will be shown");
+                }
+            }
+        }
+
+        final DisplayData wpdData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
+        boolean success = false;
+
+        try {
+            stream = new FileInputStream(file);
+            TypedXmlPullParser parser = Xml.resolvePullParser(stream);
+
+            int type;
+            do {
+                type = parser.next();
+                if (type == XmlPullParser.START_TAG) {
+                    String tag = parser.getName();
+                    if ("wp".equals(tag)) {
+                        // Common to system + lock wallpapers
+                        parseWallpaperAttributes(parser, wallpaper, keepDimensionHints);
+
+                        // A system wallpaper might also be a live wallpaper
+                        String comp = parser.getAttributeValue(null, "component");
+                        wallpaper.nextWallpaperComponent = comp != null
+                                ? ComponentName.unflattenFromString(comp)
+                                : null;
+                        if (wallpaper.nextWallpaperComponent == null
+                                || "android".equals(wallpaper.nextWallpaperComponent
+                                .getPackageName())) {
+                            wallpaper.nextWallpaperComponent = mImageWallpaper;
+                        }
+
+                        if (DEBUG) {
+                            Slog.v(TAG, "mWidth:" + wpdData.mWidth);
+                            Slog.v(TAG, "mHeight:" + wpdData.mHeight);
+                            Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
+                            Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
+                            Slog.v(TAG, "mName:" + wallpaper.name);
+                            Slog.v(TAG, "mNextWallpaperComponent:"
+                                    + wallpaper.nextWallpaperComponent);
+                        }
+                    } else if ("kwp".equals(tag)) {
+                        // keyguard-specific wallpaper for this user
+
+                        if (lockWallpaper == null) {
+                            lockWallpaper = new WallpaperData(userId, FLAG_LOCK);
+                        }
+                        parseWallpaperAttributes(parser, lockWallpaper, false);
+                    }
+                }
+            } while (type != XmlPullParser.END_DOCUMENT);
+            success = true;
+        } catch (FileNotFoundException e) {
+            Slog.w(TAG, "no current wallpaper -- first boot?");
+        } catch (NullPointerException e) {
+            Slog.w(TAG, "failed parsing " + file + " " + e);
+        } catch (NumberFormatException e) {
+            Slog.w(TAG, "failed parsing " + file + " " + e);
+        } catch (XmlPullParserException e) {
+            Slog.w(TAG, "failed parsing " + file + " " + e);
+        } catch (IOException e) {
+            Slog.w(TAG, "failed parsing " + file + " " + e);
+        } catch (IndexOutOfBoundsException e) {
+            Slog.w(TAG, "failed parsing " + file + " " + e);
+        }
+        IoUtils.closeQuietly(stream);
+
+        if (!success) {
+            wallpaper.cropHint.set(0, 0, 0, 0);
+            wpdData.mPadding.set(0, 0, 0, 0);
+            wallpaper.name = "";
+            lockWallpaper = null;
+        } else {
+            if (wallpaper.wallpaperId <= 0) {
+                wallpaper.wallpaperId = makeWallpaperIdLocked();
+                if (DEBUG) {
+                    Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
+                            + "); now " + wallpaper.wallpaperId);
+                }
+            }
+        }
+
+        mWallpaperDisplayHelper.ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
+        ensureSaneWallpaperData(wallpaper);
+        if (lockWallpaper != null) {
+            ensureSaneWallpaperData(lockWallpaper);
+            lockWallpaper.mWhich = FLAG_LOCK;
+            wallpaper.mWhich = FLAG_SYSTEM;
+        } else {
+            wallpaper.mWhich = FLAG_SYSTEM | FLAG_LOCK;
+        }
+
+        return new WallpaperLoadingResult(wallpaper, lockWallpaper, success);
+    }
+
+    private void ensureSaneWallpaperData(WallpaperData wallpaper) {
+        // Only overwrite cropHint if the rectangle is invalid.
+        if (wallpaper.cropHint.width() < 0
+                || wallpaper.cropHint.height() < 0) {
+            wallpaper.cropHint.set(0, 0, 0, 0);
+        }
+    }
+
+
+    private void migrateFromOld() {
+        // Pre-N, what existed is the one we're now using as the display crop
+        File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
+        // In the very-long-ago, imagery lived with the settings app
+        File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
+        File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
+
+        // Migrations from earlier wallpaper image storage schemas
+        if (preNWallpaper.exists()) {
+            if (!newWallpaper.exists()) {
+                // we've got the 'wallpaper' crop file but not the nominal source image,
+                // so do the simple "just take everything" straight copy of legacy data
+                if (DEBUG) {
+                    Slog.i(TAG, "Migrating wallpaper schema");
+                }
+                FileUtils.copyFile(preNWallpaper, newWallpaper);
+            } // else we're in the usual modern case: both source & crop exist
+        } else if (originalWallpaper.exists()) {
+            // VERY old schema; make sure things exist and are in the right place
+            if (DEBUG) {
+                Slog.i(TAG, "Migrating antique wallpaper schema");
+            }
+            File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
+            if (oldInfo.exists()) {
+                File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
+                oldInfo.renameTo(newInfo);
+            }
+
+            FileUtils.copyFile(originalWallpaper, preNWallpaper);
+            originalWallpaper.renameTo(newWallpaper);
+        }
+    }
+
+    @VisibleForTesting
+    void parseWallpaperAttributes(TypedXmlPullParser parser, WallpaperData wallpaper,
+            boolean keepDimensionHints) throws XmlPullParserException {
+        final int id = parser.getAttributeInt(null, "id", -1);
+        if (id != -1) {
+            wallpaper.wallpaperId = id;
+            if (id > WallpaperUtils.getCurrentWallpaperId()) {
+                WallpaperUtils.setCurrentWallpaperId(id);
+            }
+        } else {
+            wallpaper.wallpaperId = makeWallpaperIdLocked();
+        }
+
+        final DisplayData wpData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
+
+        if (!keepDimensionHints) {
+            wpData.mWidth = parser.getAttributeInt(null, "width");
+            wpData.mHeight = parser.getAttributeInt(null, "height");
+        }
+        wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
+        wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
+        wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
+        wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
+        wpData.mPadding.left = getAttributeInt(parser, "paddingLeft", 0);
+        wpData.mPadding.top = getAttributeInt(parser, "paddingTop", 0);
+        wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
+        wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
+        wallpaper.mWallpaperDimAmount = getAttributeFloat(parser, "dimAmount", 0f);
+        int dimAmountsCount = getAttributeInt(parser, "dimAmountsCount", 0);
+        if (dimAmountsCount > 0) {
+            SparseArray<Float> allDimAmounts = new SparseArray<>(dimAmountsCount);
+            for (int i = 0; i < dimAmountsCount; i++) {
+                int uid = getAttributeInt(parser, "dimUID" + i, 0);
+                float dimValue = getAttributeFloat(parser, "dimValue" + i, 0f);
+                allDimAmounts.put(uid, dimValue);
+            }
+            wallpaper.mUidToDimAmount = allDimAmounts;
+        }
+        int colorsCount = getAttributeInt(parser, "colorsCount", 0);
+        int allColorsCount =  getAttributeInt(parser, "allColorsCount", 0);
+        if (allColorsCount > 0) {
+            Map<Integer, Integer> allColors = new HashMap<>(allColorsCount);
+            for (int i = 0; i < allColorsCount; i++) {
+                int colorInt = getAttributeInt(parser, "allColorsValue" + i, 0);
+                int population = getAttributeInt(parser, "allColorsPopulation" + i, 0);
+                allColors.put(colorInt, population);
+            }
+            int colorHints = getAttributeInt(parser, "colorHints", 0);
+            wallpaper.primaryColors = new WallpaperColors(allColors, colorHints);
+        } else if (colorsCount > 0) {
+            Color primary = null, secondary = null, tertiary = null;
+            for (int i = 0; i < colorsCount; i++) {
+                Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0));
+                if (i == 0) {
+                    primary = color;
+                } else if (i == 1) {
+                    secondary = color;
+                } else if (i == 2) {
+                    tertiary = color;
+                } else {
+                    break;
+                }
+            }
+            int colorHints = getAttributeInt(parser, "colorHints", 0);
+            wallpaper.primaryColors = new WallpaperColors(primary, secondary, tertiary, colorHints);
+        }
+        wallpaper.name = parser.getAttributeValue(null, "name");
+        wallpaper.allowBackup = parser.getAttributeBoolean(null, "backup", false);
+    }
+
+    private int getAttributeInt(TypedXmlPullParser parser, String name, int defValue) {
+        return parser.getAttributeInt(null, name, defValue);
+    }
+
+    private float getAttributeFloat(TypedXmlPullParser parser, String name, float defValue) {
+        return parser.getAttributeFloat(null, name, defValue);
+    }
+
+    void saveSettingsLocked(int userId, WallpaperData wallpaper, WallpaperData lockWallpaper) {
+        JournaledFile journal = makeJournaledFile(userId);
+        FileOutputStream fstream = null;
+        try {
+            fstream = new FileOutputStream(journal.chooseForWrite(), false);
+            TypedXmlSerializer out = Xml.resolveSerializer(fstream);
+            out.startDocument(null, true);
+
+            if (wallpaper != null) {
+                writeWallpaperAttributes(out, "wp", wallpaper);
+            }
+
+            if (lockWallpaper != null) {
+                writeWallpaperAttributes(out, "kwp", lockWallpaper);
+            }
+
+            out.endDocument();
+
+            fstream.flush();
+            FileUtils.sync(fstream);
+            fstream.close();
+            journal.commit();
+        } catch (IOException e) {
+            IoUtils.closeQuietly(fstream);
+            journal.rollback();
+        }
+    }
+
+    @VisibleForTesting
+    void writeWallpaperAttributes(TypedXmlSerializer out, String tag, WallpaperData wallpaper)
+            throws IllegalArgumentException, IllegalStateException, IOException {
+        if (DEBUG) {
+            Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
+        }
+        final DisplayData wpdData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
+        out.startTag(null, tag);
+        out.attributeInt(null, "id", wallpaper.wallpaperId);
+        out.attributeInt(null, "width", wpdData.mWidth);
+        out.attributeInt(null, "height", wpdData.mHeight);
+
+        out.attributeInt(null, "cropLeft", wallpaper.cropHint.left);
+        out.attributeInt(null, "cropTop", wallpaper.cropHint.top);
+        out.attributeInt(null, "cropRight", wallpaper.cropHint.right);
+        out.attributeInt(null, "cropBottom", wallpaper.cropHint.bottom);
+
+        if (wpdData.mPadding.left != 0) {
+            out.attributeInt(null, "paddingLeft", wpdData.mPadding.left);
+        }
+        if (wpdData.mPadding.top != 0) {
+            out.attributeInt(null, "paddingTop", wpdData.mPadding.top);
+        }
+        if (wpdData.mPadding.right != 0) {
+            out.attributeInt(null, "paddingRight", wpdData.mPadding.right);
+        }
+        if (wpdData.mPadding.bottom != 0) {
+            out.attributeInt(null, "paddingBottom", wpdData.mPadding.bottom);
+        }
+
+        out.attributeFloat(null, "dimAmount", wallpaper.mWallpaperDimAmount);
+        int dimAmountsCount = wallpaper.mUidToDimAmount.size();
+        out.attributeInt(null, "dimAmountsCount", dimAmountsCount);
+        if (dimAmountsCount > 0) {
+            int index = 0;
+            for (int i = 0; i < wallpaper.mUidToDimAmount.size(); i++) {
+                out.attributeInt(null, "dimUID" + index, wallpaper.mUidToDimAmount.keyAt(i));
+                out.attributeFloat(null, "dimValue" + index, wallpaper.mUidToDimAmount.valueAt(i));
+                index++;
+            }
+        }
+
+        if (wallpaper.primaryColors != null) {
+            int colorsCount = wallpaper.primaryColors.getMainColors().size();
+            out.attributeInt(null, "colorsCount", colorsCount);
+            if (colorsCount > 0) {
+                for (int i = 0; i < colorsCount; i++) {
+                    final Color wc = wallpaper.primaryColors.getMainColors().get(i);
+                    out.attributeInt(null, "colorValue" + i, wc.toArgb());
+                }
+            }
+
+            int allColorsCount = wallpaper.primaryColors.getAllColors().size();
+            out.attributeInt(null, "allColorsCount", allColorsCount);
+            if (allColorsCount > 0) {
+                int index = 0;
+                for (Map.Entry<Integer, Integer> entry : wallpaper.primaryColors.getAllColors()
+                        .entrySet()) {
+                    out.attributeInt(null, "allColorsValue" + index, entry.getKey());
+                    out.attributeInt(null, "allColorsPopulation" + index, entry.getValue());
+                    index++;
+                }
+            }
+
+            out.attributeInt(null, "colorHints", wallpaper.primaryColors.getColorHints());
+        }
+
+        out.attribute(null, "name", wallpaper.name);
+        if (wallpaper.wallpaperComponent != null
+                && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
+            out.attribute(null, "component",
+                    wallpaper.wallpaperComponent.flattenToShortString());
+        }
+
+        if (wallpaper.allowBackup) {
+            out.attributeBoolean(null, "backup", true);
+        }
+
+        out.endTag(null, tag);
+    }
+
+    // Restore the named resource bitmap to both source + crop files
+    boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
+        if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
+            String resName = wallpaper.name.substring(4);
+
+            String pkg = null;
+            int colon = resName.indexOf(':');
+            if (colon > 0) {
+                pkg = resName.substring(0, colon);
+            }
+
+            String ident = null;
+            int slash = resName.lastIndexOf('/');
+            if (slash > 0) {
+                ident = resName.substring(slash + 1);
+            }
+
+            String type = null;
+            if (colon > 0 && slash > 0 && (slash - colon) > 1) {
+                type = resName.substring(colon + 1, slash);
+            }
+
+            if (pkg != null && ident != null && type != null) {
+                int resId = -1;
+                InputStream res = null;
+                FileOutputStream fos = null;
+                FileOutputStream cos = null;
+                try {
+                    Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
+                    Resources r = c.getResources();
+                    resId = r.getIdentifier(resName, null, null);
+                    if (resId == 0) {
+                        Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
+                                + " ident=" + ident);
+                        return false;
+                    }
+
+                    res = r.openRawResource(resId);
+                    if (wallpaper.wallpaperFile.exists()) {
+                        wallpaper.wallpaperFile.delete();
+                        wallpaper.cropFile.delete();
+                    }
+                    fos = new FileOutputStream(wallpaper.wallpaperFile);
+                    cos = new FileOutputStream(wallpaper.cropFile);
+
+                    byte[] buffer = new byte[32768];
+                    int amt;
+                    while ((amt = res.read(buffer)) > 0) {
+                        fos.write(buffer, 0, amt);
+                        cos.write(buffer, 0, amt);
+                    }
+                    // mWallpaperObserver will notice the close and send the change broadcast
+
+                    Slog.v(TAG, "Restored wallpaper: " + resName);
+                    return true;
+                } catch (PackageManager.NameNotFoundException e) {
+                    Slog.e(TAG, "Package name " + pkg + " not found");
+                } catch (Resources.NotFoundException e) {
+                    Slog.e(TAG, "Resource not found: " + resId);
+                } catch (IOException e) {
+                    Slog.e(TAG, "IOException while restoring wallpaper ", e);
+                } finally {
+                    IoUtils.closeQuietly(res);
+                    if (fos != null) {
+                        FileUtils.sync(fos);
+                    }
+                    if (cos != null) {
+                        FileUtils.sync(cos);
+                    }
+                    IoUtils.closeQuietly(fos);
+                    IoUtils.closeQuietly(cos);
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperDisplayHelper.java b/services/core/java/com/android/server/wallpaper/WallpaperDisplayHelper.java
index f02ee66..3f02266 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperDisplayHelper.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperDisplayHelper.java
@@ -30,6 +30,7 @@
 import com.android.server.wm.WindowManagerInternal;
 
 import java.util.function.Consumer;
+
 /**
  * Internal class used to store all the display data relevant to the wallpapers
  */
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 262b964..198c339 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -17,7 +17,6 @@
 package com.android.server.wallpaper;
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.Manifest.permission.QUERY_ALL_PACKAGES;
 import static android.Manifest.permission.READ_WALLPAPER_INTERNAL;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
 import static android.app.WallpaperManager.COMMAND_REAPPLY;
@@ -36,7 +35,6 @@
 import static com.android.server.wallpaper.WallpaperUtils.RECORD_FILE;
 import static com.android.server.wallpaper.WallpaperUtils.RECORD_LOCK_FILE;
 import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER;
-import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_CROP;
 import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_INFO;
 import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_LOCK_ORIG;
 import static com.android.server.wallpaper.WallpaperUtils.getWallpaperDir;
@@ -57,7 +55,6 @@
 import android.app.WallpaperManager;
 import android.app.WallpaperManager.SetWallpaperFlags;
 import android.app.admin.DevicePolicyManagerInternal;
-import android.app.backup.WallpaperBackupHelper;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -67,13 +64,12 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
-import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.hardware.display.DisplayManager;
@@ -101,12 +97,10 @@
 import android.service.wallpaper.WallpaperService;
 import android.system.ErrnoException;
 import android.system.Os;
-import android.util.ArrayMap;
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
-import android.util.Xml;
 import android.view.Display;
 
 import com.android.internal.R;
@@ -114,9 +108,6 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.DumpUtils;
-import com.android.internal.util.JournaledFile;
-import com.android.modules.utils.TypedXmlPullParser;
-import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.EventLogTags;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
@@ -125,22 +116,16 @@
 import com.android.server.utils.TimingsTraceAndSlog;
 import com.android.server.wm.WindowManagerInternal;
 
-import libcore.io.IoUtils;
-
-import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -152,7 +137,6 @@
     private static final String TAG = "WallpaperManagerService";
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_LIVE = true;
-    private static final boolean DEBUG_CROP = true;
 
     private static final @NonNull RectF LOCAL_COLOR_BOUNDS =
             new RectF(0, 0, 1, 1);
@@ -759,6 +743,7 @@
 
     private final Context mContext;
     private final WindowManagerInternal mWindowManagerInternal;
+    private final PackageManagerInternal mPackageManagerInternal;
     private final IPackageManager mIPackageManager;
     private final ActivityManager mActivityManager;
     private final MyPackageMonitor mMonitor;
@@ -848,6 +833,9 @@
     private LocalColorRepository mLocalColorRepo = new LocalColorRepository();
 
     @VisibleForTesting
+    final WallpaperDataParser mWallpaperDataParser;
+
+    @VisibleForTesting
     final WallpaperDisplayHelper mWallpaperDisplayHelper;
     final WallpaperCropper mWallpaperCropper;
 
@@ -1604,12 +1592,15 @@
                 context.getResources().getString(R.string.image_wallpaper_component));
         mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
         mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mIPackageManager = AppGlobals.getPackageManager();
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         DisplayManager dm = mContext.getSystemService(DisplayManager.class);
         dm.registerDisplayListener(mDisplayListener, null /* handler */);
         mWallpaperDisplayHelper = new WallpaperDisplayHelper(dm, mWindowManagerInternal);
         mWallpaperCropper = new WallpaperCropper(mWallpaperDisplayHelper);
+        mWallpaperDataParser = new WallpaperDataParser(
+                mContext, mWallpaperDisplayHelper, mWallpaperCropper);
         mActivityManager = mContext.getSystemService(ActivityManager.class);
         mMonitor = new MyPackageMonitor();
         mColorsChangedListeners = new SparseArray<>();
@@ -1897,7 +1888,6 @@
                     // bound into place
                     wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
                     final WallpaperData fallback = new WallpaperData(wallpaper.userId, FLAG_LOCK);
-                    ensureSaneWallpaperData(fallback);
                     bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
                     mWaitingForUnlock = true;
                 }
@@ -2283,20 +2273,23 @@
 
     @Override
     public WallpaperInfo getWallpaperInfoWithFlags(@SetWallpaperFlags int which, int userId) {
-        final boolean allow =
-                hasPermission(READ_WALLPAPER_INTERNAL) || hasPermission(QUERY_ALL_PACKAGES);
-        if (allow) {
-            userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
-                    Binder.getCallingUid(), userId, false, true, "getWallpaperInfo", null);
-            synchronized (mLock) {
-                WallpaperData wallpaper = (which == FLAG_LOCK) ? mLockWallpaperMap.get(userId)
-                        : mWallpaperMap.get(userId);
-                if (wallpaper != null && wallpaper.connection != null) {
-                    return wallpaper.connection.mInfo;
-                }
+
+        userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+                Binder.getCallingUid(), userId, false, true, "getWallpaperInfo", null);
+        synchronized (mLock) {
+            WallpaperData wallpaper = (which == FLAG_LOCK) ? mLockWallpaperMap.get(userId)
+                    : mWallpaperMap.get(userId);
+            if (wallpaper == null
+                    || wallpaper.connection == null
+                    || wallpaper.connection.mInfo == null) return null;
+
+            WallpaperInfo info = wallpaper.connection.mInfo;
+            if (hasPermission(READ_WALLPAPER_INTERNAL)
+                    || mPackageManagerInternal.canQueryPackage(
+                            Binder.getCallingUid(), info.getComponent().getPackageName())) {
+                return info;
             }
         }
-
         return null;
     }
 
@@ -2625,12 +2618,10 @@
      *
      * @param uidToDimAmountMap Map of UIDs to dim amounts
      */
-    private float getHighestDimAmountFromMap(ArrayMap<Integer, Float> uidToDimAmountMap) {
+    private float getHighestDimAmountFromMap(SparseArray<Float> uidToDimAmountMap) {
         float maxDimAmount = 0.0f;
-        for (Map.Entry<Integer, Float> entry : uidToDimAmountMap.entrySet()) {
-            if (entry.getValue() > maxDimAmount) {
-                maxDimAmount = entry.getValue();
-            }
+        for (int i = 0; i < uidToDimAmountMap.size(); i++) {
+            maxDimAmount = Math.max(maxDimAmount, uidToDimAmountMap.valueAt(i));
         }
         return maxDimAmount;
     }
@@ -3427,169 +3418,14 @@
         }
     }
 
-    private JournaledFile makeJournaledFile(int userId) {
-        final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
-        return new JournaledFile(new File(base), new File(base + ".tmp"));
-    }
-
     void saveSettingsLocked(int userId) {
         TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
         t.traceBegin("WPMS.saveSettingsLocked-" + userId);
-        JournaledFile journal = makeJournaledFile(userId);
-        FileOutputStream fstream = null;
-        try {
-            fstream = new FileOutputStream(journal.chooseForWrite(), false);
-            TypedXmlSerializer out = Xml.resolveSerializer(fstream);
-            out.startDocument(null, true);
-
-            WallpaperData wallpaper;
-
-            wallpaper = mWallpaperMap.get(userId);
-            if (wallpaper != null) {
-                writeWallpaperAttributes(out, "wp", wallpaper);
-            }
-            wallpaper = mLockWallpaperMap.get(userId);
-            if (wallpaper != null) {
-                writeWallpaperAttributes(out, "kwp", wallpaper);
-            }
-
-            out.endDocument();
-
-            fstream.flush();
-            FileUtils.sync(fstream);
-            fstream.close();
-            journal.commit();
-        } catch (IOException e) {
-            IoUtils.closeQuietly(fstream);
-            journal.rollback();
-        }
+        mWallpaperDataParser.saveSettingsLocked(
+                userId, mWallpaperMap.get(userId), mLockWallpaperMap.get(userId));
         t.traceEnd();
     }
 
-
-    @VisibleForTesting
-    void writeWallpaperAttributes(TypedXmlSerializer out, String tag,
-            WallpaperData wallpaper)
-            throws IllegalArgumentException, IllegalStateException, IOException {
-        if (DEBUG) {
-            Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
-        }
-        final DisplayData wpdData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
-        out.startTag(null, tag);
-        out.attributeInt(null, "id", wallpaper.wallpaperId);
-        out.attributeInt(null, "width", wpdData.mWidth);
-        out.attributeInt(null, "height", wpdData.mHeight);
-
-        out.attributeInt(null, "cropLeft", wallpaper.cropHint.left);
-        out.attributeInt(null, "cropTop", wallpaper.cropHint.top);
-        out.attributeInt(null, "cropRight", wallpaper.cropHint.right);
-        out.attributeInt(null, "cropBottom", wallpaper.cropHint.bottom);
-
-        if (wpdData.mPadding.left != 0) {
-            out.attributeInt(null, "paddingLeft", wpdData.mPadding.left);
-        }
-        if (wpdData.mPadding.top != 0) {
-            out.attributeInt(null, "paddingTop", wpdData.mPadding.top);
-        }
-        if (wpdData.mPadding.right != 0) {
-            out.attributeInt(null, "paddingRight", wpdData.mPadding.right);
-        }
-        if (wpdData.mPadding.bottom != 0) {
-            out.attributeInt(null, "paddingBottom", wpdData.mPadding.bottom);
-        }
-
-        out.attributeFloat(null, "dimAmount", wallpaper.mWallpaperDimAmount);
-        int dimAmountsCount = wallpaper.mUidToDimAmount.size();
-        out.attributeInt(null, "dimAmountsCount", dimAmountsCount);
-        if (dimAmountsCount > 0) {
-            int index = 0;
-            for (Map.Entry<Integer, Float> entry : wallpaper.mUidToDimAmount.entrySet()) {
-                out.attributeInt(null, "dimUID" + index, entry.getKey());
-                out.attributeFloat(null, "dimValue" + index, entry.getValue());
-                index++;
-            }
-        }
-
-        if (wallpaper.primaryColors != null) {
-            int colorsCount = wallpaper.primaryColors.getMainColors().size();
-            out.attributeInt(null, "colorsCount", colorsCount);
-            if (colorsCount > 0) {
-                for (int i = 0; i < colorsCount; i++) {
-                    final Color wc = wallpaper.primaryColors.getMainColors().get(i);
-                    out.attributeInt(null, "colorValue" + i, wc.toArgb());
-                }
-            }
-
-            int allColorsCount = wallpaper.primaryColors.getAllColors().size();
-            out.attributeInt(null, "allColorsCount", allColorsCount);
-            if (allColorsCount > 0) {
-                int index = 0;
-                for (Map.Entry<Integer, Integer> entry : wallpaper.primaryColors.getAllColors()
-                        .entrySet()) {
-                    out.attributeInt(null, "allColorsValue" + index, entry.getKey());
-                    out.attributeInt(null, "allColorsPopulation" + index, entry.getValue());
-                    index++;
-                }
-            }
-
-            out.attributeInt(null, "colorHints", wallpaper.primaryColors.getColorHints());
-        }
-
-        out.attribute(null, "name", wallpaper.name);
-        if (wallpaper.wallpaperComponent != null
-                && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
-            out.attribute(null, "component",
-                    wallpaper.wallpaperComponent.flattenToShortString());
-        }
-
-        if (wallpaper.allowBackup) {
-            out.attributeBoolean(null, "backup", true);
-        }
-
-        out.endTag(null, tag);
-    }
-
-    private void migrateFromOld() {
-        // Pre-N, what existed is the one we're now using as the display crop
-        File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
-        // In the very-long-ago, imagery lived with the settings app
-        File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
-        File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
-
-        // Migrations from earlier wallpaper image storage schemas
-        if (preNWallpaper.exists()) {
-            if (!newWallpaper.exists()) {
-                // we've got the 'wallpaper' crop file but not the nominal source image,
-                // so do the simple "just take everything" straight copy of legacy data
-                if (DEBUG) {
-                    Slog.i(TAG, "Migrating wallpaper schema");
-                }
-                FileUtils.copyFile(preNWallpaper, newWallpaper);
-            } // else we're in the usual modern case: both source & crop exist
-        } else if (originalWallpaper.exists()) {
-            // VERY old schema; make sure things exist and are in the right place
-            if (DEBUG) {
-                Slog.i(TAG, "Migrating antique wallpaper schema");
-            }
-            File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
-            if (oldInfo.exists()) {
-                File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
-                oldInfo.renameTo(newInfo);
-            }
-
-            FileUtils.copyFile(originalWallpaper, preNWallpaper);
-            originalWallpaper.renameTo(newWallpaper);
-        }
-    }
-
-    private int getAttributeInt(TypedXmlPullParser parser, String name, int defValue) {
-        return parser.getAttributeInt(null, name, defValue);
-    }
-
-    private float getAttributeFloat(TypedXmlPullParser parser, String name, float defValue) {
-        return parser.getAttributeFloat(null, name, defValue);
-    }
-
     /**
      * Determines and returns the current wallpaper for the given user and destination, creating
      * a valid entry if it does not already exist and adding it to the appropriate wallpaper map.
@@ -3624,14 +3460,12 @@
                 if (which == FLAG_LOCK) {
                     wallpaper = new WallpaperData(userId, FLAG_LOCK);
                     mLockWallpaperMap.put(userId, wallpaper);
-                    ensureSaneWallpaperData(wallpaper);
                 } else {
                     // rationality fallback: we're in bad shape, but establishing a known
                     // valid system+lock WallpaperData will keep us from dying.
                     Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
                     wallpaper = new WallpaperData(userId, FLAG_SYSTEM);
                     mWallpaperMap.put(userId, wallpaper);
-                    ensureSaneWallpaperData(wallpaper);
                 }
             }
         }
@@ -3639,114 +3473,17 @@
     }
 
     private void loadSettingsLocked(int userId, boolean keepDimensionHints) {
-        JournaledFile journal = makeJournaledFile(userId);
-        FileInputStream stream = null;
-        File file = journal.chooseForRead();
+        initializeFallbackWallpaper();
+        WallpaperData wallpaperData = mWallpaperMap.get(userId);
+        WallpaperData lockWallpaperData = mLockWallpaperMap.get(userId);
+        WallpaperDataParser.WallpaperLoadingResult result = mWallpaperDataParser.loadSettingsLocked(
+                userId, keepDimensionHints, wallpaperData, lockWallpaperData);
 
-        WallpaperData wallpaper = mWallpaperMap.get(userId);
-        if (wallpaper == null) {
-            // Do this once per boot
-            migrateFromOld();
-
-            wallpaper = new WallpaperData(userId, FLAG_SYSTEM);
-            wallpaper.allowBackup = true;
-            mWallpaperMap.put(userId, wallpaper);
-            if (!wallpaper.cropExists()) {
-                if (wallpaper.sourceExists()) {
-                    mWallpaperCropper.generateCrop(wallpaper);
-                } else {
-                    Slog.i(TAG, "No static wallpaper imagery; defaults will be shown");
-                }
-            }
-            initializeFallbackWallpaper();
-        }
-        boolean success = false;
-        final DisplayData wpdData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
-        try {
-            stream = new FileInputStream(file);
-            TypedXmlPullParser parser = Xml.resolvePullParser(stream);
-
-            int type;
-            do {
-                type = parser.next();
-                if (type == XmlPullParser.START_TAG) {
-                    String tag = parser.getName();
-                    if ("wp".equals(tag)) {
-                        // Common to system + lock wallpapers
-                        parseWallpaperAttributes(parser, wallpaper, keepDimensionHints);
-
-                        // A system wallpaper might also be a live wallpaper
-                        String comp = parser.getAttributeValue(null, "component");
-                        wallpaper.nextWallpaperComponent = comp != null
-                                ? ComponentName.unflattenFromString(comp)
-                                : null;
-                        if (wallpaper.nextWallpaperComponent == null
-                                || "android".equals(wallpaper.nextWallpaperComponent
-                                        .getPackageName())) {
-                            wallpaper.nextWallpaperComponent = mImageWallpaper;
-                        }
-
-                        if (DEBUG) {
-                            Slog.v(TAG, "mWidth:" + wpdData.mWidth);
-                            Slog.v(TAG, "mHeight:" + wpdData.mHeight);
-                            Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
-                            Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
-                            Slog.v(TAG, "mName:" + wallpaper.name);
-                            Slog.v(TAG, "mNextWallpaperComponent:"
-                                    + wallpaper.nextWallpaperComponent);
-                        }
-                    } else if ("kwp".equals(tag)) {
-                        // keyguard-specific wallpaper for this user
-                        WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
-                        if (lockWallpaper == null) {
-                            lockWallpaper = new WallpaperData(userId, FLAG_LOCK);
-                            mLockWallpaperMap.put(userId, lockWallpaper);
-                        }
-                        parseWallpaperAttributes(parser, lockWallpaper, false);
-                    }
-                }
-            } while (type != XmlPullParser.END_DOCUMENT);
-            success = true;
-        } catch (FileNotFoundException e) {
-            Slog.w(TAG, "no current wallpaper -- first boot?");
-        } catch (NullPointerException e) {
-            Slog.w(TAG, "failed parsing " + file + " " + e);
-        } catch (NumberFormatException e) {
-            Slog.w(TAG, "failed parsing " + file + " " + e);
-        } catch (XmlPullParserException e) {
-            Slog.w(TAG, "failed parsing " + file + " " + e);
-        } catch (IOException e) {
-            Slog.w(TAG, "failed parsing " + file + " " + e);
-        } catch (IndexOutOfBoundsException e) {
-            Slog.w(TAG, "failed parsing " + file + " " + e);
-        }
-        IoUtils.closeQuietly(stream);
-
-        if (!success) {
-            wallpaper.cropHint.set(0, 0, 0, 0);
-            wpdData.mPadding.set(0, 0, 0, 0);
-            wallpaper.name = "";
-
+        mWallpaperMap.put(userId, result.getSystemWallpaperData());
+        if (result.success()) {
+            mLockWallpaperMap.put(userId, result.getLockWallpaperData());
+        } else {
             mLockWallpaperMap.remove(userId);
-        } else {
-            if (wallpaper.wallpaperId <= 0) {
-                wallpaper.wallpaperId = makeWallpaperIdLocked();
-                if (DEBUG) {
-                    Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
-                            + "); now " + wallpaper.wallpaperId);
-                }
-            }
-        }
-
-        mWallpaperDisplayHelper.ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
-        ensureSaneWallpaperData(wallpaper);
-        WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
-        if (lockWallpaper != null) {
-            ensureSaneWallpaperData(lockWallpaper);
-            lockWallpaper.mWhich = FLAG_LOCK;
-            wallpaper.mWhich = FLAG_SYSTEM;
-        } else {
-            wallpaper.mWhich = FLAG_SYSTEM | FLAG_LOCK;
         }
     }
 
@@ -3761,84 +3498,6 @@
         }
     }
 
-    private void ensureSaneWallpaperData(WallpaperData wallpaper) {
-        // Only overwrite cropHint if the rectangle is invalid.
-        if (wallpaper.cropHint.width() < 0
-                || wallpaper.cropHint.height() < 0) {
-            wallpaper.cropHint.set(0, 0, 0, 0);
-        }
-    }
-
-    @VisibleForTesting
-    void parseWallpaperAttributes(TypedXmlPullParser parser, WallpaperData wallpaper,
-            boolean keepDimensionHints) throws XmlPullParserException {
-        final int id = parser.getAttributeInt(null, "id", -1);
-        if (id != -1) {
-            wallpaper.wallpaperId = id;
-            if (id > WallpaperUtils.getCurrentWallpaperId()) {
-                WallpaperUtils.setCurrentWallpaperId(id);
-            }
-        } else {
-            wallpaper.wallpaperId = makeWallpaperIdLocked();
-        }
-
-        final DisplayData wpData = mWallpaperDisplayHelper.getDisplayDataOrCreate(DEFAULT_DISPLAY);
-
-        if (!keepDimensionHints) {
-            wpData.mWidth = parser.getAttributeInt(null, "width");
-            wpData.mHeight = parser.getAttributeInt(null, "height");
-        }
-        wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
-        wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
-        wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
-        wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
-        wpData.mPadding.left = getAttributeInt(parser, "paddingLeft", 0);
-        wpData.mPadding.top = getAttributeInt(parser, "paddingTop", 0);
-        wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
-        wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
-        wallpaper.mWallpaperDimAmount = getAttributeFloat(parser, "dimAmount", 0f);
-        int dimAmountsCount = getAttributeInt(parser, "dimAmountsCount", 0);
-        if (dimAmountsCount > 0) {
-            ArrayMap<Integer, Float> allDimAmounts = new ArrayMap<>(dimAmountsCount);
-            for (int i = 0; i < dimAmountsCount; i++) {
-                int uid = getAttributeInt(parser, "dimUID" + i, 0);
-                float dimValue = getAttributeFloat(parser, "dimValue" + i, 0f);
-                allDimAmounts.put(uid, dimValue);
-            }
-            wallpaper.mUidToDimAmount = allDimAmounts;
-        }
-        int colorsCount = getAttributeInt(parser, "colorsCount", 0);
-        int allColorsCount =  getAttributeInt(parser, "allColorsCount", 0);
-        if (allColorsCount > 0) {
-            Map<Integer, Integer> allColors = new HashMap<>(allColorsCount);
-            for (int i = 0; i < allColorsCount; i++) {
-                int colorInt = getAttributeInt(parser, "allColorsValue" + i, 0);
-                int population = getAttributeInt(parser, "allColorsPopulation" + i, 0);
-                allColors.put(colorInt, population);
-            }
-            int colorHints = getAttributeInt(parser, "colorHints", 0);
-            wallpaper.primaryColors = new WallpaperColors(allColors, colorHints);
-        } else if (colorsCount > 0) {
-            Color primary = null, secondary = null, tertiary = null;
-            for (int i = 0; i < colorsCount; i++) {
-                Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0));
-                if (i == 0) {
-                    primary = color;
-                } else if (i == 1) {
-                    secondary = color;
-                } else if (i == 2) {
-                    tertiary = color;
-                } else {
-                    break;
-                }
-            }
-            int colorHints = getAttributeInt(parser, "colorHints", 0);
-            wallpaper.primaryColors = new WallpaperColors(primary, secondary, tertiary, colorHints);
-        }
-        wallpaper.name = parser.getAttributeValue(null, "name");
-        wallpaper.allowBackup = parser.getAttributeBoolean(null, "backup", false);
-    }
-
     // Called by SystemBackupAgent after files are restored to disk.
     public void settingsRestored() {
         // Verify caller is the system
@@ -3873,7 +3532,7 @@
                     success = true;
                 } else {
                     if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
-                    success = restoreNamedResourceLocked(wallpaper);
+                    success = mWallpaperDataParser.restoreNamedResourceLocked(wallpaper);
                 }
                 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
                         + " id=" + wallpaper.wallpaperId);
@@ -3896,83 +3555,6 @@
         }
     }
 
-    // Restore the named resource bitmap to both source + crop files
-    private boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
-        if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
-            String resName = wallpaper.name.substring(4);
-
-            String pkg = null;
-            int colon = resName.indexOf(':');
-            if (colon > 0) {
-                pkg = resName.substring(0, colon);
-            }
-
-            String ident = null;
-            int slash = resName.lastIndexOf('/');
-            if (slash > 0) {
-                ident = resName.substring(slash+1);
-            }
-
-            String type = null;
-            if (colon > 0 && slash > 0 && (slash-colon) > 1) {
-                type = resName.substring(colon+1, slash);
-            }
-
-            if (pkg != null && ident != null && type != null) {
-                int resId = -1;
-                InputStream res = null;
-                FileOutputStream fos = null;
-                FileOutputStream cos = null;
-                try {
-                    Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
-                    Resources r = c.getResources();
-                    resId = r.getIdentifier(resName, null, null);
-                    if (resId == 0) {
-                        Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
-                                + " ident=" + ident);
-                        return false;
-                    }
-
-                    res = r.openRawResource(resId);
-                    if (wallpaper.wallpaperFile.exists()) {
-                        wallpaper.wallpaperFile.delete();
-                        wallpaper.cropFile.delete();
-                    }
-                    fos = new FileOutputStream(wallpaper.wallpaperFile);
-                    cos = new FileOutputStream(wallpaper.cropFile);
-
-                    byte[] buffer = new byte[32768];
-                    int amt;
-                    while ((amt=res.read(buffer)) > 0) {
-                        fos.write(buffer, 0, amt);
-                        cos.write(buffer, 0, amt);
-                    }
-                    // mWallpaperObserver will notice the close and send the change broadcast
-
-                    Slog.v(TAG, "Restored wallpaper: " + resName);
-                    return true;
-                } catch (NameNotFoundException e) {
-                    Slog.e(TAG, "Package name " + pkg + " not found");
-                } catch (Resources.NotFoundException e) {
-                    Slog.e(TAG, "Resource not found: " + resId);
-                } catch (IOException e) {
-                    Slog.e(TAG, "IOException while restoring wallpaper ", e);
-                } finally {
-                    IoUtils.closeQuietly(res);
-                    if (fos != null) {
-                        FileUtils.sync(fos);
-                    }
-                    if (cos != null) {
-                        FileUtils.sync(cos);
-                    }
-                    IoUtils.closeQuietly(fos);
-                    IoUtils.closeQuietly(cos);
-                }
-            }
-        }
-        return false;
-    }
-
     @Override // Binder call
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
             FileDescriptor err, String[] args, ShellCallback callback,
@@ -3981,6 +3563,56 @@
                 args, callback, resultReceiver);
     }
 
+    private void dumpWallpaper(WallpaperData wallpaper, PrintWriter pw) {
+        pw.print(" User "); pw.print(wallpaper.userId);
+        pw.print(": id="); pw.print(wallpaper.wallpaperId);
+        pw.print(": mWhich="); pw.print(wallpaper.mWhich);
+        pw.print(": mSystemWasBoth="); pw.println(wallpaper.mSystemWasBoth);
+        pw.println(" Display state:");
+        mWallpaperDisplayHelper.forEachDisplayData(wpSize -> {
+            pw.print("  displayId=");
+            pw.println(wpSize.mDisplayId);
+            pw.print("  mWidth=");
+            pw.print(wpSize.mWidth);
+            pw.print("  mHeight=");
+            pw.println(wpSize.mHeight);
+            pw.print("  mPadding="); pw.println(wpSize.mPadding);
+        });
+        pw.print("  mCropHint="); pw.println(wallpaper.cropHint);
+        pw.print("  mName=");  pw.println(wallpaper.name);
+        pw.print("  mAllowBackup="); pw.println(wallpaper.allowBackup);
+        pw.print("  mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
+        pw.print("  mWallpaperDimAmount="); pw.println(wallpaper.mWallpaperDimAmount);
+        pw.print("  isColorExtracted="); pw.println(wallpaper.mIsColorExtractedFromDim);
+        pw.println("  mUidToDimAmount:");
+        for (int j = 0; j < wallpaper.mUidToDimAmount.size(); j++) {
+            pw.print("    UID="); pw.print(wallpaper.mUidToDimAmount.keyAt(j));
+            pw.print(" dimAmount="); pw.println(wallpaper.mUidToDimAmount.valueAt(j));
+        }
+        if (wallpaper.connection != null) {
+            WallpaperConnection conn = wallpaper.connection;
+            pw.print("  Wallpaper connection ");
+            pw.print(conn);
+            pw.println(":");
+            if (conn.mInfo != null) {
+                pw.print("    mInfo.component=");
+                pw.println(conn.mInfo.getComponent());
+            }
+            conn.forEachDisplayConnector(connector -> {
+                pw.print("     mDisplayId=");
+                pw.println(connector.mDisplayId);
+                pw.print("     mToken=");
+                pw.println(connector.mToken);
+                pw.print("     mEngine=");
+                pw.println(connector.mEngine);
+            });
+            pw.print("    mService=");
+            pw.println(conn.mService);
+            pw.print("    mLastDiedTime=");
+            pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
+        }
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -3991,90 +3623,15 @@
         synchronized (mLock) {
             pw.println("System wallpaper state:");
             for (int i = 0; i < mWallpaperMap.size(); i++) {
-                WallpaperData wallpaper = mWallpaperMap.valueAt(i);
-                pw.print(" User "); pw.print(wallpaper.userId);
-                pw.print(": id="); pw.println(wallpaper.wallpaperId);
-                pw.println(" Display state:");
-                mWallpaperDisplayHelper.forEachDisplayData(wpSize -> {
-                    pw.print("  displayId=");
-                    pw.println(wpSize.mDisplayId);
-                    pw.print("  mWidth=");
-                    pw.print(wpSize.mWidth);
-                    pw.print("  mHeight=");
-                    pw.println(wpSize.mHeight);
-                    pw.print("  mPadding="); pw.println(wpSize.mPadding);
-                });
-                pw.print("  mCropHint="); pw.println(wallpaper.cropHint);
-                pw.print("  mName=");  pw.println(wallpaper.name);
-                pw.print("  mAllowBackup="); pw.println(wallpaper.allowBackup);
-                pw.print("  mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
-                pw.print("  mWallpaperDimAmount="); pw.println(wallpaper.mWallpaperDimAmount);
-                pw.print("  isColorExtracted="); pw.println(wallpaper.mIsColorExtractedFromDim);
-                pw.println("  mUidToDimAmount:");
-                for (Map.Entry<Integer, Float> entry : wallpaper.mUidToDimAmount.entrySet()) {
-                    pw.print("    UID="); pw.print(entry.getKey());
-                    pw.print(" dimAmount="); pw.println(entry.getValue());
-                }
-                if (wallpaper.connection != null) {
-                    WallpaperConnection conn = wallpaper.connection;
-                    pw.print("  Wallpaper connection ");
-                    pw.print(conn);
-                    pw.println(":");
-                    if (conn.mInfo != null) {
-                        pw.print("    mInfo.component=");
-                        pw.println(conn.mInfo.getComponent());
-                    }
-                    conn.forEachDisplayConnector(connector -> {
-                        pw.print("     mDisplayId=");
-                        pw.println(connector.mDisplayId);
-                        pw.print("     mToken=");
-                        pw.println(connector.mToken);
-                        pw.print("     mEngine=");
-                        pw.println(connector.mEngine);
-                    });
-                    pw.print("    mService=");
-                    pw.println(conn.mService);
-                    pw.print("    mLastDiedTime=");
-                    pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
-                }
+                dumpWallpaper(mWallpaperMap.valueAt(i), pw);
             }
             pw.println("Lock wallpaper state:");
             for (int i = 0; i < mLockWallpaperMap.size(); i++) {
-                WallpaperData wallpaper = mLockWallpaperMap.valueAt(i);
-                pw.print(" User "); pw.print(wallpaper.userId);
-                pw.print(": id="); pw.println(wallpaper.wallpaperId);
-                pw.print("  mCropHint="); pw.println(wallpaper.cropHint);
-                pw.print("  mName=");  pw.println(wallpaper.name);
-                pw.print("  mAllowBackup="); pw.println(wallpaper.allowBackup);
-                pw.print("  mWallpaperDimAmount="); pw.println(wallpaper.mWallpaperDimAmount);
+                dumpWallpaper(mLockWallpaperMap.valueAt(i), pw);
             }
             pw.println("Fallback wallpaper state:");
-            pw.print(" User "); pw.print(mFallbackWallpaper.userId);
-            pw.print(": id="); pw.println(mFallbackWallpaper.wallpaperId);
-            pw.print("  mCropHint="); pw.println(mFallbackWallpaper.cropHint);
-            pw.print("  mName=");  pw.println(mFallbackWallpaper.name);
-            pw.print("  mAllowBackup="); pw.println(mFallbackWallpaper.allowBackup);
-            if (mFallbackWallpaper.connection != null) {
-                WallpaperConnection conn = mFallbackWallpaper.connection;
-                pw.print("  Fallback Wallpaper connection ");
-                pw.print(conn);
-                pw.println(":");
-                if (conn.mInfo != null) {
-                    pw.print("    mInfo.component=");
-                    pw.println(conn.mInfo.getComponent());
-                }
-                conn.forEachDisplayConnector(connector -> {
-                    pw.print("     mDisplayId=");
-                    pw.println(connector.mDisplayId);
-                    pw.print("     mToken=");
-                    pw.println(connector.mToken);
-                    pw.print("     mEngine=");
-                    pw.println(connector.mEngine);
-                });
-                pw.print("    mService=");
-                pw.println(conn.mService);
-                pw.print("    mLastDiedTime=");
-                pw.println(mFallbackWallpaper.lastDiedTime - SystemClock.uptimeMillis());
+            if (mFallbackWallpaper != null) {
+                dumpWallpaper(mFallbackWallpaper, pw);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 65127e4..a0d8dfb 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -342,6 +342,18 @@
         // Not relevant for the window observer.
     }
 
+    void onWMTransition(int displayId, @WindowManager.TransitionType int type) {
+        if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
+            mAccessibilityTracing.logTrace(TAG + ".onAppWindowTransition",
+                    FLAGS_MAGNIFICATION_CALLBACK, "displayId=" + displayId + "; type=" + type);
+        }
+        final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+        if (displayMagnifier != null) {
+            displayMagnifier.onWMTransition(displayId, type);
+        }
+        // Not relevant for the window observer.
+    }
+
     void onWindowTransition(WindowState windowState, int transition) {
         if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK
                 | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) {
@@ -708,6 +720,28 @@
             }
         }
 
+        void onWMTransition(int displayId, @WindowManager.TransitionType int type) {
+            if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
+                mAccessibilityTracing.logTrace(LOG_TAG + ".onWMTransition",
+                        FLAGS_MAGNIFICATION_CALLBACK, "displayId=" + displayId + "; type=" + type);
+            }
+            if (DEBUG_WINDOW_TRANSITIONS) {
+                Slog.i(LOG_TAG, "Window transition: " + WindowManager.transitTypeToString(type)
+                        + " displayId: " + displayId);
+            }
+            final boolean magnifying = mMagnifedViewport.isMagnifying();
+            if (magnifying) {
+                // All opening/closing situations.
+                switch (type) {
+                    case WindowManager.TRANSIT_OPEN:
+                    case WindowManager.TRANSIT_TO_FRONT:
+                    case WindowManager.TRANSIT_CLOSE:
+                    case WindowManager.TRANSIT_TO_BACK:
+                        mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_USER_CONTEXT_CHANGED);
+                }
+            }
+        }
+
         void onWindowTransition(WindowState windowState, int transition) {
             if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
                 mAccessibilityTracing.logTrace(LOG_TAG + ".onWindowTransition",
@@ -960,7 +994,7 @@
                     // navigation bar insets into nonMagnifiedBounds. It happens when
                     // navigation mode is gestural.
                     if (isUntouchableNavigationBar(windowState, mTempRegion3)) {
-                        final Rect navBarInsets = getNavBarInsets(mDisplayContent);
+                        final Rect navBarInsets = getSystemBarInsetsFrame(windowState);
                         nonMagnifiedBounds.op(navBarInsets, Region.Op.UNION);
                         availableBounds.op(navBarInsets, Region.Op.DIFFERENCE);
                     }
@@ -1425,10 +1459,12 @@
         return touchableRegion.isEmpty();
     }
 
-    static Rect getNavBarInsets(DisplayContent displayContent) {
-        final InsetsSource source = displayContent.getInsetsStateController().getRawInsetsState()
-                .peekSource(ITYPE_NAVIGATION_BAR);
-        return source != null ? source.getFrame() : EMPTY_RECT;
+    static Rect getSystemBarInsetsFrame(WindowState win) {
+        if (win == null) {
+            return EMPTY_RECT;
+        }
+        final InsetsSourceProvider provider = win.getControllableInsetProvider();
+        return provider != null ? provider.getSource().getFrame() : EMPTY_RECT;
     }
 
     /**
@@ -1581,7 +1617,10 @@
                         // region of navigation bar inset because all touch events from this region
                         // would be received by launcher, i.e. this region is a un-touchable one
                         // for the application.
-                        unaccountedSpace.op(getNavBarInsets(dc), unaccountedSpace,
+                        unaccountedSpace.op(
+                                getSystemBarInsetsFrame(
+                                        mService.mWindowMap.get(a11yWindow.getWindowInfo().token)),
+                                unaccountedSpace,
                                 Region.Op.REVERSE_DIFFERENCE);
                     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 316b12a..4507637 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -749,6 +749,8 @@
             synchronized (mGlobalLock) {
                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
                 if (r != null) {
+                    EventLogTags.writeWmSetRequestedOrientation(requestedOrientation,
+                            r.shortComponentName);
                     r.setRequestedOrientation(requestedOrientation);
                 }
             }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 0c97d7d..2b9364c2 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3919,6 +3919,10 @@
         }
     }
 
+    boolean isFinishing() {
+        return finishing;
+    }
+
     /**
      * This method is to only be called from the client via binder when the activity is destroyed
      * AND finished.
@@ -10333,8 +10337,8 @@
     // TODO(b/263592337): Explore enabling compat fake focus for fullscreen, e.g. for when
     // covered with bubbles.
     boolean shouldSendCompatFakeFocus() {
-        return mWmService.mLetterboxConfiguration.isCompatFakeFocusEnabled(info)
-                && inMultiWindowMode() && !inPinnedWindowingMode() && !inFreeformWindowingMode();
+        return mLetterboxUiController.shouldSendFakeFocus() && inMultiWindowMode()
+                && !inPinnedWindowingMode() && !inFreeformWindowingMode();
     }
 
     static class Builder {
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index a7883cb..5e066fa 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -605,11 +605,16 @@
         final Task task = r.getTask();
         mService.deferWindowLayout();
         try {
-            r.mTransitionController.requestStartTransition(transition,
-                    task, remoteTransition, null /* displayChange */);
-            r.mTransitionController.collect(task);
-            r.mTransitionController.setTransientLaunch(r,
-                    TaskDisplayArea.getRootTaskAbove(rootTask));
+            final TransitionController controller = r.mTransitionController;
+            if (controller.getTransitionPlayer() != null) {
+                controller.requestStartTransition(transition, task, remoteTransition,
+                        null /* displayChange */);
+                controller.collect(task);
+                controller.setTransientLaunch(r, TaskDisplayArea.getRootTaskAbove(rootTask));
+            } else {
+                // The transition player might be died when executing the queued transition.
+                transition.abort();
+            }
             task.moveToFront("startExistingRecents");
             task.mInResumeTopActivity = true;
             task.resumeTopActivity(null /* prev */, options, true /* deferPause */);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 50eb356..c37a3d7 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1033,10 +1033,33 @@
             return err;
         }
 
-        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
-                requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
-                request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord,
-                resultRootTask);
+        boolean abort;
+        try {
+            abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
+                    requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
+                    request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord,
+                    resultRootTask);
+        } catch (SecurityException e) {
+            // Return activity not found for the explicit intent if the caller can't see the target
+            // to prevent the disclosure of package existence.
+            final Intent originalIntent = request.ephemeralIntent;
+            if (originalIntent != null && (originalIntent.getComponent() != null
+                    || originalIntent.getPackage() != null)) {
+                final String targetPackageName = originalIntent.getComponent() != null
+                        ? originalIntent.getComponent().getPackageName()
+                        : originalIntent.getPackage();
+                if (mService.getPackageManagerInternalLocked()
+                        .filterAppAccess(targetPackageName, callingUid, userId)) {
+                    if (resultRecord != null) {
+                        resultRecord.sendResult(INVALID_UID, resultWho, requestCode,
+                                RESULT_CANCELED, null /* data */, null /* dataGrants */);
+                    }
+                    SafeActivityOptions.abort(options);
+                    return ActivityManager.START_CLASS_NOT_FOUND;
+                }
+            }
+            throw e;
+        }
         abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                 callingPid, resolvedType, aInfo.applicationInfo);
         abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 2f82167..e8a0386 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1027,7 +1027,7 @@
         synchronized (mGlobalLock) {
             mWindowManager = wm;
             mRootWindowContainer = wm.mRoot;
-            mWindowOrganizerController.setWindowManager(wm);
+            mWindowOrganizerController.mTransitionController.setWindowManager(wm);
             mTempConfig.setToDefaults();
             mTempConfig.setLocales(LocaleList.getDefault());
             mConfigurationSeq = mTempConfig.seq = 1;
@@ -4748,16 +4748,27 @@
         updateResumedAppTrace(r);
         mLastResumedActivity = r;
 
-        final boolean changed = r.mDisplayContent.setFocusedApp(r);
-        if (changed) {
-            mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
-                    true /*updateInputWindows*/);
-        }
-        if (prevTask == null || task != prevTask) {
-            if (prevTask != null) {
-                mTaskChangeNotificationController.notifyTaskFocusChanged(prevTask.mTaskId, false);
+        // Don't take focus when transient launching. We don't want the app to know anything
+        // until we've committed to the gesture. The focus will be transferred at the end of
+        // the transition (if the transient launch is committed) or early if explicitly requested
+        // via `setFocused*`.
+        if (!getTransitionController().isTransientCollect(r)) {
+            final Task prevFocusTask = r.mDisplayContent.mFocusedApp != null
+                    ? r.mDisplayContent.mFocusedApp.getTask() : null;
+            final boolean changed = r.mDisplayContent.setFocusedApp(r);
+            if (changed) {
+                mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+                        true /*updateInputWindows*/);
             }
-            mTaskChangeNotificationController.notifyTaskFocusChanged(task.mTaskId, true);
+            if (task != prevFocusTask) {
+                if (prevFocusTask != null) {
+                    mTaskChangeNotificationController.notifyTaskFocusChanged(
+                            prevFocusTask.mTaskId, false);
+                }
+                mTaskChangeNotificationController.notifyTaskFocusChanged(task.mTaskId, true);
+            }
+        }
+        if (task != prevTask) {
             mTaskSupervisor.mRecentTasks.add(task);
         }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 0f1f51f..f34dc94 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -2053,7 +2053,7 @@
         // Stop any activities that are scheduled to do so but have been waiting for the transition
         // animation to finish.
         ArrayList<ActivityRecord> readyToStopActivities = null;
-        for (int i = mStoppingActivities.size() - 1; i >= 0; --i) {
+        for (int i = 0; i < mStoppingActivities.size(); i++) {
             final ActivityRecord s = mStoppingActivities.get(i);
             final boolean animating = s.isInTransition();
             ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "
@@ -2074,6 +2074,7 @@
                 readyToStopActivities.add(s);
 
                 mStoppingActivities.remove(i);
+                i--;
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/AnrController.java b/services/core/java/com/android/server/wm/AnrController.java
index 7c0d658..bbe7a33 100644
--- a/services/core/java/com/android/server/wm/AnrController.java
+++ b/services/core/java/com/android/server/wm/AnrController.java
@@ -81,6 +81,10 @@
                     Slog.e(TAG_WM, "Unknown app appToken:" + applicationHandle.name
                             + ". Dropping notifyNoFocusedWindowAnr request");
                     return;
+                } else if (activity.mAppStopped) {
+                    Slog.d(TAG_WM, "App is in stopped state:" + applicationHandle.name
+                            + ". Dropping notifyNoFocusedWindowAnr request");
+                    return;
                 }
 
                 // App is unresponsive, but we are actively trying to give focus to a window.
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index cc71155..bc5f67b 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -19,7 +19,6 @@
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
-import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -28,12 +27,12 @@
 import static com.android.server.wm.BackNavigationProto.ANIMATION_IN_PROGRESS;
 import static com.android.server.wm.BackNavigationProto.LAST_BACK_TYPE;
 import static com.android.server.wm.BackNavigationProto.SHOW_WALLPAPER;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_PREDICT_BACK;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.hardware.HardwareBuffer;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteCallback;
@@ -45,6 +44,7 @@
 import android.view.IWindowFocusObserver;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
+import android.view.WindowInsets;
 import android.window.BackAnimationAdapter;
 import android.window.BackNavigationInfo;
 import android.window.IBackAnimationFinishedCallback;
@@ -54,8 +54,11 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.server.LocalServices;
+import com.android.server.wm.utils.InsetUtils;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.function.Consumer;
 
 /**
  * Controller to handle actions related to the back gesture on the server side.
@@ -69,7 +72,7 @@
     private boolean mShowWallpaper;
     private Runnable mPendingAnimation;
 
-    private final AnimationTargets mAnimationTargets = new AnimationTargets();
+    private AnimationHandler mAnimationHandler;
     private final ArrayList<WindowContainer> mTmpOpenApps = new ArrayList<>();
     private final ArrayList<WindowContainer> mTmpCloseApps = new ArrayList<>();
 
@@ -233,7 +236,6 @@
                 return infoBuilder.build();
             }
 
-            mBackAnimationInProgress = true;
             // We don't have an application callback, let's find the destination of the back gesture
             // The search logic should align with ActivityClientController#finishActivity
             prevActivity = currentTask.topRunningActivity(currentActivity.token, INVALID_TASK_ID);
@@ -314,8 +316,17 @@
             }
 
             if (prepareAnimation) {
-                prepareAnimationIfNeeded(currentTask, prevTask, prevActivity,
-                        removedWindowContainer, backType, adapter);
+                mPendingAnimation = mAnimationHandler.scheduleAnimation(backType, adapter,
+                        currentTask, prevTask, currentActivity, prevActivity);
+                prepareAnimation = mPendingAnimation != null;
+                mBackAnimationInProgress = prepareAnimation;
+                if (prepareAnimation) {
+                    mWindowManagerService.mWindowPlacerLocked.requestTraversal();
+                    if (mShowWallpaper) {
+                        currentTask.getDisplayContent().mWallpaperController
+                                .adjustWallpaperWindows();
+                    }
+                }
             }
             infoBuilder.setPrepareRemoteAnimation(prepareAnimation);
         } // Release wm Lock
@@ -333,7 +344,7 @@
     }
 
     boolean isWaitBackTransition() {
-        return mAnimationTargets.mComposed && mAnimationTargets.mWaitTransition;
+        return mAnimationHandler.mComposed && mAnimationHandler.mWaitTransition;
     }
 
     boolean isKeyguardOccluded(WindowState focusWindow) {
@@ -359,18 +370,19 @@
         boolean result = false;
         // Note: TmpOpenApps is empty. Unlike shell transition, the open apps will be removed from
         // mOpeningApps if there is no visibility change.
-        if (mAnimationTargets.containsBackAnimationTargets(mTmpOpenApps, mTmpCloseApps)) {
+        if (mAnimationHandler.containsBackAnimationTargets(mTmpOpenApps, mTmpCloseApps)) {
             // remove close target from close list, open target from open list;
             // but the open target can be in close list.
             for (int i = openApps.size() - 1; i >= 0; --i) {
                 final ActivityRecord ar = openApps.valueAt(i);
-                if (mAnimationTargets.isTarget(ar, true /* open */)) {
+                if (mAnimationHandler.isTarget(ar, true /* open */)) {
                     openApps.removeAt(i);
+                    mAnimationHandler.mOpenTransitionTargetMatch = true;
                 }
             }
             for (int i = closeApps.size() - 1; i >= 0; --i) {
                 final ActivityRecord ar = closeApps.valueAt(i);
-                if (mAnimationTargets.isTarget(ar, false /* open */)) {
+                if (mAnimationHandler.isTarget(ar, false /* open */)) {
                     closeApps.removeAt(i);
                 }
             }
@@ -391,7 +403,7 @@
      *  animations, and shouldn't join next transition.
      */
     boolean containsBackAnimationTargets(Transition transition) {
-        if (!mAnimationTargets.mComposed
+        if (!mAnimationHandler.mComposed
                 || (transition.mType != TRANSIT_CLOSE && transition.mType != TRANSIT_TO_BACK)) {
             return false;
         }
@@ -408,18 +420,22 @@
                 mTmpCloseApps.add(wc);
             }
         }
-        final boolean result = mAnimationTargets.containsBackAnimationTargets(
+        final boolean result = mAnimationHandler.containsBackAnimationTargets(
                 mTmpOpenApps, mTmpCloseApps);
+        if (result) {
+            mAnimationHandler.mOpenTransitionTargetMatch =
+                    mAnimationHandler.containTarget(mTmpOpenApps, true);
+        }
         mTmpOpenApps.clear();
         mTmpCloseApps.clear();
         return result;
     }
 
     boolean isMonitorTransitionTarget(WindowContainer wc) {
-        if (!mAnimationTargets.mComposed || !mAnimationTargets.mWaitTransition) {
+        if (!mAnimationHandler.mComposed || !mAnimationHandler.mWaitTransition) {
             return false;
         }
-        return mAnimationTargets.isTarget(wc, wc.isVisibleRequested() /* open */);
+        return mAnimationHandler.isTarget(wc, wc.isVisibleRequested() /* open */);
     }
 
     /**
@@ -428,60 +444,106 @@
      *                           cleanup together.
      */
     void clearBackAnimations(SurfaceControl.Transaction cleanupTransaction) {
-        mAnimationTargets.clearBackAnimateTarget(cleanupTransaction);
+        mAnimationHandler.clearBackAnimateTarget(cleanupTransaction);
     }
 
     /**
-     * TODO: Animation composer
-     * prepareAnimationIfNeeded will become too complicated in order to support
-     * ActivityRecord/WindowState, using a factory class to create the RemoteAnimationTargets for
-     * different scenario.
+     * Create and handling animations status for an open/close animation targets.
      */
-    private static class AnimationTargets {
-        ActivityRecord mCloseTarget; // Must be activity
-        WindowContainer mOpenTarget; // Can be activity or task if activity was removed
+    private static class AnimationHandler {
+        private final WindowManagerService mWindowManagerService;
+        private BackWindowAnimationAdaptor mCloseAdaptor;
+        private BackWindowAnimationAdaptor mOpenAdaptor;
         private boolean mComposed;
         private boolean mWaitTransition;
         private int mSwitchType = UNKNOWN;
         private SurfaceControl.Transaction mFinishedTransaction;
+        // This will be set before transition happen, to know whether the real opening target
+        // exactly match animating target. When target match, reparent the starting surface to
+        // the opening target like starting window do.
+        private boolean mOpenTransitionTargetMatch;
+        // The starting surface task Id. Used to clear the starting surface if the animation has
+        // request one during animating.
+        private int mRequestedStartingSurfaceTaskId;
+        private SurfaceControl mStartingSurface;
 
+        AnimationHandler(WindowManagerService wms) {
+            mWindowManagerService = wms;
+        }
         private static final int UNKNOWN = 0;
         private static final int TASK_SWITCH = 1;
         private static final int ACTIVITY_SWITCH = 2;
 
-        void reset(@NonNull WindowContainer close, @NonNull WindowContainer open) {
-            clearBackAnimateTarget(null);
-            if (close == null || open == null) {
-                Slog.e(TAG, "reset animation with null target close: "
-                        + close + " open: " + open);
-                return;
-            }
+        private void initiate(WindowContainer close, WindowContainer open)  {
+            WindowContainer closeTarget;
             if (close.asActivityRecord() != null && open.asActivityRecord() != null
                     && (close.asActivityRecord().getTask() == open.asActivityRecord().getTask())) {
                 mSwitchType = ACTIVITY_SWITCH;
-                mCloseTarget = close.asActivityRecord();
+                closeTarget = close.asActivityRecord();
             } else if (close.asTask() != null && open.asTask() != null
                     && close.asTask() != open.asTask()) {
                 mSwitchType = TASK_SWITCH;
-                mCloseTarget = close.asTask().getTopNonFinishingActivity();
+                closeTarget = close.asTask().getTopNonFinishingActivity();
             } else {
                 mSwitchType = UNKNOWN;
                 return;
             }
 
-            mOpenTarget = open;
-            mComposed = false;
-            mWaitTransition = false;
+            mCloseAdaptor = createAdaptor(closeTarget, false /* isOpen */);
+            mOpenAdaptor = createAdaptor(open, true /* isOpen */);
+
+            if (mCloseAdaptor.mAnimationTarget == null || mOpenAdaptor.mAnimationTarget == null) {
+                Slog.w(TAG, "composeNewAnimations fail, skip");
+                clearBackAnimateTarget(null /* cleanupTransaction */);
+            }
         }
 
-        void composeNewAnimations(@NonNull WindowContainer close, @NonNull WindowContainer open) {
-            reset(close, open);
-            if (mSwitchType == UNKNOWN || mComposed || mCloseTarget == mOpenTarget
-                    || mCloseTarget == null || mOpenTarget == null) {
-                return;
+        boolean composeAnimations(@NonNull WindowContainer close, @NonNull WindowContainer open) {
+            clearBackAnimateTarget(null /* cleanupTransaction */);
+            if (close == null || open == null) {
+                Slog.e(TAG, "reset animation with null target close: "
+                        + close + " open: " + open);
+                return false;
+            }
+            initiate(close, open);
+            if (mSwitchType == UNKNOWN) {
+                return false;
             }
             mComposed = true;
             mWaitTransition = false;
+            return true;
+        }
+
+        RemoteAnimationTarget[] getAnimationTargets() {
+            return mComposed ? new RemoteAnimationTarget[] {
+                    mCloseAdaptor.mAnimationTarget, mOpenAdaptor.mAnimationTarget} : null;
+        }
+
+        boolean isSupportWindowlessSurface() {
+            return mWindowManagerService.mAtmService.mTaskOrganizerController
+                    .isSupportWindowlessStartingSurface();
+        }
+
+        void createStartingSurface(TaskSnapshot snapshot) {
+            if (!mComposed) {
+                return;
+            }
+
+            final ActivityRecord topActivity = getTopOpenActivity();
+            if (topActivity == null) {
+                Slog.e(TAG, "createStartingSurface fail, no open activity: " + this);
+                return;
+            }
+            // TODO (b/257857570) draw snapshot by starting surface.
+        }
+
+        private ActivityRecord getTopOpenActivity() {
+            if (mSwitchType == ACTIVITY_SWITCH) {
+                return mOpenAdaptor.mTarget.asActivityRecord();
+            } else if (mSwitchType == TASK_SWITCH) {
+                return mOpenAdaptor.mTarget.asTask().getTopNonFinishingActivity();
+            }
+            return null;
         }
 
         boolean containTarget(ArrayList<WindowContainer> wcs, boolean open) {
@@ -495,13 +557,13 @@
 
         boolean isTarget(WindowContainer wc, boolean open) {
             if (open) {
-                return wc == mOpenTarget || mOpenTarget.hasChild(wc);
+                return wc == mOpenAdaptor.mTarget || mOpenAdaptor.mTarget.hasChild(wc);
             }
             if (mSwitchType == TASK_SWITCH) {
-                return  wc == mCloseTarget
-                        || (wc.asTask() != null && wc.hasChild(mCloseTarget));
+                return  wc == mCloseAdaptor.mTarget
+                        || (wc.asTask() != null && wc.hasChild(mCloseAdaptor.mTarget));
             } else if (mSwitchType == ACTIVITY_SWITCH) {
-                return wc == mCloseTarget;
+                return wc == mCloseAdaptor.mTarget;
             }
             return false;
         }
@@ -519,19 +581,53 @@
                 return;
             }
             final SurfaceControl.Transaction pt = t != null ? t
-                    : mOpenTarget.getPendingTransaction();
+                    : mOpenAdaptor.mTarget.getPendingTransaction();
             if (mFinishedTransaction != null) {
                 pt.merge(mFinishedTransaction);
                 mFinishedTransaction = null;
             }
+            cleanUpWindowlessSurface();
+
+            if (mCloseAdaptor != null) {
+                mCloseAdaptor.mTarget.cancelAnimation();
+                mCloseAdaptor = null;
+            }
+            if (mOpenAdaptor != null) {
+                mOpenAdaptor.mTarget.cancelAnimation();
+                mOpenAdaptor = null;
+            }
+        }
+
+        private void cleanUpWindowlessSurface() {
+            final ActivityRecord ar = getTopOpenActivity();
+            if (ar == null) {
+                Slog.w(TAG, "finishPresentAnimations without top activity: " + this);
+            }
+            final SurfaceControl.Transaction pendingT = ar != null ? ar.getPendingTransaction()
+                    : mOpenAdaptor.mTarget.getPendingTransaction();
+            // ensure open target is visible before cancel animation.
+            mOpenTransitionTargetMatch &= ar != null;
+            if (mOpenTransitionTargetMatch) {
+                pendingT.show(ar.getSurfaceControl());
+            }
+            if (mRequestedStartingSurfaceTaskId != 0) {
+                // If open target match, reparent to open activity
+                if (mStartingSurface != null && mOpenTransitionTargetMatch) {
+                    pendingT.reparent(mStartingSurface, ar.getSurfaceControl());
+                }
+                // remove starting surface.
+                mStartingSurface = null;
+                // TODO (b/257857570) draw snapshot by starting surface.
+                mRequestedStartingSurfaceTaskId = 0;
+            }
         }
 
         void clearBackAnimateTarget(SurfaceControl.Transaction cleanupTransaction) {
             finishPresentAnimations(cleanupTransaction);
-            mCloseTarget = null;
-            mOpenTarget = null;
             mComposed = false;
             mWaitTransition = false;
+            mOpenTransitionTargetMatch = false;
+            mRequestedStartingSurfaceTaskId = 0;
             mSwitchType = UNKNOWN;
             if (mFinishedTransaction != null) {
                 Slog.w(TAG, "Clear back animation, found un-processed finished transaction");
@@ -555,211 +651,284 @@
 
         @Override
         public String toString() {
-            final StringBuilder sb = new StringBuilder(128);
-            sb.append("AnimationTargets{");
-            sb.append(" mOpenTarget= ");
-            sb.append(mOpenTarget);
-            sb.append(" mCloseTarget= ");
-            sb.append(mCloseTarget);
-            sb.append(" mSwitchType= ");
-            sb.append(mSwitchType);
-            sb.append(" mComposed= ");
-            sb.append(mComposed);
-            sb.append(" mWaitTransition= ");
-            sb.append(mWaitTransition);
-            sb.append('}');
-            return sb.toString();
+            return "AnimationTargets{"
+                    + " openTarget= "
+                    + mOpenAdaptor.mTarget
+                    + " closeTarget= "
+                    + mCloseAdaptor.mTarget
+                    + " mSwitchType= "
+                    + mSwitchType
+                    + " mComposed= "
+                    + mComposed
+                    + " mWaitTransition= "
+                    + mWaitTransition
+                    + '}';
         }
-    }
 
-    private void prepareAnimationIfNeeded(Task currentTask,
-            Task prevTask, ActivityRecord prevActivity, WindowContainer<?> removedWindowContainer,
-            int backType, BackAnimationAdapter adapter) {
-        final ArrayList<SurfaceControl> leashes = new ArrayList<>();
-        final SurfaceControl.Transaction startedTransaction = currentTask.getPendingTransaction();
-        final SurfaceControl.Transaction finishedTransaction = new SurfaceControl.Transaction();
-        // Prepare a leash to animate for the departing window
-        final SurfaceControl animLeash = currentTask.makeAnimationLeash()
-                .setName("BackPreview Leash for " + currentTask)
-                .setHidden(false)
-                .build();
-        removedWindowContainer.reparentSurfaceControl(startedTransaction, animLeash);
+        private static BackWindowAnimationAdaptor createAdaptor(
+                WindowContainer target, boolean isOpen) {
+            final BackWindowAnimationAdaptor adaptor =
+                    new BackWindowAnimationAdaptor(target, isOpen);
+            target.startAnimation(target.getPendingTransaction(), adaptor, false /* hidden */,
+                    ANIMATION_TYPE_PREDICT_BACK);
+            return adaptor;
+        }
 
-        final RemoteAnimationTarget topAppTarget = createRemoteAnimationTargetLocked(
-                currentTask, animLeash, MODE_CLOSING);
+        private static class BackWindowAnimationAdaptor implements AnimationAdapter {
+            SurfaceControl mCapturedLeash;
+            private final Rect mBounds = new Rect();
+            private final WindowContainer mTarget;
+            private final boolean mIsOpen;
+            private RemoteAnimationTarget mAnimationTarget;
 
-        // reset leash after animation finished.
-        leashes.add(animLeash);
-        removedWindowContainer.reparentSurfaceControl(finishedTransaction,
-                removedWindowContainer.getParentSurfaceControl());
+            BackWindowAnimationAdaptor(WindowContainer closeTarget, boolean isOpen) {
+                mBounds.set(closeTarget.getBounds());
+                mTarget = closeTarget;
+                mIsOpen = isOpen;
+            }
+            @Override
+            public boolean getShowWallpaper() {
+                return false;
+            }
 
-        // Prepare a leash to animate for the entering window.
-        RemoteAnimationTarget behindAppTarget = null;
-        if (needsScreenshot(backType)) {
-            HardwareBuffer screenshotBuffer = null;
-            Task backTargetTask = prevTask;
-            switch(backType) {
-                case BackNavigationInfo.TYPE_CROSS_TASK:
-                    int prevTaskId = prevTask != null ? prevTask.mTaskId : 0;
-                    int prevUserId = prevTask != null ? prevTask.mUserId : 0;
-                    screenshotBuffer = getTaskSnapshot(prevTaskId, prevUserId);
-                    break;
+            @Override
+            public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t,
+                    int type, SurfaceAnimator.OnAnimationFinishedCallback finishCallback) {
+                mCapturedLeash = animationLeash;
+                createRemoteAnimationTarget(mIsOpen);
+            }
+
+            @Override
+            public void onAnimationCancelled(SurfaceControl animationLeash) {
+                if (mCapturedLeash == animationLeash) {
+                    mCapturedLeash = null;
+                }
+            }
+
+            @Override
+            public long getDurationHint() {
+                return 0;
+            }
+
+            @Override
+            public long getStatusBarTransitionsStartTime() {
+                return 0;
+            }
+
+            @Override
+            public void dump(PrintWriter pw, String prefix) {
+                pw.print(prefix + "BackWindowAnimationAdaptor mCapturedLeash=");
+                pw.print(mCapturedLeash);
+                pw.println();
+            }
+
+            @Override
+            public void dumpDebug(ProtoOutputStream proto) {
+
+            }
+
+            RemoteAnimationTarget createRemoteAnimationTarget(boolean isOpen) {
+                if (mAnimationTarget != null) {
+                    return mAnimationTarget;
+                }
+                Task t = mTarget.asTask();
+                final ActivityRecord r = t != null ? t.getTopNonFinishingActivity()
+                        : mTarget.asActivityRecord();
+                if (t == null && r != null) {
+                    t = r.getTask();
+                }
+                if (t == null || r == null) {
+                    Slog.e(TAG, "createRemoteAnimationTarget fail " + mTarget);
+                    return null;
+                }
+                final WindowState mainWindow = r.findMainWindow();
+                Rect insets;
+                if (mainWindow != null) {
+                    insets = mainWindow.getInsetsStateWithVisibilityOverride().calculateInsets(
+                            mBounds, WindowInsets.Type.systemBars(),
+                            false /* ignoreVisibility */).toRect();
+                    InsetUtils.addInsets(insets, mainWindow.mActivityRecord.getLetterboxInsets());
+                } else {
+                    insets = new Rect();
+                }
+                final int mode = isOpen ? MODE_OPENING : MODE_CLOSING;
+                mAnimationTarget = new RemoteAnimationTarget(t.mTaskId, mode, mCapturedLeash,
+                        !r.fillsParent(), new Rect(),
+                        insets, r.getPrefixOrderIndex(), new Point(mBounds.left, mBounds.top),
+                        mBounds, mBounds, t.getWindowConfiguration(),
+                        true /* isNotInRecents */, null, null, t.getTaskInfo(),
+                        r.checkEnterPictureInPictureAppOpsState());
+                return mAnimationTarget;
+            }
+        }
+
+        Runnable scheduleAnimation(int backType, BackAnimationAdapter adapter,
+                Task currentTask, Task previousTask, ActivityRecord currentActivity,
+                ActivityRecord previousActivity) {
+            switch (backType) {
+                case BackNavigationInfo.TYPE_RETURN_TO_HOME:
+                    return new ScheduleAnimationBuilder(backType, adapter)
+                            .setIsLaunchBehind(true)
+                            .setComposeTarget(currentTask, previousTask)
+                            .build();
                 case BackNavigationInfo.TYPE_CROSS_ACTIVITY:
-                    if (prevActivity != null && prevActivity.mActivityComponent != null) {
-                        screenshotBuffer = getActivitySnapshot(currentTask, prevActivity);
+                    return new ScheduleAnimationBuilder(backType, adapter)
+                            .setComposeTarget(currentActivity, previousActivity)
+                            .setOpeningSnapshot(getActivitySnapshot(previousActivity)).build();
+                case BackNavigationInfo.TYPE_CROSS_TASK:
+                    return new ScheduleAnimationBuilder(backType, adapter)
+                            .setComposeTarget(currentTask, previousTask)
+                            .setOpeningSnapshot(getTaskSnapshot(previousTask)).build();
+            }
+            return null;
+        }
+
+        private class ScheduleAnimationBuilder {
+            final int mType;
+            final BackAnimationAdapter mBackAnimationAdapter;
+            WindowContainer mCloseTarget;
+            WindowContainer mOpenTarget;
+            TaskSnapshot mOpenSnapshot;
+            boolean mIsLaunchBehind;
+
+            ScheduleAnimationBuilder(int type, BackAnimationAdapter backAnimationAdapter) {
+                mType = type;
+                mBackAnimationAdapter = backAnimationAdapter;
+            }
+
+            ScheduleAnimationBuilder setComposeTarget(WindowContainer close, WindowContainer open) {
+                mCloseTarget = close;
+                mOpenTarget = open;
+                return this;
+            }
+
+            ScheduleAnimationBuilder setOpeningSnapshot(TaskSnapshot snapshot) {
+                mOpenSnapshot = snapshot;
+                return this;
+            }
+
+            ScheduleAnimationBuilder setIsLaunchBehind(boolean launchBehind) {
+                mIsLaunchBehind = launchBehind;
+                return this;
+            }
+
+            Runnable build() {
+                if (mOpenTarget == null || mCloseTarget == null) {
+                    return null;
+                }
+                final boolean shouldLaunchBehind = mIsLaunchBehind || !isSupportWindowlessSurface();
+                final ActivityRecord launchBehindActivity = !shouldLaunchBehind ? null
+                        : mOpenTarget.asTask() != null
+                                ? mOpenTarget.asTask().getTopNonFinishingActivity()
+                                : mOpenTarget.asActivityRecord() != null
+                                        ? mOpenTarget.asActivityRecord() : null;
+                if (shouldLaunchBehind && launchBehindActivity == null) {
+                    Slog.e(TAG, "No opening activity");
+                    return null;
+                }
+
+                if (!composeAnimations(mCloseTarget, mOpenTarget)) {
+                    return null;
+                }
+                if (launchBehindActivity != null) {
+                    setLaunchBehind(launchBehindActivity);
+                } else {
+                    createStartingSurface(mOpenSnapshot);
+                }
+
+                final IBackAnimationFinishedCallback callback = makeAnimationFinishedCallback(
+                        launchBehindActivity != null ? triggerBack -> {
+                            if (!triggerBack) {
+                                restoreLaunchBehind(launchBehindActivity);
+                            }
+                        } : null,
+                        mCloseTarget);
+                final RemoteAnimationTarget[] targets = getAnimationTargets();
+
+                return () -> {
+                    try {
+                        mBackAnimationAdapter.getRunner().onAnimationStart(mType,
+                                targets, null, null, callback);
+                    } catch (RemoteException e) {
+                        e.printStackTrace();
                     }
-                    backTargetTask = currentTask;
-                    break;
+                };
             }
 
-            // Find a screenshot of the previous activity if we actually have an animation
-            SurfaceControl animationLeashParent = removedWindowContainer.getAnimationLeashParent();
-            if (screenshotBuffer != null) {
-                final SurfaceControl screenshotSurface = new SurfaceControl.Builder()
-                        .setName("BackPreview Screenshot for " + prevActivity)
-                        .setHidden(false)
-                        .setParent(animationLeashParent)
-                        .setBLASTLayer()
-                        .build();
-                startedTransaction.setBuffer(screenshotSurface, screenshotBuffer);
-
-                // The Animation leash needs to be above the screenshot surface, but the animation
-                // leash needs to be added before to be in the synchronized block.
-                startedTransaction.setLayer(topAppTarget.leash, 1);
-
-                behindAppTarget =
-                        createRemoteAnimationTargetLocked(
-                                backTargetTask, screenshotSurface, MODE_OPENING);
-
-                // reset leash after animation finished.
-                leashes.add(screenshotSurface);
-            }
-        } else if (prevTask != null && prevActivity != null) {
-            // Make previous task show from behind by marking its top activity as visible
-            // and launch-behind to bump its visibility for the duration of the back gesture.
-            setLaunchBehind(prevActivity);
-
-            final SurfaceControl leash = prevActivity.makeAnimationLeash()
-                    .setName("BackPreview Leash for " + prevActivity)
-                    .setHidden(false)
-                    .build();
-            prevActivity.reparentSurfaceControl(startedTransaction, leash);
-            behindAppTarget = createRemoteAnimationTargetLocked(
-                    prevTask, leash, MODE_OPENING);
-
-            // reset leash after animation finished.
-            leashes.add(leash);
-            prevActivity.reparentSurfaceControl(finishedTransaction,
-                    prevActivity.getParentSurfaceControl());
-        }
-
-        if (mShowWallpaper) {
-            currentTask.getDisplayContent().mWallpaperController.adjustWallpaperWindows();
-            // TODO(b/241808055): If the current animation need to show wallpaper and animate the
-            //  wallpaper, start the wallpaper animation to collect wallpaper target and deliver it
-            //  to the back animation controller.
-        }
-
-        final RemoteAnimationTarget[] targets = (behindAppTarget == null)
-                ? new RemoteAnimationTarget[] {topAppTarget}
-                : new RemoteAnimationTarget[] {topAppTarget, behindAppTarget};
-
-        final ActivityRecord finalPrevActivity = prevActivity;
-        final IBackAnimationFinishedCallback callback =
-                new IBackAnimationFinishedCallback.Stub() {
+            private IBackAnimationFinishedCallback makeAnimationFinishedCallback(
+                    Consumer<Boolean> b, WindowContainer closeTarget) {
+                return new IBackAnimationFinishedCallback.Stub() {
                     @Override
                     public void onAnimationFinished(boolean triggerBack) {
-                        for (SurfaceControl sc: leashes) {
-                            finishedTransaction.remove(sc);
-                        }
+                        final SurfaceControl.Transaction finishedTransaction =
+                                new SurfaceControl.Transaction();
                         synchronized (mWindowManagerService.mGlobalLock) {
+                            if (b != null) {
+                                b.accept(triggerBack);
+                            }
                             if (triggerBack) {
                                 final SurfaceControl surfaceControl =
-                                        removedWindowContainer.getSurfaceControl();
+                                        closeTarget.getSurfaceControl();
                                 if (surfaceControl != null && surfaceControl.isValid()) {
-                                    // The animation is finish and start waiting for transition,
-                                    // hide the task surface before it re-parented to avoid flicker.
+                                    // Hide the close target surface when transition start.
                                     finishedTransaction.hide(surfaceControl);
                                 }
-                            } else if (!needsScreenshot(backType)) {
-                                restoreLaunchBehind(finalPrevActivity);
                             }
-                            if (!mAnimationTargets.setFinishTransaction(finishedTransaction)) {
+                            if (!setFinishTransaction(finishedTransaction)) {
                                 finishedTransaction.apply();
                             }
                             if (!triggerBack) {
-                                mAnimationTargets.clearBackAnimateTarget(null);
+                                clearBackAnimateTarget(
+                                        null /* cleanupTransaction */);
                             } else {
-                                mAnimationTargets.mWaitTransition = true;
+                                mWaitTransition = true;
                             }
                         }
                         // TODO Add timeout monitor if transition didn't happen
                     }
                 };
-        if (backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
-            mAnimationTargets.composeNewAnimations(removedWindowContainer, prevActivity);
-        } else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
-                || backType == BackNavigationInfo.TYPE_CROSS_TASK) {
-            mAnimationTargets.composeNewAnimations(removedWindowContainer, prevTask);
-        }
-        scheduleAnimationLocked(backType, targets, adapter, callback);
-    }
-
-    @NonNull
-    private static RemoteAnimationTarget createRemoteAnimationTargetLocked(
-            Task task, SurfaceControl animLeash, int mode) {
-        ActivityRecord topApp = task.getTopRealVisibleActivity();
-        if (topApp == null) {
-            topApp = task.getTopNonFinishingActivity();
-        }
-
-        final WindowState mainWindow = topApp != null
-                ? topApp.findMainWindow()
-                : null;
-        int windowType = INVALID_WINDOW_TYPE;
-        if (mainWindow != null) {
-            windowType = mainWindow.getWindowType();
-        }
-
-        Rect bounds = new Rect(task.getBounds());
-        Rect localBounds = new Rect(bounds);
-        Point tmpPos = new Point();
-        task.getRelativePosition(tmpPos);
-        localBounds.offsetTo(tmpPos.x, tmpPos.y);
-
-        return new RemoteAnimationTarget(
-                task.mTaskId,
-                mode,
-                animLeash,
-                false /* isTransluscent */,
-                new Rect() /* clipRect */,
-                new Rect() /* contentInsets */,
-                task.getPrefixOrderIndex(),
-                tmpPos /* position */,
-                localBounds /* localBounds */,
-                bounds /* screenSpaceBounds */,
-                task.getWindowConfiguration(),
-                true /* isNotInRecent */,
-                null,
-                null,
-                task.getTaskInfo(),
-                false,
-                windowType);
-    }
-
-    @VisibleForTesting
-    void scheduleAnimationLocked(@BackNavigationInfo.BackTargetType int type,
-            RemoteAnimationTarget[] targets, BackAnimationAdapter backAnimationAdapter,
-            IBackAnimationFinishedCallback callback) {
-        mPendingAnimation = () -> {
-            try {
-                backAnimationAdapter.getRunner().onAnimationStart(type,
-                        targets, null, null, callback);
-            } catch (RemoteException e) {
-                e.printStackTrace();
             }
-        };
-        mWindowManagerService.mWindowPlacerLocked.requestTraversal();
+
+            private void setLaunchBehind(ActivityRecord activity) {
+                if (activity == null) {
+                    return;
+                }
+                if (!activity.isVisibleRequested()) {
+                    activity.setVisibility(true);
+                }
+                activity.mLaunchTaskBehind = true;
+
+                // Handle fixed rotation launching app.
+                final DisplayContent dc = activity.mDisplayContent;
+                dc.rotateInDifferentOrientationIfNeeded(activity);
+                if (activity.hasFixedRotationTransform()) {
+                    // Set the record so we can recognize it to continue to update display
+                    // orientation if the previous activity becomes the top later.
+                    dc.setFixedRotationLaunchingApp(activity,
+                            activity.getWindowConfiguration().getRotation());
+                }
+
+                ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+                        "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
+                activity.mTaskSupervisor.mStoppingActivities.remove(activity);
+                activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
+                        0 /* configChanges */, false /* preserveWindows */, true);
+            }
+            private void restoreLaunchBehind(ActivityRecord activity) {
+                if (activity == null) {
+                    return;
+                }
+
+                activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
+
+                // Restore the launch-behind state.
+                activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
+                activity.mLaunchTaskBehind = false;
+                ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+                        "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+                        activity);
+            }
+        }
     }
 
     void checkAnimationReady(WallpaperController wallpaperController) {
@@ -796,80 +965,36 @@
         mShowWallpaper = false;
     }
 
-    private HardwareBuffer getActivitySnapshot(@NonNull Task task, ActivityRecord r) {
-        return task.getSnapshotForActivityRecord(r);
-    }
-
-    private HardwareBuffer getTaskSnapshot(int taskId, int userId) {
-        if (mWindowManagerService.mTaskSnapshotController == null) {
+    private static TaskSnapshot getActivitySnapshot(@NonNull ActivityRecord r) {
+        if (!isScreenshotEnabled()) {
             return null;
         }
-        TaskSnapshot snapshot = mWindowManagerService.mTaskSnapshotController.getSnapshot(taskId,
-                userId, true /* restoreFromDisk */, false  /* isLowResolution */);
-        return snapshot != null ? snapshot.getHardwareBuffer() : null;
+        // Check if we have a screenshot of the previous activity, indexed by its
+        // component name.
+        // TODO return TaskSnapshot when feature complete.
+//        final HardwareBuffer hw = r.getTask().getSnapshotForActivityRecord(r);
+        return null;
     }
 
-    private boolean needsScreenshot(int backType) {
+    private static TaskSnapshot getTaskSnapshot(Task task) {
         if (!isScreenshotEnabled()) {
-            return false;
+            return null;
         }
-        switch (backType) {
-            case BackNavigationInfo.TYPE_RETURN_TO_HOME:
-            case BackNavigationInfo.TYPE_DIALOG_CLOSE:
-                return false;
-        }
-        return true;
+        // Don't read from disk!!
+        return  task.mRootWindowContainer.mWindowManager.mTaskSnapshotController.getSnapshot(
+                task.mTaskId, task.mUserId, false /* restoreFromDisk */,
+                false /* isLowResolution */);
     }
 
     void setWindowManager(WindowManagerService wm) {
         mWindowManagerService = wm;
-    }
-
-    private void setLaunchBehind(ActivityRecord activity) {
-        if (activity == null) {
-            return;
-        }
-        if (!activity.isVisibleRequested()) {
-            activity.setVisibility(true);
-        }
-        activity.mLaunchTaskBehind = true;
-
-        // Handle fixed rotation launching app.
-        final DisplayContent dc = activity.mDisplayContent;
-        dc.rotateInDifferentOrientationIfNeeded(activity);
-        if (activity.hasFixedRotationTransform()) {
-            // Set the record so we can recognize it to continue to update display orientation
-            // if the previous activity becomes the top later.
-            dc.setFixedRotationLaunchingApp(activity,
-                    activity.getWindowConfiguration().getRotation());
-        }
-
-        ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
-                "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
-        activity.mTaskSupervisor.mStoppingActivities.remove(activity);
-        activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
-                0 /* configChanges */, false /* preserveWindows */, true);
-    }
-
-    private void restoreLaunchBehind(ActivityRecord activity) {
-        if (activity == null) {
-            return;
-        }
-
-        activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
-
-        // Restore the launch-behind state.
-        activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
-        activity.mLaunchTaskBehind = false;
-        ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
-                "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
-                activity);
+        mAnimationHandler = new AnimationHandler(wm);
     }
 
     boolean isWallpaperVisible(WindowState w) {
-        return mAnimationTargets.mComposed && mShowWallpaper
+        return mAnimationHandler.mComposed && mShowWallpaper
                 && w.mAttrs.type == TYPE_BASE_APPLICATION && w.mActivityRecord != null
-                && mAnimationTargets.isTarget(w.mActivityRecord, true /* open */);
+                && mAnimationHandler.isTarget(w.mActivityRecord, true /* open */);
     }
 
     // Called from WindowManagerService to write to a protocol buffer output stream.
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index cd79f2e..e1fdeca1 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -32,6 +32,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.BackgroundStartPrivileges;
+import android.app.ComponentOptions;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -166,7 +167,8 @@
         final boolean useCallingUidState =
                 originatingPendingIntent == null
                         || checkedOptions == null
-                        || !checkedOptions.getIgnorePendingIntentCreatorForegroundState();
+                        || checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
+                                != ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
         if (useCallingUidState) {
             if (callingUid == Process.ROOT_UID
                     || callingAppId == Process.SYSTEM_UID
diff --git a/services/core/java/com/android/server/wm/DeviceStateController.java b/services/core/java/com/android/server/wm/DeviceStateController.java
index 7d9a4ec..3f28522 100644
--- a/services/core/java/com/android/server/wm/DeviceStateController.java
+++ b/services/core/java/com/android/server/wm/DeviceStateController.java
@@ -24,6 +24,7 @@
 import android.os.HandlerExecutor;
 
 import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ArrayUtils;
 
 import java.util.ArrayList;
@@ -48,9 +49,12 @@
     private final int[] mRearDisplayDeviceStates;
     @NonNull
     private final int[] mReverseRotationAroundZAxisStates;
+    @GuardedBy("this")
     @NonNull
     private final List<Consumer<DeviceState>> mDeviceStateCallbacks = new ArrayList<>();
 
+    private final boolean mMatchBuiltInDisplayOrientationToDefaultDisplay;
+
     @Nullable
     private DeviceState mLastDeviceState;
     private int mCurrentState;
@@ -72,20 +76,19 @@
                 .getIntArray(R.array.config_rearDisplayDeviceStates);
         mReverseRotationAroundZAxisStates = context.getResources()
                 .getIntArray(R.array.config_deviceStatesToReverseDefaultDisplayRotationAroundZAxis);
+        mMatchBuiltInDisplayOrientationToDefaultDisplay = context.getResources()
+                .getBoolean(R.bool
+                        .config_matchSecondaryInternalDisplaysOrientationToReverseDefaultDisplay);
 
         if (mDeviceStateManager != null) {
             mDeviceStateManager.registerCallback(new HandlerExecutor(handler), this);
         }
     }
 
-    void unregisterFromDeviceStateManager() {
-        if (mDeviceStateManager != null) {
-            mDeviceStateManager.unregisterCallback(this);
-        }
-    }
-
     void registerDeviceStateCallback(@NonNull Consumer<DeviceState> callback) {
-        mDeviceStateCallbacks.add(callback);
+        synchronized (this) {
+            mDeviceStateCallbacks.add(callback);
+        }
     }
 
     /**
@@ -95,6 +98,15 @@
         return ArrayUtils.contains(mReverseRotationAroundZAxisStates, mCurrentState);
     }
 
+    /**
+     * @return true if non-default built-in displays should match the default display's rotation.
+     */
+    boolean shouldMatchBuiltInDisplayOrientationToReverseDefaultDisplay() {
+        // TODO(b/265991392): This should come from display_settings.xml once it's easier to
+        //  extend with complex configurations.
+        return mMatchBuiltInDisplayOrientationToDefaultDisplay;
+    }
+
     @Override
     public void onStateChanged(int state) {
         mCurrentState = state;
@@ -115,8 +127,10 @@
         if (mLastDeviceState == null || !mLastDeviceState.equals(deviceState)) {
             mLastDeviceState = deviceState;
 
-            for (Consumer<DeviceState> callback : mDeviceStateCallbacks) {
-                callback.accept(mLastDeviceState);
+            synchronized (this) {
+                for (Consumer<DeviceState> callback : mDeviceStateCallbacks) {
+                    callback.accept(mLastDeviceState);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index de63191..c2ddb41 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -246,7 +247,22 @@
                 || orientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
             return false;
         }
-        return getIgnoreOrientationRequest();
+        return getIgnoreOrientationRequest()
+                && !shouldRespectOrientationRequestDueToPerAppOverride();
+    }
+
+    private boolean shouldRespectOrientationRequestDueToPerAppOverride() {
+        if (mDisplayContent == null) {
+            return false;
+        }
+        ActivityRecord activity = mDisplayContent.topRunningActivity(
+                /* considerKeyguardState= */ true);
+        return activity != null && activity.getTaskFragment() != null
+                // Checking TaskFragment rather than ActivityRecord to ensure that transition
+                // between fullscreen and PiP would work well. Checking TaskFragment rather than
+                // Task to ensure that Activity Embedding is excluded.
+                && activity.getTaskFragment().getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+                && activity.mLetterboxUiController.isOverrideRespectRequestedOrientationEnabled();
     }
 
     boolean getIgnoreOrientationRequest() {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f183760..ca3cfaf 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -46,9 +46,7 @@
 import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
 import static android.view.Display.STATE_UNKNOWN;
 import static android.view.Display.isSuspendedState;
-import static android.view.InsetsState.ITYPE_IME;
-import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
-import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
@@ -57,10 +55,10 @@
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
 import static android.view.WindowInsets.Type.systemBars;
+import static android.view.WindowInsets.Type.systemGestures;
 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
-import static android.view.WindowManager.LayoutParams;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -120,12 +118,10 @@
 import static com.android.server.wm.DisplayContentProto.FOCUSED_APP;
 import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID;
 import static com.android.server.wm.DisplayContentProto.ID;
-import static com.android.server.wm.DisplayContentProto.IME_INSETS_SOURCE_PROVIDER;
 import static com.android.server.wm.DisplayContentProto.IME_POLICY;
 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_CONTROL_TARGET;
 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_INPUT_TARGET;
 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_TARGET;
-import static com.android.server.wm.DisplayContentProto.INSETS_SOURCE_PROVIDERS;
 import static com.android.server.wm.DisplayContentProto.IS_SLEEPING;
 import static com.android.server.wm.DisplayContentProto.KEEP_CLEAR_AREAS;
 import static com.android.server.wm.DisplayContentProto.MIN_SIZE_OF_RESIZEABLE_TASK_DP;
@@ -176,6 +172,7 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.ColorSpace;
+import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -223,7 +220,6 @@
 import android.view.InputDevice;
 import android.view.InsetsSource;
 import android.view.InsetsState;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.MagnificationSpec;
 import android.view.PrivacyIndicatorBounds;
 import android.view.RemoteAnimationDefinition;
@@ -250,7 +246,6 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.ToBooleanFunction;
-import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.internal.util.function.pooled.PooledPredicate;
 import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -293,6 +288,13 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface ForceScalingMode {}
 
+    private static final InsetsState.OnTraverseCallbacks COPY_SOURCE_VISIBILITY =
+            new InsetsState.OnTraverseCallbacks() {
+                public void onIdMatch(InsetsSource source1, InsetsSource source2) {
+                    source1.setVisible(source2.isVisible());
+                }
+            };
+
     final ActivityTaskManagerService mAtmService;
 
     /**
@@ -461,6 +463,8 @@
     private boolean mSystemGestureExclusionWasRestricted = false;
     private final Region mSystemGestureExclusionUnrestricted = new Region();
     private int mSystemGestureExclusionLimit;
+    private final Rect mSystemGestureFrameLeft = new Rect();
+    private final Rect mSystemGestureFrameRight = new Rect();
 
     private Set<Rect> mRestrictedKeepClearAreas = new ArraySet<>();
     private Set<Rect> mUnrestrictedKeepClearAreas = new ArraySet<>();
@@ -590,7 +594,8 @@
     final FixedRotationTransitionListener mFixedRotationTransitionListener =
             new FixedRotationTransitionListener();
 
-    private final DeviceStateController mDeviceStateController;
+    @VisibleForTesting
+    final DeviceStateController mDeviceStateController;
     private final PhysicalDisplaySwitchTransitionLauncher mDisplaySwitchTransitionLauncher;
     final RemoteDisplayChangeController mRemoteDisplayChangeController;
 
@@ -1086,7 +1091,8 @@
      * @param display May not be null.
      * @param root {@link RootWindowContainer}
      */
-    DisplayContent(Display display, RootWindowContainer root) {
+    DisplayContent(Display display, RootWindowContainer root,
+            @NonNull DeviceStateController deviceStateController) {
         super(root.mWindowManager, "DisplayContent", FEATURE_ROOT);
         if (mWmService.mRoot.getDisplayContent(display.getDisplayId()) != null) {
             throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
@@ -1146,11 +1152,11 @@
                     mWmService.mAtmService.getRecentTasks().getInputListener());
         }
 
-        mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH);
+        mDeviceStateController = deviceStateController;
 
         mDisplayPolicy = new DisplayPolicy(mWmService, this);
         mDisplayRotation = new DisplayRotation(mWmService, this, mDisplayInfo.address,
-                mDeviceStateController);
+                mDeviceStateController, root.getDisplayRotationCoordinator());
 
         final Consumer<DeviceStateController.DeviceState> deviceStateConsumer =
                 (@NonNull DeviceStateController.DeviceState newFoldState) -> {
@@ -1512,31 +1518,6 @@
         return mDisplayRotation;
     }
 
-    void setInsetProvider(@InternalInsetsType int type, WindowContainer win,
-            @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider) {
-        setInsetProvider(type, win, frameProvider, null /* overrideFrameProviders */);
-    }
-
-    /**
-     * Marks a window as providing insets for the rest of the windows in the system.
-     *
-     * @param type The type of inset this window provides.
-     * @param win The window.
-     * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of
-     *                      the window should be taken. Only for non-WindowState providers, nav bar
-     *                      and status bar.
-     * @param overrideFrameProviders Functions to compute the frame when dispatching insets to the
-     *                               given window types, or {@code null} if the normal frame should
-     *                               be taken.
-     */
-    void setInsetProvider(@InternalInsetsType int type, WindowContainer win,
-            @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider,
-            @Nullable SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>>
-                    overrideFrameProviders) {
-        mInsetsStateController.getSourceProvider(type).setWindowContainer(win, frameProvider,
-                overrideFrameProviders);
-    }
-
     InsetsStateController getInsetsStateController() {
         return mInsetsStateController;
     }
@@ -1725,7 +1706,7 @@
             }
             // The orientation source may not be the top if it uses SCREEN_ORIENTATION_BEHIND.
             final ActivityRecord topCandidate = !r.isVisibleRequested() ? topRunningActivity() : r;
-            if (handleTopActivityLaunchingInDifferentOrientation(
+            if (topCandidate != null && handleTopActivityLaunchingInDifferentOrientation(
                     topCandidate, r, true /* checkOpening */)) {
                 // Display orientation should be deferred until the top fixed rotation is finished.
                 return false;
@@ -1756,12 +1737,9 @@
             return ROTATION_UNDEFINED;
         }
         if (activityOrientation == ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
-            // TODO(b/266280737): Use ActivityRecord#canDefineOrientationForActivitiesAbove
             final ActivityRecord nextCandidate = getActivity(
-                    a -> a.getOverrideOrientation() != SCREEN_ORIENTATION_UNSET
-                            && a.getOverrideOrientation()
-                                    != ActivityInfo.SCREEN_ORIENTATION_BEHIND,
-                    r, false /* includeBoundary */, true /* traverseTopToBottom */);
+                    a -> a.canDefineOrientationForActivitiesAbove() /* callback */,
+                    r /* boundary */, false /* includeBoundary */, true /* traverseTopToBottom */);
             if (nextCandidate != null) {
                 r = nextCandidate;
             }
@@ -2091,12 +2069,7 @@
                     mFixedRotationLaunchingApp.getFixedRotationTransformInsetsState();
             if (rotatedState != null) {
                 final InsetsState state = mInsetsStateController.getRawInsetsState();
-                for (int i = 0; i < InsetsState.SIZE; i++) {
-                    final InsetsSource source = state.peekSource(i);
-                    if (source != null) {
-                        rotatedState.setSourceVisible(i, source.isVisible());
-                    }
-                }
+                InsetsState.traverse(rotatedState, state, COPY_SOURCE_VISIBILITY);
             }
         }
         forAllWindows(dispatchInsetsChanged, true /* traverseTopToBottom */);
@@ -2166,6 +2139,10 @@
                 w.seamlesslyRotateIfAllowed(transaction, oldRotation, rotation, rotateSeamlessly);
             }, true /* traverseTopToBottom */);
             mPinnedTaskController.startSeamlessRotationIfNeeded(transaction, oldRotation, rotation);
+            if (!mDisplayRotation.hasSeamlessRotatingWindow()) {
+                // Make sure DisplayRotation#isRotatingSeamlessly() will return false.
+                mDisplayRotation.cancelSeamlessRotation();
+            }
         }
 
         mWmService.mDisplayManagerInternal.performTraversal(transaction);
@@ -3325,7 +3302,7 @@
             mTransitionController.unregisterLegacyListener(mFixedRotationTransitionListener);
             handleAnimatingStoppedAndTransition();
             mWmService.stopFreezingDisplayLocked();
-            mDeviceStateController.unregisterFromDeviceStateManager();
+            mDisplayRotation.removeDefaultDisplayRotationChangedCallback();
             super.removeImmediately();
             if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
             mPointerEventDispatcher.dispose();
@@ -3380,7 +3357,7 @@
 
     int getInputMethodWindowVisibleHeight() {
         final InsetsState state = getInsetsStateController().getRawInsetsState();
-        final InsetsSource imeSource = state.peekSource(ITYPE_IME);
+        final InsetsSource imeSource = state.peekSource(ID_IME);
         if (imeSource == null || !imeSource.isVisible()) {
             return 0;
         }
@@ -3547,14 +3524,7 @@
             mCurrentFocus.dumpDebug(proto, CURRENT_FOCUS, logLevel);
         }
         if (mInsetsStateController != null) {
-            for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
-                final WindowContainerInsetsSourceProvider provider = mInsetsStateController
-                        .peekSourceProvider(type);
-                if (provider != null) {
-                    provider.dumpDebug(proto, type == ITYPE_IME ? IME_INSETS_SOURCE_PROVIDER :
-                            INSETS_SOURCE_PROVIDERS, logLevel);
-                }
-            }
+            mInsetsStateController.dumpDebug(proto, logLevel);
         }
         proto.write(IME_POLICY, getImePolicy());
         for (Rect r : getKeepClearAreas()) {
@@ -3814,6 +3784,17 @@
      */
     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows,
             int topFocusedDisplayId) {
+        // Don't re-assign focus automatically away from a should-keep-focus app window.
+        // `findFocusedWindow` will always grab the transient-launch app since it is "on top" which
+        // would create a mismatch, so just early-out here.
+        if (mCurrentFocus != null && mTransitionController.shouldKeepFocus(mCurrentFocus)
+                // This is only keeping focus, so don't early-out if the focused-app has been
+                // explicitly changed (eg. via setFocusedTask).
+                && mFocusedApp != null && mCurrentFocus.isDescendantOf(mFocusedApp)
+                && mCurrentFocus.isVisible() && mCurrentFocus.isFocusable()) {
+            ProtoLog.v(WM_DEBUG_FOCUS, "Current transition prevents automatic focus change");
+            return false;
+        }
         WindowState newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
         if (mCurrentFocus == newFocus) {
             return false;
@@ -3971,23 +3952,6 @@
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
-    // TODO: This should probably be called any time a visual change is made to the hierarchy like
-    // moving containers or resizing them. Need to investigate the best way to have it automatically
-    // happen so we don't run into issues with programmers forgetting to do it.
-    void layoutAndAssignWindowLayersIfNeeded() {
-        mWmService.mWindowsChanged = true;
-        setLayoutNeeded();
-
-        if (!mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                false /*updateInputWindows*/)) {
-            assignWindowLayers(false /* setLayoutNeeded */);
-        }
-
-        mInputMonitor.setUpdateInputWindowsNeededLw();
-        mWmService.mWindowPlacerLocked.performSurfacePlacement();
-        mInputMonitor.updateInputWindowsLw(false /*force*/);
-    }
-
     /** Returns true if a leaked surface was destroyed */
     boolean destroyLeakedSurfaces() {
         // Used to indicate that a surface was leaked.
@@ -4041,7 +4005,7 @@
             final int imePid = mInputMethodWindow.mSession.mPid;
             mAtmService.onImeWindowSetOnDisplayArea(imePid, mImeWindowsContainer);
         }
-        mInsetsStateController.getSourceProvider(ITYPE_IME).setWindowContainer(win,
+        mInsetsStateController.getImeSourceProvider().setWindowContainer(win,
                 mDisplayPolicy.getImeSourceFrameProvider(), null);
         computeImeTarget(true /* updateImeTarget */);
         updateImeControlTarget();
@@ -4290,7 +4254,8 @@
         assignWindowLayers(true /* setLayoutNeeded */);
         // 3. The z-order of IME might have been changed. Update the above insets state.
         mInsetsStateController.updateAboveInsetsState(
-                mInsetsStateController.getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
+                mInsetsStateController.getRawInsetsState().isSourceOrDefaultVisible(
+                        ID_IME, ime()));
         // 4. Update the IME control target to apply any inset change and animation.
         // 5. Reparent the IME container surface to either the input target app, or the IME window
         // parent.
@@ -4338,6 +4303,11 @@
             return mImeTarget;
         }
 
+        @VisibleForTesting
+        SurfaceControl getImeScreenshotSurface() {
+            return mImeSurface;
+        }
+
         private SurfaceControl createImeSurface(ScreenCapture.ScreenshotHardwareBuffer b,
                 Transaction t) {
             final HardwareBuffer buffer = b.getHardwareBuffer();
@@ -4447,33 +4417,45 @@
         }
     }
 
-    private void attachAndShowImeScreenshotOnTarget() {
+    private void attachImeScreenshotOnTargetIfNeeded() {
         // No need to attach screenshot if the IME target not exists or screen is off.
         if (!shouldImeAttachedToApp() || !mWmService.mPolicy.isScreenOn()) {
             return;
         }
 
-        final SurfaceControl.Transaction t = getPendingTransaction();
         // Prepare IME screenshot for the target if it allows to attach into.
         if (mInputMethodWindow != null && mInputMethodWindow.isVisible()) {
-            // Remove the obsoleted IME snapshot first in case the new snapshot happens to
-            // override the current one before the transition finish and the surface never be
-            // removed on the task.
-            removeImeSurfaceImmediately();
-            mImeScreenshot = new ImeScreenshot(
-                    mWmService.mSurfaceControlFactory.apply(null), mImeLayeringTarget);
-            mImeScreenshot.attachAndShow(t);
+            attachImeScreenshotOnTarget(mImeLayeringTarget);
         }
     }
 
+    private void attachImeScreenshotOnTarget(WindowState imeTarget) {
+        final SurfaceControl.Transaction t = getPendingTransaction();
+        // Remove the obsoleted IME snapshot first in case the new snapshot happens to
+        // override the current one before the transition finish and the surface never be
+        // removed on the task.
+        removeImeSurfaceImmediately();
+        mImeScreenshot = new ImeScreenshot(
+                mWmService.mSurfaceControlFactory.apply(null), imeTarget);
+        mImeScreenshot.attachAndShow(t);
+    }
+
     /**
-     * Shows the IME screenshot and attach to the IME target window.
+     * Shows the IME screenshot and attach to the IME layering target window.
      *
      * Used when the IME target window with IME visible is transitioning to the next target.
      * e.g. App transitioning or swiping this the task of the IME target window to recents app.
      */
     void showImeScreenshot() {
-        attachAndShowImeScreenshotOnTarget();
+        attachImeScreenshotOnTargetIfNeeded();
+    }
+
+    /**
+     * Shows the IME screenshot and attach it to the given IME target window.
+     */
+    @VisibleForTesting
+    void showImeScreenshot(WindowState imeTarget) {
+        attachImeScreenshotOnTarget(imeTarget);
     }
 
     /**
@@ -4516,7 +4498,7 @@
             ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
             setImeInputTarget(target);
             mInsetsStateController.updateAboveInsetsState(mInsetsStateController
-                    .getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
+                    .getRawInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
             // Force updating the IME parent when the IME control target has been updated to the
             // remote target but updateImeParent not happen because ImeLayeringTarget and
             // ImeInputTarget are different. Then later updateImeParent would be ignored when there
@@ -4634,24 +4616,9 @@
      */
     @VisibleForTesting
     SurfaceControl computeImeParent() {
-        if (mImeLayeringTarget != null) {
-            // Ensure changing the IME parent when the layering target that may use IME has
-            // became to the input target for preventing IME flickers.
-            // Note that:
-            // 1) For the imeLayeringTarget that may not use IME but requires IME on top
-            // of it (e.g. an overlay window with NOT_FOCUSABLE|ALT_FOCUSABLE_IM flags), we allow
-            // it to re-parent the IME on top the display to keep the legacy behavior.
-            // 2) Even though the starting window won't use IME, the associated activity
-            // behind the starting window may request the input. If so, then we should still hold
-            // the IME parent change until the activity started the input.
-            boolean imeLayeringTargetMayUseIme =
-                    LayoutParams.mayUseInputMethod(mImeLayeringTarget.mAttrs.flags)
-                    || mImeLayeringTarget.mAttrs.type == TYPE_APPLICATION_STARTING;
-            if (imeLayeringTargetMayUseIme && (mImeInputTarget == null
-                    || mImeLayeringTarget.mActivityRecord != mImeInputTarget.getActivityRecord())) {
-                // Do not change parent if the window hasn't requested IME.
-                return null;
-            }
+        if (!ImeTargetVisibilityPolicy.isReadyToComputeImeParent(mImeLayeringTarget,
+                mImeInputTarget)) {
+            return null;
         }
         // Attach it to app if the target is part of an app and such app is covering the entire
         // screen. If it's not covering the entire screen the IME might extend beyond the apps
@@ -4936,7 +4903,7 @@
         mInsetsStateController.getImeSourceProvider().checkShowImePostLayout();
 
         mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
-        if (!mWmService.mDisplayFrozen) {
+        if (!inTransition() && !mDisplayRotation.isRotatingSeamlessly()) {
             mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
                     mLastHasContent,
                     mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
@@ -5711,10 +5678,12 @@
         final Region unhandled = Region.obtain();
         unhandled.set(0, 0, mDisplayFrames.mWidth, mDisplayFrames.mHeight);
 
-        final Rect leftEdge = mInsetsStateController.getSourceProvider(ITYPE_LEFT_GESTURES)
-                .getSource().getFrame();
-        final Rect rightEdge = mInsetsStateController.getSourceProvider(ITYPE_RIGHT_GESTURES)
-                .getSource().getFrame();
+        final InsetsState state = mInsetsStateController.getRawInsetsState();
+        final Rect df = state.getDisplayFrame();
+        final Insets gestureInsets = state.calculateInsets(df, systemGestures(),
+                false /* ignoreVisibility */);
+        mSystemGestureFrameLeft.set(df.left, df.top, gestureInsets.left, df.bottom);
+        mSystemGestureFrameRight.set(gestureInsets.right, df.top, df.right, df.bottom);
 
         final Region touchableRegion = Region.obtain();
         final Region local = Region.obtain();
@@ -5758,25 +5727,25 @@
             if (needsGestureExclusionRestrictions(w, false /* ignoreRequest */)) {
 
                 // Processes the region along the left edge.
-                remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
-                        remainingLeftRight[0], w, EXCLUSION_LEFT);
+                remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion,
+                        mSystemGestureFrameLeft, remainingLeftRight[0], w, EXCLUSION_LEFT);
 
                 // Processes the region along the right edge.
-                remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
-                        remainingLeftRight[1], w, EXCLUSION_RIGHT);
+                remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, outExclusion,
+                        mSystemGestureFrameRight, remainingLeftRight[1], w, EXCLUSION_RIGHT);
 
                 // Adds the middle (unrestricted area)
                 final Region middle = Region.obtain(local);
-                middle.op(leftEdge, Op.DIFFERENCE);
-                middle.op(rightEdge, Op.DIFFERENCE);
+                middle.op(mSystemGestureFrameLeft, Op.DIFFERENCE);
+                middle.op(mSystemGestureFrameRight, Op.DIFFERENCE);
                 outExclusion.op(middle, Op.UNION);
                 middle.recycle();
             } else {
                 boolean loggable = needsGestureExclusionRestrictions(w, true /* ignoreRequest */);
                 if (loggable) {
-                    addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
+                    addToGlobalAndConsumeLimit(local, outExclusion, mSystemGestureFrameLeft,
                             Integer.MAX_VALUE, w, EXCLUSION_LEFT);
-                    addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
+                    addToGlobalAndConsumeLimit(local, outExclusion, mSystemGestureFrameRight,
                             Integer.MAX_VALUE, w, EXCLUSION_RIGHT);
                 }
                 outExclusion.op(local, Op.UNION);
@@ -6864,12 +6833,12 @@
         public void showInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme,
                 @Nullable ImeTracker.Token statsToken) {
             try {
-                ImeTracker.get().onProgress(statsToken,
+                ImeTracker.forLogging().onProgress(statsToken,
                         ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS);
                 mRemoteInsetsController.showInsets(types, fromIme, statsToken);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failed to deliver showInsets", e);
-                ImeTracker.get().onFailed(statsToken,
+                ImeTracker.forLogging().onFailed(statsToken,
                         ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS);
             }
         }
@@ -6878,12 +6847,12 @@
         public void hideInsets(@InsetsType int types, boolean fromIme,
                 @Nullable ImeTracker.Token statsToken) {
             try {
-                ImeTracker.get().onProgress(statsToken,
+                ImeTracker.forLogging().onProgress(statsToken,
                         ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS);
                 mRemoteInsetsController.hideInsets(types, fromIme, statsToken);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Failed to deliver hideInsets", e);
-                ImeTracker.get().onFailed(statsToken,
+                ImeTracker.forLogging().onFailed(statsToken,
                         ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS);
             }
         }
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index e984456..7f785af 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -16,10 +16,8 @@
 
 package com.android.server.wm;
 
-import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
-import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
-import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT;
-import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT;
+import static android.view.InsetsSource.createId;
+import static android.view.WindowInsets.Type.displayCutout;
 
 import android.annotation.NonNull;
 import android.graphics.Rect;
@@ -38,6 +36,12 @@
  * @hide
  */
 public class DisplayFrames {
+
+    private static final int ID_DISPLAY_CUTOUT_LEFT = createId(null, 0, displayCutout());
+    private static final int ID_DISPLAY_CUTOUT_TOP = createId(null, 1, displayCutout());
+    private static final int ID_DISPLAY_CUTOUT_RIGHT = createId(null, 2, displayCutout());
+    private static final int ID_DISPLAY_CUTOUT_BOTTOM = createId(null, 3, displayCutout());
+
     public final InsetsState mInsetsState;
 
     /**
@@ -97,28 +101,28 @@
         state.setDisplayShape(displayShape);
         state.getDisplayCutoutSafe(safe);
         if (safe.left > unrestricted.left) {
-            state.getSource(ITYPE_LEFT_DISPLAY_CUTOUT).setFrame(
+            state.getOrCreateSource(ID_DISPLAY_CUTOUT_LEFT, displayCutout()).setFrame(
                     unrestricted.left, unrestricted.top, safe.left, unrestricted.bottom);
         } else {
-            state.removeSource(ITYPE_LEFT_DISPLAY_CUTOUT);
+            state.removeSource(ID_DISPLAY_CUTOUT_LEFT);
         }
         if (safe.top > unrestricted.top) {
-            state.getSource(ITYPE_TOP_DISPLAY_CUTOUT).setFrame(
+            state.getOrCreateSource(ID_DISPLAY_CUTOUT_TOP, displayCutout()).setFrame(
                     unrestricted.left, unrestricted.top, unrestricted.right, safe.top);
         } else {
-            state.removeSource(ITYPE_TOP_DISPLAY_CUTOUT);
+            state.removeSource(ID_DISPLAY_CUTOUT_TOP);
         }
         if (safe.right < unrestricted.right) {
-            state.getSource(ITYPE_RIGHT_DISPLAY_CUTOUT).setFrame(
+            state.getOrCreateSource(ID_DISPLAY_CUTOUT_RIGHT, displayCutout()).setFrame(
                     safe.right, unrestricted.top, unrestricted.right, unrestricted.bottom);
         } else {
-            state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
+            state.removeSource(ID_DISPLAY_CUTOUT_RIGHT);
         }
         if (safe.bottom < unrestricted.bottom) {
-            state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(
+            state.getOrCreateSource(ID_DISPLAY_CUTOUT_BOTTOM, displayCutout()).setFrame(
                     unrestricted.left, safe.bottom, unrestricted.right, unrestricted.bottom);
         } else {
-            state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT);
+            state.removeSource(ID_DISPLAY_CUTOUT_BOTTOM);
         }
         return true;
     }
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index d759ff5..d324356 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -108,7 +108,6 @@
 import android.view.InsetsFrameProvider;
 import android.view.InsetsSource;
 import android.view.InsetsState;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.Surface;
 import android.view.View;
 import android.view.ViewDebug;
@@ -171,9 +170,8 @@
     /** Use the transit animation in style resource (see {@link #selectAnimation}). */
     static final int ANIMATION_STYLEABLE = 0;
 
-    private static final int[] SHOW_TYPES_FOR_SWIPE = {ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR,
-            ITYPE_CLIMATE_BAR, ITYPE_EXTRA_NAVIGATION_BAR};
-    private static final int[] SHOW_TYPES_FOR_PANIC = {ITYPE_NAVIGATION_BAR};
+    private static final int SHOW_TYPES_FOR_SWIPE = Type.statusBars() | Type.navigationBars();
+    private static final int SHOW_TYPES_FOR_PANIC = Type.navigationBars();
 
     private final WindowManagerService mService;
     private final Context mContext;
@@ -251,7 +249,7 @@
 
     private boolean mIsFreeformWindowOverlappingWithNavBar;
 
-    private boolean mLastImmersiveMode;
+    private boolean mIsImmersiveMode;
 
     // The windows we were told about in focusChanged.
     private WindowState mFocusedWindow;
@@ -1077,8 +1075,16 @@
                 } else {
                     overrideProviders = null;
                 }
-                mDisplayContent.setInsetProvider(provider.type, win, frameProvider,
-                        overrideProviders);
+                // TODO (b/234093736): Let InsetsFrameProvider have the following fields:
+                //                     - IBinder owner.
+                //                     - int index.
+                //                     - @InsetsType int type.
+                //                     So we can create the id by using InsetsSource#createId.
+                //                     And we won't need toPublicType anymore.
+                final int id = provider.type;
+                final @InsetsType int type = InsetsState.toPublicType(id);
+                mDisplayContent.getInsetsStateController().getOrCreateSourceProvider(id, type)
+                        .setWindowContainer(win, frameProvider, overrideProviders);
                 mInsetsSourceWindowsExceptIme.add(win);
             }
         }
@@ -1171,10 +1177,17 @@
             mLastFocusedWindow = null;
         }
 
-        final SparseArray<InsetsSource> sources = win.getProvidedInsetsSources();
-        for (int index = sources.size() - 1; index >= 0; index--) {
-            final @InternalInsetsType int type = sources.keyAt(index);
-            mDisplayContent.setInsetProvider(type, null /* win */, null /* frameProvider */);
+        if (win.hasInsetsSourceProvider()) {
+            final SparseArray<InsetsSourceProvider> providers = win.getInsetsSourceProviders();
+            final InsetsStateController controller = mDisplayContent.getInsetsStateController();
+            for (int index = providers.size() - 1; index >= 0; index--) {
+                final InsetsSourceProvider provider = providers.valueAt(index);
+                provider.setWindowContainer(
+                        null /* windowContainer */,
+                        null /* frameProvider */,
+                        null /* overrideFrameProviders */);
+                controller.removeSourceProvider(provider.getSource().getId());
+            }
         }
         mInsetsSourceWindowsExceptIme.remove(win);
     }
@@ -1243,7 +1256,6 @@
      * some temporal states, but doesn't change the window frames used to show on screen.
      */
     void simulateLayoutDisplay(DisplayFrames displayFrames) {
-        final InsetsStateController controller = mDisplayContent.getInsetsStateController();
         sTmpClientFrames.attachedFrame = null;
         for (int i = mInsetsSourceWindowsExceptIme.size() - 1; i >= 0; i--) {
             final WindowState win = mInsetsSourceWindowsExceptIme.valueAt(i);
@@ -1252,11 +1264,10 @@
                     displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH,
                     UNSPECIFIED_LENGTH, win.getRequestedVisibleTypes(), win.mGlobalScale,
                     sTmpClientFrames);
-            final SparseArray<InsetsSource> sources = win.getProvidedInsetsSources();
+            final SparseArray<InsetsSourceProvider> providers = win.getInsetsSourceProviders();
             final InsetsState state = displayFrames.mInsetsState;
-            for (int index = sources.size() - 1; index >= 0; index--) {
-                final int type = sources.keyAt(index);
-                state.addSource(controller.getSourceProvider(type).createSimulatedSource(
+            for (int index = providers.size() - 1; index >= 0; index--) {
+                state.addSource(providers.valueAt(index).createSimulatedSource(
                         displayFrames, sTmpClientFrames.frame));
             }
         }
@@ -1359,30 +1370,33 @@
             mIsFreeformWindowOverlappingWithNavBar = true;
         }
 
-        final SparseArray<InsetsSource> sources = win.getProvidedInsetsSources();
-        final Rect bounds = win.getBounds();
-        for (int index = sources.size() - 1; index >= 0; index--) {
-            final InsetsSource source = sources.valueAt(index);
-            if ((source.getType()
-                    & (Type.systemGestures() | Type.mandatorySystemGestures())) == 0) {
-                continue;
-            }
-            if (mLeftGestureHost != null && mTopGestureHost != null
-                    && mRightGestureHost != null && mBottomGestureHost != null) {
-                continue;
-            }
-            final Insets insets = source.calculateInsets(bounds, false /* ignoreVisibility */);
-            if (mLeftGestureHost == null && insets.left > 0) {
-                mLeftGestureHost = win;
-            }
-            if (mTopGestureHost == null && insets.top > 0) {
-                mTopGestureHost = win;
-            }
-            if (mRightGestureHost == null && insets.right > 0) {
-                mRightGestureHost = win;
-            }
-            if (mBottomGestureHost == null && insets.bottom > 0) {
-                mBottomGestureHost = win;
+        if (win.hasInsetsSourceProvider()) {
+            final SparseArray<InsetsSourceProvider> providers = win.getInsetsSourceProviders();
+            final Rect bounds = win.getBounds();
+            for (int index = providers.size() - 1; index >= 0; index--) {
+                final InsetsSourceProvider provider = providers.valueAt(index);
+                final InsetsSource source = provider.getSource();
+                if ((source.getType()
+                        & (Type.systemGestures() | Type.mandatorySystemGestures())) == 0) {
+                    continue;
+                }
+                if (mLeftGestureHost != null && mTopGestureHost != null
+                        && mRightGestureHost != null && mBottomGestureHost != null) {
+                    continue;
+                }
+                final Insets insets = source.calculateInsets(bounds, false /* ignoreVisibility */);
+                if (mLeftGestureHost == null && insets.left > 0) {
+                    mLeftGestureHost = win;
+                }
+                if (mTopGestureHost == null && insets.top > 0) {
+                    mTopGestureHost = win;
+                }
+                if (mRightGestureHost == null && insets.right > 0) {
+                    mRightGestureHost = win;
+                }
+                if (mBottomGestureHost == null && insets.bottom > 0) {
+                    mBottomGestureHost = win;
+                }
             }
         }
 
@@ -1741,21 +1755,6 @@
     }
 
     /**
-     * Get the Navigation Bar Frame height. This dimension is the height of the navigation bar that
-     * is used for spacing to show additional buttons on the navigation bar (such as the ime
-     * switcher when ime is visible).
-     *
-     * @param rotation specifies rotation to return dimension from
-     * @return navigation bar frame height
-     */
-    private int getNavigationBarFrameHeight(int rotation) {
-        if (mNavigationBar == null) {
-            return 0;
-        }
-        return mNavigationBar.mAttrs.forRotation(rotation).height;
-    }
-
-    /**
      * Return corner radius in pixels that should be used on windows in order to cover the display.
      *
      * The radius is only valid for internal displays, since the corner radius of external displays
@@ -2186,14 +2185,27 @@
         appearance = configureNavBarOpacity(appearance, multiWindowTaskVisible,
                 freeformRootTaskVisible);
 
+        // Show immersive mode confirmation if needed.
+        final boolean wasImmersiveMode = mIsImmersiveMode;
+        final boolean isImmersiveMode = isImmersiveMode(win);
+        if (wasImmersiveMode != isImmersiveMode) {
+            mIsImmersiveMode = isImmersiveMode;
+            // The immersive confirmation window should be attached to the immersive window root.
+            final RootDisplayArea root = win.getRootDisplayArea();
+            final int rootDisplayAreaId = root == null ? FEATURE_UNDEFINED : root.mFeatureId;
+            mImmersiveModeConfirmation.immersiveModeChangedLw(rootDisplayAreaId, isImmersiveMode,
+                    mService.mPolicy.isUserSetupComplete(),
+                    isNavBarEmpty(disableFlags));
+        }
+
+        // Show transient bars for panic if needed.
         final boolean requestHideNavBar = !win.isRequestedVisible(Type.navigationBars());
         final long now = SystemClock.uptimeMillis();
         final boolean pendingPanic = mPendingPanicGestureUptime != 0
                 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
         final DisplayPolicy defaultDisplayPolicy =
                 mService.getDefaultDisplayContentLocked().getDisplayPolicy();
-        if (pendingPanic && requestHideNavBar && win != mNotificationShade
-                && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)
+        if (pendingPanic && requestHideNavBar && isImmersiveMode
                 // TODO (b/111955725): Show keyguard presentation on all external displays
                 && defaultDisplayPolicy.isKeyguardDrawComplete()) {
             // The user performed the panic gesture recently, we're about to hide the bars,
@@ -2205,19 +2217,6 @@
             }
         }
 
-        // update navigation bar
-        boolean oldImmersiveMode = mLastImmersiveMode;
-        boolean newImmersiveMode = isImmersiveMode(win);
-        if (oldImmersiveMode != newImmersiveMode) {
-            mLastImmersiveMode = newImmersiveMode;
-            // The immersive confirmation window should be attached to the immersive window root.
-            final RootDisplayArea root = win.getRootDisplayArea();
-            final int rootDisplayAreaId = root == null ? FEATURE_UNDEFINED : root.mFeatureId;
-            mImmersiveModeConfirmation.immersiveModeChangedLw(rootDisplayAreaId, newImmersiveMode,
-                    mService.mPolicy.isUserSetupComplete(),
-                    isNavBarEmpty(disableFlags));
-        }
-
         return appearance;
     }
 
@@ -2228,23 +2227,40 @@
         return intersectsAnyInsets(win.getFrame(), win.getInsetsState(), type);
     }
 
-    private Rect getBarContentFrameForWindow(WindowState win, @InternalInsetsType int type) {
+    private Rect getBarContentFrameForWindow(WindowState win, @InsetsType int type) {
         final DisplayFrames displayFrames = win.getDisplayFrames(mDisplayContent.mDisplayFrames);
         final InsetsState state = displayFrames.mInsetsState;
-        final Rect tmpRect = new Rect();
-        sTmpDisplayCutoutSafe.set(displayFrames.mDisplayCutoutSafe);
-        if (type == ITYPE_STATUS_BAR) {
-            // The status bar content can extend into regular display cutout insets but not
-            // waterfall insets.
-            sTmpDisplayCutoutSafe.top =
-                    Math.max(state.getDisplayCutout().getWaterfallInsets().top, 0);
+        final Rect df = displayFrames.mUnrestricted;
+        final Rect safe = sTmpDisplayCutoutSafe;
+        final Insets waterfallInsets = state.getDisplayCutout().getWaterfallInsets();
+        final Rect outRect = new Rect();
+        final Rect sourceContent = sTmpRect;
+        safe.set(displayFrames.mDisplayCutoutSafe);
+        for (int i = state.sourceSize() - 1; i >= 0; i--) {
+            final InsetsSource source = state.sourceAt(i);
+            if (source.getType() != type) {
+                continue;
+            }
+            if (type == Type.statusBars()) {
+                safe.set(displayFrames.mDisplayCutoutSafe);
+                final Insets insets = source.calculateInsets(df, true /* ignoreVisibility */);
+                // The status bar content can extend into regular display cutout insets if they are
+                // at the same side, but the content cannot extend into waterfall insets.
+                if (insets.left > 0) {
+                    safe.left = Math.max(df.left + waterfallInsets.left, df.left);
+                } else if (insets.top > 0) {
+                    safe.top = Math.max(df.top + waterfallInsets.top, df.top);
+                } else if (insets.right > 0) {
+                    safe.right = Math.max(df.right - waterfallInsets.right, df.right);
+                } else if (insets.bottom > 0) {
+                    safe.bottom = Math.max(df.bottom - waterfallInsets.bottom, df.bottom);
+                }
+            }
+            sourceContent.set(source.getFrame());
+            sourceContent.intersect(safe);
+            outRect.union(sourceContent);
         }
-        final InsetsSource source = state.peekSource(type);
-        if (source != null) {
-            tmpRect.set(source.getFrame());
-            tmpRect.intersect(sTmpDisplayCutoutSafe);
-        }
-        return tmpRect;
+        return outRect;
     }
 
     /**
@@ -2257,7 +2273,7 @@
      * be drawn over letterboxed activity.
      */
     @VisibleForTesting
-    boolean isFullyTransparentAllowed(WindowState win, @InternalInsetsType int type) {
+    boolean isFullyTransparentAllowed(WindowState win, @InsetsType int type) {
         if (win == null) {
             return true;
         }
@@ -2284,7 +2300,7 @@
         for (int i = mStatusBarBackgroundWindows.size() - 1; i >= 0; i--) {
             final WindowState window = mStatusBarBackgroundWindows.get(i);
             drawBackground &= drawsBarBackground(window);
-            isFullyTransparentAllowed &= isFullyTransparentAllowed(window, ITYPE_STATUS_BAR);
+            isFullyTransparentAllowed &= isFullyTransparentAllowed(window, Type.statusBars());
         }
 
         if (drawBackground) {
@@ -2324,7 +2340,7 @@
             }
         }
 
-        if (!isFullyTransparentAllowed(mNavBarBackgroundWindow, ITYPE_NAVIGATION_BAR)) {
+        if (!isFullyTransparentAllowed(mNavBarBackgroundWindow, Type.navigationBars())) {
             appearance |= APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
         }
 
@@ -2339,18 +2355,10 @@
         if (win == null) {
             return false;
         }
-        return getNavigationBar() != null
-                && canHideNavigationBar()
-                && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)
-                && win != getNotificationShade()
-                && !win.isActivityTypeDream();
-    }
-
-    /**
-     * @return whether the navigation bar can be hidden, e.g. the device has a navigation bar
-     */
-    private boolean canHideNavigationBar() {
-        return hasNavigationBar();
+        if (win == getNotificationShade() || win.isActivityTypeDream()) {
+            return false;
+        }
+        return getInsetsPolicy().hasHiddenSources(Type.navigationBars());
     }
 
     private static boolean isNavBarEmpty(int systemUiFlags) {
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 3404279..c081725 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -58,6 +58,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArraySet;
+import android.util.RotationUtils;
 import android.util.Slog;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
@@ -120,6 +121,11 @@
     private FoldController mFoldController;
     @NonNull
     private final DeviceStateController mDeviceStateController;
+    @NonNull
+    private final DisplayRotationCoordinator mDisplayRotationCoordinator;
+    @NonNull
+    @VisibleForTesting
+    final Runnable mDefaultDisplayRotationChangedCallback;
 
     @ScreenOrientation
     private int mCurrentAppOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
@@ -221,17 +227,19 @@
     private boolean mDemoRotationLock;
 
     DisplayRotation(WindowManagerService service, DisplayContent displayContent,
-            DisplayAddress displayAddress, @NonNull DeviceStateController deviceStateController) {
+            DisplayAddress displayAddress, @NonNull DeviceStateController deviceStateController,
+            @NonNull DisplayRotationCoordinator displayRotationCoordinator) {
         this(service, displayContent, displayAddress, displayContent.getDisplayPolicy(),
                 service.mDisplayWindowSettings, service.mContext, service.getWindowManagerLock(),
-                deviceStateController);
+                deviceStateController, displayRotationCoordinator);
     }
 
     @VisibleForTesting
     DisplayRotation(WindowManagerService service, DisplayContent displayContent,
             DisplayAddress displayAddress, DisplayPolicy displayPolicy,
             DisplayWindowSettings displayWindowSettings, Context context, Object lock,
-            @NonNull DeviceStateController deviceStateController) {
+            @NonNull DeviceStateController deviceStateController,
+            @NonNull DisplayRotationCoordinator displayRotationCoordinator) {
         mService = service;
         mDisplayContent = displayContent;
         mDisplayPolicy = displayPolicy;
@@ -252,6 +260,19 @@
         int defaultRotation = readDefaultDisplayRotation(displayAddress);
         mRotation = defaultRotation;
 
+        mDisplayRotationCoordinator = displayRotationCoordinator;
+        if (isDefaultDisplay) {
+            mDisplayRotationCoordinator.setDefaultDisplayDefaultRotation(mRotation);
+        }
+        mDefaultDisplayRotationChangedCallback = this::updateRotationAndSendNewConfigIfChanged;
+
+        if (DisplayRotationCoordinator.isSecondaryInternalDisplay(displayContent)
+                && mDeviceStateController
+                        .shouldMatchBuiltInDisplayOrientationToReverseDefaultDisplay()) {
+            mDisplayRotationCoordinator.setDefaultDisplayRotationChangedCallback(
+                    mDefaultDisplayRotationChangedCallback);
+        }
+
         if (isDefaultDisplay) {
             final Handler uiHandler = UiThread.getHandler();
             mOrientationListener =
@@ -494,8 +515,11 @@
             return false;
         }
 
+        @Surface.Rotation
         final int oldRotation = mRotation;
+        @ScreenOrientation
         final int lastOrientation = mLastOrientation;
+        @Surface.Rotation
         int rotation = rotationForOrientation(lastOrientation, oldRotation);
         // Use the saved rotation for tabletop mode, if set.
         if (mFoldController != null && mFoldController.shouldRevertOverriddenRotation()) {
@@ -507,6 +531,14 @@
                     Surface.rotationToString(oldRotation),
                     Surface.rotationToString(prevRotation));
         }
+
+        if (DisplayRotationCoordinator.isSecondaryInternalDisplay(mDisplayContent)
+                && mDeviceStateController
+                        .shouldMatchBuiltInDisplayOrientationToReverseDefaultDisplay()) {
+            rotation = RotationUtils.reverseRotationDirectionAroundZAxis(
+                    mDisplayRotationCoordinator.getDefaultDisplayCurrentRotation());
+        }
+
         ProtoLog.v(WM_DEBUG_ORIENTATION,
                 "Computed rotation=%s (%d) for display id=%d based on lastOrientation=%s (%d) and "
                         + "oldRotation=%s (%d)",
@@ -525,6 +557,10 @@
             return false;
         }
 
+        if (isDefaultDisplay) {
+            mDisplayRotationCoordinator.onDefaultDisplayRotationChanged(rotation);
+        }
+
         // Preemptively cancel the running recents animation -- SysUI can't currently handle this
         // case properly since the signals it receives all happen post-change. We do this earlier
         // in the rotation flow, since DisplayContent.updateDisplayOverrideConfigurationLocked seems
@@ -599,7 +635,8 @@
 
         if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) {
             if (!mDisplayContent.mTransitionController.isCollecting()) {
-                throw new IllegalStateException("Trying to rotate outside a transition");
+                // The remote may be too slow to response before transition timeout.
+                Slog.e(TAG, "Trying to continue rotation outside a transition");
             }
             mDisplayContent.mTransitionController.collect(mDisplayContent);
         }
@@ -1142,17 +1179,12 @@
             return mUserRotation;
         }
 
+        @Surface.Rotation
         int sensorRotation = mOrientationListener != null
                 ? mOrientationListener.getProposedRotation() // may be -1
                 : -1;
         if (mDeviceStateController.shouldReverseRotationDirectionAroundZAxis()) {
-            // Flipping 270 and 90 has the same effect as changing the direction which rotation is
-            // applied.
-            if (sensorRotation == Surface.ROTATION_90) {
-                sensorRotation = Surface.ROTATION_270;
-            } else if (sensorRotation == Surface.ROTATION_270) {
-                sensorRotation = Surface.ROTATION_90;
-            }
+            sensorRotation = RotationUtils.reverseRotationDirectionAroundZAxis(sensorRotation);
         }
         mLastSensorRotation = sensorRotation;
         if (sensorRotation < 0) {
@@ -1167,6 +1199,7 @@
         final boolean deskDockEnablesAccelerometer =
                 mDisplayPolicy.isDeskDockEnablesAccelerometer();
 
+        @Surface.Rotation
         final int preferredRotation;
         if (!isDefaultDisplay) {
             // For secondary displays we ignore things like displays sensors, docking mode and
@@ -1536,6 +1569,12 @@
         return shouldUpdateRotation;
     }
 
+    void removeDefaultDisplayRotationChangedCallback() {
+        if (DisplayRotationCoordinator.isSecondaryInternalDisplay(mDisplayContent)) {
+            mDisplayRotationCoordinator.removeDefaultDisplayRotationChangedCallback();
+        }
+    }
+
     void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "DisplayRotation");
         pw.println(prefix + "  mCurrentAppOrientation="
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index 3ffb2fa..e04900c 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
@@ -34,6 +36,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.RefreshCallbackItem;
 import android.app.servertransaction.ResumeActivityItem;
@@ -44,10 +47,13 @@
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.widget.Toast;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.UiThread;
 
 import java.util.Map;
 import java.util.Set;
@@ -232,6 +238,27 @@
         activity.mLetterboxUiController.setIsRefreshAfterRotationRequested(false);
     }
 
+    /**
+     * Notifies that animation in {@link ScreenAnimationRotation} has finished.
+     *
+     * <p>This class uses this signal as a trigger for notifying the user about forced rotation
+     * reason with the {@link Toast}.
+     */
+    void onScreenRotationAnimationFinished() {
+        if (!isTreatmentEnabledForDisplay() || mCameraIdPackageBiMap.isEmpty()) {
+            return;
+        }
+        ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+                    /* considerKeyguardState= */ true);
+        if (topActivity == null
+                // Checking windowing mode on activity level because we don't want to
+                // show toast in case of activity embedding.
+                || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+            return;
+        }
+        showToast(R.string.display_rotation_camera_compat_toast_after_rotation);
+    }
+
     String getSummaryForDisplayRotationHistoryRecord() {
         String summaryIfEnabled = "";
         if (isTreatmentEnabledForDisplay()) {
@@ -281,6 +308,10 @@
                 && mDisplayContent.getDisplay().getType() == TYPE_INTERNAL;
     }
 
+    boolean isActivityEligibleForOrientationOverride(@NonNull ActivityRecord activity) {
+        return isTreatmentEnabledForDisplay() && isCameraActiveInFullscreen(activity);
+    }
+
     /**
      * Whether camera compat treatment is applicable for the given activity.
      *
@@ -292,12 +323,16 @@
      * </ul>
      */
     boolean isTreatmentEnabledForActivity(@Nullable ActivityRecord activity) {
-        return activity != null && !activity.inMultiWindowMode()
+        return activity != null && isCameraActiveInFullscreen(activity)
                 && activity.getRequestedConfigurationOrientation() != ORIENTATION_UNDEFINED
                 // "locked" and "nosensor" values are often used by camera apps that can't
                 // handle dynamic changes so we shouldn't force rotate them.
                 && activity.getOverrideOrientation() != SCREEN_ORIENTATION_NOSENSOR
-                && activity.getOverrideOrientation() != SCREEN_ORIENTATION_LOCKED
+                && activity.getOverrideOrientation() != SCREEN_ORIENTATION_LOCKED;
+    }
+
+    private boolean isCameraActiveInFullscreen(@NonNull ActivityRecord activity) {
+        return !activity.inMultiWindowMode()
                 && mCameraIdPackageBiMap.containsPackageName(activity.packageName)
                 && activity.mLetterboxUiController.shouldForceRotateForCameraCompat();
     }
@@ -334,7 +369,31 @@
             }
             mCameraIdPackageBiMap.put(packageName, cameraId);
         }
-        updateOrientationWithWmLock();
+        ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+                    /* considerKeyguardState= */ true);
+        if (topActivity == null || topActivity.getTask() == null) {
+            return;
+        }
+        // Checking whether an activity in fullscreen rather than the task as this camera compat
+        // treatment doesn't cover activity embedding.
+        if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+            if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
+                topActivity.recomputeConfiguration();
+            }
+            updateOrientationWithWmLock();
+            return;
+        }
+        // Checking that the whole app is in multi-window mode as we shouldn't show toast
+        // for the activity embedding case.
+        if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) {
+            showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
+        }
+    }
+
+    @VisibleForTesting
+    void showToast(@StringRes int stringRes) {
+        UiThread.getHandler().post(
+                () -> Toast.makeText(mWmService.mContext, stringRes, Toast.LENGTH_LONG).show());
     }
 
     private synchronized void notifyCameraClosed(@NonNull String cameraId) {
@@ -375,6 +434,17 @@
         ProtoLog.v(WM_DEBUG_ORIENTATION,
                 "Display id=%d is notified that Camera %s is closed, updating rotation.",
                 mDisplayContent.mDisplayId, cameraId);
+        ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+                /* considerKeyguardState= */ true);
+        if (topActivity == null
+                // Checking whether an activity in fullscreen rather than the task as this camera
+                // compat treatment doesn't cover activity embedding.
+                || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+            return;
+        }
+        if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
+            topActivity.recomputeConfiguration();
+        }
         updateOrientationWithWmLock();
     }
 
@@ -396,6 +466,10 @@
         private final Map<String, String> mPackageToCameraIdMap = new ArrayMap<>();
         private final Map<String, String> mCameraIdToPackageMap = new ArrayMap<>();
 
+        boolean isEmpty() {
+            return mCameraIdToPackageMap.isEmpty();
+        }
+
         void put(String packageName, String cameraId) {
             // Always using the last connected camera ID for the package even for the concurrent
             // camera use case since we can't guess which camera is more important anyway.
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCoordinator.java b/services/core/java/com/android/server/wm/DisplayRotationCoordinator.java
new file mode 100644
index 0000000..ae3787c
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayRotationCoordinator.java
@@ -0,0 +1,99 @@
+/*
+ * 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.wm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.view.Display;
+import android.view.Surface;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Singleton for coordinating rotation across multiple displays. Used to notify non-default
+ * displays when the default display rotates.
+ *
+ * Note that this class does not need locking because it is always protected by WindowManagerService
+ * mGlobalLock.
+ */
+class DisplayRotationCoordinator {
+
+    private static final String TAG = "DisplayRotationCoordinator";
+
+    @Surface.Rotation
+    private int mDefaultDisplayDefaultRotation;
+
+    @Nullable
+    @VisibleForTesting
+    Runnable mDefaultDisplayRotationChangedCallback;
+
+    @Surface.Rotation
+    private int mDefaultDisplayCurrentRotation;
+
+    /**
+     * Notifies clients when the default display rotation changes.
+     */
+    void onDefaultDisplayRotationChanged(@Surface.Rotation int rotation) {
+        mDefaultDisplayCurrentRotation = rotation;
+
+        if (mDefaultDisplayRotationChangedCallback != null) {
+            mDefaultDisplayRotationChangedCallback.run();
+        }
+    }
+
+    void setDefaultDisplayDefaultRotation(@Surface.Rotation int rotation) {
+        mDefaultDisplayDefaultRotation = rotation;
+    }
+
+    @Surface.Rotation
+    int getDefaultDisplayCurrentRotation() {
+        return mDefaultDisplayCurrentRotation;
+    }
+
+    /**
+     * Register a callback to be notified when the default display's rotation changes. Clients can
+     * query the default display's current rotation via {@link #getDefaultDisplayCurrentRotation()}.
+     */
+    void setDefaultDisplayRotationChangedCallback(@NonNull Runnable callback) {
+        if (mDefaultDisplayRotationChangedCallback != null) {
+            throw new UnsupportedOperationException("Multiple clients unsupported");
+        }
+
+        mDefaultDisplayRotationChangedCallback = callback;
+
+        if (mDefaultDisplayCurrentRotation != mDefaultDisplayDefaultRotation) {
+            callback.run();
+        }
+    }
+
+    /**
+     * Removes the callback that was added via
+     * {@link #setDefaultDisplayRotationChangedCallback(Runnable)}.
+     */
+    void removeDefaultDisplayRotationChangedCallback() {
+        mDefaultDisplayRotationChangedCallback = null;
+    }
+
+    static boolean isSecondaryInternalDisplay(@NonNull DisplayContent displayContent) {
+        if (displayContent.isDefaultDisplay) {
+            return false;
+        } else if (displayContent.mDisplay == null) {
+            return false;
+        }
+        return displayContent.mDisplay.getType() == Display.TYPE_INTERNAL;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
index 154fb0c..1fb97f9 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
@@ -21,6 +21,7 @@
 import android.app.WindowConfiguration;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.os.Process;
 import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.Slog;
@@ -138,10 +139,14 @@
                 true /* includeOverlays */);
         if (topActivity != mTopRunningActivity) {
             mTopRunningActivity = topActivity;
-            mDisplayWindowPolicyController.onTopActivityChanged(
-                    topActivity == null ? null : topActivity.info.getComponentName(),
-                    topActivity == null
-                            ? UserHandle.USER_NULL : topActivity.info.applicationInfo.uid);
+            if (topActivity == null) {
+                mDisplayWindowPolicyController.onTopActivityChanged(null, Process.INVALID_UID,
+                        UserHandle.USER_NULL);
+            } else {
+                mDisplayWindowPolicyController.onTopActivityChanged(
+                        topActivity.info.getComponentName(), topActivity.info.applicationInfo.uid,
+                        topActivity.mUserId);
+            }
         }
 
         // Update running uid.
diff --git a/services/core/java/com/android/server/wm/EventLogTags.logtags b/services/core/java/com/android/server/wm/EventLogTags.logtags
index b36f835..031e022 100644
--- a/services/core/java/com/android/server/wm/EventLogTags.logtags
+++ b/services/core/java/com/android/server/wm/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
 
 option java_package com.android.server.wm
 
@@ -59,6 +59,10 @@
 31002 wm_task_moved (TaskId|1|5),(Root Task ID|1|5),(Display Id|1|5),(ToTop|1),(Index|1)
 # Task removed with source explanation.
 31003 wm_task_removed (TaskId|1|5),(Root Task ID|1|5),(Display Id|1|5),(Reason|3)
+
+# Set the requested orientation of an activity.
+31006 wm_set_requested_orientation (Orientation|1|5),(Component Name|3)
+
 # bootanim finished:
 31007 wm_boot_animation_done (time|2|3)
 
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 85938e3..4be98a3 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -17,7 +17,7 @@
 package com.android.server.wm;
 
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
 import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
@@ -57,7 +57,7 @@
     private Runnable mShowImeRunner;
     private boolean mIsImeLayoutDrawn;
     private boolean mImeShowing;
-    private final InsetsSource mLastSource = new InsetsSource(ITYPE_IME, WindowInsets.Type.ime());
+    private final InsetsSource mLastSource = new InsetsSource(ID_IME, WindowInsets.Type.ime());
 
     /** @see #setFrozen(boolean) */
     private boolean mFrozen;
@@ -182,7 +182,8 @@
         boolean targetChanged = isTargetChangedWithinActivity(imeTarget);
         mImeRequester = imeTarget;
         // There was still a stats token, so that request presumably failed.
-        ImeTracker.get().onFailed(mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
+        ImeTracker.forLogging().onFailed(
+                mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
         mImeRequesterStatsToken = statsToken;
         if (targetChanged) {
             // target changed, check if new target can show IME.
@@ -197,12 +198,12 @@
         ProtoLog.d(WM_DEBUG_IME, "Schedule IME show for %s", mImeRequester.getWindow() == null
                 ? mImeRequester : mImeRequester.getWindow().getName());
         mShowImeRunner = () -> {
-            ImeTracker.get().onProgress(mImeRequesterStatsToken,
+            ImeTracker.forLogging().onProgress(mImeRequesterStatsToken,
                     ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
             ProtoLog.d(WM_DEBUG_IME, "Run showImeRunner");
             // Target should still be the same.
             if (isReadyToShowIme()) {
-                ImeTracker.get().onProgress(mImeRequesterStatsToken,
+                ImeTracker.forLogging().onProgress(mImeRequesterStatsToken,
                         ImeTracker.PHASE_WM_SHOW_IME_READY);
                 final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_CONTROL);
 
@@ -219,7 +220,7 @@
                                     ? mImeRequester.getWindow().getName() : ""));
                 }
             } else {
-                ImeTracker.get().onFailed(mImeRequesterStatsToken,
+                ImeTracker.forLogging().onFailed(mImeRequesterStatsToken,
                         ImeTracker.PHASE_WM_SHOW_IME_READY);
             }
             // Clear token here so we don't report an error in abortShowImePostLayout().
@@ -258,7 +259,8 @@
         mImeRequester = null;
         mIsImeLayoutDrawn = false;
         mShowImeRunner = null;
-        ImeTracker.get().onCancelled(mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
+        ImeTracker.forLogging().onCancelled(
+                mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
         mImeRequesterStatsToken = null;
     }
 
diff --git a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
new file mode 100644
index 0000000..49218ad
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
@@ -0,0 +1,80 @@
+/*
+ * 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.wm;
+
+
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+
+import android.os.IBinder;
+import android.view.WindowManager;
+
+/**
+ * A class for {@link com.android.server.inputmethod.InputMethodManagerService} to
+ * control IME visibility operations in {@link WindowManagerService}.
+ */
+public abstract class ImeTargetVisibilityPolicy {
+
+    /**
+     * Shows the IME screenshot and attach it to the given IME target window.
+     *
+     * @param imeTarget The target window to show the IME screenshot.
+     * @param displayId A unique id to identify the display.
+     * @return {@code true} if success, {@code false} otherwise.
+     */
+    public abstract boolean showImeScreenShot(IBinder imeTarget, int displayId);
+
+    /**
+     * Updates the IME parent for target window.
+     *
+     * @param imeTarget The target window to update the IME parent.
+     * @param displayId A unique id to identify the display.
+     * @return {@code true} if success, {@code false} otherwise.
+     */
+    public abstract boolean updateImeParent(IBinder imeTarget, int displayId);
+
+    /**
+     * Called when {@link DisplayContent#computeImeParent()} to check if it's valid to keep
+     * computing the ime parent.
+     *
+     * @return {@code true} to keep computing the ime parent, {@code false} to defer this operation
+     */
+    public static boolean isReadyToComputeImeParent(WindowState imeLayeringTarget,
+            InputTarget imeInputTarget) {
+        if (imeLayeringTarget == null) {
+            return false;
+        }
+        // Ensure changing the IME parent when the layering target that may use IME has
+        // became to the input target for preventing IME flickers.
+        // Note that:
+        // 1) For the imeLayeringTarget that may not use IME but requires IME on top
+        // of it (e.g. an overlay window with NOT_FOCUSABLE|ALT_FOCUSABLE_IM flags), we allow
+        // it to re-parent the IME on top the display to keep the legacy behavior.
+        // 2) Even though the starting window won't use IME, the associated activity
+        // behind the starting window may request the input. If so, then we should still hold
+        // the IME parent change until the activity started the input.
+        boolean imeLayeringTargetMayUseIme =
+                WindowManager.LayoutParams.mayUseInputMethod(imeLayeringTarget.mAttrs.flags)
+                        || imeLayeringTarget.mAttrs.type == TYPE_APPLICATION_STARTING;
+
+        // Do not change parent if the window hasn't requested IME.
+        var inputAndLayeringTargetsDisagree = (imeInputTarget == null
+                || imeLayeringTarget.mActivityRecord != imeInputTarget.getActivityRecord());
+        var inputTargetStale = imeLayeringTargetMayUseIme && inputAndLayeringTargetsDisagree;
+
+        return !inputTargetStale;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 3e1105b..8c59548 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -405,8 +405,12 @@
             // Apply recents input consumer when the focusing window is in recents animation.
             final boolean shouldApplyRecentsInputConsumer = (recentsAnimationController != null
                     && recentsAnimationController.shouldApplyInputConsumer(focus.mActivityRecord))
-                    // Shell transitions doesn't use RecentsAnimationController
-                    || getWeak(mActiveRecentsActivity) != null && focus.inTransition();
+                    // Shell transitions doesn't use RecentsAnimationController but we still
+                    // have carryover legacy logic that relies on the consumer.
+                    || (getWeak(mActiveRecentsActivity) != null && focus.inTransition()
+                            // only take focus from the recents activity to avoid intercepting
+                            // events before the gesture officially starts.
+                            && focus.isActivityTypeHomeOrRecents());
             if (shouldApplyRecentsInputConsumer) {
                 if (mInputFocus != recentsAnimationInputConsumer.mWindowHandle.token) {
                     requestFocus(recentsAnimationInputConsumer.mWindowHandle.token,
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 1df534f..0b8af4a 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -25,9 +25,7 @@
 import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
 import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
 import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
-import static android.view.InsetsState.ITYPE_IME;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
@@ -41,8 +39,6 @@
 import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.res.Resources;
-import android.util.ArrayMap;
-import android.util.IntArray;
 import android.util.SparseArray;
 import android.view.InsetsAnimationControlCallbacks;
 import android.view.InsetsAnimationControlImpl;
@@ -52,7 +48,6 @@
 import android.view.InsetsSource;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.InternalInsetsAnimationController;
 import android.view.SurfaceControl;
 import android.view.SyncRtSurfaceTransactionApplier;
@@ -81,7 +76,6 @@
     private final InsetsStateController mStateController;
     private final DisplayContent mDisplayContent;
     private final DisplayPolicy mPolicy;
-    private final IntArray mShowingTransientTypes = new IntArray();
 
     /** For resetting visibilities of insets sources. */
     private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() {
@@ -95,7 +89,7 @@
                 return;
             }
             for (InsetsSourceControl control : controls) {
-                if (mShowingTransientTypes.indexOf(control.getId()) != -1) {
+                if (isTransient(control.getType())) {
                     // The visibilities of transient bars will be handled with animations.
                     continue;
                 }
@@ -117,13 +111,16 @@
     };
 
     private WindowState mFocusedWin;
-    private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
-    private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
+    private final BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
+    private final BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
+    private @InsetsType int mShowingTransientTypes;
     private boolean mAnimatingShown;
+
     /**
      * Let remote insets controller control system bars regardless of other settings.
      */
     private boolean mRemoteInsetsControllerControlsSystemBars;
+
     private final boolean mHideNavBarForKeyboard;
     private final float[] mTmpFloat9 = new float[9];
 
@@ -178,37 +175,46 @@
         mNavBar.updateVisibility(navControlTarget, Type.navigationBars());
     }
 
-    boolean isHidden(@InternalInsetsType int type) {
-        final WindowContainerInsetsSourceProvider provider = mStateController
-                .peekSourceProvider(type);
-        return provider != null && provider.hasWindowContainer()
-                && !provider.getSource().isVisible();
+    boolean hasHiddenSources(@InsetsType int types) {
+        final InsetsState state = mStateController.getRawInsetsState();
+        for (int i = state.sourceSize() - 1; i >= 0; i--) {
+            final InsetsSource source = state.sourceAt(i);
+            if ((source.getType() & types) == 0) {
+                continue;
+            }
+            if (!source.getFrame().isEmpty() && !source.isVisible()) {
+                return true;
+            }
+        }
+        return false;
     }
 
-    void showTransient(@InternalInsetsType int[] types, boolean isGestureOnSystemBar) {
-        boolean changed = false;
-        for (int i = types.length - 1; i >= 0; i--) {
-            final @InternalInsetsType int type = types[i];
-            if (!isHidden(type)) {
+    void showTransient(@InsetsType int types, boolean isGestureOnSystemBar) {
+        @InsetsType int showingTransientTypes = mShowingTransientTypes;
+        final InsetsState rawState = mStateController.getRawInsetsState();
+        for (int i = rawState.sourceSize() - 1; i >= 0; i--) {
+            final InsetsSource source = rawState.sourceAt(i);
+            if (source.isVisible()) {
                 continue;
             }
-            if (mShowingTransientTypes.indexOf(type) != -1) {
+            final @InsetsType int type = source.getType();
+            if ((source.getType() & types) == 0) {
                 continue;
             }
-            mShowingTransientTypes.add(type);
-            changed = true;
+            showingTransientTypes |= type;
         }
-        if (changed) {
+        if (mShowingTransientTypes != showingTransientTypes) {
+            mShowingTransientTypes = showingTransientTypes;
             StatusBarManagerInternal statusBarManagerInternal =
                     mPolicy.getStatusBarManagerInternal();
             if (statusBarManagerInternal != null) {
                 statusBarManagerInternal.showTransient(mDisplayContent.getDisplayId(),
-                        mShowingTransientTypes.toArray(), isGestureOnSystemBar);
+                        showingTransientTypes, isGestureOnSystemBar);
             }
             updateBarControlTarget(mFocusedWin);
             dispatchTransientSystemBarsVisibilityChanged(
                     mFocusedWin,
-                    isTransient(ITYPE_STATUS_BAR) || isTransient(ITYPE_NAVIGATION_BAR),
+                    (showingTransientTypes & (Type.statusBars() | Type.navigationBars())) != 0,
                     isGestureOnSystemBar);
 
             // The leashes can be created while updating bar control target. The surface transaction
@@ -224,7 +230,7 @@
     }
 
     void hideTransient() {
-        if (mShowingTransientTypes.size() == 0) {
+        if (mShowingTransientTypes == 0) {
             return;
         }
 
@@ -235,20 +241,25 @@
 
         startAnimation(false /* show */, () -> {
             synchronized (mDisplayContent.mWmService.mGlobalLock) {
-                for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+                final SparseArray<WindowContainerInsetsSourceProvider> providers =
+                        mStateController.getSourceProviders();
+                for (int i = providers.size() - 1; i >= 0; i--) {
+                    final WindowContainerInsetsSourceProvider provider = providers.valueAt(i);
+                    if (!isTransient(provider.getSource().getType())) {
+                        continue;
+                    }
                     // We are about to clear mShowingTransientTypes, we don't want the transient bar
                     // can cause insets on the client. Restore the client visibility.
-                    final @InternalInsetsType int type = mShowingTransientTypes.get(i);
-                    mStateController.getSourceProvider(type).setClientVisible(false);
+                    provider.setClientVisible(false);
                 }
-                mShowingTransientTypes.clear();
+                mShowingTransientTypes = 0;
                 updateBarControlTarget(mFocusedWin);
             }
         });
     }
 
-    boolean isTransient(@InternalInsetsType int type) {
-        return mShowingTransientTypes.indexOf(type) != -1;
+    boolean isTransient(@InsetsType int type) {
+        return (mShowingTransientTypes & type) != 0;
     }
 
     /**
@@ -280,9 +291,9 @@
                 ? token.getFixedRotationTransformInsetsState()
                 : mStateController.getRawInsetsState();
         outInsetsState.set(srcState, true /* copySources */);
-        for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
-            final InsetsSource source = outInsetsState.peekSource(mShowingTransientTypes.get(i));
-            if (source != null) {
+        for (int i = outInsetsState.sourceSize() - 1; i >= 0; i--) {
+            final InsetsSource source = outInsetsState.sourceAt(i);
+            if (isTransient(source.getType())) {
                 source.setVisible(false);
             }
         }
@@ -315,12 +326,14 @@
         // The caller should not receive the visible insets provided by itself.
         if (attrs.type == TYPE_INPUT_METHOD) {
             state = new InsetsState(state);
-            state.removeSource(ITYPE_IME);
+            state.removeSource(ID_IME);
         } else if (attrs.providedInsets != null) {
             for (InsetsFrameProvider provider : attrs.providedInsets) {
                 // TODO(b/234093736): Let InsetsFrameProvider return the public type and the ID.
                 final int sourceId = provider.type;
-                final @InsetsType int type = InsetsState.toPublicType(sourceId);
+                final @InsetsType int type = sourceId == ID_IME
+                        ? WindowInsets.Type.ime()
+                        : InsetsState.toPublicType(sourceId);
                 if ((type & WindowInsets.Type.systemBars()) == 0) {
                     continue;
                 }
@@ -331,8 +344,8 @@
             }
         }
 
-        final ArrayMap<Integer, WindowContainerInsetsSourceProvider> providers = mStateController
-                .getSourceProviders();
+        final SparseArray<WindowContainerInsetsSourceProvider> providers =
+                mStateController.getSourceProviders();
         final int windowType = attrs.type;
         for (int i = providers.size() - 1; i >= 0; i--) {
             final WindowContainerInsetsSourceProvider otherProvider = providers.valueAt(i);
@@ -340,8 +353,7 @@
                 if (state == originalState) {
                     state = new InsetsState(state);
                 }
-                final InsetsSource override =
-                        new InsetsSource(state.getSource(otherProvider.getSource().getId()));
+                final InsetsSource override = new InsetsSource(otherProvider.getSource());
                 override.setFrame(otherProvider.getOverriddenFrame(windowType));
                 state.addSource(override);
             }
@@ -364,18 +376,17 @@
 
     private InsetsState adjustVisibilityForTransientTypes(InsetsState originalState) {
         InsetsState state = originalState;
-        for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
-            final @InternalInsetsType int type = mShowingTransientTypes.get(i);
-            final InsetsSource originalSource = state.peekSource(type);
-            if (originalSource != null && originalSource.isVisible()) {
+        for (int i = state.sourceSize() - 1; i >= 0; i--) {
+            final InsetsSource source = state.sourceAt(i);
+            if (isTransient(source.getType()) && source.isVisible()) {
                 if (state == originalState) {
                     // The source will be modified, create a non-deep copy to store the new one.
                     state = new InsetsState(originalState);
                 }
                 // Replace the source with a copy in invisible state.
-                final InsetsSource source = new InsetsSource(originalSource);
-                source.setVisible(false);
-                state.addSource(source);
+                final InsetsSource outSource = new InsetsSource(source);
+                outSource.setVisible(false);
+                state.addSource(outSource);
             }
         }
         return state;
@@ -384,23 +395,28 @@
     private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
             boolean copyState) {
         if (w.mIsImWindow) {
+            InsetsState state = originalState;
             // If navigation bar is not hidden by IME, IME should always receive visible
             // navigation bar insets.
             final boolean navVisible = !mHideNavBarForKeyboard;
-            final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
-            if (originalNavSource != null && originalNavSource.isVisible() != navVisible) {
-                final InsetsState state = copyState ? new InsetsState(originalState)
-                        : originalState;
-                final InsetsSource navSource = new InsetsSource(originalNavSource);
+            for (int i = originalState.sourceSize() - 1; i >= 0; i--) {
+                final InsetsSource source = originalState.sourceAt(i);
+                if (source.getType() != Type.navigationBars() || source.isVisible() == navVisible) {
+                    continue;
+                }
+                if (state == originalState && copyState) {
+                    state = new InsetsState(originalState);
+                }
+                final InsetsSource navSource = new InsetsSource(source);
                 navSource.setVisible(navVisible);
                 state.addSource(navSource);
-                return state;
             }
+            return state;
         } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) {
             // During switching tasks with gestural navigation, before the next IME input target
             // starts the input, we should adjust and freeze the last IME visibility of the window
             // in case delivering obsoleted IME insets state during transitioning.
-            final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME);
+            final InsetsSource originalImeSource = originalState.peekSource(ID_IME);
 
             if (originalImeSource != null) {
                 final boolean imeVisibility = w.isRequestedVisible(Type.ime());
@@ -446,23 +462,22 @@
      * @param caller who changed the insets state.
      */
     private void checkAbortTransient(InsetsControlTarget caller) {
-        if (mShowingTransientTypes.size() != 0) {
-            final IntArray abortTypes = new IntArray();
-            final boolean imeRequestedVisible = caller.isRequestedVisible(Type.ime());
-            for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
-                final @InternalInsetsType int type = mShowingTransientTypes.get(i);
-                if ((mStateController.isFakeTarget(type, caller)
-                                && caller.isRequestedVisible(InsetsState.toPublicType(type)))
-                        || (type == ITYPE_NAVIGATION_BAR && imeRequestedVisible)) {
-                    mShowingTransientTypes.remove(i);
-                    abortTypes.add(type);
-                }
-            }
-            StatusBarManagerInternal statusBarManagerInternal =
-                    mPolicy.getStatusBarManagerInternal();
-            if (abortTypes.size() > 0 && statusBarManagerInternal != null) {
-                statusBarManagerInternal.abortTransient(
-                        mDisplayContent.getDisplayId(), abortTypes.toArray());
+        if (mShowingTransientTypes == 0) {
+            return;
+        }
+        final boolean isImeVisible = mStateController.getImeSourceProvider().isClientVisible();
+        final @InsetsType int fakeControllingTypes =
+                mStateController.getFakeControllingTypes(caller);
+        final @InsetsType int abortTypes =
+                (fakeControllingTypes & caller.getRequestedVisibleTypes())
+                | (isImeVisible ? Type.navigationBars() : 0);
+        mShowingTransientTypes &= ~abortTypes;
+        if (abortTypes != 0) {
+            mDisplayContent.setLayoutNeeded();
+            mDisplayContent.mWmService.requestTraversal();
+            final StatusBarManagerInternal statusBarManager = mPolicy.getStatusBarManagerInternal();
+            if (statusBarManager != null) {
+                statusBarManager.abortTransient(mDisplayContent.getDisplayId(), abortTypes);
             }
         }
     }
@@ -472,12 +487,16 @@
      * updateBarControlTarget(mFocusedWin) after this invocation.
      */
     private void abortTransient() {
-        StatusBarManagerInternal statusBarManagerInternal = mPolicy.getStatusBarManagerInternal();
-        if (statusBarManagerInternal != null) {
-            statusBarManagerInternal.abortTransient(
-                    mDisplayContent.getDisplayId(), mShowingTransientTypes.toArray());
+        if (mShowingTransientTypes == 0) {
+            return;
         }
-        mShowingTransientTypes.clear();
+        final StatusBarManagerInternal statusBarManager = mPolicy.getStatusBarManagerInternal();
+        if (statusBarManager != null) {
+            statusBarManager.abortTransient(mDisplayContent.getDisplayId(), mShowingTransientTypes);
+        }
+        mShowingTransientTypes = 0;
+        mDisplayContent.setLayoutNeeded();
+        mDisplayContent.mWmService.requestTraversal();
 
         dispatchTransientSystemBarsVisibilityChanged(
                 mFocusedWin,
@@ -487,7 +506,7 @@
 
     private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin,
             boolean fake) {
-        if (!fake && isShowingTransientTypes(Type.statusBars())) {
+        if (!fake && isTransient(Type.statusBars())) {
             return mDummyControlTarget;
         }
         final WindowState notificationShade = mPolicy.getNotificationShade();
@@ -540,7 +559,7 @@
             // configured to be hidden by the IME.
             return null;
         }
-        if (!fake && isShowingTransientTypes(Type.navigationBars())) {
+        if (!fake && isTransient(Type.navigationBars())) {
             return mDummyControlTarget;
         }
         if (focusedWin == mPolicy.getNotificationShade()) {
@@ -576,16 +595,6 @@
         return focusedWin;
     }
 
-    private boolean isShowingTransientTypes(@InsetsType int types) {
-        final IntArray showingTransientTypes = mShowingTransientTypes;
-        for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
-            if ((InsetsState.toPublicType(showingTransientTypes.get(i)) & types) != 0) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     /**
      * Determines whether the remote insets controller should take control of system bars for all
      * windows.
@@ -621,21 +630,23 @@
 
     @VisibleForTesting
     void startAnimation(boolean show, Runnable callback) {
-        int typesReady = 0;
-        final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
-        final IntArray showingTransientTypes = mShowingTransientTypes;
-        for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
-            final int sourceId = showingTransientTypes.get(i);
-            final WindowContainerInsetsSourceProvider provider =
-                    mStateController.getSourceProvider(sourceId);
-            final InsetsSourceControl control = provider.getControl(mDummyControlTarget);
-            if (control == null || control.getLeash() == null) {
-                continue;
+        @InsetsType int typesReady = 0;
+        final SparseArray<InsetsSourceControl> controlsReady = new SparseArray<>();
+        final InsetsSourceControl[] controls =
+                mStateController.getControlsForDispatch(mDummyControlTarget);
+        if (controls == null) {
+            if (callback != null) {
+                DisplayThread.getHandler().post(callback);
             }
-            typesReady |= control.getType();
-            controls.put(sourceId, new InsetsSourceControl(control));
+            return;
         }
-        controlAnimationUnchecked(typesReady, controls, show, callback);
+        for (InsetsSourceControl control : controls) {
+            if (isTransient(control.getType()) && control.getLeash() != null) {
+                typesReady |= control.getType();
+                controlsReady.put(control.getId(), new InsetsSourceControl(control));
+            }
+        }
+        controlAnimationUnchecked(typesReady, controlsReady, show, callback);
     }
 
     private void controlAnimationUnchecked(int typesReady,
@@ -707,7 +718,8 @@
 
         InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types) {
             super(show, false /* hasCallbacks */, types, BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE,
-                    false /* disable */, 0 /* floatingImeBottomInsets */, null);
+                    false /* disable */, 0 /* floatingImeBottomInsets */,
+                    null /* loggingListener */, null /* jankContext */);
             mFinishCallback = finishCallback;
             mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this);
         }
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 49eaea2..2b7a451 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_INSETS;
 import static com.android.server.wm.InsetsSourceProviderProto.CAPTURED_LEASH;
@@ -164,7 +164,7 @@
             // TODO: Ideally, we should wait for the animation to finish so previous window can
             // animate-out as new one animates-in.
             mWindowContainer.cancelAnimation();
-            mWindowContainer.getProvidedInsetsSources().remove(mSource.getId());
+            mWindowContainer.getInsetsSourceProviders().remove(mSource.getId());
             mSeamlessRotating = false;
         }
         ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "InsetsSource setWin %s for type %s",
@@ -180,7 +180,7 @@
             mSource.setInsetsRoundedCornerFrame(false);
             mSourceFrame.setEmpty();
         } else {
-            mWindowContainer.getProvidedInsetsSources().put(mSource.getId(), mSource);
+            mWindowContainer.getInsetsSourceProviders().put(mSource.getId(), this);
             if (mControllable) {
                 mWindowContainer.setControllableInsetProvider(this);
                 if (mPendingControlTarget != null) {
@@ -192,13 +192,6 @@
     }
 
     /**
-     * @return Whether there is a window container which backs this source.
-     */
-    boolean hasWindowContainer() {
-        return mWindowContainer != null;
-    }
-
-    /**
      * The source frame can affect the layout of other windows, so this should be called once the
      * window container gets laid out.
      */
@@ -363,9 +356,9 @@
     }
 
     /**
-     * @see InsetsStateController#onControlFakeTargetChanged(int, InsetsControlTarget)
+     * @see InsetsStateController#onControlTargetChanged
      */
-    void updateControlForFakeTarget(@Nullable InsetsControlTarget fakeTarget) {
+    void updateFakeControlTarget(@Nullable InsetsControlTarget fakeTarget) {
         if (fakeTarget == mFakeControlTarget) {
             return;
         }
@@ -541,7 +534,7 @@
             return false;
         }
         for (int i = 0; i < providers.length; i++) {
-            if (providers[i].type == ITYPE_IME) {
+            if (providers[i].type == ID_IME) {
                 return true;
             }
         }
@@ -570,6 +563,10 @@
         return mControlTarget;
     }
 
+    InsetsControlTarget getFakeControlTarget() {
+        return mFakeControlTarget;
+    }
+
     boolean isClientVisible() {
         return mClientVisible;
     }
@@ -609,15 +606,15 @@
         }
         if (mControlTarget != null) {
             pw.print(prefix + "mControlTarget=");
-            pw.println(mControlTarget.getWindow());
+            pw.println(mControlTarget);
         }
         if (mPendingControlTarget != null) {
             pw.print(prefix + "mPendingControlTarget=");
-            pw.println(mPendingControlTarget.getWindow());
+            pw.println(mPendingControlTarget);
         }
         if (mFakeControlTarget != null) {
             pw.print(prefix + "mFakeControlTarget=");
-            pw.println(mFakeControlTarget.getWindow());
+            pw.println(mFakeControlTarget);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 455cd48..0e1e63e 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -17,16 +17,15 @@
 package com.android.server.wm;
 
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_IME;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.mandatorySystemGestures;
 import static android.view.WindowInsets.Type.systemGestures;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.server.wm.DisplayContentProto.IME_INSETS_SOURCE_PROVIDER;
+import static com.android.server.wm.DisplayContentProto.INSETS_SOURCE_PROVIDERS;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,11 +33,12 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
 import android.view.InsetsSource;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.WindowInsets;
+import android.view.WindowInsets.Type.InsetsType;
 
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -46,7 +46,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.function.Consumer;
-import java.util.function.Function;
 
 /**
  * Manages global window inset state in the system represented by {@link InsetsState}.
@@ -57,14 +56,11 @@
     private final InsetsState mState = new InsetsState();
     private final DisplayContent mDisplayContent;
 
-    private final ArrayMap<Integer, WindowContainerInsetsSourceProvider> mProviders =
-            new ArrayMap<>();
-    private final ArrayMap<InsetsControlTarget, ArrayList<Integer>> mControlTargetTypeMap =
-            new ArrayMap<>();
-    private final SparseArray<InsetsControlTarget> mTypeControlTargetMap = new SparseArray<>();
-
-    /** @see #onControlFakeTargetChanged */
-    private final SparseArray<InsetsControlTarget> mTypeFakeControlTargetMap = new SparseArray<>();
+    private final SparseArray<WindowContainerInsetsSourceProvider> mProviders = new SparseArray<>();
+    private final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>>
+            mControlTargetProvidersMap = new ArrayMap<>();
+    private final SparseArray<InsetsControlTarget> mIdControlTargetMap = new SparseArray<>();
+    private final SparseArray<InsetsControlTarget> mIdFakeControlTargetMap = new SparseArray<>();
 
     private final ArraySet<InsetsControlTarget> mPendingControlChanged = new ArraySet<>();
 
@@ -89,17 +85,8 @@
         }
     };
 
-    private final Function<Integer, WindowContainerInsetsSourceProvider> mSourceProviderFunc;
-
     InsetsStateController(DisplayContent displayContent) {
         mDisplayContent = displayContent;
-        mSourceProviderFunc = type -> {
-            final InsetsSource source = mState.getSource(type);
-            if (type == ITYPE_IME) {
-                return new ImeInsetsSourceProvider(source, this, mDisplayContent);
-            }
-            return new WindowContainerInsetsSourceProvider(source, this, mDisplayContent);
-        };
     }
 
     InsetsState getRawInsetsState() {
@@ -107,39 +94,55 @@
     }
 
     @Nullable InsetsSourceControl[] getControlsForDispatch(InsetsControlTarget target) {
-        ArrayList<Integer> controlled = mControlTargetTypeMap.get(target);
+        final ArrayList<InsetsSourceProvider> controlled = mControlTargetProvidersMap.get(target);
         if (controlled == null) {
             return null;
         }
         final int size = controlled.size();
         final InsetsSourceControl[] result = new InsetsSourceControl[size];
         for (int i = 0; i < size; i++) {
-            result[i] = mProviders.get(controlled.get(i)).getControl(target);
+            result[i] = controlled.get(i).getControl(target);
         }
         return result;
     }
 
-    ArrayMap<Integer, WindowContainerInsetsSourceProvider> getSourceProviders() {
+    SparseArray<WindowContainerInsetsSourceProvider> getSourceProviders() {
         return mProviders;
     }
 
     /**
-     * @return The provider of a specific type.
+     * @return The provider of a specific source ID.
      */
-    WindowContainerInsetsSourceProvider getSourceProvider(@InternalInsetsType int type) {
-        return mProviders.computeIfAbsent(type, mSourceProviderFunc);
+    WindowContainerInsetsSourceProvider getOrCreateSourceProvider(int id, @InsetsType int type) {
+        WindowContainerInsetsSourceProvider provider = mProviders.get(id);
+        if (provider != null) {
+            return provider;
+        }
+        final InsetsSource source = mState.getOrCreateSource(id, type);
+        provider = id == ID_IME
+                ? new ImeInsetsSourceProvider(source, this, mDisplayContent)
+                : new WindowContainerInsetsSourceProvider(source, this, mDisplayContent);
+        mProviders.put(id, provider);
+        return provider;
     }
 
     ImeInsetsSourceProvider getImeSourceProvider() {
-        return (ImeInsetsSourceProvider) getSourceProvider(ITYPE_IME);
+        return (ImeInsetsSourceProvider) getOrCreateSourceProvider(ID_IME, ime());
+    }
+
+    void removeSourceProvider(int id) {
+        if (id != ID_IME) {
+            mState.removeSource(id);
+            mProviders.remove(id);
+        }
     }
 
     /**
-     * @return The provider of a specific type or null if we don't have it.
+     * @return The provider of a source ID or null if we don't have it.
      */
     @Nullable
-    WindowContainerInsetsSourceProvider peekSourceProvider(@InternalInsetsType int type) {
-        return mProviders.get(type);
+    WindowContainerInsetsSourceProvider peekSourceProvider(int id) {
+        return mProviders.get(id);
     }
 
     /**
@@ -207,8 +210,16 @@
         }
     }
 
-    boolean isFakeTarget(@InternalInsetsType int type, InsetsControlTarget target) {
-        return mTypeFakeControlTargetMap.get(type) == target;
+    @InsetsType int getFakeControllingTypes(InsetsControlTarget target) {
+        @InsetsType int types = 0;
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            final InsetsSourceProvider provider = mProviders.valueAt(i);
+            final InsetsControlTarget fakeControlTarget = provider.getFakeControlTarget();
+            if (target == fakeControlTarget) {
+                types |= provider.getSource().getType();
+            }
+        }
+        return types;
     }
 
     void onImeControlTargetChanged(@Nullable InsetsControlTarget imeTarget) {
@@ -216,7 +227,7 @@
         // Make sure that we always have a control target for the IME, even if the IME target is
         // null. Otherwise there is no leash that will hide it and IME becomes "randomly" visible.
         InsetsControlTarget target = imeTarget != null ? imeTarget : mEmptyImeControlTarget;
-        onControlChanged(ITYPE_IME, target);
+        onControlTargetChanged(getImeSourceProvider(), target, false /* fake */);
         ProtoLog.d(WM_DEBUG_IME, "onImeControlTargetChanged %s",
                 target != null ? target.getWindow() : "null");
         notifyPendingInsetsControlChanged();
@@ -234,101 +245,88 @@
             @Nullable InsetsControlTarget fakeStatusControlling,
             @Nullable InsetsControlTarget navControlling,
             @Nullable InsetsControlTarget fakeNavControlling) {
-        onControlChanged(ITYPE_STATUS_BAR, statusControlling);
-        onControlChanged(ITYPE_NAVIGATION_BAR, navControlling);
-        onControlChanged(ITYPE_CLIMATE_BAR, statusControlling);
-        onControlChanged(ITYPE_EXTRA_NAVIGATION_BAR, navControlling);
-        onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeStatusControlling);
-        onControlFakeTargetChanged(ITYPE_NAVIGATION_BAR, fakeNavControlling);
-        onControlFakeTargetChanged(ITYPE_CLIMATE_BAR, fakeStatusControlling);
-        onControlFakeTargetChanged(ITYPE_EXTRA_NAVIGATION_BAR, fakeNavControlling);
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            final InsetsSourceProvider provider = mProviders.valueAt(i);
+            final @InsetsType int type = provider.getSource().getType();
+            if (type == WindowInsets.Type.statusBars()) {
+                onControlTargetChanged(provider, statusControlling, false /* fake */);
+                onControlTargetChanged(provider, fakeStatusControlling, true /* fake */);
+            } else if (type == WindowInsets.Type.navigationBars()) {
+                onControlTargetChanged(provider, navControlling, false /* fake */);
+                onControlTargetChanged(provider, fakeNavControlling, true /* fake */);
+            }
+        }
         notifyPendingInsetsControlChanged();
     }
 
     void notifyControlRevoked(@NonNull InsetsControlTarget previousControlTarget,
             InsetsSourceProvider provider) {
-        removeFromControlMaps(previousControlTarget, provider.getSource().getId(),
-                false /* fake */);
+        removeFromControlMaps(previousControlTarget, provider, false /* fake */);
     }
 
-    private void onControlChanged(@InternalInsetsType int type,
-            @Nullable InsetsControlTarget target) {
-        final InsetsControlTarget previous = mTypeControlTargetMap.get(type);
-        if (target == previous) {
-            return;
-        }
-        final WindowContainerInsetsSourceProvider provider = mProviders.get(type);
-        if (provider == null) {
+    private void onControlTargetChanged(InsetsSourceProvider provider,
+            @Nullable InsetsControlTarget target, boolean fake) {
+        final InsetsControlTarget lastTarget = fake
+                ? mIdFakeControlTargetMap.get(provider.getSource().getId())
+                : mIdControlTargetMap.get(provider.getSource().getId());
+        if (target == lastTarget) {
             return;
         }
         if (!provider.isControllable()) {
             return;
         }
-        provider.updateControlForTarget(target, false /* force */);
-        target = provider.getControlTarget();
-        if (previous != null) {
-            removeFromControlMaps(previous, type, false /* fake */);
-            mPendingControlChanged.add(previous);
+        if (fake) {
+            // The fake target updated here will be used to pretend to the app that it's still under
+            // control of the bars while it's not really, but we still need to find out the apps
+            // intentions around showing/hiding. For example, when the transient bars are showing,
+            // and the fake target requests to show system bars, the transient state will be
+            // aborted.
+            provider.updateFakeControlTarget(target);
+        } else {
+            provider.updateControlForTarget(target, false /* force */);
+
+            // Get control target again in case the provider didn't accept the one we passed to it.
+            target = provider.getControlTarget();
+            if (target == lastTarget) {
+                return;
+            }
+        }
+        if (lastTarget != null) {
+            removeFromControlMaps(lastTarget, provider, fake);
+            mPendingControlChanged.add(lastTarget);
         }
         if (target != null) {
-            addToControlMaps(target, type, false /* fake */);
+            addToControlMaps(target, provider, fake);
             mPendingControlChanged.add(target);
         }
     }
 
-    /**
-     * The fake target saved here will be used to pretend to the app that it's still under control
-     * of the bars while it's not really, but we still need to find out the apps intentions around
-     * showing/hiding. For example, when the transient bars are showing, and the fake target
-     * requests to show system bars, the transient state will be aborted.
-     */
-    void onControlFakeTargetChanged(@InternalInsetsType int type,
-            @Nullable InsetsControlTarget fakeTarget) {
-        final InsetsControlTarget previous = mTypeFakeControlTargetMap.get(type);
-        if (fakeTarget == previous) {
-            return;
-        }
-        final WindowContainerInsetsSourceProvider provider = mProviders.get(type);
-        if (provider == null) {
-            return;
-        }
-        provider.updateControlForFakeTarget(fakeTarget);
-        if (previous != null) {
-            removeFromControlMaps(previous, type, true /* fake */);
-            mPendingControlChanged.add(previous);
-        }
-        if (fakeTarget != null) {
-            addToControlMaps(fakeTarget, type, true /* fake */);
-            mPendingControlChanged.add(fakeTarget);
-        }
-    }
-
     private void removeFromControlMaps(@NonNull InsetsControlTarget target,
-            @InternalInsetsType int type, boolean fake) {
-        final ArrayList<Integer> array = mControlTargetTypeMap.get(target);
+            InsetsSourceProvider provider, boolean fake) {
+        final ArrayList<InsetsSourceProvider> array = mControlTargetProvidersMap.get(target);
         if (array == null) {
             return;
         }
-        array.remove((Integer) type);
+        array.remove(provider);
         if (array.isEmpty()) {
-            mControlTargetTypeMap.remove(target);
+            mControlTargetProvidersMap.remove(target);
         }
         if (fake) {
-            mTypeFakeControlTargetMap.remove(type);
+            mIdFakeControlTargetMap.remove(provider.getSource().getId());
         } else {
-            mTypeControlTargetMap.remove(type);
+            mIdControlTargetMap.remove(provider.getSource().getId());
         }
     }
 
     private void addToControlMaps(@NonNull InsetsControlTarget target,
-            @InternalInsetsType int type, boolean fake) {
-        final ArrayList<Integer> array = mControlTargetTypeMap.computeIfAbsent(target,
-                key -> new ArrayList<>());
-        array.add(type);
+            InsetsSourceProvider provider, boolean fake) {
+        final ArrayList<InsetsSourceProvider> array = mControlTargetProvidersMap.computeIfAbsent(
+                target, key -> new ArrayList<>());
+        array.add(provider);
         if (fake) {
-            mTypeFakeControlTargetMap.put(type, target);
+            mIdFakeControlTargetMap.put(provider.getSource().getId(), target);
         } else {
-            mTypeControlTargetMap.put(type, target);
+            mIdControlTargetMap.put(provider.getSource().getId(), target);
         }
     }
 
@@ -350,7 +348,7 @@
             for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) {
                 final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i);
                 controlTarget.notifyInsetsControlChanged();
-                if (mControlTargetTypeMap.containsKey(controlTarget)) {
+                if (mControlTargetProvidersMap.containsKey(controlTarget)) {
                     // We only collect targets who get controls, not lose controls.
                     newControlTargets.add(controlTarget);
                 }
@@ -376,14 +374,40 @@
         prefix = prefix + "  ";
         mState.dump(prefix, pw);
         pw.println(prefix + "Control map:");
-        for (int i = mTypeControlTargetMap.size() - 1; i >= 0; i--) {
+        for (int i = mControlTargetProvidersMap.size() - 1; i >= 0; i--) {
+            final InsetsControlTarget controlTarget = mControlTargetProvidersMap.keyAt(i);
             pw.print(prefix + "  ");
-            pw.println(InsetsState.typeToString(mTypeControlTargetMap.keyAt(i)) + " -> "
-                    + mTypeControlTargetMap.valueAt(i));
+            pw.print(controlTarget);
+            pw.println(":");
+            final ArrayList<InsetsSourceProvider> providers = mControlTargetProvidersMap.valueAt(i);
+            for (int j = providers.size() - 1; j >= 0; j--) {
+                final InsetsSourceProvider provider = providers.get(j);
+                if (provider != null) {
+                    pw.print(prefix + "    ");
+                    if (controlTarget == provider.getFakeControlTarget()) {
+                        pw.print("(fake) ");
+                    }
+                    pw.println(provider.getControl(controlTarget));
+                }
+            }
+        }
+        if (mControlTargetProvidersMap.isEmpty()) {
+            pw.print(prefix + "  none");
         }
         pw.println(prefix + "InsetsSourceProviders:");
         for (int i = mProviders.size() - 1; i >= 0; i--) {
             mProviders.valueAt(i).dump(pw, prefix + "  ");
         }
     }
+
+    void dumpDebug(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) {
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            final InsetsSourceProvider provider = mProviders.valueAt(i);
+            provider.dumpDebug(proto,
+                    provider.getSource().getType() == ime()
+                            ? IME_INSETS_SOURCE_PROVIDER
+                            : INSETS_SOURCE_PROVIDERS,
+                    logLevel);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 800fe09..5136670 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -18,14 +18,15 @@
 
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ALLOW_IGNORE_ORIENTATION_REQUEST;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_CAMERA_COMPAT_TREATMENT;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_COMPAT_FAKE_FOCUS;
 import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
 import android.graphics.Color;
 import android.provider.DeviceConfig;
 import android.util.Slog;
@@ -42,10 +43,6 @@
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxConfiguration" : TAG_ATM;
 
-    @VisibleForTesting
-    static final String DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS =
-            "enable_compat_fake_focus";
-
     /**
      * Override of aspect ratio for fixed orientation letterboxing that is set via ADB with
      * set-fixed-orientation-letterbox-aspect-ratio or via {@link
@@ -115,12 +112,6 @@
     /** Letterboxed app window is aligned to the right side. */
     static final int LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM = 2;
 
-    @VisibleForTesting
-    static final String PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN = "com.android.COMPAT_FAKE_FOCUS_OPT_IN";
-    @VisibleForTesting
-    static final String PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT =
-            "com.android.COMPAT_FAKE_FOCUS_OPT_OUT";
-
     final Context mContext;
 
     // Responsible for the persistence of letterbox[Horizontal|Vertical]PositionMultiplier
@@ -309,14 +300,31 @@
         mIsDisplayRotationImmersiveAppCompatPolicyEnabled = mContext.getResources().getBoolean(
                 R.bool.config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled);
         mDeviceConfig.updateFlagActiveStatus(
+                /* isActive */ mIsCameraCompatTreatmentEnabled,
+                /* key */ KEY_ENABLE_CAMERA_COMPAT_TREATMENT);
+        mDeviceConfig.updateFlagActiveStatus(
                 /* isActive */ mIsDisplayRotationImmersiveAppCompatPolicyEnabled,
                 /* key */ KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY);
+        mDeviceConfig.updateFlagActiveStatus(
+                /* isActive */ true,
+                /* key */ KEY_ALLOW_IGNORE_ORIENTATION_REQUEST);
+        mDeviceConfig.updateFlagActiveStatus(
+                /* isActive */ mIsCompatFakeFocusEnabled,
+                /* key */ KEY_ENABLE_COMPAT_FAKE_FOCUS);
 
         mLetterboxConfigurationPersister = letterboxConfigurationPersister;
         mLetterboxConfigurationPersister.start();
     }
 
     /**
+     * Whether enabling ignoreOrientationRequest is allowed on the device. This value is controlled
+     * via {@link android.provider.DeviceConfig}.
+     */
+    boolean isIgnoreOrientationRequestAllowed() {
+        return mDeviceConfig.getFlag(KEY_ALLOW_IGNORE_ORIENTATION_REQUEST);
+    }
+
+    /**
      * Overrides the aspect ratio of letterbox for fixed orientation. If given value is <= {@link
      * #MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO}, both it and a value of {@link
      * com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio} will be ignored and
@@ -1050,41 +1058,9 @@
                 "enable_translucent_activity_letterbox", false);
     }
 
-    @VisibleForTesting
-    boolean getPackageManagerProperty(PackageManager pm, String property) {
-        boolean enabled = false;
-        try {
-            final PackageManager.Property p = pm.getProperty(property, mContext.getPackageName());
-            enabled = p.getBoolean();
-        } catch (PackageManager.NameNotFoundException e) {
-            // Property not found
-        }
-        return enabled;
-    }
-
-    @VisibleForTesting
-    boolean isCompatFakeFocusEnabled(ActivityInfo info) {
-        if (!isCompatFakeFocusEnabledOnDevice()) {
-            return false;
-        }
-        // See if the developer has chosen to opt in / out of treatment
-        PackageManager pm = mContext.getPackageManager();
-        if (getPackageManagerProperty(pm, PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT)) {
-            return false;
-        } else if (getPackageManagerProperty(pm, PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN)) {
-            return true;
-        }
-        if (info.isChangeEnabled(ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS)) {
-            return true;
-        }
-        return false;
-    }
-
     /** Whether fake sending focus is enabled for unfocused apps in splitscreen */
-    boolean isCompatFakeFocusEnabledOnDevice() {
-        return mIsCompatFakeFocusEnabled
-                && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                        DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, true);
+    boolean isCompatFakeFocusEnabled() {
+        return mIsCompatFakeFocusEnabled && mDeviceConfig.getFlag(KEY_ENABLE_COMPAT_FAKE_FOCUS);
     }
 
     /**
@@ -1106,15 +1082,8 @@
 
     /** Whether camera compatibility treatment is enabled. */
     boolean isCameraCompatTreatmentEnabled(boolean checkDeviceConfig) {
-        return mIsCameraCompatTreatmentEnabled
-                && (!checkDeviceConfig || isCameraCompatTreatmentAllowed());
-    }
-
-    // TODO(b/262977416): Cache a runtime flag and implement
-    // DeviceConfig.OnPropertiesChangedListener
-    private static boolean isCameraCompatTreatmentAllowed() {
-        return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                "enable_compat_camera_treatment", true);
+        return mIsCameraCompatTreatmentEnabled && (!checkDeviceConfig
+                || mDeviceConfig.getFlag(KEY_ENABLE_CAMERA_COMPAT_TREATMENT));
     }
 
     /** Whether camera compatibility refresh is enabled. */
diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
index cf123a1..b364872 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
@@ -33,17 +33,38 @@
 final class LetterboxConfigurationDeviceConfig
         implements DeviceConfig.OnPropertiesChangedListener {
 
+    static final String KEY_ENABLE_CAMERA_COMPAT_TREATMENT = "enable_compat_camera_treatment";
+    private static final boolean DEFAULT_VALUE_ENABLE_CAMERA_COMPAT_TREATMENT = true;
+
     static final String KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY =
             "enable_display_rotation_immersive_app_compat_policy";
     private static final boolean DEFAULT_VALUE_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY =
             true;
 
+    static final String KEY_ALLOW_IGNORE_ORIENTATION_REQUEST =
+            "allow_ignore_orientation_request";
+    private static final boolean DEFAULT_VALUE_ALLOW_IGNORE_ORIENTATION_REQUEST = true;
+
+    static final String KEY_ENABLE_COMPAT_FAKE_FOCUS = "enable_compat_fake_focus";
+    private static final boolean DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS = true;
+
     @VisibleForTesting
     static final Map<String, Boolean> sKeyToDefaultValueMap = Map.of(
+            KEY_ENABLE_CAMERA_COMPAT_TREATMENT,
+            DEFAULT_VALUE_ENABLE_CAMERA_COMPAT_TREATMENT,
             KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY,
-            DEFAULT_VALUE_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY
+            DEFAULT_VALUE_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY,
+            KEY_ALLOW_IGNORE_ORIENTATION_REQUEST,
+            DEFAULT_VALUE_ALLOW_IGNORE_ORIENTATION_REQUEST,
+            KEY_ENABLE_COMPAT_FAKE_FOCUS,
+            DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS
     );
 
+    // Whether camera compatibility treatment is enabled.
+    // See DisplayRotationCompatPolicy for context.
+    private boolean mIsCameraCompatTreatmentEnabled =
+            DEFAULT_VALUE_ENABLE_CAMERA_COMPAT_TREATMENT;
+
     // Whether enabling rotation compat policy for immersive apps that prevents auto rotation
     // into non-optimal screen orientation while in fullscreen. This is needed because immersive
     // apps, such as games, are often not optimized for all orientations and can have a poor UX
@@ -52,6 +73,15 @@
     private boolean mIsDisplayRotationImmersiveAppCompatPolicyEnabled =
             DEFAULT_VALUE_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
 
+    // Whether enabling ignoreOrientationRequest is allowed on the device.
+    private boolean mIsAllowIgnoreOrientationRequest =
+            DEFAULT_VALUE_ALLOW_IGNORE_ORIENTATION_REQUEST;
+
+    // Whether sending compat fake focus for split screen resumed activities is enabled. This is
+    // needed because some game engines wait to get focus before drawing the content of the app
+    // which isn't guaranteed by default in multi-window modes.
+    private boolean mIsCompatFakeFocusAllowed = DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS;
+
     // Set of active device configs that need to be updated in
     // DeviceConfig.OnPropertiesChangedListener#onPropertiesChanged.
     private final ArraySet<String> mActiveDeviceConfigsSet = new ArraySet<>();
@@ -91,8 +121,14 @@
      */
     boolean getFlag(String key) {
         switch (key) {
+            case KEY_ENABLE_CAMERA_COMPAT_TREATMENT:
+                return mIsCameraCompatTreatmentEnabled;
             case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
                 return mIsDisplayRotationImmersiveAppCompatPolicyEnabled;
+            case KEY_ALLOW_IGNORE_ORIENTATION_REQUEST:
+                return mIsAllowIgnoreOrientationRequest;
+            case KEY_ENABLE_COMPAT_FAKE_FOCUS:
+                return mIsCompatFakeFocusAllowed;
             default:
                 throw new AssertionError("Unexpected flag name: " + key);
         }
@@ -104,10 +140,22 @@
             throw new AssertionError("Haven't found default value for flag: " + key);
         }
         switch (key) {
+            case KEY_ENABLE_CAMERA_COMPAT_TREATMENT:
+                mIsCameraCompatTreatmentEnabled =
+                        getDeviceConfig(key, defaultValue);
+                break;
             case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
                 mIsDisplayRotationImmersiveAppCompatPolicyEnabled =
                         getDeviceConfig(key, defaultValue);
                 break;
+            case KEY_ALLOW_IGNORE_ORIENTATION_REQUEST:
+                mIsAllowIgnoreOrientationRequest =
+                        getDeviceConfig(key, defaultValue);
+                break;
+            case KEY_ENABLE_COMPAT_FAKE_FOCUS:
+                mIsCompatFakeFocusAllowed =
+                        getDeviceConfig(key, defaultValue);
+                break;
             default:
                 throw new AssertionError("Unexpected flag name: " + key);
         }
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index c5a50ca..1aa0ec3 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -21,8 +21,11 @@
 import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION;
 import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH;
 import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
+import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS;
 import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
 import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
+import static android.content.pm.ActivityInfo.OVERRIDE_RESPECT_REQUESTED_ORIENTATION;
 import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
 import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT;
 import static android.content.pm.ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION;
@@ -41,6 +44,7 @@
 import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE;
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS;
 import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
 
 import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
@@ -101,6 +105,7 @@
 
 import java.io.PrintWriter;
 import java.util.function.BooleanSupplier;
+import java.util.function.Predicate;
 
 /** Controls behaviour of the letterbox UI for {@link mActivityRecord}. */
 // TODO(b/185262487): Improve test coverage of this class. Parts of it are tested in
@@ -110,6 +115,9 @@
 // TODO(b/263021211): Consider renaming to more generic CompatUIController.
 final class LetterboxUiController {
 
+    private static final Predicate<ActivityRecord> FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE =
+            activityRecord -> activityRecord.fillsParent() && !activityRecord.isFinishing();
+
     private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxUiController" : TAG_ATM;
 
     private static final float UNDEFINED_ASPECT_RATIO = 0f;
@@ -136,8 +144,12 @@
     private final boolean mIsOverrideToNosensorOrientationEnabled;
     // Corresponds to OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE
     private final boolean mIsOverrideToReverseLandscapeOrientationEnabled;
+    // Corresponds to OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA
+    private final boolean mIsOverrideOrientationOnlyForCameraEnabled;
     // Corresponds to OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION
     private final boolean mIsOverrideUseDisplayLandscapeNaturalOrientationEnabled;
+    // Corresponds to OVERRIDE_RESPECT_REQUESTED_ORIENTATION
+    private final boolean mIsOverrideRespectRequestedOrientationEnabled;
 
     // Corresponds to OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION
     private final boolean mIsOverrideCameraCompatDisableForceRotationEnabled;
@@ -149,6 +161,9 @@
     // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION
     private final boolean mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled;
 
+    // Corresponds to OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS
+    private final boolean mIsOverrideEnableCompatFakeFocusEnabled;
+
     @Nullable
     private final Boolean mBooleanPropertyAllowOrientationOverride;
     @Nullable
@@ -204,6 +219,9 @@
     @Nullable
     private final Boolean mBooleanPropertyIgnoreRequestedOrientation;
 
+    @Nullable
+    private final Boolean mBooleanPropertyFakeFocus;
+
     private boolean mIsRelauchingAfterRequestedOrientationChanged;
 
     LetterboxUiController(WindowManagerService wmService, ActivityRecord activityRecord) {
@@ -218,6 +236,10 @@
                 readComponentProperty(packageManager, mActivityRecord.packageName,
                         mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled,
                         PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION);
+        mBooleanPropertyFakeFocus =
+                readComponentProperty(packageManager, mActivityRecord.packageName,
+                        mLetterboxConfiguration::isCompatFakeFocusEnabled,
+                        PROPERTY_COMPAT_ENABLE_FAKE_FOCUS);
         mBooleanPropertyCameraCompatAllowForceRotation =
                 readComponentProperty(packageManager, mActivityRecord.packageName,
                         () -> mLetterboxConfiguration.isCameraCompatTreatmentEnabled(
@@ -253,8 +275,12 @@
                 isCompatChangeEnabled(OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE);
         mIsOverrideToNosensorOrientationEnabled =
                 isCompatChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR);
+        mIsOverrideOrientationOnlyForCameraEnabled =
+                isCompatChangeEnabled(OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA);
         mIsOverrideUseDisplayLandscapeNaturalOrientationEnabled =
                 isCompatChangeEnabled(OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION);
+        mIsOverrideRespectRequestedOrientationEnabled =
+                isCompatChangeEnabled(OVERRIDE_RESPECT_REQUESTED_ORIENTATION);
 
         mIsOverrideCameraCompatDisableForceRotationEnabled =
                 isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION);
@@ -265,6 +291,9 @@
 
         mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled =
                 isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION);
+
+        mIsOverrideEnableCompatFakeFocusEnabled =
+                isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS);
     }
 
     /**
@@ -360,6 +389,25 @@
     }
 
     /**
+     * Whether sending compat fake focus for split screen resumed activities is enabled. Needed
+     * because some game engines wait to get focus before drawing the content of the app which isn't
+     * guaranteed by default in multi-window modes.
+     *
+     * <p>This treatment is enabled when the following conditions are met:
+     * <ul>
+     *     <li>Flag gating the treatment is enabled
+     *     <li>Component property is NOT set to false
+     *     <li>Component property is set to true or per-app override is enabled
+     * </ul>
+     */
+    boolean shouldSendFakeFocus() {
+        return shouldEnableWithOverrideAndProperty(
+                /* gatingCondition */ mLetterboxConfiguration::isCompatFakeFocusEnabled,
+                mIsOverrideEnableCompatFakeFocusEnabled,
+                mBooleanPropertyFakeFocus);
+    }
+
+    /**
      * Sets whether an activity is relaunching after the app has called {@link
      * android.app.Activity#setRequestedOrientation}.
      */
@@ -379,6 +427,10 @@
         mIsRefreshAfterRotationRequested = isRequested;
     }
 
+    boolean isOverrideRespectRequestedOrientationEnabled() {
+        return mIsOverrideRespectRequestedOrientationEnabled;
+    }
+
     /**
      * Whether should fix display orientation to landscape natural orientation when a task is
      * fullscreen and the display is ignoring orientation requests.
@@ -410,6 +462,14 @@
             return candidate;
         }
 
+        DisplayContent displayContent = mActivityRecord.mDisplayContent;
+        if (mIsOverrideOrientationOnlyForCameraEnabled && displayContent != null
+                && (displayContent.mDisplayRotationCompatPolicy == null
+                        || !displayContent.mDisplayRotationCompatPolicy
+                                .isActivityEligibleForOrientationOverride(mActivityRecord))) {
+            return candidate;
+        }
+
         if (mIsOverrideToReverseLandscapeOrientationEnabled
                 && (isFixedOrientationLandscape(candidate) || mIsOverrideAnyOrientationEnabled)) {
             Slog.w(TAG, "Requested orientation  " + screenOrientationToString(candidate) + " for "
@@ -439,6 +499,10 @@
         return candidate;
     }
 
+    boolean isOverrideOrientationOnlyForCameraEnabled() {
+        return mIsOverrideOrientationOnlyForCameraEnabled;
+    }
+
     /**
      * Whether activity is eligible for activity "refresh" after camera compat force rotation
      * treatment. See {@link DisplayRotationCompatPolicy} for context.
@@ -1330,7 +1394,8 @@
             return;
         }
         final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity(
-                ActivityRecord::fillsParent, mActivityRecord, false /* includeBoundary */,
+                FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE /* callback */,
+                mActivityRecord /* boundary */, false /* includeBoundary */,
                 true /* traverseTopToBottom */);
         if (firstOpaqueActivityBeneath == null) {
             // We skip letterboxing if the translucent activity doesn't have any opaque
diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
index de42c55..99831d3 100644
--- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java
+++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
@@ -19,9 +19,6 @@
 import static android.hardware.display.DisplayManager.SWITCHING_TYPE_NONE;
 import static android.hardware.display.DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY;
 
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
-
 import android.hardware.display.DisplayManager;
 import android.view.Display;
 import android.view.Display.Mode;
@@ -59,6 +56,8 @@
         }
     }
 
+    private final DisplayInfo mDisplayInfo;
+    private final Mode mDefaultMode;
     private final Mode mLowRefreshRateMode;
     private final PackageRefreshRate mNonHighRefreshRatePackages = new PackageRefreshRate();
     private final HighRefreshRateDenylist mHighRefreshRateDenylist;
@@ -89,7 +88,9 @@
 
     RefreshRatePolicy(WindowManagerService wmService, DisplayInfo displayInfo,
             HighRefreshRateDenylist denylist) {
-        mLowRefreshRateMode = findLowRefreshRateMode(displayInfo);
+        mDisplayInfo = displayInfo;
+        mDefaultMode = displayInfo.getDefaultMode();
+        mLowRefreshRateMode = findLowRefreshRateMode(displayInfo, mDefaultMode);
         mHighRefreshRateDenylist = denylist;
         mWmService = wmService;
     }
@@ -98,10 +99,9 @@
      * Finds the mode id with the lowest refresh rate which is >= 60hz and same resolution as the
      * default mode.
      */
-    private Mode findLowRefreshRateMode(DisplayInfo displayInfo) {
-        Mode mode = displayInfo.getDefaultMode();
+    private Mode findLowRefreshRateMode(DisplayInfo displayInfo, Mode defaultMode) {
         float[] refreshRates = displayInfo.getDefaultRefreshRates();
-        float bestRefreshRate = mode.getRefreshRate();
+        float bestRefreshRate = defaultMode.getRefreshRate();
         mMinSupportedRefreshRate = bestRefreshRate;
         mMaxSupportedRefreshRate = bestRefreshRate;
         for (int i = refreshRates.length - 1; i >= 0; i--) {
@@ -127,13 +127,39 @@
     }
 
     int getPreferredModeId(WindowState w) {
-        // If app is animating, it's not able to control refresh rate because we want the animation
-        // to run in default refresh rate.
-        if (w.isAnimating(TRANSITION | PARENTS)) {
+        final int preferredDisplayModeId = w.mAttrs.preferredDisplayModeId;
+        if (preferredDisplayModeId <= 0) {
+            // Unspecified, use default mode.
             return 0;
         }
 
-        return w.mAttrs.preferredDisplayModeId;
+        // If app is animating, it's not able to control refresh rate because we want the animation
+        // to run in default refresh rate. But if the display size of default mode is different
+        // from the using preferred mode, then still keep the preferred mode to avoid disturbing
+        // the animation.
+        if (w.isAnimationRunningSelfOrParent()) {
+            Display.Mode preferredMode = null;
+            for (Display.Mode mode : mDisplayInfo.supportedModes) {
+                if (preferredDisplayModeId == mode.getModeId()) {
+                    preferredMode = mode;
+                    break;
+                }
+            }
+            if (preferredMode != null) {
+                final int pW = preferredMode.getPhysicalWidth();
+                final int pH = preferredMode.getPhysicalHeight();
+                if ((pW != mDefaultMode.getPhysicalWidth()
+                        || pH != mDefaultMode.getPhysicalHeight())
+                        && pW == mDisplayInfo.getNaturalWidth()
+                        && pH == mDisplayInfo.getNaturalHeight()) {
+                    // Prefer not to change display size when animating.
+                    return preferredDisplayModeId;
+                }
+            }
+            return 0;
+        }
+
+        return preferredDisplayModeId;
     }
 
     /**
@@ -225,7 +251,7 @@
 
         // If app is animating, it's not able to control refresh rate because we want the animation
         // to run in default refresh rate.
-        if (w.isAnimating(TRANSITION | PARENTS)) {
+        if (w.isAnimationRunningSelfOrParent()) {
             return w.mFrameRateVote.reset();
         }
 
@@ -234,14 +260,10 @@
         if (refreshRateSwitchingType != SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY) {
             final int preferredModeId = w.mAttrs.preferredDisplayModeId;
             if (preferredModeId > 0) {
-                DisplayInfo info = w.getDisplayInfo();
-                if (info != null) {
-                    for (Display.Mode mode : info.supportedModes) {
-                        if (preferredModeId == mode.getModeId()) {
-                            return w.mFrameRateVote.update(mode.getRefreshRate(),
-                                    Surface.FRAME_RATE_COMPATIBILITY_EXACT);
-
-                        }
+                for (Display.Mode mode : mDisplayInfo.supportedModes) {
+                    if (preferredModeId == mode.getModeId()) {
+                        return w.mFrameRateVote.update(mode.getRefreshRate(),
+                                Surface.FRAME_RATE_COMPATIBILITY_EXACT);
                     }
                 }
             }
@@ -268,7 +290,7 @@
     float getPreferredMinRefreshRate(WindowState w) {
         // If app is animating, it's not able to control refresh rate because we want the animation
         // to run in default refresh rate.
-        if (w.isAnimating(TRANSITION | PARENTS)) {
+        if (w.isAnimationRunningSelfOrParent()) {
             return 0;
         }
 
@@ -291,7 +313,7 @@
     float getPreferredMaxRefreshRate(WindowState w) {
         // If app is animating, it's not able to control refresh rate because we want the animation
         // to run in default refresh rate.
-        if (w.isAnimating(TRANSITION | PARENTS)) {
+        if (w.isAnimationRunningSelfOrParent()) {
             return 0;
         }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 8ba54ff..110cce2 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -136,6 +136,7 @@
 import android.view.DisplayInfo;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
+import android.window.TaskFragmentAnimationParams;
 import android.window.WindowContainerToken;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -234,6 +235,10 @@
     WindowManagerService mWindowManager;
     DisplayManager mDisplayManager;
     private DisplayManagerInternal mDisplayManagerInternal;
+    @NonNull
+    private final DeviceStateController mDeviceStateController;
+    @NonNull
+    private final DisplayRotationCoordinator mDisplayRotationCoordinator;
 
     /** Reference to default display so we can quickly look it up. */
     private DisplayContent mDefaultDisplay;
@@ -380,9 +385,9 @@
             }
 
             ProtoLog.d(WM_DEBUG_TASKS, "Comparing existing cls=%s /aff=%s to new cls=%s /aff=%s",
-                    r.getTask().rootAffinity, mIntent.getComponent().flattenToShortString(),
-                    mInfo.taskAffinity, (task.realActivity != null
-                            ? task.realActivity.flattenToShortString() : ""));
+                    (task.realActivity != null ? task.realActivity.flattenToShortString() : ""),
+                    task.rootAffinity, mIntent.getComponent().flattenToShortString(),
+                    mTaskAffinity);
             // TODO Refactor to remove duplications. Check if logic can be simplified.
             if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
                     && Objects.equals(documentData, taskDocumentData)) {
@@ -440,6 +445,8 @@
         mTaskSupervisor = mService.mTaskSupervisor;
         mTaskSupervisor.mRootWindowContainer = this;
         mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirerImpl(DISPLAY_OFF_SLEEP_TOKEN_TAG);
+        mDeviceStateController = new DeviceStateController(service.mContext, service.mH);
+        mDisplayRotationCoordinator = new DisplayRotationCoordinator();
     }
 
     /**
@@ -1279,7 +1286,8 @@
         final Display[] displays = mDisplayManager.getDisplays();
         for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
             final Display display = displays[displayNdx];
-            final DisplayContent displayContent = new DisplayContent(display, this);
+            final DisplayContent displayContent =
+                    new DisplayContent(display, this, mDeviceStateController);
             addChild(displayContent, POSITION_BOTTOM);
             if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
                 mDefaultDisplay = displayContent;
@@ -1297,6 +1305,10 @@
         return mDefaultDisplay;
     }
 
+    DisplayRotationCoordinator getDisplayRotationCoordinator() {
+        return mDisplayRotationCoordinator;
+    }
+
     /**
      * Get the default display area on the device dedicated to app windows. This one should be used
      * only as a fallback location for activity launches when no target display area is specified,
@@ -1358,7 +1370,7 @@
             return null;
         }
         // The display hasn't been added to ActivityManager yet, create a new record now.
-        displayContent = new DisplayContent(display, this);
+        displayContent = new DisplayContent(display, this, mDeviceStateController);
         addChild(displayContent, POSITION_BOTTOM);
         return displayContent;
     }
@@ -2082,6 +2094,8 @@
                     return;
                 }
                 tf.resetAdjacentTaskFragment();
+                tf.setCompanionTaskFragment(null /* companionTaskFragment */);
+                tf.setAnimationParams(TaskFragmentAnimationParams.DEFAULT);
                 if (tf.getTopNonFinishingActivity() != null) {
                     // When the Task is entering picture-in-picture, we should clear all override
                     // from the client organizer, so the PIP activity can get the correct config
@@ -2275,7 +2289,7 @@
                 }
                 if (rootTask.getDisplayArea().isTopRootTask(rootTask)
                         && topRunningActivity.isState(RESUMED)) {
-                    // Kick off any lingering app transitions form the MoveTaskToFront
+                    // Kick off any lingering app transitions from the MoveTaskToFront
                     // operation, but only consider the top task and root-task on that
                     // display.
                     rootTask.executeAppTransition(targetOptions);
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index 98ca9ae..5860776 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -146,8 +146,8 @@
                 .setLaunchRootTask(options.getLaunchRootTask())
                 .setPendingIntentBackgroundActivityStartMode(
                         options.getPendingIntentBackgroundActivityStartMode())
-                .setIgnorePendingIntentCreatorForegroundState(
-                        options.getIgnorePendingIntentCreatorForegroundState());
+                .setPendingIntentCreatorBackgroundActivityStartMode(
+                        options.getPendingIntentCreatorBackgroundActivityStartMode());
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index db88f0f..b5df3e0 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -799,6 +799,10 @@
                 if (mDisplayContent.getRotationAnimation() == ScreenRotationAnimation.this) {
                     // It also invokes kill().
                     mDisplayContent.setRotationAnimation(null);
+                    if (mDisplayContent.mDisplayRotationCompatPolicy != null) {
+                        mDisplayContent.mDisplayRotationCompatPolicy
+                                .onScreenRotationAnimationFinished();
+                    }
                 } else {
                     kill();
                 }
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index ca86db9..408ea6e 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -565,6 +565,11 @@
     public static final int ANIMATION_TYPE_STARTING_REVEAL = 1 << 7;
 
     /**
+     * Animation when a back gesture animation is applied to a window container.
+     * @hide
+     */
+    public static final int ANIMATION_TYPE_PREDICT_BACK = 1 << 8;
+    /**
      * Bitmask to include all animation types. This is NOT an {@link AnimationType}
      * @hide
      */
@@ -583,7 +588,8 @@
             ANIMATION_TYPE_WINDOW_ANIMATION,
             ANIMATION_TYPE_INSETS_CONTROL,
             ANIMATION_TYPE_TOKEN_TRANSFORM,
-            ANIMATION_TYPE_STARTING_REVEAL
+            ANIMATION_TYPE_STARTING_REVEAL,
+            ANIMATION_TYPE_PREDICT_BACK
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface AnimationType {}
@@ -602,6 +608,7 @@
             case ANIMATION_TYPE_INSETS_CONTROL: return "insets_animation";
             case ANIMATION_TYPE_TOKEN_TRANSFORM: return "token_transform";
             case ANIMATION_TYPE_STARTING_REVEAL: return "starting_reveal";
+            case ANIMATION_TYPE_PREDICT_BACK: return "predict_back";
             default: return "unknown type:" + type;
         }
     }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index ee11f68..986c8f4 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -149,7 +149,6 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -171,6 +170,7 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
+import android.view.InsetsSource;
 import android.view.InsetsState;
 import android.view.RemoteAnimationAdapter;
 import android.view.Surface;
@@ -2833,14 +2833,13 @@
     void adjustAnimationBoundsForTransition(Rect animationBounds) {
         TaskTransitionSpec spec = mWmService.mTaskTransitionSpec;
         if (spec != null) {
-            for (@InsetsState.InternalInsetsType int insetType : spec.animationBoundInsets) {
-                WindowContainerInsetsSourceProvider insetProvider = getDisplayContent()
-                        .getInsetsStateController()
-                        .getSourceProvider(insetType);
-
-                Insets insets = insetProvider.getSource().calculateVisibleInsets(
-                        animationBounds);
-                animationBounds.inset(insets);
+            final InsetsState state =
+                    getDisplayContent().getInsetsStateController().getRawInsetsState();
+            for (int id : spec.animationBoundInsets) {
+                final InsetsSource source = state.peekSource(id);
+                if (source != null) {
+                    animationBounds.inset(source.calculateVisibleInsets(animationBounds));
+                }
             }
         }
     }
@@ -5874,9 +5873,6 @@
         }
 
         positionChildAt(POSITION_TOP, child, true /* includingParents */);
-
-        final DisplayContent displayContent = getDisplayContent();
-        displayContent.layoutAndAssignWindowLayersIfNeeded();
     }
 
     void positionChildAtBottom(Task child) {
@@ -5897,7 +5893,6 @@
         }
 
         positionChildAt(POSITION_BOTTOM, child, includingParents);
-        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
     }
 
     @Override
@@ -5911,12 +5906,6 @@
             // Non-root task position changed.
             mRootWindowContainer.invalidateTaskLayers();
         }
-
-        final boolean isTop = getTopChild() == child;
-        if (isTop) {
-            final DisplayContent displayContent = getDisplayContent();
-            displayContent.layoutAndAssignWindowLayersIfNeeded();
-        }
     }
 
     void reparent(TaskDisplayArea newParent, boolean onTop) {
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 0457408..a0608db 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -405,8 +405,6 @@
 
         child.updateTaskMovement(moveToTop, targetPosition);
 
-        mDisplayContent.layoutAndAssignWindowLayersIfNeeded();
-
         // The insert position may be adjusted to non-top when there is always-on-top root task.
         // Since the original position is preferred to be top, the root task should have higher
         // priority when we are looking for top focusable root task. The condition {@code
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index eb06b91..294e90b 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2813,7 +2813,7 @@
     void removeImmediately() {
         mIsRemovalRequested = false;
         resetAdjacentTaskFragment();
-        cleanUp();
+        cleanUpEmbeddedTaskFragment();
         final boolean shouldExecuteAppTransition =
                 mClearedTaskFragmentForPip && isTaskVisibleRequested();
         super.removeImmediately();
@@ -2830,10 +2830,20 @@
     }
 
     /** Called on remove to cleanup. */
-    private void cleanUp() {
-        if (mIsEmbedded) {
-            mAtmService.mWindowOrganizerController.cleanUpEmbeddedTaskFragment(this);
+    private void cleanUpEmbeddedTaskFragment() {
+        if (!mIsEmbedded) {
+            return;
         }
+        mAtmService.mWindowOrganizerController.cleanUpEmbeddedTaskFragment(this);
+        final Task task = getTask();
+        if (task == null) {
+            return;
+        }
+        task.forAllLeafTaskFragments(taskFragment -> {
+            if (taskFragment.getCompanionTaskFragment() == this) {
+                taskFragment.setCompanionTaskFragment(null /* companionTaskFragment */);
+            }
+        }, false /* traverseTopToBottom */);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 8570db2..3a30e4b 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -722,6 +722,14 @@
         return true;
     }
 
+    boolean isSupportWindowlessStartingSurface() {
+        // Enable after ag/20426257
+        final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
+        if (lastOrganizer == null) {
+            return false;
+        }
+        return false;
+    }
     /**
      * Notify the shell ({@link com.android.wm.shell.ShellTaskOrganizer} that the client has
      * removed the splash screen view.
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index d2f30ce..71bb99c 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -92,6 +92,7 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.statusbar.StatusBarManagerInternal;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -216,6 +217,12 @@
 
     final TransitionController.Logger mLogger = new TransitionController.Logger();
 
+    /**
+     * {@code false} if this transition runs purely in WMCore (meaning Shell is completely unaware
+     * of it). Currently, this happens before the display is ready since nothing can be seen yet.
+     */
+    boolean mIsPlayerEnabled = true;
+
     Transition(@TransitionType int type, @TransitionFlags int flags,
             TransitionController controller, BLASTSyncEngine syncEngine) {
         mType = type;
@@ -225,7 +232,7 @@
         mToken = new Token(this);
 
         mLogger.mCreateWallTimeMs = System.currentTimeMillis();
-        mLogger.mCreateTimeNs = SystemClock.uptimeNanos();
+        mLogger.mCreateTimeNs = SystemClock.elapsedRealtimeNanos();
         controller.mTransitionTracer.logState(this);
     }
 
@@ -277,6 +284,17 @@
         return false;
     }
 
+    /** @return whether `wc` is a descendent of a transient-hide window. */
+    boolean isInTransientHide(@NonNull WindowContainer wc) {
+        if (mTransientLaunches == null) return false;
+        for (int i = 0; i < mTransientLaunches.size(); ++i) {
+            if (wc.isDescendantOf(mTransientLaunches.valueAt(i))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     boolean isTransientLaunch(@NonNull ActivityRecord activity) {
         return mTransientLaunches != null && mTransientLaunches.containsKey(activity);
     }
@@ -374,6 +392,14 @@
         return mState == STATE_STARTED;
     }
 
+    boolean isPlaying() {
+        return mState == STATE_PLAYING;
+    }
+
+    boolean isFinished() {
+        return mState == STATE_FINISHED;
+    }
+
     @VisibleForTesting
     void startCollecting(long timeoutMs) {
         startCollecting(timeoutMs, TransitionController.SYNC_METHOD);
@@ -388,7 +414,7 @@
         mSyncId = mSyncEngine.startSyncSet(this, timeoutMs, TAG, method);
 
         mLogger.mSyncId = mSyncId;
-        mLogger.mCollectTimeNs = SystemClock.uptimeNanos();
+        mLogger.mCollectTimeNs = SystemClock.elapsedRealtimeNanos();
         mController.mTransitionTracer.logState(this);
     }
 
@@ -401,14 +427,17 @@
         if (mState < STATE_COLLECTING) {
             throw new IllegalStateException("Can't start Transition which isn't collecting.");
         } else if (mState >= STATE_STARTED) {
-            Slog.w(TAG, "Transition already started: " + mSyncId);
+            Slog.w(TAG, "Transition already started id=" + mSyncId + " state=" + mState);
+            // The transition may be aborted (STATE_ABORT) or timed out (STATE_PLAYING by
+            // SyncGroup#finishNow), so do not revert the state to STATE_STARTED.
+            return;
         }
         mState = STATE_STARTED;
         ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Starting Transition %d",
                 mSyncId);
         applyReady();
 
-        mLogger.mStartTimeNs = SystemClock.uptimeNanos();
+        mLogger.mStartTimeNs = SystemClock.elapsedRealtimeNanos();
         mController.mTransitionTracer.logState(this);
 
         mController.updateAnimatingState(mTmpTransaction);
@@ -618,7 +647,7 @@
         ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                 "Set transition ready=%b %d", ready, mSyncId);
         mSyncEngine.setReady(mSyncId, ready);
-        if (ready) mLogger.mReadyTimeNs = SystemClock.uptimeNanos();
+        if (ready) mLogger.mReadyTimeNs = SystemClock.elapsedRealtimeNanos();
     }
 
     /**
@@ -766,11 +795,11 @@
      * be called directly; use {@link TransitionController#finishTransition} instead.
      */
     void finishTransition() {
-        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
+        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER) && mIsPlayerEnabled) {
             Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, TRACE_NAME_PLAY_TRANSITION,
                     System.identityHashCode(this));
         }
-        mLogger.mFinishTimeNs = SystemClock.uptimeNanos();
+        mLogger.mFinishTimeNs = SystemClock.elapsedRealtimeNanos();
         mController.mLoggerHandler.post(mLogger::logOnFinish);
         // Close the transactions now. They were originally copied to Shell in case we needed to
         // apply them due to a remote failure. Since we don't need to apply them anymore, free them
@@ -825,6 +854,11 @@
                         && ar.isVisible()) {
                     // Transient launch was committed, so report enteringAnimation
                     ar.mEnteringAnimation = true;
+                    // Since transient launches don't automatically take focus, make sure we
+                    // synchronize focus since we committed to the launch.
+                    if (ar.isTopRunningActivity()) {
+                        ar.moveFocusableActivityToTop("transitionFinished");
+                    }
                 }
                 continue;
             }
@@ -1096,13 +1130,15 @@
             controller.setupStartTransaction(transaction);
         }
         buildFinishTransaction(mFinishTransaction, info.getRootLeash());
-        if (mController.getTransitionPlayer() != null) {
+        if (mController.getTransitionPlayer() != null && mIsPlayerEnabled) {
             mController.dispatchLegacyAppTransitionStarting(info, mStatusBarTransitionDelay);
             try {
                 ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                         "Calling onTransitionReady: %s", info);
-                mLogger.mSendTimeNs = SystemClock.uptimeNanos();
+                mLogger.mSendTimeNs = SystemClock.elapsedRealtimeNanos();
                 mLogger.mInfo = info;
+                mController.mTransitionTracer.logSentTransition(
+                        this, mTargets, mLogger.mCreateTimeNs, mLogger.mSendTimeNs, info);
                 mController.getTransitionPlayer().onTransitionReady(
                         mToken, info, transaction, mFinishTransaction);
                 if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
@@ -1112,11 +1148,21 @@
             } catch (RemoteException e) {
                 // If there's an exception when trying to send the mergedTransaction to the
                 // client, we should finish and apply it here so the transactions aren't lost.
-                cleanUpOnFailure();
+                postCleanupOnFailure();
+            }
+            final AccessibilityController accessibilityController =
+                    dc.mWmService.mAccessibilityController;
+            if (accessibilityController.hasCallbacks()) {
+                accessibilityController.onWMTransition(dc.getDisplayId(), mType);
             }
         } else {
-            // No player registered, so just finish/apply immediately
-            cleanUpOnFailure();
+            // No player registered or it's not enabled, so just finish/apply immediately
+            if (!mIsPlayerEnabled) {
+                mLogger.mSendTimeNs = SystemClock.uptimeNanos();
+                ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Apply and finish immediately"
+                        + " because player is disabled for transition #%d .", mSyncId);
+            }
+            postCleanupOnFailure();
         }
         mController.mLoggerHandler.post(mLogger::logOnSend);
         mOverrideOptions = null;
@@ -1127,6 +1173,14 @@
         info.releaseAnimSurfaces();
     }
 
+    private void postCleanupOnFailure() {
+        mController.mAtm.mH.post(() -> {
+            synchronized (mController.mAtm.mGlobalLock) {
+                cleanUpOnFailure();
+            }
+        });
+    }
+
     /**
      * If the remote failed for any reason, use this to do any appropriate clean-up. Do not call
      * this directly, it's designed to by called by {@link TransitionController} only.
@@ -1170,6 +1224,7 @@
         }
     }
 
+    // TODO(b/188595497): Remove after migrating to shell.
     /** @see RecentsAnimationController#attachNavigationBarToApp */
     private void handleLegacyRecentsStartBehavior(DisplayContent dc, TransitionInfo info) {
         if ((mFlags & TRANSIT_FLAG_IS_RECENTS) == 0) {
@@ -1250,8 +1305,9 @@
             // Place the nav bar on top of anything else in the top activity.
             t.setLayer(navSurfaceControl, Integer.MAX_VALUE);
         }
-        if (mController.mStatusBar != null) {
-            mController.mStatusBar.setNavigationBarLumaSamplingEnabled(mRecentsDisplayId, false);
+        final StatusBarManagerInternal bar = dc.getDisplayPolicy().getStatusBarManagerInternal();
+        if (bar != null) {
+            bar.setNavigationBarLumaSamplingEnabled(mRecentsDisplayId, false);
         }
     }
 
@@ -1265,12 +1321,12 @@
             mRecentsDisplayId = DEFAULT_DISPLAY;
         }
 
-        if (mController.mStatusBar != null) {
-            mController.mStatusBar.setNavigationBarLumaSamplingEnabled(mRecentsDisplayId, true);
-        }
-
         final DisplayContent dc =
                 mController.mAtm.mRootWindowContainer.getDisplayContent(mRecentsDisplayId);
+        final StatusBarManagerInternal bar = dc.getDisplayPolicy().getStatusBarManagerInternal();
+        if (bar != null) {
+            bar.setNavigationBarLumaSamplingEnabled(mRecentsDisplayId, true);
+        }
         final WindowState navWindow = dc.getDisplayPolicy().getNavigationBar();
         if (navWindow == null) return;
         navWindow.setSurfaceTranslationY(0);
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 5e116ba..ed7e9ed 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -55,8 +55,6 @@
 import com.android.internal.protolog.ProtoLogGroup;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.server.FgThread;
-import com.android.server.LocalServices;
-import com.android.server.statusbar.StatusBarManagerInternal;
 
 import java.util.ArrayList;
 import java.util.function.LongConsumer;
@@ -88,12 +86,12 @@
 
     private ITransitionPlayer mTransitionPlayer;
     final TransitionMetricsReporter mTransitionMetricsReporter = new TransitionMetricsReporter();
-    final TransitionTracer mTransitionTracer;
 
     private WindowProcessController mTransitionPlayerProc;
     final ActivityTaskManagerService mAtm;
-    final TaskSnapshotController mTaskSnapshotController;
     final RemotePlayer mRemotePlayer;
+    TaskSnapshotController mTaskSnapshotController;
+    TransitionTracer mTransitionTracer;
 
     private final ArrayList<WindowManagerInternal.AppTransitionListener> mLegacyListeners =
             new ArrayList<>();
@@ -111,9 +109,6 @@
     /** The transition currently being constructed (collecting participants). */
     private Transition mCollectingTransition = null;
 
-    // TODO(b/188595497): remove when not needed.
-    final StatusBarManagerInternal mStatusBar;
-
     /**
      * `true` when building surface layer order for the finish transaction. We want to prevent
      * wm from touching z-order of surfaces during transitions, but we still need to be able to
@@ -126,14 +121,16 @@
 
     final Handler mLoggerHandler = FgThread.getHandler();
 
-    TransitionController(ActivityTaskManagerService atm,
-            TaskSnapshotController taskSnapshotController,
-            TransitionTracer transitionTracer) {
+    /**
+     * {@code true} While this waits for the display to become enabled (during boot). While waiting
+     * for the display, all core-initiated transitions will be "local".
+     * Note: This defaults to false so that it doesn't interfere with unit tests.
+     */
+    boolean mIsWaitingForDisplayEnabled = false;
+
+    TransitionController(ActivityTaskManagerService atm) {
         mAtm = atm;
         mRemotePlayer = new RemotePlayer(atm);
-        mStatusBar = LocalServices.getService(StatusBarManagerInternal.class);
-        mTaskSnapshotController = taskSnapshotController;
-        mTransitionTracer = transitionTracer;
         mTransitionPlayerDeath = () -> {
             synchronized (mAtm.mGlobalLock) {
                 detachPlayer();
@@ -141,6 +138,13 @@
         };
     }
 
+    void setWindowManager(WindowManagerService wms) {
+        mTaskSnapshotController = wms.mTaskSnapshotController;
+        mTransitionTracer = wms.mTransitionTracer;
+        mIsWaitingForDisplayEnabled = !wms.mDisplayEnabled;
+        registerLegacyListener(wms.mActivityManagerAppTransitionNotifier);
+    }
+
     private void detachPlayer() {
         if (mTransitionPlayer == null) return;
         // Clean-up/finish any playing transitions.
@@ -353,11 +357,37 @@
     }
 
     /**
+     * During transient-launch, the "behind" app should retain focus during the transition unless
+     * something takes focus from it explicitly (eg. by calling ATMS.setFocusedTask or by another
+     * transition interrupting this one.
+     *
+     * The rules around this are basically: if there is exactly one active transition and `wc` is
+     * the "behind" of a transient launch, then it can retain focus.
+     */
+    boolean shouldKeepFocus(@NonNull WindowContainer wc) {
+        if (mCollectingTransition != null) {
+            if (!mPlayingTransitions.isEmpty()) return false;
+            return mCollectingTransition.isInTransientHide(wc);
+        } else if (mPlayingTransitions.size() == 1) {
+            return mPlayingTransitions.get(0).isInTransientHide(wc);
+        }
+        return false;
+    }
+
+    /**
+     * @return {@code true} if {@param ar} is part of a transient-launch activity in the
+     * collecting transition.
+     */
+    boolean isTransientCollect(@NonNull ActivityRecord ar) {
+        return mCollectingTransition != null && mCollectingTransition.isTransientLaunch(ar);
+    }
+
+    /**
      * @return {@code true} if {@param ar} is part of a transient-launch activity in an active
      * transition.
      */
     boolean isTransientLaunch(@NonNull ActivityRecord ar) {
-        if (mCollectingTransition != null && mCollectingTransition.isTransientLaunch(ar)) {
+        if (isTransientCollect(ar)) {
             return true;
         }
         for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
@@ -460,6 +490,15 @@
     Transition requestStartTransition(@NonNull Transition transition, @Nullable Task startTask,
             @Nullable RemoteTransition remoteTransition,
             @Nullable TransitionRequestInfo.DisplayChange displayChange) {
+        if (mIsWaitingForDisplayEnabled) {
+            ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Disabling player for transition"
+                    + " #%d because display isn't enabled yet", transition.getSyncId());
+            transition.mIsPlayerEnabled = false;
+            transition.mLogger.mRequestTimeNs = SystemClock.uptimeNanos();
+            mAtm.mH.post(() -> mAtm.mWindowOrganizerController.startTransition(
+                    transition.getToken(), null));
+            return transition;
+        }
         try {
             ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                     "Requesting StartTransition: %s", transition);
@@ -470,7 +509,7 @@
             }
             final TransitionRequestInfo request = new TransitionRequestInfo(
                     transition.mType, info, remoteTransition, displayChange);
-            transition.mLogger.mRequestTimeNs = SystemClock.uptimeNanos();
+            transition.mLogger.mRequestTimeNs = SystemClock.elapsedRealtimeNanos();
             transition.mLogger.mRequest = request;
             mTransitionPlayer.requestStartTransition(transition.getToken(), request);
             transition.setRemoteTransition(remoteTransition);
diff --git a/services/core/java/com/android/server/wm/TransitionTracer.java b/services/core/java/com/android/server/wm/TransitionTracer.java
index 022c19b..7b1975d 100644
--- a/services/core/java/com/android/server/wm/TransitionTracer.java
+++ b/services/core/java/com/android/server/wm/TransitionTracer.java
@@ -21,19 +21,14 @@
 import static com.android.server.wm.shell.ChangeInfo.CHANGE_FLAGS;
 import static com.android.server.wm.shell.ChangeInfo.HAS_CHANGED;
 import static com.android.server.wm.shell.ChangeInfo.TRANSIT_MODE;
+import static com.android.server.wm.shell.ChangeInfo.WINDOWING_MODE;
 import static com.android.server.wm.shell.ChangeInfo.WINDOW_IDENTIFIER;
-import static com.android.server.wm.shell.Transition.CHANGE;
-import static com.android.server.wm.shell.Transition.FINISH_TRANSACTION_ID;
-import static com.android.server.wm.shell.Transition.FLAGS;
-import static com.android.server.wm.shell.Transition.ID;
-import static com.android.server.wm.shell.Transition.START_TRANSACTION_ID;
-import static com.android.server.wm.shell.Transition.STATE;
-import static com.android.server.wm.shell.Transition.TIMESTAMP;
-import static com.android.server.wm.shell.Transition.TRANSITION_TYPE;
+import static com.android.server.wm.shell.TransitionInfoChange.LAYER_ID;
+import static com.android.server.wm.shell.TransitionInfoChange.MODE;
+import static com.android.server.wm.shell.TransitionState.CHANGE;
 import static com.android.server.wm.shell.TransitionTraceProto.MAGIC_NUMBER;
 import static com.android.server.wm.shell.TransitionTraceProto.MAGIC_NUMBER_H;
 import static com.android.server.wm.shell.TransitionTraceProto.MAGIC_NUMBER_L;
-import static com.android.server.wm.shell.TransitionTraceProto.TRANSITION;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -41,14 +36,15 @@
 import android.os.Trace;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
+import android.window.TransitionInfo;
 
 import com.android.internal.util.TraceBuffer;
 import com.android.server.wm.Transition.ChangeInfo;
-import com.android.server.wm.shell.TransitionTraceProto;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 
 /**
  * Helper class to collect and dump transition traces.
@@ -57,10 +53,8 @@
 
     private static final String LOG_TAG = "TransitionTracer";
 
-    /**
-     * Maximum buffer size, currently defined as 5 MB
-     */
-    private static final int BUFFER_CAPACITY = 5120 * 1024; // 5 MB
+    private static final int ALWAYS_ON_TRACING_CAPACITY = 15 * 1024; // 15 KB
+    private static final int ACTIVE_TRACING_BUFFER_CAPACITY = 5000 * 1024; // 5 MB
     static final String WINSCOPE_EXT = ".winscope";
     private static final String TRACE_FILE = "/data/misc/wmtrace/transition_trace" + WINSCOPE_EXT;
     private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
@@ -68,28 +62,129 @@
     private final TransitionTraceBuffer mTraceBuffer = new TransitionTraceBuffer();
 
     private final Object mEnabledLock = new Object();
-    private volatile boolean mEnabled = false;
+    private volatile boolean mActiveTracingEnabled = false;
 
-    private long mTraceStartTimestamp;
+    /**
+     * Records key information about a transition that has been sent to Shell to be played.
+     * @param transition The transition that has been sent to Shell.
+     * @param targets Information about the target windows of the transition.
+     * @param createTimeNs System elapsed time (nanoseconds since boot including sleep time) at
+ *                     which the transition to be recorded was created.
+     * @param sendTimeNs System elapsed time (nanoseconds since boot including sleep time) at which
+     * @param info
+     */
+    public void logSentTransition(Transition transition, ArrayList<ChangeInfo> targets,
+            long createTimeNs, long sendTimeNs, TransitionInfo info) {
+        mTraceBuffer.pushSentTransition(transition, targets, createTimeNs, sendTimeNs);
+        logTransitionInfo(transition, info);
+    }
+
+    /**
+     * Records the current state of a transition in the transition trace (if it is running).
+     * @param transition the transition that we want to record the state of.
+     */
+    public void logState(com.android.server.wm.Transition transition) {
+        if (!mActiveTracingEnabled) {
+            return;
+        }
+        mTraceBuffer.pushTransitionState(transition);
+    }
+
+    /**
+     * Records the transition info that is being sent over to Shell.
+     * @param transition The transition the info is associated with.
+     * @param info The transition info we want to log.
+     */
+    private void logTransitionInfo(Transition transition, TransitionInfo info) {
+        if (!mActiveTracingEnabled) {
+            return;
+        }
+        mTraceBuffer.pushTransitionInfo(transition, info);
+    }
 
     private class TransitionTraceBuffer {
-        private final TraceBuffer mBuffer = new TraceBuffer(BUFFER_CAPACITY);
+        private final TraceBuffer mBuffer = new TraceBuffer(ALWAYS_ON_TRACING_CAPACITY);
+        private final TraceBuffer mStateBuffer = new TraceBuffer(ACTIVE_TRACING_BUFFER_CAPACITY);
+        private final TraceBuffer mTransitionInfoBuffer =
+                new TraceBuffer(ACTIVE_TRACING_BUFFER_CAPACITY);
+
+        public void pushSentTransition(
+                Transition transition,
+                ArrayList<ChangeInfo> targets,
+                long createTimeNs,
+                long sendTimeNs
+        ) {
+            Trace.beginSection("TransitionTraceBuffer#pushSentTransition");
+            final ProtoOutputStream outputStream = new ProtoOutputStream();
+            final long transitionToken = outputStream
+                    .start(com.android.server.wm.shell.TransitionTraceProto.SENT_TRANSITIONS);
+
+            if (mActiveTracingEnabled) {
+                outputStream.write(com.android.server.wm.shell.Transition.ID,
+                        transition.getSyncId());
+            }
+
+            outputStream.write(com.android.server.wm.shell.Transition.START_TRANSACTION_ID,
+                    transition.getStartTransaction().getId());
+            outputStream.write(com.android.server.wm.shell.Transition.FINISH_TRANSACTION_ID,
+                    transition.getFinishTransaction().getId());
+
+            outputStream.write(com.android.server.wm.shell.Transition.CREATE_TIME_NS, createTimeNs);
+            outputStream.write(com.android.server.wm.shell.Transition.SEND_TIME_NS, sendTimeNs);
+
+            for (int i = 0; i < targets.size(); ++i) {
+                final long changeToken = outputStream
+                        .start(com.android.server.wm.shell.Transition.TARGETS);
+
+                final Transition.ChangeInfo target = targets.get(i);
+
+                final int mode = target.getTransitMode(target.mContainer);
+                final int layerId;
+                if (target.mContainer.mSurfaceControl.isValid()) {
+                    layerId = target.mContainer.mSurfaceControl.getLayerId();
+                } else {
+                    layerId = -1;
+                }
+
+                outputStream.write(com.android.server.wm.shell.Target.MODE, mode);
+                outputStream.write(com.android.server.wm.shell.Target.LAYER_ID, layerId);
+
+                if (mActiveTracingEnabled) {
+                    // What we use in the WM trace
+                    final int windowId = System.identityHashCode(target.mContainer);
+                    outputStream.write(com.android.server.wm.shell.Target.WINDOW_ID, windowId);
+                }
+
+                outputStream.end(changeToken);
+            }
+
+            outputStream.end(transitionToken);
+            mBuffer.add(outputStream);
+
+            Trace.endSection();
+        }
 
         private void pushTransitionState(Transition transition) {
+            Trace.beginSection("TransitionTraceBuffer#pushTransitionState");
             final ProtoOutputStream outputStream = new ProtoOutputStream();
-            final long transitionEntryToken = outputStream.start(TRANSITION);
+            final long stateToken = outputStream
+                    .start(com.android.server.wm.shell.TransitionTraceProto.TRANSITION_STATES);
 
-            outputStream.write(ID, transition.getSyncId());
-            outputStream.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
-            outputStream.write(TRANSITION_TYPE, transition.mType);
-            outputStream.write(STATE, transition.getState());
-            outputStream.write(FLAGS, transition.getFlags());
-            if (transition.getStartTransaction() != null) {
-                outputStream.write(START_TRANSACTION_ID, transition.getStartTransaction().getId());
-            }
-            if (transition.getFinishTransaction() != null) {
-                outputStream.write(FINISH_TRANSACTION_ID,
-                        transition.getFinishTransaction().getId());
+            outputStream.write(com.android.server.wm.shell.TransitionState.TIME_NS,
+                    SystemClock.elapsedRealtimeNanos());
+            outputStream.write(com.android.server.wm.shell.TransitionState.TRANSITION_ID,
+                    transition.getSyncId());
+            outputStream.write(com.android.server.wm.shell.TransitionState.TRANSITION_TYPE,
+                    transition.mType);
+            outputStream.write(com.android.server.wm.shell.TransitionState.STATE,
+                    transition.getState());
+            outputStream.write(com.android.server.wm.shell.TransitionState.FLAGS,
+                    transition.getFlags());
+
+            for (int i = 0; i < transition.mChanges.size(); ++i) {
+                final WindowContainer window = transition.mChanges.keyAt(i);
+                final ChangeInfo changeInfo = transition.mChanges.valueAt(i);
+                writeChange(outputStream, window, changeInfo);
             }
 
             for (int i = 0; i < transition.mChanges.size(); ++i) {
@@ -98,29 +193,71 @@
                 writeChange(outputStream, window, changeInfo);
             }
 
-            outputStream.end(transitionEntryToken);
+            for (int i = 0; i < transition.mParticipants.size(); ++i) {
+                final WindowContainer window = transition.mParticipants.valueAt(i);
+                window.writeIdentifierToProto(outputStream,
+                        com.android.server.wm.shell.TransitionState.PARTICIPANTS);
+            }
 
-            mBuffer.add(outputStream);
+            outputStream.end(stateToken);
+
+            mStateBuffer.add(outputStream);
+            Trace.endSection();
+        }
+
+        private void pushTransitionInfo(Transition transition, TransitionInfo info) {
+            Trace.beginSection("TransitionTraceBuffer#pushTransitionInfo");
+            final ProtoOutputStream outputStream = new ProtoOutputStream();
+            final long transitionInfoToken = outputStream
+                    .start(com.android.server.wm.shell.TransitionTraceProto.TRANSITION_INFO);
+
+            outputStream.write(com.android.server.wm.shell.TransitionInfo.TRANSITION_ID,
+                    transition.getSyncId());
+            for (int i = 0; i < info.getChanges().size(); ++i) {
+                TransitionInfo.Change change = info.getChanges().get(i);
+                writeTransitionInfoChange(outputStream, change);
+            }
+
+            outputStream.end(transitionInfoToken);
+            mTransitionInfoBuffer.add(outputStream);
+            Trace.endSection();
         }
 
         private void writeChange(ProtoOutputStream outputStream, WindowContainer window,
                 ChangeInfo changeInfo) {
-            Trace.beginSection("TransitionProto#addChange");
+            Trace.beginSection("TransitionTraceBuffer#writeChange");
             final long changeEntryToken = outputStream.start(CHANGE);
 
             final int transitMode = changeInfo.getTransitMode(window);
             final boolean hasChanged = changeInfo.hasChanged();
             final int changeFlags = changeInfo.getChangeFlags(window);
+            final int windowingMode = changeInfo.mWindowingMode;
 
             outputStream.write(TRANSIT_MODE, transitMode);
             outputStream.write(HAS_CHANGED, hasChanged);
             outputStream.write(CHANGE_FLAGS, changeFlags);
+            outputStream.write(WINDOWING_MODE, windowingMode);
             window.writeIdentifierToProto(outputStream, WINDOW_IDENTIFIER);
 
             outputStream.end(changeEntryToken);
             Trace.endSection();
         }
 
+        private void writeTransitionInfoChange(
+                ProtoOutputStream outputStream,
+                TransitionInfo.Change change
+        ) {
+            Trace.beginSection("TransitionTraceBuffer#writeTransitionInfoChange");
+            final long changeEntryToken = outputStream
+                    .start(com.android.server.wm.shell.TransitionInfo.CHANGE);
+
+            outputStream.write(LAYER_ID, change.getLeash().getLayerId());
+            outputStream.write(MODE, change.getMode());
+
+            outputStream.end(changeEntryToken);
+            Trace.endSection();
+        }
+
         public void writeToFile(File file, ProtoOutputStream proto) throws IOException {
             mBuffer.writeTraceToFile(file, proto);
         }
@@ -131,19 +268,6 @@
     }
 
     /**
-     * Records the current state of a transition in the transition trace (if it is running).
-     * @param transition the transition that we want to record the state of.
-     */
-    public void logState(com.android.server.wm.Transition transition) {
-        if (!mEnabled) {
-            return;
-        }
-
-        Log.d(LOG_TAG, "Logging state of transition " + transition);
-        mTraceBuffer.pushTransitionState(transition);
-    }
-
-    /**
      * Starts collecting transitions for the trace.
      * If called while a trace is already running, this will reset the trace.
      */
@@ -155,8 +279,8 @@
         Trace.beginSection("TransitionTracer#startTrace");
         LogAndPrintln.i(pw, "Starting shell transition trace.");
         synchronized (mEnabledLock) {
-            mTraceStartTimestamp = SystemClock.elapsedRealtime();
-            mEnabled = true;
+            mActiveTracingEnabled = true;
+            mTraceBuffer.mBuffer.setCapacity(ACTIVE_TRACING_BUFFER_CAPACITY);
             mTraceBuffer.reset();
         }
         Trace.endSection();
@@ -183,20 +307,15 @@
         Trace.beginSection("TransitionTracer#stopTrace");
         LogAndPrintln.i(pw, "Stopping shell transition trace.");
         synchronized (mEnabledLock) {
-            if (!mEnabled) {
-                LogAndPrintln.e(pw,
-                        "Error: Tracing can't be stopped because it hasn't been started.");
-                return;
-            }
-
-            mEnabled = false;
+            mActiveTracingEnabled = false;
             writeTraceToFileLocked(pw, outputFile);
+            mTraceBuffer.mBuffer.setCapacity(ALWAYS_ON_TRACING_CAPACITY);
         }
         Trace.endSection();
     }
 
-    boolean isEnabled() {
-        return mEnabled;
+    boolean isActiveTracingEnabled() {
+        return mActiveTracingEnabled;
     }
 
     private void writeTraceToFileLocked(@Nullable PrintWriter pw, File file) {
@@ -204,7 +323,6 @@
         try {
             ProtoOutputStream proto = new ProtoOutputStream();
             proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
-            proto.write(TransitionTraceProto.TIMESTAMP, mTraceStartTimestamp);
             int pid = android.os.Process.myPid();
             LogAndPrintln.i(pw, "Writing file to " + file.getAbsolutePath()
                     + " from process " + pid);
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 210d5a5..6b2bf59 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -99,7 +99,6 @@
         }
     }
 
-    /** Returns {@code true} if visibility is changed. */
     void updateWallpaperWindows(boolean visible) {
         boolean changed = false;
         if (mVisibleRequested != visible) {
@@ -117,6 +116,10 @@
                     linkFixedRotationTransform(wallpaperTarget.mToken);
                 }
             }
+            // If wallpaper is in transition, setVisible() will be called from commitVisibility()
+            // when finishing transition. Otherwise commitVisibility() is already called from above
+            // setVisibility().
+            return;
         }
 
         final WindowState wallpaperTarget =
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index b06bdb1..eec9973 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -170,9 +170,9 @@
     protected InsetsSourceProvider mControllableInsetProvider;
 
     /**
-     * The insets sources provided by this windowContainer.
+     * The {@link InsetsSourceProvider}s provided by this window container.
      */
-    protected SparseArray<InsetsSource> mProvidedInsetsSources = null;
+    protected SparseArray<InsetsSourceProvider> mInsetsSourceProviders = null;
 
     // List of children for this window container. List is in z-order as the children appear on
     // screen with the top-most window container at the tail of the list.
@@ -366,7 +366,7 @@
      * {@link WindowState#mMergedLocalInsetsSources} by visiting the entire hierarchy.
      *
      * {@link WindowState#mAboveInsetsState} is updated by visiting all the windows in z-order
-     * top-to-bottom manner and considering the {@link WindowContainer#mProvidedInsetsSources}
+     * top-to-bottom manner and considering the {@link WindowContainer#mInsetsSourceProviders}
      * provided by the {@link WindowState}s at the top.
      * {@link WindowState#updateAboveInsetsState(InsetsState, SparseArray, ArraySet)} visits the
      * IME container in the correct order to make sure the IME insets are passed correctly to the
@@ -566,7 +566,6 @@
             onDisplayChanged(dc);
             prevDc.setLayoutNeeded();
         }
-        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
 
         // Send onParentChanged notification here is we disabled sending it in setParent for
         // reparenting case.
@@ -1035,11 +1034,21 @@
         }
     }
 
-    public SparseArray<InsetsSource> getProvidedInsetsSources() {
-        if (mProvidedInsetsSources == null) {
-            mProvidedInsetsSources = new SparseArray<>();
+    /**
+     * Returns {@code true} if this node provides insets.
+     */
+    public boolean hasInsetsSourceProvider() {
+        return mInsetsSourceProviders != null;
+    }
+
+    /**
+     * Returns {@link InsetsSourceProvider}s provided by this node.
+     */
+    public SparseArray<InsetsSourceProvider> getInsetsSourceProviders() {
+        if (mInsetsSourceProviders == null) {
+            mInsetsSourceProviders = new SparseArray<>();
         }
-        return mProvidedInsetsSources;
+        return mInsetsSourceProviders;
     }
 
     public DisplayContent getDisplayContent() {
@@ -4102,13 +4111,13 @@
             }
         }
 
-        private void hideInsetSourceViewOverflows(Set<Integer> insetTypes) {
-            final ArrayList<SurfaceControl> surfaceControls =
-                    new ArrayList<>(insetTypes.size());
-
-            for (int insetType : insetTypes) {
-                WindowContainerInsetsSourceProvider insetProvider = getDisplayContent()
-                        .getInsetsStateController().getSourceProvider(insetType);
+        private void hideInsetSourceViewOverflows(Set<Integer> sourceIds) {
+            final InsetsStateController controller = getDisplayContent().getInsetsStateController();
+            for (int id : sourceIds) {
+                final InsetsSourceProvider insetProvider = controller.peekSourceProvider(id);
+                if (insetProvider == null) {
+                    return;
+                }
 
                 // Will apply it immediately to current leash and to all future inset animations
                 // until we disable it.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a596eed..ad81982 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -113,6 +113,7 @@
 import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
 import static com.android.server.LockGuard.INDEX_WINDOW;
 import static com.android.server.LockGuard.installLock;
+import static com.android.server.policy.PhoneWindowManager.TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
 import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
@@ -309,6 +310,7 @@
 import com.android.internal.policy.IKeyguardLockedStateListener;
 import com.android.internal.policy.IShortcutService;
 import com.android.internal.policy.KeyInterceptionInfo;
+import com.android.internal.protolog.ProtoLogGroup;
 import com.android.internal.protolog.ProtoLogImpl;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.DumpUtils;
@@ -365,6 +367,7 @@
 public class WindowManagerService extends IWindowManager.Stub
         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowManagerService" : TAG_WM;
+    private static final int TRACE_MAX_SECTION_NAME_LENGTH = 127;
 
     static final int LAYOUT_REPEAT_THRESHOLD = 4;
 
@@ -1335,6 +1338,8 @@
         mConstants.start(new HandlerExecutor(mH));
 
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
+        LocalServices.addService(
+                ImeTargetVisibilityPolicy.class, new ImeTargetVisibilityPolicyImpl());
         mEmbeddedWindowController = new EmbeddedWindowController(mAtmService);
 
         mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources(
@@ -3774,6 +3779,12 @@
 
         // Make sure the last requested orientation has been applied.
         updateRotationUnchecked(false, false);
+
+        synchronized (mGlobalLock) {
+            mAtmService.getTransitionController().mIsWaitingForDisplayEnabled = false;
+            ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Notified TransitionController "
+                    + "that the display is ready.");
+        }
     }
 
     private boolean checkBootAnimationCompleteLocked() {
@@ -3833,8 +3844,9 @@
      *
      * If {@code com.android.internal.R.bool.config_perDisplayFocusEnabled} is set to true, then
      * only the display represented by the {@code displayId} parameter will be requested to switch
-     * the touch mode state. Otherwise all all displays will be requested to switch their touch mode
-     * state (disregarding {@code displayId} parameter).
+     * the touch mode state. Otherwise all displays that do not maintain their own focus and touch
+     * mode will be requested to switch their touch mode state (disregarding {@code displayId}
+     * parameter).
      *
      * To be able to change touch mode state, the caller must either own the focused window, or must
      * have the {@link android.Manifest.permission#MODIFY_TOUCH_MODE_STATE} permission. Instrumented
@@ -3846,27 +3858,9 @@
      */
     @Override // Binder call
     public void setInTouchMode(boolean inTouch, int displayId) {
-        boolean perDisplayFocusEnabled = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_perDisplayFocusEnabled);
-        setInTouchMode(inTouch, displayId, perDisplayFocusEnabled);
-    }
-
-    /**
-     * Sets the touch mode state on all displays (disregarding the value of
-     * {@code com.android.internal.R.bool.config_perDisplayFocusEnabled}).
-     *
-     * @param inTouch the touch mode to set
-     */
-    @Override // Binder call
-    public void setInTouchModeOnAllDisplays(boolean inTouch) {
-        setInTouchMode(inTouch, /* any display id */ DEFAULT_DISPLAY,
-                /* perDisplayFocusEnabled= */ false);
-    }
-
-    private void setInTouchMode(boolean inTouch, int displayId, boolean perDisplayFocusEnabled) {
         synchronized (mGlobalLock) {
             final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-            if (perDisplayFocusEnabled && (displayContent == null
+            if (mPerDisplayFocusEnabled && (displayContent == null
                     || displayContent.isInTouchMode() == inTouch)) {
                 return;
             }
@@ -3877,15 +3871,12 @@
             }
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
-            final boolean hasPermission =
-                    mAtmService.instrumentationSourceHasPermission(pid, MODIFY_TOUCH_MODE_STATE)
-                            || checkCallingPermission(MODIFY_TOUCH_MODE_STATE, "setInTouchMode()",
-                            /* printlog= */ false);
+            final boolean hasPermission = hasTouchModePermission(pid);
             final long token = Binder.clearCallingIdentity();
             try {
-                // If perDisplayFocusEnabled is set or the display maintains its own touch mode,
+                // If mPerDisplayFocusEnabled is set or the display maintains its own touch mode,
                 // then just update the display pointed by displayId
-                if (perDisplayFocusEnabled || displayHasOwnTouchMode) {
+                if (mPerDisplayFocusEnabled || displayHasOwnTouchMode) {
                     if (mInputManager.setInTouchMode(inTouch, pid, uid, hasPermission, displayId)) {
                         displayContent.setInTouchMode(inTouch);
                     }
@@ -3909,6 +3900,41 @@
     }
 
     /**
+     * Sets the touch mode state forcibly on all displays (disregarding both the value of
+     * {@code com.android.internal.R.bool.config_perDisplayFocusEnabled} and whether the display
+     * maintains its own focus and touch mode).
+     *
+     * @param inTouch the touch mode to set
+     */
+    @Override // Binder call
+    public void setInTouchModeOnAllDisplays(boolean inTouch) {
+        final int pid = Binder.getCallingPid();
+        final int uid = Binder.getCallingUid();
+        final boolean hasPermission = hasTouchModePermission(pid);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mGlobalLock) {
+                for (int i = 0; i < mRoot.mChildren.size(); ++i) {
+                    DisplayContent dc = mRoot.mChildren.get(i);
+                    if (dc.isInTouchMode() != inTouch
+                            && mInputManager.setInTouchMode(inTouch, pid, uid, hasPermission,
+                            dc.mDisplayId)) {
+                        dc.setInTouchMode(inTouch);
+                    }
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private boolean hasTouchModePermission(int pid) {
+        return mAtmService.instrumentationSourceHasPermission(pid, MODIFY_TOUCH_MODE_STATE)
+                || checkCallingPermission(MODIFY_TOUCH_MODE_STATE, "setInTouchMode()",
+                /* printlog= */ false);
+    }
+
+    /**
      * Returns the touch mode state for the display id passed as argument.
      */
     @Override  // Binder call
@@ -4210,7 +4236,8 @@
      * <p>Note: this assumes that {@link #mGlobalLock} is held by the caller.
      */
     boolean isIgnoreOrientationRequestDisabled() {
-        return mIsIgnoreOrientationRequestDisabled;
+        return mIsIgnoreOrientationRequestDisabled
+                || !mLetterboxConfiguration.isIgnoreOrientationRequestAllowed();
     }
 
     @Override
@@ -5460,10 +5487,15 @@
 
                 case WAITING_FOR_DRAWN_TIMEOUT: {
                     Runnable callback = null;
-                    final WindowContainer container = (WindowContainer) msg.obj;
+                    final WindowContainer<?> container = (WindowContainer<?>) msg.obj;
                     synchronized (mGlobalLock) {
                         ProtoLog.w(WM_ERROR, "Timeout waiting for drawn: undrawn=%s",
                                 container.mWaitingForDrawn);
+                        if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
+                            for (int i = 0; i < container.mWaitingForDrawn.size(); i++) {
+                                traceEndWaitingForWindowDrawn(container.mWaitingForDrawn.get(i));
+                            }
+                        }
                         container.mWaitingForDrawn.clear();
                         callback = mWaitingForDrawnCallbacks.remove(container);
                     }
@@ -5995,7 +6027,7 @@
 
     @Override
     public boolean isTransitionTraceEnabled() {
-        return mTransitionTracer.isEnabled();
+        return mTransitionTracer.isActiveTracingEnabled();
     }
 
     @Override
@@ -6079,10 +6111,16 @@
                     // Window has been removed or hidden; no draw will now happen, so stop waiting.
                     ProtoLog.w(WM_DEBUG_SCREEN_ON, "Aborted waiting for drawn: %s", win);
                     container.mWaitingForDrawn.remove(win);
+                    if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
+                        traceEndWaitingForWindowDrawn(win);
+                    }
                 } else if (win.hasDrawn()) {
                     // Window is now drawn (and shown).
                     ProtoLog.d(WM_DEBUG_SCREEN_ON, "Window drawn win=%s", win);
                     container.mWaitingForDrawn.remove(win);
+                    if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
+                        traceEndWaitingForWindowDrawn(win);
+                    }
                 }
             }
             if (container.mWaitingForDrawn.isEmpty()) {
@@ -6093,6 +6131,22 @@
         });
     }
 
+    private void traceStartWaitingForWindowDrawn(WindowState window) {
+        final String traceName = TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD + "#"
+                + window.getWindowTag();
+        final String shortenedTraceName = traceName.substring(0, Math.min(
+                TRACE_MAX_SECTION_NAME_LENGTH, traceName.length()));
+        Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, shortenedTraceName, /* cookie= */ 0);
+    }
+
+    private void traceEndWaitingForWindowDrawn(WindowState window) {
+        final String traceName = TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD + "#"
+                + window.getWindowTag();
+        final String shortenedTraceName = traceName.substring(0, Math.min(
+                TRACE_MAX_SECTION_NAME_LENGTH, traceName.length()));
+        Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, shortenedTraceName, /* cookie= */ 0);
+    }
+
     void requestTraversal() {
         mWindowPlacerLocked.requestTraversal();
     }
@@ -7811,7 +7865,7 @@
 
         @Override
         public void waitForAllWindowsDrawn(Runnable callback, long timeout, int displayId) {
-            final WindowContainer container = displayId == INVALID_DISPLAY
+            final WindowContainer<?> container = displayId == INVALID_DISPLAY
                     ? mRoot : mRoot.getDisplayContent(displayId);
             if (container == null) {
                 // The waiting container doesn't exist, no need to wait to run the callback. Run and
@@ -7827,6 +7881,12 @@
                 if (container.mWaitingForDrawn.isEmpty()) {
                     allWindowsDrawn = true;
                 } else {
+                    if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
+                        for (int i = 0; i < container.mWaitingForDrawn.size(); i++) {
+                            traceStartWaitingForWindowDrawn(container.mWaitingForDrawn.get(i));
+                        }
+                    }
+
                     mWaitingForDrawnCallbacks.put(container, callback);
                     mH.sendNewMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, container, timeout);
                     checkDrawnWindowsLocked();
@@ -8082,14 +8142,14 @@
                     dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
                 }
                 if (dc != null && dc.getImeTarget(IME_TARGET_CONTROL) != null) {
-                    ImeTracker.get().onProgress(statsToken,
+                    ImeTracker.forLogging().onProgress(statsToken,
                             ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET);
                     ProtoLog.d(WM_DEBUG_IME, "hideIme Control target: %s ",
                             dc.getImeTarget(IME_TARGET_CONTROL));
                     dc.getImeTarget(IME_TARGET_CONTROL).hideInsets(WindowInsets.Type.ime(),
                             true /* fromIme */, statsToken);
                 } else {
-                    ImeTracker.get().onFailed(statsToken,
+                    ImeTracker.forLogging().onFailed(statsToken,
                             ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET);
                 }
                 if (dc != null) {
@@ -8344,6 +8404,47 @@
         }
     }
 
+    private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy {
+
+        // TODO(b/258048231): Track IME visibility change in bugreport when invocations.
+        @Override
+        public boolean showImeScreenShot(@NonNull IBinder imeTarget, int displayId) {
+            synchronized (mGlobalLock) {
+                final WindowState imeTargetWindow = mWindowMap.get(imeTarget);
+                if (imeTargetWindow == null) {
+                    return false;
+                }
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    Slog.w(TAG, "Invalid displayId:" + displayId + ", fail to show ime screenshot");
+                    return false;
+                }
+
+                dc.showImeScreenshot(imeTargetWindow);
+                return true;
+            }
+        }
+
+        // TODO(b/258048231): Track IME visibility change in bugreport when invocations.
+        @Override
+        public boolean updateImeParent(@NonNull IBinder imeTarget, int displayId) {
+            synchronized (mGlobalLock) {
+                final WindowState imeTargetWindow = mWindowMap.get(imeTarget);
+                if (imeTargetWindow == null) {
+                    return false;
+                }
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    Slog.w(TAG, "Invalid displayId:" + displayId + ", fail to update ime parent");
+                    return false;
+                }
+
+                dc.updateImeParent();
+                return true;
+            }
+        }
+    }
+
     void registerAppFreezeListener(AppFreezeListener listener) {
         if (!mAppFreezeListeners.contains(listener)) {
             mAppFreezeListeners.add(listener);
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 29d3462..3faf9e0 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -52,7 +52,6 @@
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_SHORTCUT;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
-import static com.android.server.wm.ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED;
 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
@@ -146,7 +145,8 @@
     final DisplayAreaOrganizerController mDisplayAreaOrganizerController;
     final TaskFragmentOrganizerController mTaskFragmentOrganizerController;
 
-    TransitionController mTransitionController;
+    final TransitionController mTransitionController;
+
     /**
      * A Map which manages the relationship between
      * {@link TaskFragmentCreationParams#getFragmentToken()} and {@link TaskFragment}
@@ -163,12 +163,7 @@
         mTaskOrganizerController = new TaskOrganizerController(mService);
         mDisplayAreaOrganizerController = new DisplayAreaOrganizerController(mService);
         mTaskFragmentOrganizerController = new TaskFragmentOrganizerController(atm, this);
-    }
-
-    void setWindowManager(WindowManagerService wms) {
-        mTransitionController = new TransitionController(mService, wms.mTaskSnapshotController,
-                wms.mTransitionTracer);
-        mTransitionController.registerLegacyListener(wms.mActivityManagerAppTransitionNotifier);
+        mTransitionController = new TransitionController(atm);
     }
 
     TransitionController getTransitionController() {
@@ -431,6 +426,7 @@
                 applyTransaction(wct, -1 /* syncId */, transition, caller);
                 mTransitionController.requestStartTransition(transition, null /* startTask */,
                         null /* remoteTransition */, null /* displayChange */);
+                transition.setAllReady();
                 return;
             }
 
@@ -469,6 +465,7 @@
                             mTransitionController.requestStartTransition(nextTransition,
                                     null /* startTask */, null /* remoteTransition */,
                                     null /* displayChange */);
+                            nextTransition.setAllReady();
                         } else {
                             nextTransition.abort();
                         }
@@ -619,8 +616,8 @@
                 }
             }
 
-            if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
-                mService.addWindowLayoutReasons(LAYOUT_REASON_CONFIG_CHANGED);
+            if (effects != 0) {
+                mService.mWindowManager.mWindowPlacerLocked.requestTraversal();
             }
         } finally {
             mService.mTaskSupervisor.setDeferRootVisibilityUpdate(false /* deferUpdate */);
@@ -1036,17 +1033,30 @@
                 taskDisplayArea.moveRootTaskBehindRootTask(thisTask.getRootTask(), restoreAt);
                 break;
             }
-            case HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER:
+            case HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER: {
                 final Rect insetsProviderWindowContainer = hop.getInsetsProviderFrame();
-                final WindowContainer receiverWindowContainer =
+                final WindowContainer container =
                         WindowContainer.fromBinder(hop.getContainer());
-                receiverWindowContainer.addLocalRectInsetsSourceProvider(
+                if (container == null) {
+                    Slog.e(TAG, "Attempt to add local insets source provider on unknown: "
+                                    + container);
+                    break;
+                }
+                container.addLocalRectInsetsSourceProvider(
                         insetsProviderWindowContainer, hop.getInsetsTypes());
                 break;
-            case HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER:
-                WindowContainer.fromBinder(hop.getContainer())
-                        .removeLocalInsetsSourceProvider(hop.getInsetsTypes());
+            }
+            case HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER: {
+                final WindowContainer container =
+                        WindowContainer.fromBinder(hop.getContainer());
+                if (container == null) {
+                    Slog.e(TAG, "Attempt to remove local insets source provider from unknown: "
+                                    + container);
+                    break;
+                }
+                container.removeLocalInsetsSourceProvider(hop.getInsetsTypes());
                 break;
+            }
             case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: {
                 final WindowContainer container = WindowContainer.fromBinder(hop.getContainer());
                 if (container == null || container.asDisplayArea() == null
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 33af563..e429db9 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -225,7 +225,6 @@
 import android.view.InputWindowHandle;
 import android.view.InsetsSource;
 import android.view.InsetsState;
-import android.view.InsetsState.InternalInsetsType;
 import android.view.Surface;
 import android.view.Surface.Rotation;
 import android.view.SurfaceControl;
@@ -1393,15 +1392,18 @@
     }
 
     void updateSourceFrame(Rect winFrame) {
+        if (!hasInsetsSourceProvider()) {
+            // This window doesn't provide any insets.
+            return;
+        }
         if (mGivenInsetsPending) {
             // The given insets are pending, and they are not reliable for now. The source frame
             // should be updated after the new given insets are sent to window manager.
             return;
         }
-        final SparseArray<InsetsSource> providedSources = getProvidedInsetsSources();
-        final InsetsStateController controller = getDisplayContent().getInsetsStateController();
-        for (int i = providedSources.size() - 1; i >= 0; i--) {
-            controller.getSourceProvider(providedSources.keyAt(i)).updateSourceFrame(winFrame);
+        final SparseArray<InsetsSourceProvider> providers = getInsetsSourceProviders();
+        for (int i = providers.size() - 1; i >= 0; i--) {
+            providers.valueAt(i).updateSourceFrame(winFrame);
         }
     }
 
@@ -1531,6 +1533,10 @@
                 winAnimator.mDrawState = DRAW_PENDING;
                 if (mActivityRecord != null) {
                     mActivityRecord.clearAllDrawn();
+                    if (mAttrs.type == TYPE_APPLICATION_STARTING
+                            && mActivityRecord.mStartingData != null) {
+                        mActivityRecord.mStartingData.mIsDisplayed = false;
+                    }
                 }
             }
             if (!mWmService.mResizingWindows.contains(this)) {
@@ -1696,14 +1702,12 @@
      * Returns the insets state for the window and applies the requested visibility.
      */
     InsetsState getInsetsStateWithVisibilityOverride() {
-        final InsetsState state = new InsetsState(getInsetsState());
-        for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
-            final boolean requestedVisible = isRequestedVisible(InsetsState.toPublicType(type));
-            InsetsSource source = state.peekSource(type);
-            if (source != null && source.isVisible() != requestedVisible) {
-                source = new InsetsSource(source);
+        final InsetsState state = new InsetsState(getInsetsState(), true /* copySources */);
+        for (int i = state.sourceSize() - 1; i >= 0; i--) {
+            final InsetsSource source = state.sourceAt(i);
+            final boolean requestedVisible = isRequestedVisible(source.getType());
+            if (source.isVisible() != requestedVisible) {
                 source.setVisible(requestedVisible);
-                state.addSource(source);
             }
         }
         return state;
@@ -1878,12 +1882,12 @@
     }
 
     boolean providesNonDecorInsets() {
-        if (mProvidedInsetsSources == null) {
+        if (mInsetsSourceProviders == null) {
             return false;
         }
-        for (int i = mProvidedInsetsSources.size() - 1; i >= 0; i--) {
-            final int type = mProvidedInsetsSources.keyAt(i);
-            if ((InsetsState.toPublicType(type) & WindowInsets.Type.navigationBars()) != 0) {
+        for (int i = mInsetsSourceProviders.size() - 1; i >= 0; i--) {
+            final InsetsSource source = mInsetsSourceProviders.valueAt(i).getSource();
+            if (source.getType() == WindowInsets.Type.navigationBars()) {
                 return true;
             }
         }
@@ -2080,7 +2084,7 @@
         final ActivityRecord atoken = mActivityRecord;
         return isDrawn() && isVisibleByPolicy()
                 && ((!isParentWindowHidden() && (atoken == null || atoken.isVisibleRequested()))
-                        || isAnimating(TRANSITION | PARENTS));
+                        || isAnimationRunningSelfOrParent());
     }
 
     /**
@@ -2323,7 +2327,7 @@
 
     boolean isObscuringDisplay() {
         Task task = getTask();
-        if (task != null && task.getRootTask() != null && !task.getRootTask().fillsParent()) {
+        if (task != null && !task.fillsParent()) {
             return false;
         }
         return isOpaqueDrawn() && fillsDisplay();
@@ -2374,7 +2378,11 @@
         // IME parent may failed to attach to the app during rotating the screen.
         // See DisplayContent#shouldImeAttachedToApp, DisplayContent#isImeControlledByApp
         if (windowConfigChanged) {
-            getDisplayContent().updateImeControlTarget();
+            // If the window was the IME layering target, updates the IME surface parent in case
+            // the IME surface may be wrongly positioned when the window configuration affects the
+            // IME surface association. (e.g. Attach IME surface on the display instead of the
+            // app when the app bounds being letterboxed.)
+            mDisplayContent.updateImeControlTarget(isImeLayeringTarget() /* updateImeParent */);
         }
     }
 
@@ -2584,7 +2592,7 @@
                     }
                 }
                 final boolean isAnimating = allowExitAnimation
-                        && (mAnimatingExit || isExitAnimationRunningSelfOrParent());
+                        && (mAnimatingExit || isAnimationRunningSelfOrParent());
                 final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null
                         && mActivityRecord.isLastWindow(this);
                 // We delay the removal of a window if it has a showing surface that can be used to run
@@ -3155,15 +3163,25 @@
                 + (mActivityRecord == null || mActivityRecord.windowsAreFocusable(fromUserTouch))
                 + " canReceiveTouchInput=" + canReceiveTouchInput()
                 + " displayIsOnTop=" + getDisplayContent().isOnTop()
-                + " displayIsTrusted=" + getDisplayContent().isTrusted();
+                + " displayIsTrusted=" + getDisplayContent().isTrusted()
+                + " transitShouldKeepFocus=" + (mActivityRecord != null
+                        && mTransitionController.shouldKeepFocus(mActivityRecord));
     }
 
     public boolean canReceiveKeys(boolean fromUserTouch) {
+        if (mActivityRecord != null && mTransitionController.shouldKeepFocus(mActivityRecord)) {
+            // During transient launch, the transient-hide windows are not visibleRequested
+            // or on-top but are kept focusable and thus can receive keys.
+            return true;
+        }
         final boolean canReceiveKeys = isVisibleRequestedOrAdding()
                 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
                 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
                 && (mActivityRecord == null || mActivityRecord.windowsAreFocusable(fromUserTouch))
-                && canReceiveTouchInput();
+                // can it receive touches
+                && (mActivityRecord == null || mActivityRecord.getTask() == null
+                        || !mActivityRecord.getTask().getRootTask().shouldIgnoreInput());
+
         if (!canReceiveKeys) {
             return false;
         }
@@ -3189,6 +3207,11 @@
         if (mActivityRecord == null  || mActivityRecord.getTask() == null) {
             return true;
         }
+        // During transient launch, the transient-hide windows are not visibleRequested
+        // or on-top but are kept focusable and thus can receive touch input.
+        if (mTransitionController.shouldKeepFocus(mActivityRecord)) {
+            return true;
+        }
 
         return !mActivityRecord.getTask().getRootTask().shouldIgnoreInput()
                 && mActivityRecord.isVisibleRequested();
@@ -3993,12 +4016,12 @@
     public void showInsets(@InsetsType int types, boolean fromIme,
             @Nullable ImeTracker.Token statsToken) {
         try {
-            ImeTracker.get().onProgress(statsToken,
+            ImeTracker.forLogging().onProgress(statsToken,
                     ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS);
             mClient.showInsets(types, fromIme, statsToken);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to deliver showInsets", e);
-            ImeTracker.get().onFailed(statsToken,
+            ImeTracker.forLogging().onFailed(statsToken,
                     ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS);
         }
     }
@@ -4007,12 +4030,12 @@
     public void hideInsets(@InsetsType int types, boolean fromIme,
             @Nullable ImeTracker.Token statsToken) {
         try {
-            ImeTracker.get().onProgress(statsToken,
+            ImeTracker.forLogging().onProgress(statsToken,
                     ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS);
             mClient.hideInsets(types, fromIme, statsToken);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to deliver hideInsets", e);
-            ImeTracker.get().onFailed(statsToken,
+            ImeTracker.forLogging().onFailed(statsToken,
                     ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS);
         }
     }
@@ -4820,10 +4843,10 @@
                 insetsChangedWindows.add(w);
             }
 
-            final SparseArray<InsetsSource> providedSources = w.mProvidedInsetsSources;
-            if (providedSources != null) {
-                for (int i = providedSources.size() - 1; i >= 0; i--) {
-                    aboveInsetsState.addSource(providedSources.valueAt(i));
+            final SparseArray<InsetsSourceProvider> providers = w.mInsetsSourceProviders;
+            if (providers != null) {
+                for (int i = providers.size() - 1; i >= 0; i--) {
+                    aboveInsetsState.addSource(providers.valueAt(i).getSource());
                 }
             }
         }, true /* traverseTopToBottom */);
@@ -4966,7 +4989,7 @@
         return false;
     }
 
-    boolean isExitAnimationRunningSelfOrParent() {
+    boolean isAnimationRunningSelfOrParent() {
         return inTransitionSelfOrParent()
                 || isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION);
     }
@@ -4982,7 +5005,7 @@
             return true;
         }
         // Exit animation is running.
-        if (isExitAnimationRunningSelfOrParent()) {
+        if (isAnimationRunningSelfOrParent()) {
             ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isAnimating: %s",
                     this);
             return false;
@@ -5642,14 +5665,6 @@
                     && imeTarget.compareTo(this) <= 0;
             return inTokenWithAndAboveImeTarget;
         }
-
-        // The condition is for the system dialog not belonging to any Activity.
-        // (^FLAG_NOT_FOCUSABLE & FLAG_ALT_FOCUSABLE_IM) means the dialog is still focusable but
-        // should be placed above the IME window.
-        if ((mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM))
-                == FLAG_ALT_FOCUSABLE_IM && isTrustedOverlay() && canAddInternalSystemWindow()) {
-            return true;
-        }
         return false;
     }
 
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index e661688..e2bdcdd 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -62,9 +62,9 @@
         "com_android_server_tv_TvInputHal.cpp",
         "com_android_server_vr_VrManagerService.cpp",
         "com_android_server_UsbAlsaJackDetector.cpp",
+        "com_android_server_UsbAlsaMidiDevice.cpp",
         "com_android_server_UsbDeviceManager.cpp",
         "com_android_server_UsbDescriptorParser.cpp",
-        "com_android_server_UsbMidiDevice.cpp",
         "com_android_server_UsbHostManager.cpp",
         "com_android_server_vibrator_VibratorController.cpp",
         "com_android_server_vibrator_VibratorManagerService.cpp",
diff --git a/services/core/jni/com_android_server_UsbMidiDevice.cpp b/services/core/jni/com_android_server_UsbAlsaMidiDevice.cpp
similarity index 83%
rename from services/core/jni/com_android_server_UsbMidiDevice.cpp
rename to services/core/jni/com_android_server_UsbAlsaMidiDevice.cpp
index c8e7698..93938b1 100644
--- a/services/core/jni/com_android_server_UsbMidiDevice.cpp
+++ b/services/core/jni/com_android_server_UsbAlsaMidiDevice.cpp
@@ -14,27 +14,25 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "UsbMidiDeviceJNI"
+#define LOG_TAG "UsbAlsaMidiDeviceJNI"
 #define LOG_NDEBUG 0
-#include "utils/Log.h"
-
-#include "jni.h"
-#include <nativehelper/JNIPlatformHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/Log.h"
-
 #include <asm/byteorder.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <nativehelper/JNIPlatformHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
 #include <sound/asound.h>
 #include <stdio.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
-namespace android
-{
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
+#include "jni.h"
+#include "utils/Log.h"
+
+namespace android {
 
 static jclass sFileDescriptorClass;
 static jfieldID sPipeFDField;
@@ -46,10 +44,10 @@
 // 1. Input O_RDONLY file descriptor
 // 2. Special input file descriptor to block the input thread
 // 3. Output O_WRONLY file descriptor
-static jobjectArray android_server_UsbMidiDevice_open(JNIEnv *env, jobject thiz, jint card,
-                                                      jint device, jint numInputs,
-                                                      jint numOutputs) {
-    char    path[100];
+static jobjectArray android_server_UsbAlsaMidiDevice_open(JNIEnv *env, jobject thiz, jint card,
+                                                          jint device, jint numInputs,
+                                                          jint numOutputs) {
+    char path[100];
     int fd;
 
     snprintf(path, sizeof(path), "/dev/snd/midiC%dD%d", card, device);
@@ -126,9 +124,7 @@
     return NULL;
 }
 
-static void
-android_server_UsbMidiDevice_close(JNIEnv *env, jobject thiz, jobjectArray fds)
-{
+static void android_server_UsbAlsaMidiDevice_close(JNIEnv *env, jobject thiz, jobjectArray fds) {
     // write to mPipeFD to unblock input thread
     jint pipeFD = env->GetIntField(thiz, sPipeFDField);
     write(pipeFD, &pipeFD, sizeof(pipeFD));
@@ -144,12 +140,12 @@
 
 static JNINativeMethod method_table[] = {
         {"nativeOpen", "(IIII)[Ljava/io/FileDescriptor;",
-         (void *)android_server_UsbMidiDevice_open},
-        {"nativeClose", "([Ljava/io/FileDescriptor;)V", (void *)android_server_UsbMidiDevice_close},
+         (void *)android_server_UsbAlsaMidiDevice_open},
+        {"nativeClose", "([Ljava/io/FileDescriptor;)V",
+         (void *)android_server_UsbAlsaMidiDevice_close},
 };
 
-int register_android_server_UsbMidiDevice(JNIEnv *env)
-{
+int register_android_server_UsbAlsaMidiDevice(JNIEnv *env) {
     jclass clazz = env->FindClass("java/io/FileDescriptor");
     if (clazz == NULL) {
         ALOGE("Can't find java/io/FileDescriptor");
@@ -157,19 +153,19 @@
     }
     sFileDescriptorClass = (jclass)env->NewGlobalRef(clazz);
 
-    clazz = env->FindClass("com/android/server/usb/UsbMidiDevice");
+    clazz = env->FindClass("com/android/server/usb/UsbAlsaMidiDevice");
     if (clazz == NULL) {
-        ALOGE("Can't find com/android/server/usb/UsbMidiDevice");
+        ALOGE("Can't find com/android/server/usb/UsbAlsaMidiDevice");
         return -1;
     }
     sPipeFDField = env->GetFieldID(clazz, "mPipeFD", "I");
     if (sPipeFDField == NULL) {
-        ALOGE("Can't find UsbMidiDevice.mPipeFD");
+        ALOGE("Can't find UsbAlsaMidiDevice.mPipeFD");
         return -1;
     }
 
-    return jniRegisterNativeMethods(env, "com/android/server/usb/UsbMidiDevice",
-            method_table, NELEM(method_table));
+    return jniRegisterNativeMethods(env, "com/android/server/usb/UsbAlsaMidiDevice", method_table,
+                                    NELEM(method_table));
 }
 
-};
+}; // namespace android
diff --git a/services/core/jni/com_android_server_companion_virtual_InputController.cpp b/services/core/jni/com_android_server_companion_virtual_InputController.cpp
index 4cb7a8f..dd757bc 100644
--- a/services/core/jni/com_android_server_companion_virtual_InputController.cpp
+++ b/services/core/jni/com_android_server_companion_virtual_InputController.cpp
@@ -29,8 +29,17 @@
 #include <utils/Log.h>
 
 #include <map>
+#include <set>
 #include <string>
 
+/**
+ * Log debug messages about native virtual input devices.
+ * Enable this via "adb shell setprop log.tag.InputController DEBUG"
+ */
+static bool isDebug() {
+    return __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO);
+}
+
 namespace android {
 
 enum class DeviceType {
@@ -194,6 +203,15 @@
         {AKEYCODE_NUMPAD_COMMA, KEY_KPCOMMA},
 };
 
+/*
+ * Map from the uinput touchscreen fd to the pointers present in the previous touch events that
+ * hasn't been lifted.
+ * We only allow pointer id to go up to MAX_POINTERS because the maximum slots of virtual
+ * touchscreen is set up with MAX_POINTERS. Note that in other cases Android allows pointer id to go
+ * up to MAX_POINTERS_ID.
+ */
+static std::map<int32_t, std::bitset<MAX_POINTERS>> unreleasedTouches;
+
 /** Creates a new uinput device and assigns a file descriptor. */
 static int openUinput(const char* readableName, jint vendorId, jint productId, const char* phys,
                       DeviceType deviceType, jint screenHeight, jint screenWidth) {
@@ -366,6 +384,12 @@
 
 static bool nativeCloseUinput(JNIEnv* env, jobject thiz, jint fd) {
     ioctl(fd, UI_DEV_DESTROY);
+    if (auto touchesOnFd = unreleasedTouches.find(fd); touchesOnFd != unreleasedTouches.end()) {
+        const size_t remainingPointers = touchesOnFd->second.size();
+        unreleasedTouches.erase(touchesOnFd);
+        ALOGW_IF(remainingPointers > 0, "Closing touchscreen %d, erased %zu unreleased pointers.",
+                 fd, remainingPointers);
+    }
     return close(fd);
 }
 
@@ -425,6 +449,69 @@
     return true;
 }
 
+static bool handleTouchUp(int fd, int pointerId) {
+    if (!writeInputEvent(fd, EV_ABS, ABS_MT_TRACKING_ID, static_cast<int32_t>(-1))) {
+        return false;
+    }
+    auto touchesOnFd = unreleasedTouches.find(fd);
+    if (touchesOnFd == unreleasedTouches.end()) {
+        ALOGE("PointerId %d action UP received with no prior events on touchscreen %d.", pointerId,
+              fd);
+        return false;
+    }
+    ALOGD_IF(isDebug(), "Unreleased touches found for touchscreen %d in the map", fd);
+
+    // When a pointer is no longer in touch, remove the pointer id from the corresponding
+    // entry in the unreleased touches map.
+    if (pointerId < 0 || pointerId >= MAX_POINTERS) {
+        ALOGE("Virtual touch event has invalid pointer id %d; value must be between 0 and %zu",
+              pointerId, MAX_POINTERS - 1);
+        return false;
+    }
+    if (!touchesOnFd->second.test(pointerId)) {
+        ALOGE("PointerId %d action UP received with no prior action DOWN on touchscreen %d.",
+              pointerId, fd);
+        return false;
+    }
+    touchesOnFd->second.reset(pointerId);
+    ALOGD_IF(isDebug(), "Pointer %d erased from the touchscreen %d", pointerId, fd);
+
+    // Only sends the BTN UP event when there's no pointers on the touchscreen.
+    if (touchesOnFd->second.none()) {
+        unreleasedTouches.erase(touchesOnFd);
+        if (!writeInputEvent(fd, EV_KEY, BTN_TOUCH, static_cast<int32_t>(UinputAction::RELEASE))) {
+            return false;
+        }
+        ALOGD_IF(isDebug(), "No pointers on touchscreen %d, BTN UP event sent.", fd);
+    }
+    return true;
+}
+
+static bool handleTouchDown(int fd, int pointerId) {
+    // When a new pointer is down on the touchscreen, add the pointer id in the corresponding
+    // entry in the unreleased touches map.
+    auto touchesOnFd = unreleasedTouches.find(fd);
+    if (touchesOnFd == unreleasedTouches.end()) {
+        // Only sends the BTN Down event when the first pointer on the touchscreen is down.
+        if (!writeInputEvent(fd, EV_KEY, BTN_TOUCH, static_cast<int32_t>(UinputAction::PRESS))) {
+            return false;
+        }
+        touchesOnFd = unreleasedTouches.insert({fd, {}}).first;
+        ALOGD_IF(isDebug(), "New touchscreen with fd %d added in the unreleased touches map.", fd);
+    }
+    if (touchesOnFd->second.test(pointerId)) {
+        ALOGE("Repetitive action DOWN event received on a pointer %d that is already down.",
+              pointerId);
+        return false;
+    }
+    touchesOnFd->second.set(pointerId);
+    ALOGD_IF(isDebug(), "Added pointer %d under touchscreen %d in the map", pointerId, fd);
+    if (!writeInputEvent(fd, EV_ABS, ABS_MT_TRACKING_ID, static_cast<int32_t>(pointerId))) {
+        return false;
+    }
+    return true;
+}
+
 static bool nativeWriteTouchEvent(JNIEnv* env, jobject thiz, jint fd, jint pointerId, jint toolType,
                                   jint action, jfloat locationX, jfloat locationY, jfloat pressure,
                                   jfloat majorAxisSize) {
@@ -446,15 +533,10 @@
         return false;
     }
     UinputAction uinputAction = actionIterator->second;
-    if (uinputAction == UinputAction::PRESS || uinputAction == UinputAction::RELEASE) {
-        if (!writeInputEvent(fd, EV_KEY, BTN_TOUCH, static_cast<int32_t>(uinputAction))) {
-            return false;
-        }
-        if (!writeInputEvent(fd, EV_ABS, ABS_MT_TRACKING_ID,
-                             static_cast<int32_t>(uinputAction == UinputAction::PRESS ? pointerId
-                                                                                      : -1))) {
-            return false;
-        }
+    if (uinputAction == UinputAction::PRESS && !handleTouchDown(fd, pointerId)) {
+        return false;
+    } else if (uinputAction == UinputAction::RELEASE && !handleTouchUp(fd, pointerId)) {
+        return false;
     }
     if (!writeInputEvent(fd, EV_ABS, ABS_MT_POSITION_X, locationX)) {
         return false;
diff --git a/services/core/jni/com_android_server_display_DisplayControl.cpp b/services/core/jni/com_android_server_display_DisplayControl.cpp
index ec42324..db7fced 100644
--- a/services/core/jni/com_android_server_display_DisplayControl.cpp
+++ b/services/core/jni/com_android_server_display_DisplayControl.cpp
@@ -23,9 +23,11 @@
 
 namespace android {
 
-static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj, jboolean secure) {
+static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj, jboolean secure,
+                                   jfloat requestedRefreshRate) {
     ScopedUtfChars name(env, nameObj);
-    sp<IBinder> token(SurfaceComposerClient::createDisplay(String8(name.c_str()), bool(secure)));
+    sp<IBinder> token(SurfaceComposerClient::createDisplay(String8(name.c_str()), bool(secure),
+                                                           requestedRefreshRate));
     return javaObjectForIBinder(env, token);
 }
 
@@ -134,7 +136,7 @@
 
 static const JNINativeMethod sDisplayMethods[] = {
         // clang-format off
-    {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
+    {"nativeCreateDisplay", "(Ljava/lang/String;ZF)Landroid/os/IBinder;",
             (void*)nativeCreateDisplay },
     {"nativeDestroyDisplay", "(Landroid/os/IBinder;)V",
             (void*)nativeDestroyDisplay },
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index f4d1d1e..b4e2fb6 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -137,6 +137,7 @@
     jmethodID notifyDropWindow;
     jmethodID getParentSurfaceForPointers;
     jmethodID isPerDisplayTouchModeEnabled;
+    jmethodID isStylusPointerIconEnabled;
 } gServiceClassInfo;
 
 static struct {
@@ -363,6 +364,7 @@
             std::map<PointerIconStyle, SpriteIcon>* outResources,
             std::map<PointerIconStyle, PointerAnimation>* outAnimationResources, int32_t displayId);
     virtual PointerIconStyle getDefaultPointerIconId();
+    virtual PointerIconStyle getDefaultStylusIconId();
     virtual PointerIconStyle getCustomPointerIconId();
     virtual void onPointerDisplayIdChanged(int32_t displayId, float xPos, float yPos);
 
@@ -659,6 +661,12 @@
         outConfig->pointerGestureTapSlop = hoverTapSlop;
     }
 
+    jboolean stylusPointerIconEnabled =
+            env->CallBooleanMethod(mServiceObj, gServiceClassInfo.isStylusPointerIconEnabled);
+    if (!checkAndClearExceptionFromCallback(env, "isStylusPointerIconEnabled")) {
+        outConfig->stylusPointerIconEnabled = stylusPointerIconEnabled;
+    }
+
     { // acquire lock
         AutoMutex _l(mLock);
 
@@ -1605,6 +1613,11 @@
     return PointerIconStyle::TYPE_ARROW;
 }
 
+PointerIconStyle NativeInputManager::getDefaultStylusIconId() {
+    // TODO: add resource for default stylus icon and change this
+    return PointerIconStyle::TYPE_CROSSHAIR;
+}
+
 PointerIconStyle NativeInputManager::getCustomPointerIconId() {
     return PointerIconStyle::TYPE_CUSTOM;
 }
@@ -2787,6 +2800,9 @@
     GET_METHOD_ID(gServiceClassInfo.isPerDisplayTouchModeEnabled, clazz,
                   "isPerDisplayTouchModeEnabled", "()Z");
 
+    GET_METHOD_ID(gServiceClassInfo.isStylusPointerIconEnabled, clazz, "isStylusPointerIconEnabled",
+                  "()Z");
+
     // InputDevice
 
     FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 00f851f..290ad8d 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -35,8 +35,8 @@
 int register_android_server_SerialService(JNIEnv* env);
 int register_android_server_SystemServer(JNIEnv* env);
 int register_android_server_UsbAlsaJackDetector(JNIEnv* env);
+int register_android_server_UsbAlsaMidiDevice(JNIEnv* env);
 int register_android_server_UsbDeviceManager(JNIEnv* env);
-int register_android_server_UsbMidiDevice(JNIEnv* env);
 int register_android_server_UsbHostManager(JNIEnv* env);
 int register_android_server_vr_VrManagerService(JNIEnv* env);
 int register_android_server_vibrator_VibratorController(JavaVM* vm, JNIEnv* env);
@@ -90,8 +90,8 @@
     register_android_server_InputManager(env);
     register_android_server_LightsService(env);
     register_android_server_UsbDeviceManager(env);
-    register_android_server_UsbMidiDevice(env);
     register_android_server_UsbAlsaJackDetector(env);
+    register_android_server_UsbAlsaMidiDevice(env);
     register_android_server_UsbHostManager(env);
     register_android_server_vr_VrManagerService(env);
     register_android_server_vibrator_VibratorController(vm, env);
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 97dbe04..ef5aa60 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -208,11 +208,7 @@
 
     <xs:complexType name="thermalThrottling">
         <xs:sequence>
-            <xs:element type="brightnessThrottlingMap" name="brightnessThrottlingMap">
-                <xs:annotation name="nonnull"/>
-                <xs:annotation name="final"/>
-            </xs:element>
-            <xs:element type="brightnessThrottlingMap" name="concurrentDisplaysBrightnessThrottlingMap">
+            <xs:element type="brightnessThrottlingMap" name="brightnessThrottlingMap" maxOccurs="unbounded">
                 <xs:annotation name="final"/>
             </xs:element>
         </xs:sequence>
@@ -225,6 +221,7 @@
                 <xs:annotation name="final"/>
             </xs:element>
         </xs:sequence>
+        <xs:attribute name="id" type="xs:string"/>
     </xs:complexType>
 
     <xs:complexType name="brightnessThrottlingPoint">
@@ -472,6 +469,18 @@
     </xs:complexType>
 
     <xs:complexType name="refreshRateConfigs">
+        <xs:element name="defaultRefreshRate" type="xs:nonNegativeInteger"
+                    minOccurs="0" maxOccurs="1">
+            <xs:annotation name="final"/>
+        </xs:element>
+        <xs:element name="defaultPeakRefreshRate" type="xs:nonNegativeInteger"
+                    minOccurs="0" maxOccurs="1">
+            <xs:annotation name="final"/>
+        </xs:element>
+        <xs:element name="refreshRateZoneProfiles" type="refreshRateZoneProfiles"
+                    minOccurs="0" maxOccurs="1">
+            <xs:annotation name="final"/>
+        </xs:element>
         <xs:element name="lowerBlockingZoneConfigs" type="blockingZoneConfig"
                     minOccurs="0" maxOccurs="1">
             <xs:annotation name="final"/>
@@ -482,6 +491,22 @@
         </xs:element>
     </xs:complexType>
 
+    <xs:complexType name="refreshRateZoneProfiles">
+        <xs:sequence>
+            <xs:element name="refreshRateZoneProfile" type="refreshRateZone"
+                        minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="refreshRateZone">
+        <xs:attribute name="id" use="required" type="xs:string" />
+        <xs:element name="refreshRateRange" type="refreshRateRange">
+            <xs:annotation name="final"/>
+        </xs:element>
+    </xs:complexType>
+
     <xs:complexType name="blockingZoneConfig">
         <xs:element name="defaultRefreshRate" type="xs:nonNegativeInteger"
                     minOccurs="1" maxOccurs="1">
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index aba8a2c..ed9f959 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -37,6 +37,8 @@
   public class BrightnessThrottlingMap {
     ctor public BrightnessThrottlingMap();
     method @NonNull public final java.util.List<com.android.server.display.config.BrightnessThrottlingPoint> getBrightnessThrottlingPoint();
+    method public String getId();
+    method public void setId(String);
   }
 
   public class BrightnessThrottlingPoint {
@@ -188,10 +190,16 @@
 
   public class RefreshRateConfigs {
     ctor public RefreshRateConfigs();
+    method public final java.math.BigInteger getDefaultPeakRefreshRate();
+    method public final java.math.BigInteger getDefaultRefreshRate();
     method public final com.android.server.display.config.BlockingZoneConfig getHigherBlockingZoneConfigs();
     method public final com.android.server.display.config.BlockingZoneConfig getLowerBlockingZoneConfigs();
+    method public final com.android.server.display.config.RefreshRateZoneProfiles getRefreshRateZoneProfiles();
+    method public final void setDefaultPeakRefreshRate(java.math.BigInteger);
+    method public final void setDefaultRefreshRate(java.math.BigInteger);
     method public final void setHigherBlockingZoneConfigs(com.android.server.display.config.BlockingZoneConfig);
     method public final void setLowerBlockingZoneConfigs(com.android.server.display.config.BlockingZoneConfig);
+    method public final void setRefreshRateZoneProfiles(com.android.server.display.config.RefreshRateZoneProfiles);
   }
 
   public class RefreshRateRange {
@@ -202,6 +210,19 @@
     method public final void setMinimum(java.math.BigInteger);
   }
 
+  public class RefreshRateZone {
+    ctor public RefreshRateZone();
+    method public String getId();
+    method public final com.android.server.display.config.RefreshRateRange getRefreshRateRange();
+    method public void setId(String);
+    method public final void setRefreshRateRange(com.android.server.display.config.RefreshRateRange);
+  }
+
+  public class RefreshRateZoneProfiles {
+    ctor public RefreshRateZoneProfiles();
+    method public final java.util.List<com.android.server.display.config.RefreshRateZone> getRefreshRateZoneProfile();
+  }
+
   public class SdrHdrRatioMap {
     ctor public SdrHdrRatioMap();
     method @NonNull public final java.util.List<com.android.server.display.config.SdrHdrRatioPoint> getPoint();
@@ -238,10 +259,7 @@
 
   public class ThermalThrottling {
     ctor public ThermalThrottling();
-    method @NonNull public final com.android.server.display.config.BrightnessThrottlingMap getBrightnessThrottlingMap();
-    method public final com.android.server.display.config.BrightnessThrottlingMap getConcurrentDisplaysBrightnessThrottlingMap();
-    method public final void setBrightnessThrottlingMap(@NonNull com.android.server.display.config.BrightnessThrottlingMap);
-    method public final void setConcurrentDisplaysBrightnessThrottlingMap(com.android.server.display.config.BrightnessThrottlingMap);
+    method public final java.util.List<com.android.server.display.config.BrightnessThrottlingMap> getBrightnessThrottlingMap();
   }
 
   public class ThresholdPoint {
diff --git a/services/core/xsd/display-layout-config/display-layout-config.xsd b/services/core/xsd/display-layout-config/display-layout-config.xsd
index 842d97a..45e10a8 100644
--- a/services/core/xsd/display-layout-config/display-layout-config.xsd
+++ b/services/core/xsd/display-layout-config/display-layout-config.xsd
@@ -51,8 +51,10 @@
         <xs:sequence>
             <xs:element name="address" type="xs:nonNegativeInteger"/>
             <xs:element name="position" type="xs:string" minOccurs="0" maxOccurs="1" />
+            <xs:element name="brightnessThrottlingMapId" type="xs:string" minOccurs="0" maxOccurs="1" />
         </xs:sequence>
         <xs:attribute name="enabled" type="xs:boolean" use="optional" />
         <xs:attribute name="defaultDisplay" type="xs:boolean" use="optional" />
+        <xs:attribute name="refreshRateZoneId" type="xs:string" use="optional" />
     </xs:complexType>
 </xs:schema>
diff --git a/services/core/xsd/display-layout-config/schema/current.txt b/services/core/xsd/display-layout-config/schema/current.txt
index 55f866c..2c16c37 100644
--- a/services/core/xsd/display-layout-config/schema/current.txt
+++ b/services/core/xsd/display-layout-config/schema/current.txt
@@ -4,13 +4,17 @@
   public class Display {
     ctor public Display();
     method public java.math.BigInteger getAddress();
+    method public String getBrightnessThrottlingMapId();
     method public String getPosition();
+    method public String getRefreshRateZoneId();
     method public boolean isDefaultDisplay();
     method public boolean isEnabled();
     method public void setAddress(java.math.BigInteger);
+    method public void setBrightnessThrottlingMapId(String);
     method public void setDefaultDisplay(boolean);
     method public void setEnabled(boolean);
     method public void setPosition(String);
+    method public void setRefreshRateZoneId(String);
   }
 
   public class Layout {
diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
index be60946..447c67f 100644
--- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
@@ -23,6 +23,7 @@
 import android.credentials.IClearCredentialStateCallback;
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.RequestInfo;
+import android.os.CancellationSignal;
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.CredentialProviderInfo;
@@ -41,9 +42,9 @@
 
     public ClearRequestSession(Context context, int userId, int callingUid,
             IClearCredentialStateCallback callback, ClearCredentialStateRequest request,
-            CallingAppInfo callingAppInfo) {
+            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
         super(context, userId, callingUid, request, callback, RequestInfo.TYPE_UNDEFINED,
-                callingAppInfo);
+                callingAppInfo, cancellationSignal);
     }
 
     /**
@@ -111,6 +112,12 @@
 
     private void respondToClientWithResponseAndFinish() {
         Log.i(TAG, "respondToClientWithResponseAndFinish");
+        if (isSessionCancelled()) {
+            // TODO: Differentiate btw cancelled and false
+            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+            finishSession(/*propagateCancellation=*/true);
+            return;
+        }
         try {
             mClientCallback.onSuccess();
             logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
@@ -118,18 +125,24 @@
             Log.i(TAG, "Issue while propagating the response to the client");
             logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
         }
-        finishSession();
+        finishSession(/*propagateCancellation=*/false);
     }
 
     private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
         Log.i(TAG, "respondToClientWithErrorAndFinish");
+        if (isSessionCancelled()) {
+            // TODO: Differentiate btw cancelled and false
+            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+            finishSession(/*propagateCancellation=*/true);
+            return;
+        }
         try {
             mClientCallback.onError(errorType, errorMsg);
         } catch (RemoteException e) {
             e.printStackTrace();
         }
         logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
-        finishSession();
+        finishSession(/*propagateCancellation=*/false);
     }
 
     private void processResponses() {
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 351afb9..2345e3f 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -27,6 +27,7 @@
 import android.credentials.ICreateCredentialCallback;
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.RequestInfo;
+import android.os.CancellationSignal;
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.CredentialProviderInfo;
@@ -47,9 +48,10 @@
     CreateRequestSession(@NonNull Context context, int userId, int callingUid,
             CreateCredentialRequest request,
             ICreateCredentialCallback callback,
-            CallingAppInfo callingAppInfo) {
+            CallingAppInfo callingAppInfo,
+            CancellationSignal cancellationSignal) {
         super(context, userId, callingUid, request, callback, RequestInfo.TYPE_CREATE,
-                callingAppInfo);
+                callingAppInfo, cancellationSignal);
     }
 
     /**
@@ -119,6 +121,12 @@
 
     private void respondToClientWithResponseAndFinish(CreateCredentialResponse response) {
         Log.i(TAG, "respondToClientWithResponseAndFinish");
+        if (isSessionCancelled()) {
+            // TODO: Differentiate btw cancelled and false
+            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+            finishSession(/*propagateCancellation=*/true);
+            return;
+        }
         try {
             mClientCallback.onResponse(response);
             logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
@@ -126,18 +134,24 @@
             Log.i(TAG, "Issue while responding to client: " + e.getMessage());
             logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
         }
-        finishSession();
+        finishSession(/*propagateCancellation=*/false);
     }
 
     private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
         Log.i(TAG, "respondToClientWithErrorAndFinish");
+        if (isSessionCancelled()) {
+            // TODO: Differentiate btw cancelled and false
+            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+            finishSession(/*propagateCancellation=*/true);
+            return;
+        }
         try {
             mClientCallback.onError(errorType, errorMsg);
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client: " + e.getMessage());
         }
         logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
-        finishSession();
+        finishSession(/*propagateCancellation=*/false);
     }
 
     @Override
diff --git a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
index fbdcc44..3d504ef 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
@@ -19,35 +19,72 @@
 import android.credentials.CredentialDescription;
 import android.credentials.RegisterCredentialDescriptionRequest;
 import android.credentials.UnregisterCredentialDescriptionRequest;
+import android.service.credentials.CredentialEntry;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
 
 /** Contains information on what CredentialProvider has what provisioned Credential. */
-public class CredentialDescriptionRegistry {
+public final class CredentialDescriptionRegistry {
 
     private static final int MAX_ALLOWED_CREDENTIAL_DESCRIPTIONS = 128;
     private static final int MAX_ALLOWED_ENTRIES_PER_PROVIDER = 16;
-    private static SparseArray<CredentialDescriptionRegistry> sCredentialDescriptionSessionPerUser;
+    @GuardedBy("sLock")
+    private static final SparseArray<CredentialDescriptionRegistry>
+            sCredentialDescriptionSessionPerUser;
+    private static final ReentrantLock sLock;
 
     static {
         sCredentialDescriptionSessionPerUser = new SparseArray<>();
+        sLock = new ReentrantLock();
     }
 
-    // TODO(b/265992655): add a way to update CredentialRegistry when a user is removed.
-    /** Get and/or create a {@link  CredentialDescription} for the given user id. */
-    public static CredentialDescriptionRegistry forUser(int userId) {
-        CredentialDescriptionRegistry session =
-                sCredentialDescriptionSessionPerUser.get(userId, null);
+    /** Represents the results of a given query into the registry. */
+    public static final class FilterResult {
+        final String mPackageName;
+        final List<CredentialEntry> mCredentialEntries;
 
-        if (session == null) {
-            session = new CredentialDescriptionRegistry();
-            sCredentialDescriptionSessionPerUser.put(userId, session);
+        private FilterResult(String packageName,
+                List<CredentialEntry> credentialEntries) {
+            mPackageName = packageName;
+            mCredentialEntries = credentialEntries;
         }
-        return session;
+    }
+
+    /** Get and/or create a {@link  CredentialDescription} for the given user id. */
+    @GuardedBy("sLock")
+    public static CredentialDescriptionRegistry forUser(int userId) {
+        sLock.lock();
+        try {
+            CredentialDescriptionRegistry session =
+                    sCredentialDescriptionSessionPerUser.get(userId, null);
+
+            if (session == null) {
+                session = new CredentialDescriptionRegistry();
+                sCredentialDescriptionSessionPerUser.put(userId, session);
+            }
+            return session;
+        } finally {
+            sLock.unlock();
+        }
+    }
+
+    /** Clears an existing session for a given user identifier. */
+    @GuardedBy("sLock")
+    public static void clearUserSession(int userId) {
+        sLock.lock();
+        try {
+            sCredentialDescriptionSessionPerUser.remove(userId);
+        } finally {
+            sLock.unlock();
+        }
     }
 
     private Map<String, Set<CredentialDescription>> mCredentialDescriptions;
@@ -74,7 +111,7 @@
             int size = mCredentialDescriptions.get(callingPackageName).size();
             mCredentialDescriptions.get(callingPackageName)
                     .addAll(descriptions);
-            mTotalDescriptionCount += size - mCredentialDescriptions.get(callingPackageName).size();
+            mTotalDescriptionCount += mCredentialDescriptions.get(callingPackageName).size() - size;
         }
 
     }
@@ -93,21 +130,33 @@
         }
     }
 
+    /** Returns package names and entries of a CredentialProviders that can satisfy a given
+     * {@link CredentialDescription}. */
+    public Set<FilterResult> getFilteredResultForProvider(String packageName,
+            List<String> flatRequestStrings) {
+        Set<FilterResult> result = new HashSet<>();
+        Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
+        for (CredentialDescription containedDescription: currentSet) {
+            if (flatRequestStrings.contains(containedDescription.getFlattenedRequestString())) {
+                result.add(new FilterResult(packageName, containedDescription
+                        .getCredentialEntries()));
+            }
+        }
+        return result;
+    }
+
     /** Returns package names of CredentialProviders that can satisfy a given
      * {@link CredentialDescription}. */
-    public Set<String> filterCredentials(String flatRequestString) {
-
+    public Set<String> getMatchingProviders(Set<String> flatRequestString) {
         Set<String> result = new HashSet<>();
-
-        for (String componentName: mCredentialDescriptions.keySet()) {
-            Set<CredentialDescription> currentSet = mCredentialDescriptions.get(componentName);
-            for (CredentialDescription containedDescription: currentSet) {
-                if (flatRequestString.equals(containedDescription.getFlattenedRequestString())) {
-                    result.add(componentName);
+        for (String packageName: mCredentialDescriptions.keySet()) {
+            Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
+            for (CredentialDescription containedDescription : currentSet) {
+                if (flatRequestString.contains(containedDescription.getFlattenedRequestString())) {
+                    result.add(packageName);
                 }
             }
         }
-
         return result;
     }
 
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index bb26fa9..6857239 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.credentials;
 
 import static android.content.Context.CREDENTIAL_SERVICE;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
@@ -29,8 +30,8 @@
 import android.credentials.CreateCredentialException;
 import android.credentials.CreateCredentialRequest;
 import android.credentials.CredentialDescription;
+import android.credentials.CredentialOption;
 import android.credentials.GetCredentialException;
-import android.credentials.GetCredentialOption;
 import android.credentials.GetCredentialRequest;
 import android.credentials.IClearCredentialStateCallback;
 import android.credentials.ICreateCredentialCallback;
@@ -49,8 +50,6 @@
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
-import android.service.credentials.BeginCreateCredentialRequest;
-import android.service.credentials.BeginGetCredentialRequest;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.CredentialProviderInfo;
 import android.text.TextUtils;
@@ -63,13 +62,11 @@
 import com.android.server.infra.SecureSettingsServiceNameResolver;
 
 import java.util.ArrayList;
-import java.util.Collection;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.function.Consumer;
-import java.util.function.Function;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  * Entry point service for credential management.
@@ -85,17 +82,17 @@
     private static final String TAG = "CredManSysService";
     private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
             "enable_credential_description_api";
+    private static final String PERMISSION_DENIED_ERROR = "permission_denied";
+    private static final String PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR =
+            "Caller is missing WRITE_SECURE_SETTINGS permission";
 
     private final Context mContext;
 
-    /**
-     * Cache of system service list per user id.
-     */
+    /** Cache of system service list per user id. */
     @GuardedBy("mLock")
     private final SparseArray<List<CredentialManagerServiceImpl>> mSystemServicesCacheList =
             new SparseArray<>();
 
-
     public CredentialManagerService(@NonNull Context context) {
         super(
                 context,
@@ -113,9 +110,11 @@
         List<CredentialManagerServiceImpl> services = new ArrayList<>();
         List<CredentialProviderInfo> credentialProviderInfos =
                 CredentialProviderInfo.getAvailableSystemServices(mContext, resolvedUserId);
-        credentialProviderInfos.forEach(info -> {
-            services.add(new CredentialManagerServiceImpl(this, mLock, resolvedUserId, info));
-        });
+        credentialProviderInfos.forEach(
+                info -> {
+                    services.add(
+                            new CredentialManagerServiceImpl(this, mLock, resolvedUserId, info));
+                });
         return services;
     }
 
@@ -178,10 +177,9 @@
         CredentialManagerServiceImpl serviceToBeRemoved = null;
         for (CredentialManagerServiceImpl service : services) {
             if (service != null) {
-                CredentialProviderInfo credentialProviderInfo =
-                        service.getCredentialProviderInfo();
-                ComponentName componentName = credentialProviderInfo.getServiceInfo()
-                        .getComponentName();
+                CredentialProviderInfo credentialProviderInfo = service.getCredentialProviderInfo();
+                ComponentName componentName =
+                        credentialProviderInfo.getServiceInfo().getComponentName();
                 if (packageName.equals(componentName.getPackageName())) {
                     serviceToBeRemoved = service;
                     removeServiceFromMultiModeSettings(componentName.flattenToString(), userId);
@@ -197,8 +195,6 @@
         // TODO("Iterate over system services and remove if needed")
     }
 
-
-
     @GuardedBy("mLock")
     private List<CredentialManagerServiceImpl> getOrConstructSystemServiceListLock(
             int resolvedUserId) {
@@ -210,6 +206,16 @@
         return services;
     }
 
+    private boolean hasWriteSecureSettingsPermission() {
+        final String permission = android.Manifest.permission.WRITE_SECURE_SETTINGS;
+        final boolean result =
+                mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED;
+        if (!result) {
+            Slog.e(TAG, "Caller does not have WRITE_SECURE_SETTINGS permission.");
+        }
+        return result;
+    }
+
     private void runForUser(@NonNull final Consumer<CredentialManagerServiceImpl> c) {
         final int userId = UserHandle.getCallingUserId();
         final long origId = Binder.clearCallingIdentity();
@@ -227,8 +233,7 @@
     }
 
     @GuardedBy("mLock")
-    private List<CredentialManagerServiceImpl> getAllCredentialProviderServicesLocked(
-            int userId) {
+    private List<CredentialManagerServiceImpl> getAllCredentialProviderServicesLocked(int userId) {
         List<CredentialManagerServiceImpl> concatenatedServices = new ArrayList<>();
         List<CredentialManagerServiceImpl> userConfigurableServices =
                 getServiceListForUserLocked(userId);
@@ -238,6 +243,7 @@
         concatenatedServices.addAll(getOrConstructSystemServiceListLock(userId));
         return concatenatedServices;
     }
+
     public static boolean isCredentialDescriptionApiEnabled() {
         return DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API, false);
@@ -246,44 +252,41 @@
     @SuppressWarnings("GuardedBy") // ErrorProne requires initiateProviderSessionForRequestLocked
     // to be guarded by 'service.mLock', which is the same as mLock.
     private List<ProviderSession> initiateProviderSessionsWithActiveContainers(
-            RequestSession session,
-            List<String> requestOptions, Set<ComponentName> activeCredentialContainers) {
+            GetRequestSession session,
+            List<String> requestOptions,
+            Set<String> activeCredentialContainers) {
         List<ProviderSession> providerSessions = new ArrayList<>();
         // Invoke all services of a user to initiate a provider session
-        runForUser((service) -> {
-            if (activeCredentialContainers.contains(service.getComponentName())) {
-                ProviderSession providerSession = service
-                        .initiateProviderSessionForRequestLocked(session, requestOptions);
-                if (providerSession != null) {
-                    providerSessions.add(providerSession);
-                }
-            }
-        });
+        for (String packageName : activeCredentialContainers) {
+            providerSessions.add(
+                    ProviderRegistryGetSession.createNewSession(
+                            mContext,
+                            UserHandle.getCallingUserId(),
+                            session,
+                            packageName,
+                            requestOptions));
+        }
         return providerSessions;
     }
 
     @NonNull
-    private Set<String> getMatchingProviders(GetCredentialRequest request) {
+    private Set<String> getFilteredResultFromRegistry(List<CredentialOption> options) {
         // Session for active/provisioned credential descriptions;
-        CredentialDescriptionRegistry registry = CredentialDescriptionRegistry
-                .forUser(UserHandle.getCallingUserId());
+        CredentialDescriptionRegistry registry =
+                CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
 
         // All requested credential descriptions based on the given request.
         Set<String> requestedCredentialDescriptions =
-                request.getGetCredentialOptions().stream().map(
-                        getCredentialOption -> getCredentialOption
-                                        .getCredentialRetrievalData()
-                                        .getString(GetCredentialOption
-                                                .FLATTENED_REQUEST))
+                options.stream()
+                        .map(
+                                getCredentialOption ->
+                                        getCredentialOption
+                                                .getCredentialRetrievalData()
+                                                .getString(CredentialOption.FLATTENED_REQUEST))
                         .collect(Collectors.toSet());
 
         // All requested credential descriptions based on the given request.
-        return requestedCredentialDescriptions.stream()
-                .map(registry::filterCredentials)
-                .flatMap(
-                        (Function<Set<String>, Stream<String>>)
-                                Collection::stream)
-                .collect(Collectors.toSet());
+        return registry.getMatchingProviders(requestedCredentialDescriptions);
     }
 
     @SuppressWarnings("GuardedBy") // ErrorProne requires initiateProviderSessionForRequestLocked
@@ -306,13 +309,24 @@
         return providerSessions;
     }
 
+    @Override
+    @GuardedBy("CredentialDescriptionRegistry.sLock")
+    public void onUserStopped(@NonNull TargetUser user) {
+        super.onUserStopped(user);
+        CredentialDescriptionRegistry.clearUserSession(user.getUserIdentifier());
+    }
+
     private CallingAppInfo constructCallingAppInfo(String packageName, int userId) {
         final PackageInfo packageInfo;
         try {
-            packageInfo = getContext().getPackageManager().getPackageInfoAsUser(
-                    packageName,
-                    PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNING_CERTIFICATES),
-                    userId);
+            packageInfo =
+                    getContext()
+                            .getPackageManager()
+                            .getPackageInfoAsUser(
+                                    packageName,
+                                    PackageManager.PackageInfoFlags.of(
+                                            PackageManager.GET_SIGNING_CERTIFICATES),
+                                    userId);
         } catch (PackageManager.NameNotFoundException e) {
             Log.i(TAG, "Issue while retrieving signatureInfo : " + e.getMessage());
             return new CallingAppInfo(packageName, null);
@@ -327,11 +341,12 @@
                 IGetCredentialCallback callback,
                 final String callingPackage) {
             Log.i(TAG, "starting executeGetCredential with callingPackage: " + callingPackage);
-            // TODO : Implement cancellation
             ICancellationSignal cancelTransport = CancellationSignal.createTransport();
 
-            int userId = UserHandle.getCallingUserId();
-            int callingUid = Binder.getCallingUid();
+            final int userId = UserHandle.getCallingUserId();
+            final int callingUid = Binder.getCallingUid();
+            enforceCallingPackage(callingPackage, callingUid);
+
             // New request session, scoped for this request only.
             final GetRequestSession session =
                     new GetRequestSession(
@@ -340,19 +355,79 @@
                             callingUid,
                             callback,
                             request,
-                            constructCallingAppInfo(callingPackage, userId));
+                            constructCallingAppInfo(callingPackage, userId),
+                            CancellationSignal.fromTransport(cancelTransport));
 
-            // Initiate all provider sessions
-            List<ProviderSession> providerSessions =
+            List<ProviderSession> providerSessions;
+
+            // TODO(b/268143699): temporarily disable the flag due to bug.
+            if (false) {
+                List<CredentialOption> optionsThatRequireActiveCredentials =
+                        request.getCredentialOptions().stream()
+                                .filter(
+                                        getCredentialOption ->
+                                                !TextUtils.isEmpty(
+                                                        getCredentialOption
+                                                                .getCredentialRetrievalData()
+                                                                .getString(
+                                                                        CredentialOption
+                                                                                .FLATTENED_REQUEST,
+                                                                        null)))
+                                .toList();
+
+                List<CredentialOption> optionsThatDoNotRequireActiveCredentials =
+                        request.getCredentialOptions().stream()
+                                .filter(
+                                        getCredentialOption ->
+                                                TextUtils.isEmpty(
+                                                        getCredentialOption
+                                                                .getCredentialRetrievalData()
+                                                                .getString(
+                                                                        CredentialOption
+                                                                                .FLATTENED_REQUEST,
+                                                                        null)))
+                                .toList();
+
+                List<ProviderSession> sessionsWithoutRemoteService =
+                        initiateProviderSessionsWithActiveContainers(
+                                session,
+                                optionsThatRequireActiveCredentials.stream()
+                                        .map(
+                                                getCredentialOption ->
+                                                        getCredentialOption
+                                                                .getCredentialRetrievalData()
+                                                                .getString(
+                                                                        CredentialOption
+                                                                                .FLATTENED_REQUEST))
+                                        .collect(Collectors.toList()),
+                                getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
+
+                List<ProviderSession> sessionsWithRemoteService =
                         initiateProviderSessions(
                                 session,
-                                request.getGetCredentialOptions().stream()
-                                        .map(GetCredentialOption::getType)
+                                optionsThatDoNotRequireActiveCredentials.stream()
+                                        .map(CredentialOption::getType)
                                         .collect(Collectors.toList()));
 
+                Set<ProviderSession> all = new LinkedHashSet<>();
+                all.addAll(sessionsWithRemoteService);
+                all.addAll(sessionsWithoutRemoteService);
+
+                providerSessions = new ArrayList<>(all);
+            } else {
+                // Initiate all provider sessions
+                providerSessions =
+                        initiateProviderSessions(
+                                session,
+                                request.getCredentialOptions().stream()
+                                        .map(CredentialOption::getType)
+                                        .collect(Collectors.toList()));
+            }
+
             if (providerSessions.isEmpty()) {
                 try {
-                    callback.onError(GetCredentialException.TYPE_NO_CREDENTIAL,
+                    callback.onError(
+                            GetCredentialException.TYPE_NO_CREDENTIAL,
                             "No credentials available on this device.");
                 } catch (RemoteException e) {
                     Log.i(
@@ -362,13 +437,8 @@
                                     + e.getMessage());
                 }
             }
+            providerSessions.forEach(ProviderSession::invokeSession);
 
-            // Iterate over all provider sessions and invoke the request
-            providerSessions.forEach(
-                    providerGetSession -> providerGetSession
-                    .getRemoteCredentialService().onBeginGetCredential(
-                    (BeginGetCredentialRequest) providerGetSession.getProviderRequest(),
-                    /*callback=*/providerGetSession));
             return cancelTransport;
         }
 
@@ -377,13 +447,14 @@
                 CreateCredentialRequest request,
                 ICreateCredentialCallback callback,
                 String callingPackage) {
-            Log.i(TAG, "starting executeCreateCredential with callingPackage: " + callingPackage);
-
+            Log.i(TAG, "starting executeCreateCredential with callingPackage: "
+                    + callingPackage);
             ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+            final int userId = UserHandle.getCallingUserId();
+            final int callingUid = Binder.getCallingUid();
+            enforceCallingPackage(callingPackage, callingUid);
 
             // New request session, scoped for this request only.
-            int userId = UserHandle.getCallingUserId();
-            int callingUid = Binder.getCallingUid();
             final CreateRequestSession session =
                     new CreateRequestSession(
                             getContext(),
@@ -391,7 +462,8 @@
                             callingUid,
                             request,
                             callback,
-                            constructCallingAppInfo(callingPackage, userId));
+                            constructCallingAppInfo(callingPackage, userId),
+                            CancellationSignal.fromTransport(cancelTransport));
 
             // Initiate all provider sessions
             List<ProviderSession> providerSessions =
@@ -399,7 +471,8 @@
 
             if (providerSessions.isEmpty()) {
                 try {
-                    callback.onError(CreateCredentialException.TYPE_NO_CREDENTIAL,
+                    callback.onError(
+                            CreateCredentialException.TYPE_NO_CREDENTIAL,
                             "No credentials available on this device.");
                 } catch (RemoteException e) {
                     Log.i(
@@ -411,13 +484,7 @@
             }
 
             // Iterate over all provider sessions and invoke the request
-            providerSessions.forEach(
-                    providerCreateSession -> providerCreateSession
-                            .getRemoteCredentialService()
-                            .onCreateCredential(
-                                    (BeginCreateCredentialRequest)
-                                            providerCreateSession.getProviderRequest(),
-                                    /* callback= */ providerCreateSession));
+            providerSessions.forEach(ProviderSession::invokeSession);
             return cancelTransport;
         }
 
@@ -428,6 +495,16 @@
             Log.i(TAG, "listEnabledProviders");
             ICancellationSignal cancelTransport = CancellationSignal.createTransport();
 
+            if (!hasWriteSecureSettingsPermission()) {
+                try {
+                    callback.onError(
+                            PERMISSION_DENIED_ERROR, PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Issue with invoking response: " + e.getMessage());
+                }
+                return cancelTransport;
+            }
+
             List<String> enabledProviders = new ArrayList<>();
             runForUser(
                     (service) -> {
@@ -450,6 +527,16 @@
                 List<String> providers, int userId, ISetEnabledProvidersCallback callback) {
             Log.i(TAG, "setEnabledProviders");
 
+            if (!hasWriteSecureSettingsPermission()) {
+                try {
+                    callback.onError(
+                            PERMISSION_DENIED_ERROR, PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Issue with invoking response: " + e.getMessage());
+                }
+                return;
+            }
+
             userId =
                     ActivityManager.handleIncomingUser(
                             Binder.getCallingPid(),
@@ -490,17 +577,52 @@
         }
 
         @Override
+        public boolean isEnabledCredentialProviderService(
+                ComponentName componentName, String callingPackage) {
+            Log.i(TAG, "isEnabledCredentialProviderService");
+
+            // TODO(253157366): Check additional set of services.
+            final int userId = UserHandle.getCallingUserId();
+            final int callingUid = Binder.getCallingUid();
+            enforceCallingPackage(callingPackage, callingUid);
+            synchronized (mLock) {
+                final List<CredentialManagerServiceImpl> services =
+                        getServiceListForUserLocked(userId);
+                for (CredentialManagerServiceImpl s : services) {
+                    final ComponentName serviceComponentName = s.getServiceComponentName();
+
+                    if (serviceComponentName.equals(componentName)) {
+                        if (!s.getServicePackageName().equals(callingPackage)) {
+                            // The component name and the package name do not match.
+                            Log.w(
+                                    TAG,
+                                    "isEnabledCredentialProviderService: Component name does not"
+                                            + " match package name.");
+                            return false;
+                        }
+
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        @Override
         public ICancellationSignal clearCredentialState(
                 ClearCredentialStateRequest request,
                 IClearCredentialStateCallback callback,
                 String callingPackage) {
             Log.i(TAG, "starting clearCredentialState with callingPackage: " + callingPackage);
+            final int userId = UserHandle.getCallingUserId();
+            int callingUid = Binder.getCallingUid();
+            enforceCallingPackage(callingPackage, callingUid);
+
             // TODO : Implement cancellation
             ICancellationSignal cancelTransport = CancellationSignal.createTransport();
 
             // New request session, scoped for this request only.
-            int userId = UserHandle.getCallingUserId();
-            int callingUid = Binder.getCallingUid();
             final ClearRequestSession session =
                     new ClearRequestSession(
                             getContext(),
@@ -508,7 +630,8 @@
                             callingUid,
                             callback,
                             request,
-                            constructCallingAppInfo(callingPackage, userId));
+                            constructCallingAppInfo(callingPackage, userId),
+                            CancellationSignal.fromTransport(cancelTransport));
 
             // Initiate all provider sessions
             // TODO: Determine if provider needs to have clear capability in their manifest
@@ -517,8 +640,7 @@
             if (providerSessions.isEmpty()) {
                 try {
                     // TODO("Replace with properly defined error type")
-                    callback.onError("UNKNOWN", "No crdentials available on this "
-                            + "device");
+                    callback.onError("UNKNOWN", "No crdentials available on this " + "device");
                 } catch (RemoteException e) {
                     Log.i(
                             TAG,
@@ -529,54 +651,59 @@
             }
 
             // Iterate over all provider sessions and invoke the request
-            providerSessions.forEach(
-                    providerClearSession -> {
-                        providerClearSession
-                                .getRemoteCredentialService()
-                                .onClearCredentialState(
-                                        (android.service.credentials.ClearCredentialStateRequest)
-                                                providerClearSession.getProviderRequest(),
-                                        /* callback= */ providerClearSession);
-                    });
+            providerSessions.forEach(ProviderSession::invokeSession);
             return cancelTransport;
         }
 
         @Override
         public void registerCredentialDescription(
                 RegisterCredentialDescriptionRequest request, String callingPackage)
-                throws IllegalArgumentException , NonCredentialProviderCallerException {
+                throws IllegalArgumentException, NonCredentialProviderCallerException {
             Log.i(TAG, "registerCredentialDescription");
 
-            List<CredentialProviderInfo> services =
-                    CredentialProviderInfo.getAvailableServices(mContext,
-                            UserHandle.getCallingUserId());
+            enforceCallingPackage(callingPackage, Binder.getCallingUid());
 
-            List<String> providers = services.stream()
-                    .map(credentialProviderInfo
-                            -> credentialProviderInfo.getServiceInfo().packageName).toList();
+            List<CredentialProviderInfo> services =
+                    CredentialProviderInfo.getAvailableServices(
+                            mContext, UserHandle.getCallingUserId());
+
+            List<String> providers =
+                    services.stream()
+                            .map(
+                                    credentialProviderInfo ->
+                                            credentialProviderInfo.getServiceInfo().packageName)
+                            .toList();
 
             if (!providers.contains(callingPackage)) {
                 throw new NonCredentialProviderCallerException(callingPackage);
             }
 
-            List<CredentialProviderInfo> matchingService = services.stream().filter(
-                    credentialProviderInfo ->
-                            credentialProviderInfo.getServiceInfo()
-                                    .packageName.equals(callingPackage)).toList();
+            List<CredentialProviderInfo> matchingService =
+                    services.stream()
+                            .filter(
+                                    credentialProviderInfo ->
+                                            credentialProviderInfo
+                                                    .getServiceInfo()
+                                                    .packageName
+                                                    .equals(callingPackage))
+                            .toList();
 
             CredentialProviderInfo credentialProviderInfo = matchingService.get(0);
 
-            Set<String> supportedTypes = request.getCredentialDescriptions()
-                    .stream().map(CredentialDescription::getType).filter(
-                            credentialProviderInfo::hasCapability).collect(Collectors.toSet());
+            Set<String> supportedTypes =
+                    request.getCredentialDescriptions().stream()
+                            .map(CredentialDescription::getType)
+                            .filter(credentialProviderInfo::hasCapability)
+                            .collect(Collectors.toSet());
 
             if (supportedTypes.size() != request.getCredentialDescriptions().size()) {
-                throw new IllegalArgumentException("CredentialProvider does not support one or more"
-                        + "of the registered types. Check your XML entry.");
+                throw new IllegalArgumentException(
+                        "CredentialProvider does not support one or more"
+                                + "of the registered types. Check your XML entry.");
             }
 
-            CredentialDescriptionRegistry session = CredentialDescriptionRegistry
-                    .forUser(UserHandle.getCallingUserId());
+            CredentialDescriptionRegistry session =
+                    CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
 
             session.executeRegisterRequest(request, callingPackage);
         }
@@ -586,24 +713,43 @@
                 UnregisterCredentialDescriptionRequest request, String callingPackage)
                 throws IllegalArgumentException {
             Log.i(TAG, "registerCredentialDescription");
-            ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+
+            enforceCallingPackage(callingPackage, Binder.getCallingUid());
 
             List<CredentialProviderInfo> services =
-                    CredentialProviderInfo.getAvailableServices(mContext,
-                            UserHandle.getCallingUserId());
+                    CredentialProviderInfo.getAvailableServices(
+                            mContext, UserHandle.getCallingUserId());
 
-            List<String> providers = services.stream()
-                    .map(credentialProviderInfo
-                            -> credentialProviderInfo.getServiceInfo().packageName).toList();
+            List<String> providers =
+                    services.stream()
+                            .map(
+                                    credentialProviderInfo ->
+                                            credentialProviderInfo.getServiceInfo().packageName)
+                            .toList();
 
             if (!providers.contains(callingPackage)) {
                 throw new NonCredentialProviderCallerException(callingPackage);
             }
 
-            CredentialDescriptionRegistry session = CredentialDescriptionRegistry
-                    .forUser(UserHandle.getCallingUserId());
+            CredentialDescriptionRegistry session =
+                    CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
 
             session.executeUnregisterRequest(request, callingPackage);
         }
     }
+
+    private void enforceCallingPackage(String callingPackage, int callingUid) {
+        int packageUid;
+        PackageManager pm = mContext.createContextAsUser(
+                UserHandle.getUserHandleForUid(callingUid), 0).getPackageManager();
+        try {
+            packageUid = pm.getPackageUid(callingPackage,
+                    PackageManager.PackageInfoFlags.of(0));
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new SecurityException(callingPackage + " not found");
+        }
+        if (packageUid != callingUid) {
+            throw new SecurityException(callingPackage + " does not belong to uid " + callingUid);
+        }
+    }
 }
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index e3a27ec..e732c23 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -25,6 +25,7 @@
 import android.credentials.IGetCredentialCallback;
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.RequestInfo;
+import android.os.CancellationSignal;
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.CredentialProviderInfo;
@@ -43,8 +44,9 @@
 
     public GetRequestSession(Context context, int userId, int callingUid,
             IGetCredentialCallback callback, GetCredentialRequest request,
-            CallingAppInfo callingAppInfo) {
-        super(context, userId, callingUid, request, callback, RequestInfo.TYPE_GET, callingAppInfo);
+            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
+        super(context, userId, callingUid, request, callback, RequestInfo.TYPE_GET,
+                callingAppInfo, cancellationSignal);
     }
 
     /**
@@ -102,6 +104,12 @@
     }
 
     private void respondToClientWithResponseAndFinish(GetCredentialResponse response) {
+        if (isSessionCancelled()) {
+            // TODO: Differentiate btw cancelled and false
+            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+            finishSession(/*propagateCancellation=*/true);
+            return;
+        }
         try {
             mClientCallback.onResponse(response);
             logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ true);
@@ -109,18 +117,22 @@
             Log.i(TAG, "Issue while responding to client with a response : " + e.getMessage());
             logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
         }
-        finishSession();
+        finishSession(/*propagateCancellation=*/false);
     }
 
     private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
+        if (isSessionCancelled()) {
+            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+            finishSession(/*propagateCancellation=*/true);
+            return;
+        }
         try {
             mClientCallback.onError(errorType, errorMsg);
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client with error : " + e.getMessage());
-
         }
         logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
-        finishSession();
+        finishSession(/*propagateCancellation=*/false);
     }
 
     @Override
diff --git a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
index c2b346f..efb394d 100644
--- a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
+++ b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
@@ -23,8 +23,8 @@
 import android.credentials.GetCredentialException;
 import android.credentials.GetCredentialResponse;
 import android.credentials.ui.ProviderPendingIntentResponse;
+import android.service.credentials.BeginGetCredentialResponse;
 import android.service.credentials.CredentialProviderService;
-import android.service.credentials.CredentialsResponseContent;
 
 /**
  * Helper class for setting up pending intent, and extracting objects from it.
@@ -45,14 +45,14 @@
         return pendingIntentResponse.getResultCode() == Activity.RESULT_CANCELED;
     }
 
-    /** Extracts the {@link CredentialsResponseContent} object added to the result data. */
-    public static CredentialsResponseContent extractResponseContent(Intent resultData) {
+    /** Extracts the {@link BeginGetCredentialResponse} object added to the result data. */
+    public static BeginGetCredentialResponse extractResponseContent(Intent resultData) {
         if (resultData == null) {
             return null;
         }
         return resultData.getParcelableExtra(
-                CredentialProviderService.EXTRA_CREDENTIALS_RESPONSE_CONTENT,
-                CredentialsResponseContent.class);
+                CredentialProviderService.EXTRA_BEGIN_GET_CREDENTIAL_RESPONSE,
+                BeginGetCredentialResponse.class);
     }
 
     /** Extracts the {@link CreateCredentialResponse} object added to the result data. */
diff --git a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
index 48e35b2..b20f0cd 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
@@ -115,4 +115,11 @@
             ProviderPendingIntentResponse providerPendingIntentResponse) {
         //Not applicable for clearCredential as response is not picked by the user
     }
+
+    @Override
+    protected void invokeSession() {
+        if (mRemoteCredentialService != null) {
+            mRemoteCredentialService.onClearCredentialState(mProviderRequest, this);
+        }
+    }
 }
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 7a24a22..20e358c 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
@@ -26,6 +26,7 @@
 import android.credentials.ui.CreateCredentialProviderData;
 import android.credentials.ui.Entry;
 import android.credentials.ui.ProviderPendingIntentResponse;
+import android.os.Bundle;
 import android.service.credentials.BeginCreateCredentialRequest;
 import android.service.credentials.BeginCreateCredentialResponse;
 import android.service.credentials.CallingAppInfo;
@@ -34,6 +35,7 @@
 import android.service.credentials.CredentialProviderInfo;
 import android.service.credentials.CredentialProviderService;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 
 import java.util.ArrayList;
@@ -51,6 +53,8 @@
 
     // Key to be used as an entry key for a save entry
     private static final String SAVE_ENTRY_KEY = "save_entry_key";
+    // Key to be used as an entry key for a remote entry
+    private static final String REMOTE_ENTRY_KEY = "remote_entry_key";
 
     @NonNull
     private final Map<String, CreateEntry> mUiSaveEntries = new HashMap<>();
@@ -59,6 +63,8 @@
 
     private CreateCredentialException mProviderException;
 
+    @Nullable protected Pair<String, CreateEntry> mUiRemoteEntry;
+
     /** Creates a new provider session to be used by the request session. */
     @Nullable public static ProviderCreateSession createNewSession(
             Context context,
@@ -72,10 +78,11 @@
                         createRequestSession.mClientAppInfo);
         if (providerCreateRequest != null) {
             BeginCreateCredentialRequest providerBeginCreateRequest =
-                    new BeginCreateCredentialRequest(
-                            providerCreateRequest.getCallingAppInfo(),
-                            providerCreateRequest.getType(),
-                            createRequestSession.mClientRequest.getCandidateQueryData());
+                    constructQueryPhaseRequest(createRequestSession.mClientRequest.getType(),
+                            createRequestSession.mClientRequest.getCandidateQueryData(),
+                            createRequestSession.mClientAppInfo,
+                            createRequestSession
+                                    .mClientRequest.alwaysSendAppInfoToProvider());
             return new ProviderCreateSession(context, providerInfo, createRequestSession, userId,
                     remoteCredentialService, providerBeginCreateRequest, providerCreateRequest);
         }
@@ -83,6 +90,21 @@
         return null;
     }
 
+    private static BeginCreateCredentialRequest constructQueryPhaseRequest(
+            String type, Bundle candidateQueryData, CallingAppInfo callingAppInfo,
+            boolean propagateToProvider) {
+        if (propagateToProvider) {
+            return new BeginCreateCredentialRequest(
+                    type,
+                    candidateQueryData
+            );
+        }
+        return new BeginCreateCredentialRequest(
+                type,
+                candidateQueryData,
+                callingAppInfo);
+    }
+
     @Nullable
     private static CreateCredentialRequest createProviderRequest(List<String> providerCapabilities,
             android.credentials.CreateCredentialRequest clientRequest,
@@ -166,12 +188,22 @@
             Log.i(TAG, "In prepareUiData save entries not null");
             return prepareUiProviderData(
                     prepareUiSaveEntries(response.getCreateEntries()),
-                    null,
-                    /*isDefaultProvider=*/false);
+                    prepareUiRemoteEntry(response.getRemoteCreateEntry()));
         }
         return null;
     }
 
+    private Entry prepareUiRemoteEntry(CreateEntry remoteCreateEntry) {
+        if (remoteCreateEntry == null) {
+            return null;
+        }
+        String entryId = generateUniqueId();
+        Entry remoteEntry = new Entry(REMOTE_ENTRY_KEY, entryId, remoteCreateEntry.getSlice(),
+                setUpFillInIntent());
+        mUiRemoteEntry = new Pair<>(entryId, remoteCreateEntry);
+        return remoteEntry;
+    }
+
     @Override
     public void onUiEntrySelected(String entryType, String entryKey,
             ProviderPendingIntentResponse providerPendingIntentResponse) {
@@ -197,13 +229,20 @@
         }
     }
 
+    @Override
+    protected void invokeSession() {
+        if (mRemoteCredentialService != null) {
+            mRemoteCredentialService.onCreateCredential(mProviderRequest, this);
+        }
+    }
+
     private List<Entry> prepareUiSaveEntries(@NonNull List<CreateEntry> saveEntries) {
         Log.i(TAG, "in populateUiSaveEntries");
         List<Entry> uiSaveEntries = new ArrayList<>();
 
         // Populate the save entries
         for (CreateEntry createEntry : saveEntries) {
-            String entryId = generateEntryId();
+            String entryId = generateUniqueId();
             mUiSaveEntries.put(entryId, createEntry);
             Log.i(TAG, "in prepareUiProviderData creating ui entry with id " + entryId);
             uiSaveEntries.add(new Entry(SAVE_ENTRY_KEY, entryId, createEntry.getSlice(),
@@ -220,10 +259,11 @@
     }
 
     private CreateCredentialProviderData prepareUiProviderData(List<Entry> saveEntries,
-            Entry remoteEntry, boolean isDefaultProvider) {
+            Entry remoteEntry) {
         return new CreateCredentialProviderData.Builder(
                 mComponentName.flattenToString())
                 .setSaveEntries(saveEntries)
+                .setRemoteEntry(remoteEntry)
                 .build();
     }
 
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index 95f2313..9fba95b 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -21,8 +21,8 @@
 import android.annotation.UserIdInt;
 import android.content.Context;
 import android.content.Intent;
+import android.credentials.CredentialOption;
 import android.credentials.GetCredentialException;
-import android.credentials.GetCredentialOption;
 import android.credentials.GetCredentialResponse;
 import android.credentials.ui.Entry;
 import android.credentials.ui.GetCredentialProviderData;
@@ -35,7 +35,6 @@
 import android.service.credentials.CredentialEntry;
 import android.service.credentials.CredentialProviderInfo;
 import android.service.credentials.CredentialProviderService;
-import android.service.credentials.CredentialsResponseContent;
 import android.service.credentials.GetCredentialRequest;
 import android.util.Log;
 import android.util.Pair;
@@ -46,7 +45,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
-import java.util.stream.Collectors;
 
 /**
  * Central provider session that listens for provider callbacks, and maintains provider state.
@@ -59,21 +57,25 @@
         implements
         RemoteCredentialService.ProviderCallbacks<BeginGetCredentialResponse> {
     private static final String TAG = "ProviderGetSession";
-
-    // Key to be used as an entry key for a credential entry
-    private static final String CREDENTIAL_ENTRY_KEY = "credential_key";
-
     // Key to be used as the entry key for an action entry
     private static final String ACTION_ENTRY_KEY = "action_key";
     // Key to be used as the entry key for the authentication entry
     private static final String AUTHENTICATION_ACTION_ENTRY_KEY = "authentication_action_key";
+    // Key to be used as an entry key for a remote entry
+    private static final String REMOTE_ENTRY_KEY = "remote_entry_key";
+    // Key to be used as an entry key for a credential entry
+    private static final String CREDENTIAL_ENTRY_KEY = "credential_key";
 
     @NonNull
+    private final Map<String, CredentialOption> mBeginGetOptionToCredentialOptionMap;
+    @NonNull
     private final Map<String, CredentialEntry> mUiCredentialEntries = new HashMap<>();
     @NonNull
     private final Map<String, Action> mUiActionsEntries = new HashMap<>();
     @Nullable
-    private Pair<String, Action> mUiAuthenticationAction = null;
+    private final Map<String, Action> mUiAuthenticationEntries = new HashMap<>();
+
+    @Nullable protected Pair<String, CredentialEntry> mUiRemoteEntry;
 
     /** The complete request to be used in the second round. */
     private final android.credentials.GetCredentialRequest mCompleteRequest;
@@ -92,10 +94,16 @@
                 filterOptions(providerInfo.getCapabilities(),
                         getRequestSession.mClientRequest);
         if (filteredRequest != null) {
+            Map<String, CredentialOption> beginGetOptionToCredentialOptionMap =
+                    new HashMap<>();
             BeginGetCredentialRequest beginGetCredentialRequest = constructQueryPhaseRequest(
-                    filteredRequest, getRequestSession.mClientAppInfo);
+                    filteredRequest, getRequestSession.mClientAppInfo,
+                    getRequestSession.mClientRequest.alwaysSendAppInfoToProvider(),
+                    beginGetOptionToCredentialOptionMap);
             return new ProviderGetSession(context, providerInfo, getRequestSession, userId,
-                    remoteCredentialService, beginGetCredentialRequest, filteredRequest);
+                    remoteCredentialService, beginGetCredentialRequest, filteredRequest,
+                    getRequestSession.mClientAppInfo,
+                    beginGetOptionToCredentialOptionMap);
         }
         Log.i(TAG, "Unable to create provider session");
         return null;
@@ -103,26 +111,32 @@
 
     private static BeginGetCredentialRequest constructQueryPhaseRequest(
             android.credentials.GetCredentialRequest filteredRequest,
-            CallingAppInfo callingAppInfo
+            CallingAppInfo callingAppInfo,
+            boolean propagateToProvider,
+            Map<String, CredentialOption> beginGetOptionToCredentialOptionMap
     ) {
-        return new BeginGetCredentialRequest.Builder(callingAppInfo)
-                .setBeginGetCredentialOptions(
-                        filteredRequest.getGetCredentialOptions().stream().map(
-                                option -> {
-                                    return new BeginGetCredentialOption(
-                                            option.getType(),
-                                            option.getCandidateQueryData());
-                                }).collect(Collectors.toList()))
-                .build();
+        BeginGetCredentialRequest.Builder builder = new BeginGetCredentialRequest.Builder();
+        filteredRequest.getCredentialOptions().forEach(option -> {
+            String id = generateUniqueId();
+            builder.addBeginGetCredentialOption(
+                    new BeginGetCredentialOption(
+                            id, option.getType(), option.getCandidateQueryData())
+            );
+            beginGetOptionToCredentialOptionMap.put(id, option);
+        });
+        if (propagateToProvider) {
+            builder.setCallingAppInfo(callingAppInfo);
+        }
+        return builder.build();
     }
 
     @Nullable
-    private static android.credentials.GetCredentialRequest filterOptions(
+    protected static android.credentials.GetCredentialRequest filterOptions(
             List<String> providerCapabilities,
             android.credentials.GetCredentialRequest clientRequest
     ) {
-        List<GetCredentialOption> filteredOptions = new ArrayList<>();
-        for (GetCredentialOption option : clientRequest.getGetCredentialOptions()) {
+        List<CredentialOption> filteredOptions = new ArrayList<>();
+        for (CredentialOption option : clientRequest.getCredentialOptions()) {
             if (providerCapabilities.contains(option.getType())) {
                 Log.i(TAG, "In createProviderRequest - capability found : "
                         + option.getType());
@@ -135,7 +149,7 @@
         if (!filteredOptions.isEmpty()) {
             return new android.credentials.GetCredentialRequest
                     .Builder(clientRequest.getData())
-                    .setGetCredentialOptions(
+                    .setCredentialOptions(
                             filteredOptions).build();
         }
         Log.i(TAG, "In createProviderRequest - returning null");
@@ -147,17 +161,14 @@
             ProviderInternalCallback<GetCredentialResponse> callbacks,
             int userId, RemoteCredentialService remoteCredentialService,
             BeginGetCredentialRequest beginGetRequest,
-            android.credentials.GetCredentialRequest completeGetRequest) {
+            android.credentials.GetCredentialRequest completeGetRequest,
+            CallingAppInfo callingAppInfo,
+            Map<String, CredentialOption> beginGetOptionToCredentialOptionMap) {
         super(context, info, beginGetRequest, callbacks, userId, remoteCredentialService);
         mCompleteRequest = completeGetRequest;
-        mCallingAppInfo = beginGetRequest.getCallingAppInfo();
+        mCallingAppInfo = callingAppInfo;
         setStatus(Status.PENDING);
-    }
-
-    /** Returns the credential entry maintained in state by this provider session. */
-    @Nullable
-    public CredentialEntry getCredentialEntry(@NonNull String entryId) {
-        return mUiCredentialEntries.get(entryId);
+        mBeginGetOptionToCredentialOptionMap = beginGetOptionToCredentialOptionMap;
     }
 
     /** Called when the provider response has been updated by an external source. */
@@ -210,12 +221,13 @@
                 onActionEntrySelected(providerPendingIntentResponse);
                 break;
             case AUTHENTICATION_ACTION_ENTRY_KEY:
-                if (mUiAuthenticationAction.first.equals(entryKey)) {
-                    onAuthenticationEntrySelected(providerPendingIntentResponse);
-                } else {
-                    Log.i(TAG, "Unexpected authentication entry key");
+                Action authenticationEntry = mUiAuthenticationEntries.get(entryKey);
+                if (authenticationEntry == null) {
+                    Log.i(TAG, "Unexpected authenticationEntry key");
                     invokeCallbackOnInternalInvalidState();
+                    return;
                 }
+                onAuthenticationEntrySelected(providerPendingIntentResponse);
                 break;
             case REMOTE_ENTRY_KEY:
                 if (mUiRemoteEntry.first.equals(entryKey)) {
@@ -230,6 +242,13 @@
         }
     }
 
+    @Override
+    protected void invokeSession() {
+        if (mRemoteCredentialService != null) {
+            mRemoteCredentialService.onBeginGetCredential(mProviderRequest, this);
+        }
+    }
+
     @Override // Call from request session to data to be shown on the UI
     @Nullable protected GetCredentialProviderData prepareUiData() throws IllegalArgumentException {
         Log.i(TAG, "In prepareUiData");
@@ -242,43 +261,37 @@
             Log.i(TAG, "In prepareUiData response null");
             throw new IllegalStateException("Response must be in completion mode");
         }
-        if (mProviderResponse.getAuthenticationAction() != null) {
-            Log.i(TAG, "In prepareUiData - top level authentication mode");
-            return prepareUiProviderData(null, null,
-                    prepareUiAuthenticationAction(mProviderResponse.getAuthenticationAction()),
-                    /*remoteEntry=*/null);
-        }
-        if (mProviderResponse.getCredentialsResponseContent() != null) {
-            Log.i(TAG, "In prepareUiData credentialsResponseContent not null");
-            return prepareUiProviderData(prepareUiActionEntries(
-                            mProviderResponse.getCredentialsResponseContent().getActions()),
-                    prepareUiCredentialEntries(mProviderResponse.getCredentialsResponseContent()
-                            .getCredentialEntries()),
-                    /*authenticationAction=*/null,
-                    prepareUiRemoteEntry(mProviderResponse
-                            .getCredentialsResponseContent().getRemoteCredentialEntry()));
-        }
-        return null;
+        return prepareUiProviderData(prepareUiActionEntries(
+                        mProviderResponse.getActions()),
+                prepareUiCredentialEntries(mProviderResponse.getCredentialEntries()),
+                prepareUiAuthenticationEntries(mProviderResponse.getAuthenticationActions()),
+                prepareUiRemoteEntry(mProviderResponse.getRemoteCredentialEntry()));
     }
 
     private Entry prepareUiRemoteEntry(CredentialEntry remoteCredentialEntry) {
         if (remoteCredentialEntry == null) {
             return null;
         }
-        String entryId = generateEntryId();
-        Entry remoteEntry = new Entry(REMOTE_ENTRY_KEY, entryId, remoteCredentialEntry.getSlice());
+        String entryId = generateUniqueId();
+        Entry remoteEntry = new Entry(REMOTE_ENTRY_KEY, entryId, remoteCredentialEntry.getSlice(),
+                setUpFillInIntent(remoteCredentialEntry.getType()));
         mUiRemoteEntry = new Pair<>(entryId, remoteCredentialEntry);
         return remoteEntry;
     }
 
-    private Entry prepareUiAuthenticationAction(@NonNull Action authenticationAction) {
-        String entryId = generateEntryId();
-        Entry authEntry = new Entry(
-                AUTHENTICATION_ACTION_ENTRY_KEY, entryId,
-                authenticationAction.getSlice(),
-                setUpFillInIntentForAuthentication());
-        mUiAuthenticationAction = new Pair<>(entryId, authenticationAction);
-        return authEntry;
+    private List<Entry> prepareUiAuthenticationEntries(
+            @NonNull List<Action> authenticationEntries) {
+        List<Entry> authenticationUiEntries = new ArrayList<>();
+
+        for (Action authenticationAction : authenticationEntries) {
+            String entryId = generateUniqueId();
+            mUiAuthenticationEntries.put(entryId, authenticationAction);
+            authenticationUiEntries.add(new Entry(
+                    AUTHENTICATION_ACTION_ENTRY_KEY, entryId,
+                    authenticationAction.getSlice(),
+                    setUpFillInIntentForAuthentication()));
+        }
+        return authenticationUiEntries;
     }
 
     private List<Entry> prepareUiCredentialEntries(@NonNull
@@ -288,7 +301,7 @@
 
         // Populate the credential entries
         for (CredentialEntry credentialEntry : credentialEntries) {
-            String entryId = generateEntryId();
+            String entryId = generateUniqueId();
             mUiCredentialEntries.put(entryId, credentialEntry);
             Log.i(TAG, "in prepareUiProviderData creating ui entry with id " + entryId);
             credentialUiEntries.add(new Entry(CREDENTIAL_ENTRY_KEY, entryId,
@@ -298,18 +311,17 @@
         return credentialUiEntries;
     }
 
-    private Intent setUpFillInIntent(String type) {
-        Intent intent = new Intent();
-        for (GetCredentialOption option : mCompleteRequest.getGetCredentialOptions()) {
-            if (option.getType().equals(type)) {
-                intent.putExtra(
-                        CredentialProviderService
-                                .EXTRA_GET_CREDENTIAL_REQUEST,
-                        new GetCredentialRequest(mCallingAppInfo, option));
-                return intent;
-            }
+    private Intent setUpFillInIntent(@Nullable String id) {
+        // TODO: Determine if we should skip this entry if entry id is not set, or is set
+        // but does not resolve to a valid option. For now, not skipping it because
+        // it may be possible that the provider adds their own extras and expects to receive
+        // those and complete the flow.
+        if (id == null || mBeginGetOptionToCredentialOptionMap.get(id) == null) {
+            Log.i(TAG, "Id from Credential Entry does not resolve to a valid option");
         }
-        return intent;
+        return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
+                new GetCredentialRequest(
+                        mCallingAppInfo, mBeginGetOptionToCredentialOptionMap.get(id)));
     }
 
     private Intent setUpFillInIntentForAuthentication() {
@@ -333,12 +345,12 @@
     }
 
     private GetCredentialProviderData prepareUiProviderData(List<Entry> actionEntries,
-            List<Entry> credentialEntries, Entry authenticationActionEntry,
+            List<Entry> credentialEntries, List<Entry> authenticationActionEntries,
             Entry remoteEntry) {
         return new GetCredentialProviderData.Builder(
                 mComponentName.flattenToString()).setActionChips(actionEntries)
                 .setCredentialEntries(credentialEntries)
-                .setAuthenticationEntry(authenticationActionEntry)
+                .setAuthenticationEntries(authenticationActionEntries)
                 .setRemoteEntry(remoteEntry)
                 .build();
     }
@@ -372,60 +384,8 @@
         invokeCallbackOnInternalInvalidState();
     }
 
-    private void onAuthenticationEntrySelected(
-            @Nullable ProviderPendingIntentResponse providerPendingIntentResponse) {
-        //TODO: Other provider intent statuses
-        if (providerPendingIntentResponse == null) {
-            Log.i(TAG, "providerPendingIntentResponse is null");
-            onUpdateEmptyResponse();
-        }
-
-        GetCredentialException exception = maybeGetPendingIntentException(
-                providerPendingIntentResponse);
-        if (exception != null) {
-            invokeCallbackWithError(exception.getType(),
-                    exception.getMessage());
-            return;
-        }
-
-        // Check if pending intent has the content
-        CredentialsResponseContent content = PendingIntentResultHandler
-                .extractResponseContent(providerPendingIntentResponse
-                        .getResultData());
-        if (content != null) {
-            onUpdateResponse(BeginGetCredentialResponse.createWithResponseContent(content));
-            return;
-        }
-
-        Log.i(TAG, "No error or respond found in pending intent response");
-        onUpdateEmptyResponse();
-    }
-
-    private void onActionEntrySelected(ProviderPendingIntentResponse
-            providerPendingIntentResponse) {
-        //TODO: Implement if any result expected after an action
-    }
-
-
-    /** Updates the response being maintained in state by this provider session. */
-    private void onUpdateResponse(BeginGetCredentialResponse response) {
-        mProviderResponse = response;
-        if (response.getAuthenticationAction() != null) {
-            Log.i(TAG , "updateResponse with authentication entry");
-            updateStatusAndInvokeCallback(Status.REQUIRES_AUTHENTICATION);
-        } else if (response.getCredentialsResponseContent() != null) {
-            Log.i(TAG , "updateResponse with credentialEntries");
-            // TODO validate response
-            updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
-        }
-    }
-
-    private void onUpdateEmptyResponse() {
-        updateStatusAndInvokeCallback(Status.NO_CREDENTIALS);
-    }
-
     @Nullable
-    private GetCredentialException maybeGetPendingIntentException(
+    protected GetCredentialException maybeGetPendingIntentException(
             ProviderPendingIntentResponse pendingIntentResponse) {
         if (pendingIntentResponse == null) {
             Log.i(TAG, "pendingIntentResponse is null");
@@ -446,6 +406,52 @@
         return null;
     }
 
+    private void onAuthenticationEntrySelected(
+            @Nullable ProviderPendingIntentResponse providerPendingIntentResponse) {
+        //TODO: Other provider intent statuses
+        if (providerPendingIntentResponse == null) {
+            Log.i(TAG, "providerPendingIntentResponse is null");
+            onUpdateEmptyResponse();
+            return;
+        }
+
+        GetCredentialException exception = maybeGetPendingIntentException(
+                providerPendingIntentResponse);
+        if (exception != null) {
+            invokeCallbackWithError(exception.getType(),
+                    exception.getMessage());
+            return;
+        }
+
+        // Check if pending intent has the content
+        BeginGetCredentialResponse content = PendingIntentResultHandler
+                .extractResponseContent(providerPendingIntentResponse
+                        .getResultData());
+        if (content != null) {
+            onUpdateResponse(content);
+            return;
+        }
+
+        Log.i(TAG, "No error or respond found in pending intent response");
+        onUpdateEmptyResponse();
+    }
+
+    private void onActionEntrySelected(ProviderPendingIntentResponse
+            providerPendingIntentResponse) {
+        //TODO: Implement if any result expected after an action
+    }
+
+
+    /** Updates the response being maintained in state by this provider session. */
+    private void onUpdateResponse(BeginGetCredentialResponse response) {
+        mProviderResponse = response;
+        updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
+    }
+
+    private void onUpdateEmptyResponse() {
+        updateStatusAndInvokeCallback(Status.NO_CREDENTIALS);
+    }
+
     /**
      * When an invalid state occurs, e.g. entry mismatch or no response from provider,
      * we send back a TYPE_UNKNOWN error as to the developer.
diff --git a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
new file mode 100644
index 0000000..dd9fcb6
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
@@ -0,0 +1,261 @@
+/*
+ * 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.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.Context;
+import android.content.Intent;
+import android.credentials.CredentialOption;
+import android.credentials.GetCredentialException;
+import android.credentials.GetCredentialRequest;
+import android.credentials.GetCredentialResponse;
+import android.credentials.ui.Entry;
+import android.credentials.ui.GetCredentialProviderData;
+import android.credentials.ui.ProviderData;
+import android.credentials.ui.ProviderPendingIntentResponse;
+import android.service.credentials.CallingAppInfo;
+import android.service.credentials.CredentialEntry;
+import android.service.credentials.CredentialProviderService;
+import android.telecom.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Central provider session that utilizes {@link CredentialDescriptionRegistry} and therefor is able
+ * to bypass having to use a {@link RemoteCredentialService}.
+ *
+ * @hide
+ */
+public class ProviderRegistryGetSession extends ProviderSession<GetCredentialRequest,
+        Set<CredentialDescriptionRegistry.FilterResult>> {
+
+    private static final String TAG = "ProviderRegistryGetSession";
+    private static final String CREDENTIAL_ENTRY_KEY = "credential_key";
+
+    /** Creates a new provider session to be used by the request session. */
+    @Nullable
+    public static ProviderRegistryGetSession createNewSession(
+            @NonNull Context context,
+            @UserIdInt int userId,
+            @NonNull GetRequestSession getRequestSession,
+            @NonNull String credentialProviderPackageName,
+            @NonNull List<String> requestOptions) {
+        return new ProviderRegistryGetSession(
+                context,
+                userId,
+                getRequestSession,
+                getRequestSession.mClientRequest,
+                getRequestSession.mClientAppInfo,
+                credentialProviderPackageName,
+                requestOptions);
+    }
+
+    @NonNull
+    private final Map<String, CredentialEntry> mUiCredentialEntries = new HashMap<>();
+    @NonNull
+    private final CredentialDescriptionRegistry mCredentialDescriptionRegistry;
+    @NonNull
+    private final CallingAppInfo mCallingAppInfo;
+    @NonNull
+    private final String mCredentialProviderPackageName;
+    @NonNull
+    private final GetRequestSession mGetRequestSession;
+    @NonNull
+    private final List<String> mRequestOptions;
+    private List<CredentialEntry> mCredentialEntries;
+
+    protected ProviderRegistryGetSession(@NonNull Context context,
+            @NonNull int userId,
+            @NonNull GetRequestSession session,
+            @NonNull GetCredentialRequest request,
+            @NonNull CallingAppInfo callingAppInfo,
+            @NonNull String servicePackageName,
+            @NonNull List<String> requestOptions) {
+        super(context, null, request, session, userId, null);
+        mGetRequestSession = session;
+        mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(userId);
+        mCallingAppInfo = callingAppInfo;
+        mCredentialProviderPackageName = servicePackageName;
+        mRequestOptions = requestOptions;
+    }
+
+    private List<Entry> prepareUiCredentialEntries(
+            @NonNull List<CredentialEntry> credentialEntries) {
+        Log.i(TAG, "in prepareUiProviderDataWithCredentials");
+        List<Entry> credentialUiEntries = new ArrayList<>();
+
+        // Populate the credential entries
+        for (CredentialEntry credentialEntry : credentialEntries) {
+            String entryId = generateUniqueId();
+            mUiCredentialEntries.put(entryId, credentialEntry);
+            Log.i(TAG, "in prepareUiProviderData creating ui entry with id " + entryId);
+            credentialUiEntries.add(new Entry(CREDENTIAL_ENTRY_KEY, entryId,
+                    credentialEntry.getSlice(),
+                    setUpFillInIntent(credentialEntry.getType())));
+        }
+        return credentialUiEntries;
+    }
+
+    private Intent setUpFillInIntent(String type) {
+        Intent intent = new Intent();
+        for (CredentialOption option : mProviderRequest.getCredentialOptions()) {
+            if (option.getType().equals(type)) {
+                intent.putExtra(
+                        CredentialProviderService
+                                .EXTRA_GET_CREDENTIAL_REQUEST,
+                        new android.service.credentials.GetCredentialRequest(
+                                mCallingAppInfo, option));
+                return intent;
+            }
+        }
+        return intent;
+    }
+
+    @Override
+    protected ProviderData prepareUiData() {
+        Log.i(TAG, "In prepareUiData");
+        if (!ProviderSession.isUiInvokingStatus(getStatus())) {
+            Log.i(TAG, "In prepareUiData - provider does not want to show UI: "
+                    + mComponentName.flattenToString());
+            return null;
+        }
+        if (mProviderResponse == null) {
+            Log.i(TAG, "In prepareUiData response null");
+            throw new IllegalStateException("Response must be in completion mode");
+        }
+        return new GetCredentialProviderData.Builder(
+                mComponentName.flattenToString()).setActionChips(null)
+                .setCredentialEntries(prepareUiCredentialEntries(
+                        mProviderResponse.stream().flatMap((Function<CredentialDescriptionRegistry
+                                        .FilterResult,
+                                        Stream<CredentialEntry>>) filterResult ->
+                                        filterResult.mCredentialEntries.stream())
+                                .collect(Collectors.toList())))
+                .build();
+    }
+
+    @Override // Selection call from the request provider
+    protected void onUiEntrySelected(String entryType, String entryKey,
+            ProviderPendingIntentResponse providerPendingIntentResponse) {
+        switch (entryType) {
+            case CREDENTIAL_ENTRY_KEY:
+                CredentialEntry credentialEntry = mUiCredentialEntries.get(entryKey);
+                if (credentialEntry == null) {
+                    Log.i(TAG, "Unexpected credential entry key");
+                    return;
+                }
+                onCredentialEntrySelected(credentialEntry, providerPendingIntentResponse);
+                break;
+            default:
+                Log.i(TAG, "Unsupported entry type selected");
+        }
+    }
+
+    private void onCredentialEntrySelected(CredentialEntry credentialEntry,
+            ProviderPendingIntentResponse providerPendingIntentResponse) {
+        if (!mCredentialEntries.contains(credentialEntry)) {
+            invokeCallbackWithError("",
+                    "");
+        }
+
+        if (providerPendingIntentResponse != null) {
+            // Check if pending intent has an error
+            GetCredentialException exception = maybeGetPendingIntentException(
+                    providerPendingIntentResponse);
+            if (exception != null) {
+                invokeCallbackWithError(exception.getType(),
+                        exception.getMessage());
+                return;
+            }
+
+            // Check if pending intent has a credential
+            GetCredentialResponse getCredentialResponse = PendingIntentResultHandler
+                    .extractGetCredentialResponse(
+                            providerPendingIntentResponse.getResultData());
+            if (getCredentialResponse != null) {
+                if (mCallbacks != null) {
+                    mCallbacks.onFinalResponseReceived(mComponentName,
+                            getCredentialResponse);
+                }
+                return;
+            }
+
+            Log.i(TAG, "Pending intent response contains no credential, or error");
+        }
+        Log.i(TAG, "CredentialEntry does not have a credential or a pending intent result");
+    }
+
+    @Override
+    public void onProviderResponseSuccess(
+            @Nullable Set<CredentialDescriptionRegistry.FilterResult> response) {
+        // No need to do anything since this class does not rely on a remote service.
+    }
+
+    @Override
+    public void onProviderResponseFailure(int internalErrorCode, @Nullable Exception e) {
+        // No need to do anything since this class does not rely on a remote service.
+    }
+
+    @Override
+    public void onProviderServiceDied(RemoteCredentialService service) {
+        // No need to do anything since this class does not rely on a remote service.
+    }
+
+    @Override
+    protected void invokeSession() {
+        mProviderResponse = mCredentialDescriptionRegistry
+                .getFilteredResultForProvider(mCredentialProviderPackageName,
+                        mRequestOptions);
+        mCredentialEntries = mProviderResponse.stream().flatMap(
+                        (Function<CredentialDescriptionRegistry.FilterResult,
+                                Stream<CredentialEntry>>) filterResult
+                        -> filterResult.mCredentialEntries.stream())
+                .collect(Collectors.toList());
+        setStatus(Status.CREDENTIALS_RECEIVED);
+    }
+
+    @Nullable
+    protected GetCredentialException maybeGetPendingIntentException(
+            ProviderPendingIntentResponse pendingIntentResponse) {
+        if (pendingIntentResponse == null) {
+            android.util.Log.i(TAG, "pendingIntentResponse is null");
+            return null;
+        }
+        if (PendingIntentResultHandler.isValidResponse(pendingIntentResponse)) {
+            GetCredentialException exception = PendingIntentResultHandler
+                    .extractGetCredentialException(pendingIntentResponse.getResultData());
+            if (exception != null) {
+                android.util.Log.i(TAG, "Pending intent contains provider exception");
+                return exception;
+            }
+        } else if (PendingIntentResultHandler.isCancelledResponse(pendingIntentResponse)) {
+            return new GetCredentialException(GetCredentialException.TYPE_USER_CANCELED);
+        } else {
+            return new GetCredentialException(GetCredentialException.TYPE_NO_CREDENTIAL);
+        }
+        return null;
+    }
+}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index 678c752..1ae0f3c 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -23,9 +23,10 @@
 import android.credentials.Credential;
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.ProviderPendingIntentResponse;
-import android.service.credentials.CredentialEntry;
+import android.os.ICancellationSignal;
+import android.os.RemoteException;
 import android.service.credentials.CredentialProviderInfo;
-import android.util.Pair;
+import android.util.Log;
 
 import java.util.UUID;
 
@@ -38,21 +39,20 @@
         implements RemoteCredentialService.ProviderCallbacks<R> {
 
     private static final String TAG = "ProviderSession";
-    // Key to be used as an entry key for a remote entry
-    protected static final String REMOTE_ENTRY_KEY = "remote_entry_key";
 
     @NonNull protected final Context mContext;
     @NonNull protected final ComponentName mComponentName;
-    @NonNull protected final CredentialProviderInfo mProviderInfo;
-    @NonNull protected final RemoteCredentialService mRemoteCredentialService;
+    @Nullable protected final CredentialProviderInfo mProviderInfo;
+    @Nullable protected final RemoteCredentialService mRemoteCredentialService;
     @NonNull protected final int mUserId;
     @NonNull protected Status mStatus = Status.NOT_STARTED;
-    @NonNull protected final ProviderInternalCallback mCallbacks;
+    @Nullable protected final ProviderInternalCallback mCallbacks;
     @Nullable protected Credential mFinalCredentialResponse;
+    @Nullable protected ICancellationSignal mProviderCancellationSignal;
     @NonNull protected final T mProviderRequest;
     @Nullable protected R mProviderResponse;
     @NonNull protected Boolean mProviderResponseSet = false;
-    @Nullable protected Pair<String, CredentialEntry> mUiRemoteEntry;
+
 
 
     /**
@@ -109,9 +109,9 @@
 
     protected ProviderSession(@NonNull Context context, @NonNull CredentialProviderInfo info,
             @NonNull T providerRequest,
-            @NonNull ProviderInternalCallback callbacks,
+            @Nullable ProviderInternalCallback callbacks,
             @NonNull int userId,
-            @NonNull RemoteCredentialService remoteCredentialService) {
+            @Nullable RemoteCredentialService remoteCredentialService) {
         mContext = context;
         mProviderInfo = info;
         mProviderRequest = providerRequest;
@@ -143,7 +143,7 @@
         return Status.CANCELED;
     }
 
-    protected String generateEntryId() {
+    protected static String generateUniqueId() {
         return UUID.randomUUID().toString();
     }
 
@@ -151,6 +151,18 @@
         return  mFinalCredentialResponse;
     }
 
+    /** Propagates cancellation signal to the remote provider service. */
+    public void cancelProviderRemoteSession() {
+        try {
+            if (mProviderCancellationSignal != null) {
+                mProviderCancellationSignal.cancel();
+            }
+            setStatus(Status.CANCELED);
+        } catch (RemoteException e) {
+            Log.i(TAG, "Issue while cancelling provider session: " + e.getMessage());
+        }
+    }
+
     protected void setStatus(@NonNull Status status) {
         mStatus = status;
     }
@@ -165,7 +177,7 @@
         return mComponentName;
     }
 
-    @NonNull
+    @Nullable
     protected RemoteCredentialService getRemoteCredentialService() {
         return mRemoteCredentialService;
     }
@@ -208,4 +220,8 @@
     /** Should be overridden to handle the selected entry from the UI. */
     protected abstract void onUiEntrySelected(String entryType, String entryId,
             ProviderPendingIntentResponse providerPendingIntentResponse);
+
+    /** Should be overridden to invoke the provider at a defined location. Helpful for
+     * situations such as metric generation. */
+    protected abstract void invokeSession();
 }
diff --git a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
index 8cad6ac..2dea8bd 100644
--- a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
+++ b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
@@ -110,7 +110,7 @@
      * @param callback the callback to be used to send back the provider response to the
      *                 {@link ProviderGetSession} class that maintains provider state
      */
-    public void onBeginGetCredential(@NonNull BeginGetCredentialRequest request,
+    public ICancellationSignal onBeginGetCredential(@NonNull BeginGetCredentialRequest request,
             ProviderCallbacks<BeginGetCredentialResponse> callback) {
         Log.i(TAG, "In onGetCredentials in RemoteCredentialService");
         AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
@@ -149,6 +149,8 @@
         futureRef.set(connectThenExecute);
         connectThenExecute.whenComplete((result, error) -> Handler.getMain().post(() ->
                 handleExecutionResponse(result, error, cancellationSink, callback)));
+
+        return cancellationSink.get();
     }
 
     /** Main entry point to be called for executing a beginCreateCredential call on the remote
@@ -157,7 +159,7 @@
      * @param callback the callback to be used to send back the provider response to the
      *                 {@link ProviderCreateSession} class that maintains provider state
      */
-    public void onCreateCredential(@NonNull BeginCreateCredentialRequest request,
+    public ICancellationSignal onCreateCredential(@NonNull BeginCreateCredentialRequest request,
             ProviderCallbacks<BeginCreateCredentialResponse> callback) {
         Log.i(TAG, "In onCreateCredential in RemoteCredentialService");
         AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
@@ -196,6 +198,8 @@
         futureRef.set(connectThenExecute);
         connectThenExecute.whenComplete((result, error) -> Handler.getMain().post(() ->
                 handleExecutionResponse(result, error, cancellationSink, callback)));
+
+        return cancellationSink.get();
     }
 
     /** Main entry point to be called for executing a clearCredentialState call on the remote
@@ -204,7 +208,7 @@
      * @param callback the callback to be used to send back the provider response to the
      *                 {@link ProviderClearSession} class that maintains provider state
      */
-    public void onClearCredentialState(@NonNull ClearCredentialStateRequest request,
+    public ICancellationSignal onClearCredentialState(@NonNull ClearCredentialStateRequest request,
             ProviderCallbacks<Void> callback) {
         Log.i(TAG, "In onClearCredentialState in RemoteCredentialService");
         AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
@@ -243,6 +247,8 @@
         futureRef.set(connectThenExecute);
         connectThenExecute.whenComplete((result, error) -> Handler.getMain().post(() ->
                 handleExecutionResponse(result, error, cancellationSink, callback)));
+
+        return cancellationSink.get();
     }
 
     private <T> void handleExecutionResponse(T result,
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index f92ffe2..9f1bd8f 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -29,6 +29,7 @@
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.UserSelectionDialogResult;
 import android.os.Binder;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -83,13 +84,16 @@
     private final int mCallingUid;
     @NonNull
     protected final CallingAppInfo mClientAppInfo;
+    @NonNull
+    protected final CancellationSignal mCancellationSignal;
 
     protected final Map<String, ProviderSession> mProviders = new HashMap<>();
 
     protected RequestSession(@NonNull Context context,
             @UserIdInt int userId, int callingUid, @NonNull T clientRequest, U clientCallback,
             @NonNull String requestType,
-            CallingAppInfo callingAppInfo) {
+            CallingAppInfo callingAppInfo,
+            CancellationSignal cancellationSignal) {
         mContext = context;
         mUserId = userId;
         mCallingUid = callingUid;
@@ -97,6 +101,7 @@
         mClientCallback = clientCallback;
         mRequestType = requestType;
         mClientAppInfo = callingAppInfo;
+        mCancellationSignal = cancellationSignal;
         mHandler = new Handler(Looper.getMainLooper(), null, true);
         mRequestId = new Binder();
         mCredentialManagerUi = new CredentialManagerUi(mContext,
@@ -112,6 +117,10 @@
 
     @Override // from CredentialManagerUiCallbacks
     public void onUiSelection(UserSelectionDialogResult selection) {
+        if (isSessionCancelled()) {
+            finishSession(/*propagateCancellation=*/true);
+            return;
+        }
         String providerId = selection.getProviderId();
         Log.i(TAG, "onUiSelection, providerId: " + providerId);
         ProviderSession providerSession = mProviders.get(providerId);
@@ -127,18 +136,19 @@
     @Override // from CredentialManagerUiCallbacks
     public void onUiCancellation(boolean isUserCancellation) {
         Log.i(TAG, "Ui canceled. Canceled by user: " + isUserCancellation);
+        if (isSessionCancelled()) {
+            finishSession(/*propagateCancellation=*/true);
+            return;
+        }
         // User canceled the activity
-        finishSession();
+        finishSession(/*propagateCancellation=*/false);
     }
 
-    protected void finishSession() {
+    protected void finishSession(boolean propagateCancellation) {
         Log.i(TAG, "finishing session");
-        clearProviderSessions();
-    }
-
-    protected void clearProviderSessions() {
-        Log.i(TAG, "Clearing sessions");
-        //TODO: Implement
+        if (propagateCancellation) {
+            mProviders.values().forEach(ProviderSession::cancelProviderRemoteSession);
+        }
         mProviders.clear();
     }
 
@@ -178,6 +188,10 @@
                 isSuccessful ? METRICS_API_STATUS_SUCCESS : METRICS_API_STATUS_FAILURE);
     }
 
+    protected boolean isSessionCancelled() {
+        return mCancellationSignal.isCanceled();
+    }
+
     /**
      * Returns true if at least one provider is ready for UI invocation, and no
      * provider is pending a response.
@@ -197,6 +211,11 @@
         Log.i(TAG, "In getProviderDataAndInitiateUi");
         Log.i(TAG, "In getProviderDataAndInitiateUi providers size: " + mProviders.size());
 
+        if (isSessionCancelled()) {
+            finishSession(/*propagateCancellation=*/true);
+            return;
+        }
+
         ArrayList<ProviderData> providerDataList = new ArrayList<>();
         for (ProviderSession session : mProviders.values()) {
             Log.i(TAG, "preparing data for : " + session.getComponentName());
@@ -208,7 +227,11 @@
         }
         if (!providerDataList.isEmpty()) {
             Log.i(TAG, "provider list not empty about to initiate ui");
-            launchUiWithProviderData(providerDataList);
+            if (isSessionCancelled()) {
+                Log.i(TAG, "In getProviderDataAndInitiateUi but session has been cancelled");
+            } else {
+                launchUiWithProviderData(providerDataList);
+            }
         }
     }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 36cb898..d7a2095 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -1441,8 +1441,7 @@
         if (mManagedSubscriptionsPolicy != null) {
             pw.println("mManagedSubscriptionsPolicy:");
             pw.increaseIndent();
-            pw.print("mPolicyType=");
-            mManagedSubscriptionsPolicy.getPolicyType();
+            pw.println(mManagedSubscriptionsPolicy);
             pw.decreaseIndent();
         }
     }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index cb3b021..27371c0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -20,6 +20,7 @@
 import static android.app.admin.PolicyUpdateResult.RESULT_SUCCESS;
 import static android.app.admin.PolicyUpdatesReceiver.EXTRA_POLICY_TARGET_USER_ID;
 import static android.app.admin.PolicyUpdatesReceiver.EXTRA_POLICY_UPDATE_RESULT_KEY;
+import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -32,6 +33,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.UserProperties;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
@@ -149,6 +151,8 @@
             updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin);
 
             write();
+
+            applyToInheritableProfiles(policyDefinition, enforcingAdmin, value, userId);
         }
     }
 
@@ -200,10 +204,52 @@
             updateDeviceAdminServiceOnPolicyRemoveLocked(enforcingAdmin);
 
             write();
+
+            applyToInheritableProfiles(policyDefinition, enforcingAdmin, /*value */ null, userId);
         }
     }
 
     /**
+     * If any of child user has property {@link UserProperties#INHERIT_DEVICE_POLICY_FROM_PARENT}
+     * set then propagate the policy to it if value is not null
+     * else remove the policy from child.
+     */
+    private <V> void applyToInheritableProfiles(PolicyDefinition<V> policyDefinition,
+            EnforcingAdmin enforcingAdmin, V value, int userId) {
+        if (policyDefinition.isInheritable()) {
+            Binder.withCleanCallingIdentity(() -> {
+                List<UserInfo> userInfos = mUserManager.getProfiles(userId);
+                for (UserInfo childUserInfo : userInfos) {
+                    int childUserId = childUserInfo.getUserHandle().getIdentifier();
+                    if (isProfileOfUser(childUserId, userId)
+                            && isInheritDevicePolicyFromParent(childUserInfo)) {
+                        if (value != null) {
+                            setLocalPolicy(policyDefinition, enforcingAdmin, value, childUserId);
+                        } else {
+                            removeLocalPolicy(policyDefinition, enforcingAdmin, childUserId);
+                        }
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * Checks if given parentUserId is direct parent of childUserId.
+     */
+    private boolean isProfileOfUser(int childUserId, int parentUserId) {
+        UserInfo parentInfo = mUserManager.getProfileParent(childUserId);
+        return childUserId != parentUserId && parentInfo != null
+                && parentInfo.getUserHandle().getIdentifier() == parentUserId;
+    }
+
+    private boolean isInheritDevicePolicyFromParent(UserInfo userInfo) {
+        UserProperties userProperties = mUserManager.getUserProperties(userInfo.getUserHandle());
+        return userProperties != null && mUserManager.getUserProperties(userInfo.getUserHandle())
+                .getInheritDevicePolicy() == INHERIT_DEVICE_POLICY_FROM_PARENT;
+    }
+
+    /**
      * Enforces the new policy and notifies relevant admins.
      */
     private <V> void onLocalPolicyChanged(
@@ -688,6 +734,47 @@
         }
     }
 
+    void handleUserCreated(UserInfo user) {
+        enforcePoliciesOnInheritableProfilesIfApplicable(user);
+    }
+
+    private void enforcePoliciesOnInheritableProfilesIfApplicable(UserInfo user) {
+        if (!user.isProfile()) {
+            return;
+        }
+
+        Binder.withCleanCallingIdentity(() -> {
+            UserProperties userProperties = mUserManager.getUserProperties(user.getUserHandle());
+            if (userProperties == null || userProperties.getInheritDevicePolicy()
+                    != INHERIT_DEVICE_POLICY_FROM_PARENT) {
+                return;
+            }
+
+            int userId = user.id;
+            // Apply local policies present on parent to newly created child profile.
+            UserInfo parentInfo = mUserManager.getProfileParent(userId);
+            if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) return;
+
+            for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
+                    parentInfo.getUserHandle().getIdentifier()).entrySet()) {
+                enforcePolicyOnUser(userId, entry.getValue());
+            }
+        });
+    }
+
+    private <V> void enforcePolicyOnUser(int userId, PolicyState<V> policyState) {
+        if (!policyState.getPolicyDefinition().isInheritable()) {
+            return;
+        }
+        for (Map.Entry<EnforcingAdmin, V> enforcingAdminEntry :
+                policyState.getPoliciesSetByAdmins().entrySet()) {
+            setLocalPolicy(policyState.getPolicyDefinition(),
+                    enforcingAdminEntry.getKey(),
+                    enforcingAdminEntry.getValue(),
+                    userId);
+        }
+    }
+
     /**
      * Handles internal state related to a user getting started.
      */
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9c64054..fbde1ba 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -30,6 +30,7 @@
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_APP_STANDBY;
+import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS;
 import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
 import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED;
 import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
@@ -55,6 +56,7 @@
 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
 import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
 import static android.app.admin.DevicePolicyManager.EXEMPT_FROM_APP_STANDBY;
+import static android.app.admin.DevicePolicyManager.EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS;
 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
 import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_IDS;
 import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_TYPE;
@@ -340,7 +342,6 @@
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.ParcelableKeyGenParameterSpec;
 import android.stats.devicepolicy.DevicePolicyEnums;
-import android.telecom.TelecomManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
@@ -703,6 +704,9 @@
     static {
         APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.put(
                 EXEMPT_FROM_APP_STANDBY, OPSTR_SYSTEM_EXEMPT_FROM_APP_STANDBY);
+        APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.put(
+                EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS,
+                OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS);
     }
 
     /**
@@ -750,6 +754,10 @@
     private static final String HEADLESS_FLAG = "headless";
     private static final boolean DEFAULT_HEADLESS_FLAG = true;
 
+    // TODO(b/266831522) remove the flag after rollout.
+    private static final String APPLICATION_EXEMPTIONS_FLAG = "application_exemptions";
+    private static final boolean DEFAULT_APPLICATION_EXEMPTIONS_FLAG = true;
+
     /**
      * This feature flag is checked once after boot and this value us used until the next reboot to
      * avoid needing to handle the flag changing on the fly.
@@ -7110,11 +7118,20 @@
      * @param factoryReset null: legacy behaviour, false: attempt to remove user, true: attempt to
      *                     factory reset
      */
-    private void wipeDataNoLock(ComponentName admin, int flags, String internalReason,
-            @NonNull String wipeReasonForUser, int userId, boolean calledOnParentInstance,
+    private void wipeDataNoLock(@Nullable ComponentName admin, int flags, String internalReason,
+            String wipeReasonForUser, int userId, boolean calledOnParentInstance,
             @Nullable Boolean factoryReset) {
         wtfIfInLock();
-
+        final String adminPackage;
+        if (admin != null) {
+            adminPackage = admin.getPackageName();
+        } else {
+            int callerId = mInjector.binderGetCallingUid();
+            String[] adminPackages = mInjector.getPackageManager().getPackagesForUid(callerId);
+            Preconditions.checkState(adminPackages.length > 0,
+                    "Caller %s does not have any associated packages", callerId);
+            adminPackage = adminPackages[0];
+        }
         mInjector.binderWithCleanCallingIdentity(() -> {
             // First check whether the admin is allowed to wipe the device/user/profile.
             final String restriction;
@@ -7133,7 +7150,7 @@
             boolean isSystemUser = userId == UserHandle.USER_SYSTEM;
             boolean wipeDevice;
             if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR,
-                    admin.getPackageName(),
+                    adminPackage,
                     userId)) {
                 // Legacy mode
                 wipeDevice = isSystemUser;
@@ -8779,9 +8796,10 @@
     @Override
     public boolean hasDeviceOwner() {
         final CallerIdentity caller = getCallerIdentity();
-        Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
-                        || canManageUsers(caller) || isFinancedDeviceOwner(caller)
-                        || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
+        Preconditions.checkCallAuthorization(
+                isDefaultDeviceOwner(caller) || canManageUsers(caller) || isFinancedDeviceOwner(
+                        caller) || hasCallingOrSelfPermission(
+                        permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
         return mOwners.hasDeviceOwner();
     }
 
@@ -8789,10 +8807,16 @@
         return isDeviceOwner(admin.info.getComponent(), admin.getUserHandle().getIdentifier());
     }
 
-    public boolean isDeviceOwner(ComponentName who, int userId) {
+    /**
+     * Check if the user is a Device Owner
+     *
+     * @param who    component to check against
+     * @param userId user to check
+     * @return if the user is a Device Owner
+     */
+    public boolean isDeviceOwner(@Nullable ComponentName who, int userId) {
         synchronized (getLockObject()) {
-            return mOwners.hasDeviceOwner()
-                    && mOwners.getDeviceOwnerUserId() == userId
+            return mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerUserId() == userId
                     && mOwners.getDeviceOwnerComponent().equals(who);
         }
     }
@@ -8841,9 +8865,16 @@
         }
     }
 
-    public boolean isProfileOwner(ComponentName who, int userId) {
-        final ComponentName profileOwner = mInjector.binderWithCleanCallingIdentity(() ->
-                getProfileOwnerAsUser(userId));
+    /**
+     * Check if {@link userId} is a Profile Owner
+     *
+     * @param who    component to check against
+     * @param userId user to check
+     * @return if the user is a Profile Owner
+     */
+    public boolean isProfileOwner(@Nullable ComponentName who, int userId) {
+        final ComponentName profileOwner = mInjector.binderWithCleanCallingIdentity(
+                () -> getProfileOwnerAsUser(userId));
         return who != null && who.equals(profileOwner);
     }
 
@@ -9321,7 +9352,11 @@
 
     @Override
     public CharSequence getDeviceOwnerLockScreenInfo() {
-        return mLockPatternUtils.getDeviceOwnerInfo();
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(
+                isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
+        return mInjector.binderWithCleanCallingIdentity(() ->
+            mLockPatternUtils.getDeviceOwnerInfo());
     }
 
     private void clearUserPoliciesLocked(int userId) {
@@ -11303,6 +11338,11 @@
         }
 
         final int userId = user.id;
+
+        if (isCoexistenceFlagEnabled()) {
+            mDevicePolicyEngine.handleUserCreated(user);
+        }
+
         if (token != null) {
             synchronized (getLockObject()) {
                 if (mPendingUserCreatedCallbackTokens.contains(token)) {
@@ -11403,8 +11443,8 @@
     }
 
     private boolean isAdminAffectedByRestriction(
-            ComponentName admin, String userRestriction, int userId) {
-        switch(mUserManager.getUserRestrictionSource(userRestriction, UserHandle.of(userId))) {
+            @Nullable ComponentName admin, String userRestriction, int userId) {
+        switch (mUserManager.getUserRestrictionSource(userRestriction, UserHandle.of(userId))) {
             case UserManager.RESTRICTION_NOT_SET:
                 return false;
             case UserManager.RESTRICTION_SOURCE_DEVICE_OWNER:
@@ -14189,6 +14229,14 @@
         public boolean isUserOrganizationManaged(@UserIdInt int userHandle) {
             return getDeviceStateCache().isUserOrganizationManaged(userHandle);
         }
+
+        @Override
+        public boolean isApplicationExemptionsFlagEnabled() {
+            return DeviceConfig.getBoolean(
+                    NAMESPACE_DEVICE_POLICY_MANAGER,
+                    APPLICATION_EXEMPTIONS_FLAG,
+                    DEFAULT_APPLICATION_EXEMPTIONS_FLAG);
+        }
     }
 
     private Intent createShowAdminSupportIntent(int userId) {
@@ -18435,9 +18483,9 @@
                         .addExtras(extras)
                         .build();
 
-        mInjector.getNotificationManager().notifyAsUser(
+        mHandler.post(() -> mInjector.getNotificationManager().notifyAsUser(
                 null, SystemMessage.NOTE_PERSONAL_APPS_SUSPENDED, notification,
-                UserHandle.of(getProfileParentId(profileUserId)));
+                UserHandle.of(getProfileParentId(profileUserId))));
     }
 
     private String getPersonalAppSuspensionButtonText() {
@@ -20254,6 +20302,17 @@
                         DevicePolicyManager.MTE_ENABLED);
         Preconditions.checkArgument(
                 allowedModes.contains(flags), "Provided mode is not one of the allowed values.");
+        // In general, this API should be available when "bootctl_settings_toggle" is set, which
+        // signals that there is a control for MTE in the user settings and this API fundamentally
+        // is a way for the device admin to override that setting.
+        // Allow bootctl_device_policy_manager as an override, e.g. to offer the
+        // DevicePolicyManager only without a visible user setting.
+        if (!mInjector.systemPropertiesGetBoolean(
+                "ro.arm64.memtag.bootctl_device_policy_manager",
+                mInjector.systemPropertiesGetBoolean(
+                        "ro.arm64.memtag.bootctl_settings_toggle", false))) {
+            throw new UnsupportedOperationException("device does not support MTE");
+        }
         final CallerIdentity caller = getCallerIdentity();
         if (flags == DevicePolicyManager.MTE_DISABLED) {
             Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
@@ -20372,7 +20431,7 @@
             final long id = mInjector.binderClearCallingIdentity();
             try {
                 int parentUserId = getProfileParentId(caller.getUserId());
-                installOemDefaultDialerAndMessagesApp(parentUserId, caller.getUserId());
+                installOemDefaultDialerAndSmsApp(caller.getUserId());
                 updateTelephonyCrossProfileIntentFilters(parentUserId, caller.getUserId(), true);
             } finally {
                 mInjector.binderRestoreCallingIdentity(id);
@@ -20380,32 +20439,31 @@
         }
     }
 
-    private void installOemDefaultDialerAndMessagesApp(int sourceUserId, int targetUserId) {
+    private void installOemDefaultDialerAndSmsApp(int targetUserId) {
         try {
-            UserHandle sourceUserHandle = UserHandle.of(sourceUserId);
-            TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
-            String dialerAppPackage = telecomManager.getDefaultDialerPackage(
-                    sourceUserHandle);
-            String messagesAppPackage = SmsApplication.getDefaultSmsApplicationAsUser(mContext,
-                    true, sourceUserHandle).getPackageName();
-            if (dialerAppPackage != null) {
-                mIPackageManager.installExistingPackageAsUser(dialerAppPackage, targetUserId,
-                        PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS,
+            String defaultDialerPackageName = getDefaultRoleHolderPackageName(
+                    com.android.internal.R.string.config_defaultDialer);
+            String defaultSmsPackageName = getDefaultRoleHolderPackageName(
+                    com.android.internal.R.string.config_defaultSms);
+
+            if (defaultDialerPackageName != null) {
+                mIPackageManager.installExistingPackageAsUser(defaultDialerPackageName,
+                        targetUserId, PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS,
                         PackageManager.INSTALL_REASON_POLICY, null);
             } else {
                 Slogf.w(LOG_TAG, "Couldn't install dialer app, dialer app package is null");
             }
 
-            if (messagesAppPackage != null) {
-                mIPackageManager.installExistingPackageAsUser(messagesAppPackage, targetUserId,
+            if (defaultSmsPackageName != null) {
+                mIPackageManager.installExistingPackageAsUser(defaultSmsPackageName, targetUserId,
                         PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS,
                         PackageManager.INSTALL_REASON_POLICY, null);
             } else {
-                Slogf.w(LOG_TAG, "Couldn't install messages app, messages app package is null");
+                Slogf.w(LOG_TAG, "Couldn't install sms app, sms app package is null");
             }
         } catch (RemoteException re) {
             // shouldn't happen
-            Slogf.wtf(LOG_TAG, "Failed to install dialer/messages app", re);
+            Slogf.wtf(LOG_TAG, "Failed to install dialer/sms app", re);
         }
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
index ab1658f..a7c4d5a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
@@ -44,6 +44,9 @@
     // Only use this flag if a policy can not be applied globally.
     private static final int POLICY_FLAG_LOCAL_ONLY_POLICY = 1 << 1;
 
+    // Only use this flag if a policy is inheritable by child profile from parent.
+    private static final int POLICY_FLAG_INHERITABLE = 1 << 2;
+
     private static final MostRestrictive<Boolean> FALSE_MORE_RESTRICTIVE = new MostRestrictive<>(
             List.of(false, true));
 
@@ -210,6 +213,13 @@
         return (mPolicyFlags & POLICY_FLAG_LOCAL_ONLY_POLICY) != 0;
     }
 
+    /**
+     * Returns {@code true} if the policy is inheritable by child profiles.
+     */
+    boolean isInheritable() {
+        return (mPolicyFlags & POLICY_FLAG_INHERITABLE) != 0;
+    }
+
     @Nullable
     V resolvePolicy(LinkedHashMap<EnforcingAdmin, V> adminsPolicy) {
         return mResolutionMechanism.resolve(adminsPolicy);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java
index db0a623..c293e09 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java
@@ -216,4 +216,8 @@
         }
         return new PolicyState<V>(policyDefinition, policiesSetByAdmins, currentResolvedPolicy);
     }
+
+    PolicyDefinition<V> getPolicyDefinition() {
+        return mPolicyDefinition;
+    }
 }
diff --git a/services/java/com/android/server/BootUserInitializer.java b/services/java/com/android/server/BootUserInitializer.java
deleted file mode 100644
index 3d71739..0000000
--- a/services/java/com/android/server/BootUserInitializer.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server;
-
-import android.annotation.UserIdInt;
-import android.content.ContentResolver;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-
-import com.android.server.am.ActivityManagerService;
-import com.android.server.pm.UserManagerInternal;
-import com.android.server.utils.Slogf;
-import com.android.server.utils.TimingsTraceAndSlog;
-
-/**
- * Class responsible for booting the device in the proper user on headless system user mode.
- *
- */
-// TODO(b/204091126): STOPSHIP - provide proper APIs
-final class BootUserInitializer {
-
-    private static final String TAG = BootUserInitializer.class.getSimpleName();
-
-     // TODO(b/204091126): STOPSHIP - set to false or dynamic value
-    private static final boolean DEBUG = true;
-
-    private final ActivityManagerService mAms;
-    private final ContentResolver mContentResolver;
-
-    BootUserInitializer(ActivityManagerService am, ContentResolver contentResolver) {
-        mAms = am;
-        mContentResolver = contentResolver;
-    }
-
-    public void init(TimingsTraceAndSlog t) {
-        Slogf.i(TAG, "init())");
-
-        // TODO(b/204091126): in the long term, we need to decide who's reponsible for that,
-        // this class or the setup wizard app
-        provisionHeadlessSystemUser();
-
-        unlockSystemUser(t);
-
-        try {
-            t.traceBegin("getBootUser");
-            int bootUser = LocalServices.getService(UserManagerInternal.class).getBootUser();
-            t.traceEnd();
-            t.traceBegin("switchToBootUser-" + bootUser);
-            switchToBootUser(bootUser);
-            t.traceEnd();
-        } catch (UserManager.CheckedUserOperationException e) {
-            Slogf.wtf(TAG, "Failed to created boot user", e);
-        }
-    }
-
-    /* TODO(b/261791491): STOPSHIP - SUW should be responsible for this. */
-    private void provisionHeadlessSystemUser() {
-        if (isDeviceProvisioned()) {
-            Slogf.d(TAG, "provisionHeadlessSystemUser(): already provisioned");
-            return;
-        }
-
-        Slogf.i(TAG, "Marking USER_SETUP_COMPLETE for system user");
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1);
-        Slogf.i(TAG, "Marking DEVICE_PROVISIONED for system user");
-        Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 1);
-    }
-
-    private boolean isDeviceProvisioned() {
-        try {
-            return Settings.Global.getInt(mContentResolver,
-                    Settings.Global.DEVICE_PROVISIONED) == 1;
-        } catch (Exception e) {
-            Slogf.wtf(TAG, "DEVICE_PROVISIONED setting not found.", e);
-            return false;
-        }
-    }
-
-    // NOTE: Mostly copied from Automotive's InitialUserSetter
-    private void unlockSystemUser(TimingsTraceAndSlog t) {
-        Slogf.i(TAG, "Unlocking system user");
-        t.traceBegin("unlock-system-user");
-        try {
-            // This is for force changing state into RUNNING_LOCKED. Otherwise unlock does not
-            // update the state and USER_SYSTEM unlock happens twice.
-            t.traceBegin("am.startUser");
-            boolean started = mAms.startUserInBackgroundWithListener(UserHandle.USER_SYSTEM,
-                            /* listener= */ null);
-            t.traceEnd();
-            if (!started) {
-                Slogf.w(TAG, "could not restart system user in background; trying unlock instead");
-                t.traceBegin("am.unlockUser");
-                boolean unlocked = mAms.unlockUser(UserHandle.USER_SYSTEM, /* token= */ null,
-                        /* secret= */ null, /* listener= */ null);
-                t.traceEnd();
-                if (!unlocked) {
-                    Slogf.w(TAG, "could not unlock system user either");
-                    return;
-                }
-            }
-        } finally {
-            t.traceEnd();
-        }
-    }
-
-    private void switchToBootUser(@UserIdInt int bootUserId) {
-        Slogf.i(TAG, "Switching to boot user %d", bootUserId);
-        boolean started = mAms.startUserInForegroundWithListener(bootUserId,
-                /* unlockListener= */ null);
-        if (!started) {
-            Slogf.wtf(TAG, "Failed to start user %d in foreground", bootUserId);
-        }
-    }
-}
diff --git a/services/java/com/android/server/HsumBootUserInitializer.java b/services/java/com/android/server/HsumBootUserInitializer.java
new file mode 100644
index 0000000..c4ad80e
--- /dev/null
+++ b/services/java/com/android/server/HsumBootUserInitializer.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server;
+
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.ContentResolver;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import com.android.server.am.ActivityManagerService;
+import com.android.server.pm.UserManagerInternal;
+import com.android.server.utils.Slogf;
+import com.android.server.utils.TimingsTraceAndSlog;
+
+/**
+ * Class responsible for booting the device in the proper user on headless system user mode.
+ *
+ */
+final class HsumBootUserInitializer {
+
+    private static final String TAG = HsumBootUserInitializer.class.getSimpleName();
+
+    private final UserManagerInternal mUmi;
+    private final ActivityManagerService mAms;
+    private final ContentResolver mContentResolver;
+
+    private final ContentObserver mDeviceProvisionedObserver =
+            new ContentObserver(new Handler(Looper.getMainLooper())) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    // Set USER_SETUP_COMPLETE for the (headless) system user only when the device
+                    // has been set up at least once.
+                    if (isDeviceProvisioned()) {
+                        Slogf.i(TAG, "Marking USER_SETUP_COMPLETE for system user");
+                        Settings.Secure.putInt(mContentResolver,
+                                Settings.Secure.USER_SETUP_COMPLETE, 1);
+                        mContentResolver.unregisterContentObserver(mDeviceProvisionedObserver);
+                    }
+                }
+            };
+
+    /** Whether this device should always have a non-removable MainUser, including at first boot. */
+    private final boolean mShouldAlwaysHaveMainUser;
+
+    /** Static factory method for creating a {@link HsumBootUserInitializer} instance. */
+    public static @Nullable HsumBootUserInitializer createInstance(ActivityManagerService am,
+            ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser) {
+
+        if (!UserManager.isHeadlessSystemUserMode()) {
+            return null;
+        }
+        return new HsumBootUserInitializer(
+                LocalServices.getService(UserManagerInternal.class),
+                am, contentResolver, shouldAlwaysHaveMainUser);
+    }
+
+    private HsumBootUserInitializer(UserManagerInternal umi, ActivityManagerService am,
+            ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser) {
+        mUmi = umi;
+        mAms = am;
+        mContentResolver = contentResolver;
+        this.mShouldAlwaysHaveMainUser = shouldAlwaysHaveMainUser;
+    }
+
+    /**
+     * Initialize this object, and create MainUser if needed.
+     *
+     * Should be called before PHASE_SYSTEM_SERVICES_READY as services' setups may require MainUser,
+     * but probably after PHASE_LOCK_SETTINGS_READY since that may be needed for user creation.
+     */
+    public void init(TimingsTraceAndSlog t) {
+        Slogf.i(TAG, "init())");
+
+        if (mShouldAlwaysHaveMainUser) {
+            t.traceBegin("createMainUserIfNeeded");
+            createMainUserIfNeeded();
+            t.traceEnd();
+        }
+    }
+
+    private void createMainUserIfNeeded() {
+        int mainUser = mUmi.getMainUserId();
+        if (mainUser != UserHandle.USER_NULL) {
+            Slogf.d(TAG, "Found existing MainUser, userId=%d", mainUser);
+            return;
+        }
+
+        Slogf.d(TAG, "Creating a new MainUser");
+        try {
+            final UserInfo newInitialUser = mUmi.createUserEvenWhenDisallowed(
+                    /* name= */ null, // null will appear as "Owner" in on-demand localisation
+                    UserManager.USER_TYPE_FULL_SECONDARY,
+                    UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN,
+                    /* disallowedPackages= */ null,
+                    /* token= */ null);
+            if (newInitialUser == null) {
+                Slogf.wtf(TAG, "Initial bootable MainUser creation failed: returned null");
+            } else {
+                Slogf.i(TAG, "Successfully created MainUser, userId=%d", newInitialUser.id);
+            }
+        } catch (UserManager.CheckedUserOperationException e) {
+            Slogf.wtf(TAG, "Initial bootable MainUser creation failed", e);
+        }
+    }
+
+    /**
+     * Put the device into the correct user state: unlock the system and switch to the boot user.
+     *
+     * Should only call once PHASE_THIRD_PARTY_APPS_CAN_START is reached to ensure that privileged
+     * apps have had the chance to set the boot user, if applicable.
+     */
+    public void systemRunning(TimingsTraceAndSlog t) {
+        observeDeviceProvisioning();
+        unlockSystemUser(t);
+
+        try {
+            t.traceBegin("getBootUser");
+            final int bootUser = mUmi.getBootUser();
+            t.traceEnd();
+            t.traceBegin("switchToBootUser-" + bootUser);
+            switchToBootUser(bootUser);
+            t.traceEnd();
+        } catch (UserManager.CheckedUserOperationException e) {
+            Slogf.wtf(TAG, "Failed to switch to boot user since there isn't one.");
+        }
+    }
+
+    private void observeDeviceProvisioning() {
+        if (isDeviceProvisioned()) {
+            return;
+        }
+
+        mContentResolver.registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
+                false,
+                mDeviceProvisionedObserver
+        );
+    }
+
+    private boolean isDeviceProvisioned() {
+        try {
+            return Settings.Global.getInt(mContentResolver,
+                    Settings.Global.DEVICE_PROVISIONED) == 1;
+        } catch (Exception e) {
+            Slogf.wtf(TAG, "DEVICE_PROVISIONED setting not found.", e);
+            return false;
+        }
+    }
+
+    // NOTE: Mostly copied from Automotive's InitialUserSetter
+    private void unlockSystemUser(TimingsTraceAndSlog t) {
+        Slogf.i(TAG, "Unlocking system user");
+        t.traceBegin("unlock-system-user");
+        try {
+            // This is for force changing state into RUNNING_LOCKED. Otherwise unlock does not
+            // update the state and USER_SYSTEM unlock happens twice.
+            t.traceBegin("am.startUser");
+            boolean started = mAms.startUserInBackgroundWithListener(UserHandle.USER_SYSTEM,
+                            /* listener= */ null);
+            t.traceEnd();
+            if (!started) {
+                Slogf.w(TAG, "could not restart system user in background; trying unlock instead");
+                t.traceBegin("am.unlockUser");
+                boolean unlocked = mAms.unlockUser(UserHandle.USER_SYSTEM, /* token= */ null,
+                        /* secret= */ null, /* listener= */ null);
+                t.traceEnd();
+                if (!unlocked) {
+                    Slogf.w(TAG, "could not unlock system user either");
+                    return;
+                }
+            }
+        } finally {
+            t.traceEnd();
+        }
+    }
+
+    private void switchToBootUser(@UserIdInt int bootUserId) {
+        Slogf.i(TAG, "Switching to boot user %d", bootUserId);
+        boolean started = mAms.startUserInForegroundWithListener(bootUserId,
+                /* unlockListener= */ null);
+        if (!started) {
+            Slogf.wtf(TAG, "Failed to start user %d in foreground", bootUserId);
+        }
+    }
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a15c6d2..cae6c39 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -38,6 +38,7 @@
 import android.app.SystemServiceRegistry;
 import android.app.admin.DevicePolicySafetyChecker;
 import android.app.usage.UsageStatsManagerInternal;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -75,7 +76,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.os.storage.IStorageManager;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
@@ -427,6 +427,9 @@
             "com.android.server.sdksandbox.SdkSandboxManagerService$Lifecycle";
     private static final String AD_SERVICES_MANAGER_SERVICE_CLASS =
             "com.android.server.adservices.AdServicesManagerService$Lifecycle";
+    private static final String ON_DEVICE_PERSONALIZATION_SYSTEM_SERVICE_CLASS =
+            "com.android.server.ondevicepersonalization."
+                    + "OnDevicePersonalizationSystemService$Lifecycle";
     private static final String UPDATABLE_DEVICE_CONFIG_SERVICE_CLASS =
             "com.android.server.deviceconfig.DeviceConfigInit$Lifecycle";
 
@@ -2619,6 +2622,11 @@
         mSystemServiceManager.startService(AD_SERVICES_MANAGER_SERVICE_CLASS);
         t.traceEnd();
 
+        // OnDevicePersonalizationSystemService
+        t.traceBegin("StartOnDevicePersonalizationSystemService");
+        mSystemServiceManager.startService(ON_DEVICE_PERSONALIZATION_SYSTEM_SERVICE_CLASS);
+        t.traceEnd();
+
         if (safeMode) {
             mActivityManagerService.enterSafeMode();
         }
@@ -2694,6 +2702,18 @@
         mSystemServiceManager.startBootPhase(t, SystemService.PHASE_LOCK_SETTINGS_READY);
         t.traceEnd();
 
+        // Create initial user if needed, which should be done early since some system services rely
+        // on it in their setup, but likely needs to be done after LockSettingsService is ready.
+        final HsumBootUserInitializer hsumBootUserInitializer =
+                HsumBootUserInitializer.createInstance(
+                        mActivityManagerService, mContentResolver,
+                        context.getResources().getBoolean(R.bool.config_isMainUserPermanentAdmin));
+        if (hsumBootUserInitializer != null) {
+            t.traceBegin("HsumBootUserInitializer.init");
+            hsumBootUserInitializer.init(t);
+            t.traceEnd();
+        }
+
         t.traceBegin("StartBootPhaseSystemServicesReady");
         mSystemServiceManager.startBootPhase(t, SystemService.PHASE_SYSTEM_SERVICES_READY);
         t.traceEnd();
@@ -2883,6 +2903,27 @@
                 t.traceEnd();
             }
 
+            if (isWatch) {
+                t.traceBegin("StartWearService");
+                String wearServiceComponentNameString =
+                    context.getString(R.string.config_wearServiceComponent);
+
+                if (!TextUtils.isEmpty(wearServiceComponentNameString)) {
+                    ComponentName wearServiceComponentName = ComponentName.unflattenFromString(
+                        wearServiceComponentNameString);
+
+                    if (wearServiceComponentName != null) {
+                        Intent intent = new Intent();
+                        intent.setComponent(wearServiceComponentName);
+                        intent.addFlags(Intent.FLAG_DIRECT_BOOT_AUTO);
+                        context.startServiceAsUser(intent, UserHandle.SYSTEM);
+                    } else {
+                        Slog.d(TAG, "Null wear service component name.");
+                    }
+                }
+                t.traceEnd();
+            }
+
             // Enable airplane mode in safe mode. setAirplaneMode() cannot be called
             // earlier as it sends broadcasts to other services.
             // TODO: This may actually be too late if radio firmware already started leaking
@@ -2961,10 +3002,10 @@
             mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
             t.traceEnd();
 
-            if (UserManager.isHeadlessSystemUserMode() && !isAutomotive) {
-                // TODO(b/204091126): remove isAutomotive check once the workflow is finalized
-                t.traceBegin("BootUserInitializer");
-                new BootUserInitializer(mActivityManagerService, mContentResolver).init(t);
+            if (hsumBootUserInitializer != null && !isAutomotive) {
+                // TODO(b/261924826): remove isAutomotive check once the workflow is finalized
+                t.traceBegin("HsumBootUserInitializer.systemRunning");
+                hsumBootUserInitializer.systemRunning(t);
                 t.traceEnd();
             }
 
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
index f2cff62..a26b2ac 100644
--- a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
@@ -71,6 +71,10 @@
         return opNameMapToOpIntMap(getUidModes(uid))
     }
 
+    override fun getNonDefaultPackageModes(packageName: String, userId: Int): SparseIntArray {
+        return opNameMapToOpIntMap(getPackageModes(packageName, userId))
+    }
+
     override fun getUidMode(uid: Int, op: Int): Int {
         val appId = UserHandle.getAppId(uid)
         val userId = UserHandle.getUserId(uid)
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
index 0962b0d..59551a3 100644
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
@@ -39,7 +39,6 @@
 import com.android.server.permission.access.util.hasAnyBit
 import com.android.server.permission.access.util.hasBits
 import com.android.server.permission.access.util.isInternal
-import com.android.server.permission.access.util.isRuntime
 import com.android.server.pm.KnownPackages
 import com.android.server.pm.parsing.PackageInfoUtils
 import com.android.server.pm.permission.CompatibilityPermissionInfo
@@ -197,7 +196,9 @@
 
         val changedPermissionNames = IndexedSet<String>()
         trimPermissions(packageName, changedPermissionNames)
-        trimPermissionStates(appId)
+        if (appId in newState.systemState.appIds) {
+            trimPermissionStates(appId)
+        }
         changedPermissionNames.forEachIndexed { _, permissionName ->
             evaluatePermissionStateForAllPackages(permissionName, null)
         }
@@ -224,9 +225,8 @@
             if (permission.isRemoved) {
                 return@forEachIndexed
             }
-            val isRequestedByOtherPackages = anyPackageInAppId(appId) { packageState ->
-                packageState.packageName != packageName &&
-                    permissionName in packageState.androidPackage!!.requestedPermissions
+            val isRequestedByOtherPackages = anyRequestingPackageInAppId(appId, permissionName) {
+                it.packageName != packageName
             }
             if (isRequestedByOtherPackages) {
                 return@forEachIndexed
@@ -618,12 +618,12 @@
                     newTargetSdkVersion < Build.VERSION_CODES.Q
                 val isTargetSdkVersionUpgraded = oldTargetSdkVersion < Build.VERSION_CODES.Q &&
                     newTargetSdkVersion >= Build.VERSION_CODES.Q
-                val oldIsRequestLegacyExternalStorage = anyPackageInAppId(appId, oldState) {
-                    it.androidPackage!!.isRequestLegacyExternalStorage
-                }
-                val newIsRequestLegacyExternalStorage = anyPackageInAppId(appId, newState) {
-                    it.androidPackage!!.isRequestLegacyExternalStorage
-                }
+                val oldIsRequestLegacyExternalStorage = anyRequestingPackageInAppId(
+                    appId, permissionName, oldState
+                ) { it.androidPackage!!.isRequestLegacyExternalStorage }
+                val newIsRequestLegacyExternalStorage = anyRequestingPackageInAppId(
+                    appId, permissionName, newState
+                ) { it.androidPackage!!.isRequestLegacyExternalStorage }
                 val isNewlyRequestingLegacyExternalStorage = !isTargetSdkVersionUpgraded &&
                     !oldIsRequestLegacyExternalStorage && newIsRequestLegacyExternalStorage
                 if ((isNewlyRequestingLegacyExternalStorage || isTargetSdkVersionDowngraded) &&
@@ -644,9 +644,8 @@
         val systemState = newState.systemState
         systemState.userIds.forEachIndexed { _, userId ->
             systemState.appIds.forEachKeyIndexed { _, appId ->
-                val isPermissionRequested = anyPackageInAppId(appId) { packageState ->
-                    permissionName in packageState.androidPackage!!.requestedPermissions
-                }
+                val isPermissionRequested =
+                    anyRequestingPackageInAppId(appId, permissionName) { true }
                 if (isPermissionRequested) {
                     evaluatePermissionState(appId, userId, permissionName, installedPackageState)
                 }
@@ -708,10 +707,9 @@
                 val wasRevoked = oldFlags.hasBits(PermissionFlags.INSTALL_REVOKED)
                 val isRequestedByInstalledPackage = installedPackageState != null &&
                     permissionName in installedPackageState.androidPackage!!.requestedPermissions
-                val isRequestedBySystemPackage = anyPackageInAppId(appId) {
-                    it.isSystem && permissionName in it.androidPackage!!.requestedPermissions
-                }
-                val isCompatibilityPermission = anyPackageInAppId(appId) {
+                val isRequestedBySystemPackage =
+                    anyRequestingPackageInAppId(appId, permissionName) { it.isSystem }
+                val isCompatibilityPermission = anyRequestingPackageInAppId(appId, permissionName) {
                     isCompatibilityPermissionForPackage(it.androidPackage!!, permissionName)
                 }
                 // If this is an existing, non-system package,
@@ -732,18 +730,19 @@
                 PermissionFlags.PROTECTION_GRANTED
             } else {
                 val mayGrantByPrivileged = !permission.isPrivileged || (
-                    anyPackageInAppId(appId) {
+                    anyRequestingPackageInAppId(appId, permissionName) {
                         checkPrivilegedPermissionAllowlist(it, permission)
                     }
                 )
                 val shouldGrantBySignature = permission.isSignature && (
-                    anyPackageInAppId(appId) {
+                    anyRequestingPackageInAppId(appId, permissionName) {
                         shouldGrantPermissionBySignature(it, permission)
                     }
                 )
-                val shouldGrantByProtectionFlags = anyPackageInAppId(appId) {
-                    shouldGrantPermissionByProtectionFlags(it, permission)
-                }
+                val shouldGrantByProtectionFlags =
+                    anyRequestingPackageInAppId(appId, permissionName) {
+                        shouldGrantPermissionByProtectionFlags(it, permission)
+                    }
                 if (mayGrantByPrivileged &&
                     (shouldGrantBySignature || shouldGrantByProtectionFlags)) {
                     PermissionFlags.PROTECTION_GRANTED
@@ -785,11 +784,12 @@
                     }
                 }
             } else {
+                val wasGrantedByLegacy = newFlags.hasBits(PermissionFlags.LEGACY_GRANTED)
                 newFlags = newFlags andInv PermissionFlags.LEGACY_GRANTED
                 val wasGrantedByImplicit = newFlags.hasBits(PermissionFlags.IMPLICIT_GRANTED)
                 val isLeanbackNotificationsPermission = newState.systemState.isLeanback &&
                     permissionName in NOTIFICATIONS_PERMISSIONS
-                val isImplicitPermission = anyPackageInAppId(appId) {
+                val isImplicitPermission = anyRequestingPackageInAppId(appId, permissionName) {
                     permissionName in it.androidPackage!!.implicitPermissions
                 }
                 val sourcePermissions = newState.systemState
@@ -808,10 +808,16 @@
                 } else {
                     newFlags = newFlags andInv PermissionFlags.IMPLICIT_GRANTED
                 }
+                if ((wasGrantedByLegacy || wasGrantedByImplicit) && !shouldGrantByImplicit) {
+                    // The permission was granted from a compatibility grant or an implicit grant,
+                    // however this flag might still be set if the user denied this permission in
+                    // the settings. Hence upon app upgrade and when this permission is no longer
+                    // LEGACY_GRANTED or IMPLICIT_GRANTED and we revoke the permission, we want to
+                    // remove this flag so that the app can request the permission again.
+                    newFlags = newFlags andInv PermissionFlags.APP_OP_REVOKED
+                }
                 val hasImplicitFlag = newFlags.hasBits(PermissionFlags.IMPLICIT)
                 if (!isImplicitPermission && hasImplicitFlag) {
-                    // TODO: We might not want to remove the IMPLICIT flag
-                    // for NOTIFICATION_PERMISSIONS
                     newFlags = newFlags andInv PermissionFlags.IMPLICIT
                     var shouldRetainAsNearbyDevices = false
                     if (permissionName in NEARBY_DEVICES_PERMISSIONS) {
@@ -997,12 +1003,7 @@
         permissionName: String
     ): Boolean? {
         val permissionAllowlist = newState.systemState.permissionAllowlist
-        // TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName.
-        // val apexModuleName = androidPackage.apexModuleName
-        val apexModuleName = permissionAllowlist.apexPrivilegedAppAllowlists
-            .firstNotNullOfOrNullIndexed { _, apexModuleName, apexAllowlist ->
-                if (packageState.packageName in apexAllowlist) apexModuleName else null
-            }
+        val apexModuleName = packageState.apexModuleName
         val packageName = packageState.packageName
         return when {
             packageState.isVendor -> permissionAllowlist.getVendorPrivilegedAppAllowlistState(
@@ -1043,24 +1044,24 @@
         state: AccessState = newState
     ): Int {
         var targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT
-        forEachPackageInAppId(appId, state) { packageState ->
-            val androidPackage = packageState.androidPackage!!
-            if (permissionName in androidPackage.requestedPermissions) {
-                targetSdkVersion = targetSdkVersion.coerceAtMost(androidPackage.targetSdkVersion)
-            }
+        forEachRequestingPackageInAppId(appId, permissionName, state) {
+            targetSdkVersion = targetSdkVersion.coerceAtMost(it.androidPackage!!.targetSdkVersion)
         }
         return targetSdkVersion
     }
 
-    private inline fun MutateStateScope.anyPackageInAppId(
+    private inline fun MutateStateScope.anyRequestingPackageInAppId(
         appId: Int,
+        permissionName: String,
         state: AccessState = newState,
         predicate: (PackageState) -> Boolean
     ): Boolean {
         val packageNames = state.systemState.appIds[appId]
         return packageNames.anyIndexed { _, packageName ->
             val packageState = state.systemState.packageStates[packageName]!!
-            packageState.androidPackage != null && predicate(packageState)
+            val androidPackage = packageState.androidPackage
+            androidPackage != null && permissionName in androidPackage.requestedPermissions &&
+                predicate(packageState)
         }
     }
 
@@ -1069,7 +1070,7 @@
         state: AccessState = newState,
         action: (PackageState) -> Unit
     ) {
-        val packageNames = state.systemState.appIds[appId]
+        val packageNames = state.systemState.appIds[appId]!!
         packageNames.forEachIndexed { _, packageName ->
             val packageState = state.systemState.packageStates[packageName]!!
             if (packageState.androidPackage != null) {
@@ -1078,6 +1079,22 @@
         }
     }
 
+    private inline fun MutateStateScope.forEachRequestingPackageInAppId(
+        appId: Int,
+        permissionName: String,
+        state: AccessState = newState,
+        action: (PackageState) -> Unit
+    ) {
+        val packageNames = state.systemState.appIds[appId]
+        packageNames.forEachIndexed { _, packageName ->
+            val packageState = state.systemState.packageStates[packageName]!!
+            val androidPackage = packageState.androidPackage
+            if (androidPackage != null && permissionName in androidPackage.requestedPermissions) {
+                action(packageState)
+            }
+        }
+    }
+
     private fun MutateStateScope.shouldGrantPermissionByProtectionFlags(
         packageState: PackageState,
         permission: Permission
@@ -1177,9 +1194,7 @@
             // Special permission for the recents app.
             return true
         }
-        // TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName.
-        // This should be androidPackage.apexModuleName instead
-        if (permission.isModule && androidPackage.packageName != null) {
+        if (permission.isModule && packageState.apexModuleName != null) {
             // Special permission granted for APKs inside APEX modules.
             return true
         }
@@ -1384,11 +1399,11 @@
             Manifest.permission.READ_MEDIA_VIDEO,
         )
 
-        // TODO: also add the permission NEARBY_WIFI_DEVICES to this set
         private val NEARBY_DEVICES_PERMISSIONS = indexedSetOf(
             Manifest.permission.BLUETOOTH_ADVERTISE,
             Manifest.permission.BLUETOOTH_CONNECT,
-            Manifest.permission.BLUETOOTH_SCAN
+            Manifest.permission.BLUETOOTH_SCAN,
+            Manifest.permission.NEARBY_WIFI_DEVICES
         )
 
         private val NOTIFICATIONS_PERMISSIONS = indexedSetOf(
diff --git a/services/proguard.flags b/services/proguard.flags
index ba4560f..c133044 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -103,7 +103,7 @@
 -keep,allowoptimization,allowaccessmodification class com.android.server.storage.AppFuseBridge { *; }
 -keep,allowoptimization,allowaccessmodification class com.android.server.tv.TvInputHal { *; }
 -keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbAlsaJackDetector { *; }
--keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbMidiDevice { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbAlsaMidiDevice { *; }
 -keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.VibratorController$OnVibrationCompleteListener { *; }
 -keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.VibratorManagerService$OnSyncedVibrationCompleteListener { *; }
 -keepclasseswithmembers,allowoptimization,allowaccessmodification class com.android.server.** {
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 1abcf38..bfbc0f5 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -267,7 +267,7 @@
         LocalServices.removeServiceForTest(PackageManagerInternal.class);
         LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
         mBackupEligibilityRules = new BackupEligibilityRules(mPackageManager,
-                LocalServices.getService(PackageManagerInternal.class), USER_ID,
+                LocalServices.getService(PackageManagerInternal.class), USER_ID, mContext,
                 BACKUP_DESTINATION);
     }
 
diff --git a/services/searchui/java/com/android/server/searchui/SearchUiManagerService.java b/services/searchui/java/com/android/server/searchui/SearchUiManagerService.java
index 524002a..29ad537 100644
--- a/services/searchui/java/com/android/server/searchui/SearchUiManagerService.java
+++ b/services/searchui/java/com/android/server/searchui/SearchUiManagerService.java
@@ -125,6 +125,26 @@
                     (service) -> service.queryLocked(sessionId, query, callback));
         }
 
+        public void registerEmptyQueryResultUpdateCallback(@NonNull SearchSessionId sessionId,
+                @NonNull ISearchCallback callback) {
+            runForUserLocked("registerEmptyQueryResultUpdateCallback", sessionId,
+                    (service) -> service.registerEmptyQueryResultUpdateCallbackLocked(sessionId,
+                            callback));
+        }
+
+        public void unregisterEmptyQueryResultUpdateCallback(@NonNull SearchSessionId sessionId,
+                @NonNull ISearchCallback callback) {
+            runForUserLocked("unregisterEmptyQueryResultUpdateCallback", sessionId,
+                    (service) -> service.unregisterEmptyQueryResultUpdateCallbackLocked(sessionId,
+                            callback));
+        }
+
+        @Override
+        public void requestEmptyQueryResultUpdate(@NonNull SearchSessionId sessionId) {
+            runForUserLocked("requestEmptyQueryResultUpdate", sessionId,
+                    (service) -> service.requestEmptyQueryResultUpdateLocked(sessionId));
+        }
+
         @Override
         public void destroySearchSession(@NonNull SearchSessionId sessionId) {
             runForUserLocked("destroySearchSession", sessionId,
diff --git a/services/searchui/java/com/android/server/searchui/SearchUiPerUserService.java b/services/searchui/java/com/android/server/searchui/SearchUiPerUserService.java
index 4c31978..0d70fff 100644
--- a/services/searchui/java/com/android/server/searchui/SearchUiPerUserService.java
+++ b/services/searchui/java/com/android/server/searchui/SearchUiPerUserService.java
@@ -149,6 +149,48 @@
     }
 
     /**
+     * Registers a callback for continuous updates of search targets for empty query result used for
+     * zero state.
+     */
+    @GuardedBy("mLock")
+    public void registerEmptyQueryResultUpdateCallbackLocked(@NonNull SearchSessionId sessionId,
+            @NonNull ISearchCallback callback) {
+        final SearchSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+        if (sessionInfo == null) return;
+        final boolean serviceExists = resolveService(sessionId,
+                s -> s.onRegisterEmptyQueryResultUpdateCallback(sessionId, callback));
+        if (serviceExists) {
+            sessionInfo.addCallbackLocked(callback);
+        }
+    }
+
+    /**
+     * Unregisters a callback for continuous updates of search targets for empty query result
+     * used for zero state.
+     */
+    @GuardedBy("mLock")
+    public void unregisterEmptyQueryResultUpdateCallbackLocked(@NonNull SearchSessionId sessionId,
+            @NonNull ISearchCallback callback) {
+        final SearchSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+        if (sessionInfo == null) return;
+        final boolean serviceExists = resolveService(sessionId,
+                s -> s.onUnregisterEmptyQueryResultUpdateCallback(sessionId, callback));
+        if (serviceExists) {
+            sessionInfo.removeCallbackLocked(callback);
+        }
+    }
+
+    /**
+     * Requests a new set of search targets for empty query result used for zero state.
+     */
+    @GuardedBy("mLock")
+    public void requestEmptyQueryResultUpdateLocked(@NonNull SearchSessionId sessionId) {
+        final SearchSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+        if (sessionInfo == null) return;
+        resolveService(sessionId, s->s.onRequestEmptyQueryResultUpdate(sessionId));
+    }
+
+    /**
      * Notifies the service of the end of an existing search session.
      */
     @GuardedBy("mLock")
@@ -310,18 +352,7 @@
         final IBinder.DeathRecipient mDeathRecipient;
 
         private final RemoteCallbackList<ISearchCallback> mCallbacks =
-                new RemoteCallbackList<ISearchCallback>() {
-                    @Override
-                    public void onCallbackDied(ISearchCallback callback) {
-                        if (DEBUG) {
-                            Slog.d(TAG, "Binder died for session Id=" + mSessionId
-                                    + " and callback=" + callback.asBinder());
-                        }
-                        if (mCallbacks.getRegisteredCallbackCount() == 0) {
-                            destroy();
-                        }
-                    }
-                };
+                new RemoteCallbackList<>();
 
         SearchSessionInfo(
                 @NonNull final SearchSessionId id,
@@ -337,6 +368,22 @@
             mDeathRecipient = deathRecipient;
         }
 
+        void addCallbackLocked(ISearchCallback callback) {
+            if (DEBUG) {
+                Slog.d(TAG, "Storing callback for session Id=" + mSessionId
+                        + " and callback=" + callback.asBinder());
+            }
+            mCallbacks.register(callback);
+        }
+
+        void removeCallbackLocked(ISearchCallback callback) {
+            if (DEBUG) {
+                Slog.d(TAG, "Removing callback for session Id=" + mSessionId
+                        + " and callback=" + callback.asBinder());
+            }
+            mCallbacks.unregister(callback);
+        }
+
         boolean linkToDeath() {
             try {
                 mToken.linkToDeath(mDeathRecipient, 0);
@@ -369,6 +416,9 @@
                         + callbackCount + " callbacks.");
             }
             service.onCreateSearchSessionLocked(mSearchContext, mSessionId, token);
+            mCallbacks.broadcast(
+                    callback -> service.registerEmptyQueryResultUpdateCallbackLocked(mSessionId,
+                            callback));
         }
     }
 }
diff --git a/services/tests/BackgroundInstallControlServiceTests/OWNERS b/services/tests/BackgroundInstallControlServiceTests/OWNERS
new file mode 100644
index 0000000..ca84550
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/transparency/OWNERS
diff --git a/services/tests/BackgroundInstallControlServiceTests/host/Android.bp b/services/tests/BackgroundInstallControlServiceTests/host/Android.bp
new file mode 100644
index 0000000..4fcdbfc
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/host/Android.bp
@@ -0,0 +1,40 @@
+// 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_test_host {
+    name: "BackgroundInstallControlServiceHostTest",
+    srcs: ["src/**/*.java"],
+    libs: [
+        "tradefed",
+        "compatibility-tradefed",
+        "compatibility-host-util",
+    ],
+    data: [
+        ":BackgroundInstallControlServiceTestApp",
+        ":BackgroundInstallControlMockApp1",
+        ":BackgroundInstallControlMockApp2",
+    ],
+    test_suites: [
+        "general-tests",
+    ],
+}
diff --git a/services/tests/BackgroundInstallControlServiceTests/host/AndroidTest.xml b/services/tests/BackgroundInstallControlServiceTests/host/AndroidTest.xml
new file mode 100644
index 0000000..1e7a78a
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/host/AndroidTest.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+<configuration description="Background Install Control Service integration test">
+    <option name="test-suite-tag" value="apct" />
+
+    <!-- Service is not exposed to apps. Disable SELinux for testing purpose. -->
+    <target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="install-arg" value="-t" />
+        <option name="test-file-name" value="BackgroundInstallControlServiceTestApp.apk" />
+    </target_preparer>
+
+    <!-- Load additional APKs onto device -->
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file"
+                key="BackgroundInstallControlMockApp1.apk"
+                value="/data/local/tmp/BackgroundInstallControlMockApp1.apk" />
+        <option name="push-file"
+                key="BackgroundInstallControlMockApp2.apk"
+                value="/data/local/tmp/BackgroundInstallControlMockApp2.apk" />
+    </target_preparer>
+
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="BackgroundInstallControlServiceHostTest.jar" />
+    </test>
+</configuration>
diff --git a/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java b/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java
new file mode 100644
index 0000000..7450607
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.pm.test;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+// TODO: Add @Presubmit
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class BackgroundInstallControlServiceHostTest extends BaseHostJUnit4Test {
+    private static final String PACKAGE_NAME = "com.android.server.pm.test.app";
+
+    private static final String MOCK_PACKAGE_NAME_1 = "com.android.servicestests.apps.bicmockapp1";
+    private static final String MOCK_PACKAGE_NAME_2 = "com.android.servicestests.apps.bicmockapp2";
+
+    private static final String TEST_DATA_DIR = "/data/local/tmp/";
+
+    private static final String MOCK_APK_FILE_1 = "BackgroundInstallControlMockApp1.apk";
+    private static final String MOCK_APK_FILE_2 = "BackgroundInstallControlMockApp2.apk";
+
+    @Test
+    public void testGetMockBackgroundInstalledPackages() throws Exception {
+        installPackage(TEST_DATA_DIR  + MOCK_APK_FILE_1);
+        installPackage(TEST_DATA_DIR + MOCK_APK_FILE_2);
+
+        assertThat(getDevice().getAppPackageInfo(MOCK_PACKAGE_NAME_1)).isNotNull();
+        assertThat(getDevice().getAppPackageInfo(MOCK_PACKAGE_NAME_2)).isNotNull();
+
+        assertThat(getDevice().setProperty("debug.transparency.bg-install-apps",
+                    MOCK_PACKAGE_NAME_1 + "," + MOCK_PACKAGE_NAME_2)).isTrue();
+        runDeviceTest("testGetMockBackgroundInstalledPackages");
+        assertThat(getDevice().uninstallPackage(MOCK_PACKAGE_NAME_1)).isNull();
+        assertThat(getDevice().uninstallPackage(MOCK_PACKAGE_NAME_2)).isNull();
+
+        assertThat(getDevice().getAppPackageInfo(MOCK_PACKAGE_NAME_1)).isNull();
+        assertThat(getDevice().getAppPackageInfo(MOCK_PACKAGE_NAME_2)).isNull();
+    }
+
+    private void installPackage(String path) throws DeviceNotAvailableException {
+        String cmd = "pm install -t --force-queryable " + path;
+        CommandResult result = getDevice().executeShellV2Command(cmd);
+        assertThat(result.getStatus() == CommandStatus.SUCCESS).isTrue();
+    }
+
+    private void runDeviceTest(String method) throws DeviceNotAvailableException {
+        var options = new DeviceTestRunOptions(PACKAGE_NAME);
+        options.setTestClassName(PACKAGE_NAME + ".BackgroundInstallControlServiceTest");
+        options.setTestMethodName(method);
+        runDeviceTests(options);
+    }
+}
diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/Android.bp b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/Android.bp
new file mode 100644
index 0000000..9b39f2d
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/Android.bp
@@ -0,0 +1,40 @@
+// 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "BackgroundInstallControlServiceTestApp",
+    manifest: "AndroidManifest.xml",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.core",
+        "compatibility-device-util-axt",
+        "junit",
+    ],
+    test_suites: [
+        "general-tests",
+    ],
+    platform_apis: true,
+    dex_preopt: {
+        enabled: false,
+    },
+}
diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..1fa1f84
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.server.pm.test.app">
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:label="APCT tests for background install control service"
+        android:targetPackage="com.android.server.pm.test.app" />
+</manifest>
diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java
new file mode 100644
index 0000000..b74e561
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.pm.test.app;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.pm.IBackgroundInstallControlService;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@RunWith(AndroidJUnit4.class)
+public class BackgroundInstallControlServiceTest {
+    private static final String TAG = "BackgroundInstallControlServiceTest";
+
+    private IBackgroundInstallControlService mIBics;
+
+    @Before
+    public void setUp() {
+        mIBics = IBackgroundInstallControlService.Stub.asInterface(
+                ServiceManager.getService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE));
+        assertThat(mIBics).isNotNull();
+    }
+
+    @Test
+    public void testGetMockBackgroundInstalledPackages() throws RemoteException {
+        ParceledListSlice<PackageInfo> slice = mIBics.getBackgroundInstalledPackages(
+                    PackageManager.MATCH_ALL,
+                    UserHandle.USER_ALL);
+        assertThat(slice).isNotNull();
+
+        var packageList = slice.getList();
+        assertThat(packageList).isNotNull();
+        assertThat(packageList).hasSize(2);
+
+        var expectedPackageNames = Set.of("com.android.servicestests.apps.bicmockapp1",
+                "com.android.servicestests.apps.bicmockapp2");
+        var actualPackageNames = packageList.stream().map((packageInfo) -> packageInfo.packageName)
+                .collect(Collectors.toSet());
+        assertThat(actualPackageNames).containsExactlyElementsIn(expectedPackageNames);
+    }
+}
diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/MockApp/Android.bp b/services/tests/BackgroundInstallControlServiceTests/host/test-app/MockApp/Android.bp
new file mode 100644
index 0000000..7804f4c
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/MockApp/Android.bp
@@ -0,0 +1,52 @@
+// 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_defaults {
+    name: "bic-mock-app-defaults",
+    test_suites: ["device-tests"],
+
+    srcs: ["**/*.java"],
+
+    dex_preopt: {
+        enabled: false,
+    },
+    optimize: {
+        enabled: false,
+    },
+}
+
+android_test_helper_app {
+    name: "BackgroundInstallControlMockApp1",
+    defaults: ["bic-mock-app-defaults"],
+    aaptflags: [
+        "--rename-manifest-package com.android.servicestests.apps.bicmockapp1",
+    ],
+}
+
+android_test_helper_app {
+    name: "BackgroundInstallControlMockApp2",
+    defaults: ["bic-mock-app-defaults"],
+    aaptflags: [
+        "--rename-manifest-package com.android.servicestests.apps.bicmockapp2",
+    ],
+}
diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/MockApp/AndroidManifest.xml b/services/tests/BackgroundInstallControlServiceTests/host/test-app/MockApp/AndroidManifest.xml
new file mode 100644
index 0000000..3cb39db
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/MockApp/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.servicestests.apps.bicmockapp">
+
+    <application android:hasCode="false">
+    </application>
+</manifest>
diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/MockApp/res/values/strings.xml b/services/tests/BackgroundInstallControlServiceTests/host/test-app/MockApp/res/values/strings.xml
new file mode 100644
index 0000000..984152f
--- /dev/null
+++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/MockApp/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this placeholder file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="placeholder">placeholder</string>
+</resources>
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
index 720f486..7e44049 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
@@ -34,6 +34,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
+import android.os.Binder;
 import android.os.RemoteException;
 import android.view.inputmethod.InputMethodManager;
 
@@ -66,8 +67,8 @@
     @Test
     public void testPerformShowIme() throws Exception {
         synchronized (ImfLock.class) {
-            mVisibilityApplier.performShowIme(mWindowToken, null /* statsToken */,
-                    InputMethodManager.SHOW_IMPLICIT, null, SHOW_SOFT_INPUT);
+            mVisibilityApplier.performShowIme(new Binder() /* showInputToken */,
+                    null /* statsToken */, InputMethodManager.SHOW_IMPLICIT, null, SHOW_SOFT_INPUT);
         }
         verifyShowSoftInput(false, true, InputMethodManager.SHOW_IMPLICIT);
     }
@@ -75,8 +76,8 @@
     @Test
     public void testPerformHideIme() throws Exception {
         synchronized (ImfLock.class) {
-            mVisibilityApplier.performHideIme(mWindowToken, null /* statsToken */, null,
-                    HIDE_SOFT_INPUT);
+            mVisibilityApplier.performHideIme(new Binder() /* hideInputToken */,
+                    null /* statsToken */, null, HIDE_SOFT_INPUT);
         }
         verifyHideSoftInput(false, true);
     }
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
index 75484d1..a39e021 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -1129,6 +1129,7 @@
                 false /*allowInstall*/,
                 false /*instantApp*/,
                 false /*virtualPreload*/,
+                false /* stopped */,
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
@@ -1173,6 +1174,7 @@
                 true /*allowInstall*/,
                 false /*instantApp*/,
                 false /*virtualPreload*/,
+                false /* stopped */,
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
@@ -1217,6 +1219,7 @@
                 false /*allowInstall*/,
                 false /*instantApp*/,
                 false /*virtualPreload*/,
+                false /* stopped */,
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
@@ -1262,6 +1265,7 @@
                 false /*allowInstall*/,
                 false /*instantApp*/,
                 false /*virtualPreload*/,
+                false /* stopped */,
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
@@ -1284,6 +1288,48 @@
         verifyUserState(userState, false /*notLaunched*/, false /*stopped*/, true /*installed*/);
     }
 
+    /** Create a new stopped system PackageSetting */
+    @Test
+    public void testCreateNewSetting05() {
+        final PackageSetting testPkgSetting01 = Settings.createNewSetting(
+                PACKAGE_NAME,
+                null /*originalPkg*/,
+                null /*disabledPkg*/,
+                null /*realPkgName*/,
+                null /*sharedUser*/,
+                UPDATED_CODE_PATH /*codePath*/,
+                null /*legacyNativeLibraryPath*/,
+                "arm64-v8a" /*primaryCpuAbi*/,
+                "armeabi" /*secondaryCpuAbi*/,
+                UPDATED_VERSION_CODE /*versionCode*/,
+                ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
+                0 /*pkgPrivateFlags*/,
+                UserHandle.SYSTEM /*installUser*/,
+                false /*allowInstall*/,
+                false /*instantApp*/,
+                false /*virtualPreload*/,
+                true /* stopped */,
+                UserManagerService.getInstance(),
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/,
+                UUID.randomUUID());
+        assertThat(testPkgSetting01.getAppId(), is(0));
+        assertThat(testPkgSetting01.getPath(), is(UPDATED_CODE_PATH));
+        assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME));
+        assertThat(testPkgSetting01.getFlags(), is(ApplicationInfo.FLAG_SYSTEM));
+        assertThat(testPkgSetting01.getPrivateFlags(), is(0));
+        assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("arm64-v8a"));
+        assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("arm64-v8a"));
+        assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("armeabi"));
+        assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("armeabi"));
+        assertThat(testPkgSetting01.getVersionCode(), is(UPDATED_VERSION_CODE));
+        final PackageUserState userState = testPkgSetting01.readUserState(0);
+        verifyUserState(userState, false /*notLaunched*/, true /*stopped*/, true /*installed*/);
+    }
+
     @Test
     public void testSetPkgStateLibraryFiles_addNewFiles() {
         final PackageSetting packageSetting = createPackageSetting("com.foo");
diff --git a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java
index 7b361d3..1dcd0b9 100644
--- a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java
+++ b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.argThat;
+import static org.mockito.Mockito.contains;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.eq;
@@ -39,6 +40,7 @@
 import android.security.rkp.IStoreUpgradedKeyCallback;
 import android.security.rkp.service.RegistrationProxy;
 import android.security.rkp.service.RemotelyProvisionedKey;
+import android.security.rkp.service.RkpProxyException;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -48,8 +50,9 @@
 import org.mockito.stubbing.Answer;
 import org.mockito.stubbing.VoidAnswer4;
 
-import java.time.Duration;
+import java.lang.reflect.Field;
 import java.util.Arrays;
+import java.util.Map;
 import java.util.concurrent.Executor;
 
 /**
@@ -104,7 +107,7 @@
     }
 
     @Test
-    public void getKeyHandlesError() throws Exception {
+    public void getKeyHandlesArbitraryException() throws Exception {
         Exception expectedException = new Exception("oops!");
         doAnswer(
                 answerGetKeyAsync((keyId, cancelSignal, executor, receiver) ->
@@ -112,11 +115,38 @@
                 .when(mRegistrationProxy).getKeyAsync(eq(0), any(), any(), any());
         IGetKeyCallback callback = mock(IGetKeyCallback.class);
         mRegistration.getKey(0, callback);
-        verify(callback).onError(eq(expectedException.getMessage()));
+        verify(callback).onError(eq(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN), eq("oops!"));
         verifyNoMoreInteractions(callback);
     }
 
     @Test
+    public void getKeyMapsRkpErrorsCorrectly() throws Exception {
+        Map<Byte, Integer> expectedConversions = Map.of(
+                IGetKeyCallback.ErrorCode.ERROR_UNKNOWN,
+                RkpProxyException.ERROR_UNKNOWN,
+                IGetKeyCallback.ErrorCode.ERROR_REQUIRES_SECURITY_PATCH,
+                RkpProxyException.ERROR_REQUIRES_SECURITY_PATCH,
+                IGetKeyCallback.ErrorCode.ERROR_PENDING_INTERNET_CONNECTIVITY,
+                RkpProxyException.ERROR_PENDING_INTERNET_CONNECTIVITY,
+                IGetKeyCallback.ErrorCode.ERROR_PERMANENT,
+                RkpProxyException.ERROR_PERMANENT);
+
+        for (Field errorField: IGetKeyCallback.ErrorCode.class.getFields()) {
+            byte error = (Byte) errorField.get(null);
+            Exception expectedException = new RkpProxyException(expectedConversions.get(error),
+                    errorField.getName());
+            doAnswer(
+                    answerGetKeyAsync((keyId, cancelSignal, executor, receiver) ->
+                            executor.execute(() -> receiver.onError(expectedException))))
+                    .when(mRegistrationProxy).getKeyAsync(eq(0), any(), any(), any());
+            IGetKeyCallback callback = mock(IGetKeyCallback.class);
+            mRegistration.getKey(0, callback);
+            verify(callback).onError(eq(error), contains(errorField.getName()));
+            verifyNoMoreInteractions(callback);
+        }
+    }
+
+    @Test
     public void getKeyCancelDuringProxyOperation() throws Exception {
         IGetKeyCallback callback = mock(IGetKeyCallback.class);
         doAnswer(
@@ -179,7 +209,8 @@
 
         IGetKeyCallback callback = mock(IGetKeyCallback.class);
         mRegistration.getKey(0, callback);
-        verify(callback).onError(eq(expectedException.getMessage()));
+        verify(callback).onError(eq(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN),
+                eq(expectedException.getMessage()));
         assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback));
         verifyNoMoreInteractions(callback);
     }
diff --git a/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java b/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java
index a0687f6..6e6d55b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java
@@ -15,6 +15,7 @@
  */
 package com.android.server;
 
+import android.annotation.Nullable;
 import android.util.Dumpable;
 import android.util.Log;
 
@@ -40,6 +41,8 @@
 
     private final List<Dumpable> mDumpables = new ArrayList<>();
 
+    private @Nullable String mTestName;
+
     /**
      * Adds a {@link Dumpable} to be logged if the test case fails.
      */
@@ -47,15 +50,24 @@
         mDumpables.add(dumpable);
     }
 
+    /**
+     * Gets the name of the test being executed.
+     */
+    public @Nullable String getTestName() {
+        return mTestName;
+    }
+
     @Override
     public Statement apply(Statement base, Description description) {
         return new Statement() {
             @Override
             public void evaluate() throws Throwable {
+                mTestName = description.getDisplayName();
                 try {
                     base.evaluate();
                 } catch (Throwable t) {
-                    dumpOnFailure(description.getMethodName());
+                    dumpOnFailure(mTestName);
+                    mTestName = null;
                     throw t;
                 }
             }
diff --git a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java b/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java
index 693a96d..48483a1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java
@@ -17,6 +17,7 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 
+import android.annotation.Nullable;
 import android.util.Log;
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
@@ -28,9 +29,12 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.rules.RuleChain;
+import org.mockito.Mockito;
 import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
 
+import java.lang.reflect.Constructor;
+
 /**
  * Base class to make it easier to write tests that uses {@code ExtendedMockito}.
  *
@@ -39,7 +43,25 @@
 
     private static final String TAG = ExtendedMockitoTestCase.class.getSimpleName();
 
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    /**
+     * Number of invocations, used to force a failure on {@link #forceFailure(int, Class, String)}.
+     */
+    private static int sInvocationsCounter;
+
+    /**
+     * Sessions follow the "Highlander Rule": There can be only one!
+     *
+     * <p>So, we keep track of that and force-close it if needed.
+     */
+    @Nullable
+    private static MockitoSession sHighlanderSession;
+
+    /**
+     * Points to where the current session was created.
+     */
+    private static Exception sSessionCreationLocation;
 
     private MockitoSession mSession;
 
@@ -51,16 +73,43 @@
             .outerRule(mDumpableDumperRule)
             .around(mExpect);
 
+    public ExtendedMockitoTestCase() {
+        sInvocationsCounter++;
+    }
+
     @Before
-    public void startSession() {
-        if (DEBUG) {
-            Log.d(TAG, "startSession()");
+    public final void startSession() {
+        if (VERBOSE) {
+            Log.v(TAG, "startSession() for " + getTestName() + " on thread "
+                    + Thread.currentThread() + "; sHighlanderSession=" + sHighlanderSession);
         }
+        createSessionLocation();
+        finishHighlanderSessionIfNeeded("startSession()");
         StaticMockitoSessionBuilder builder = mockitoSession()
                 .initMocks(this)
-                .strictness(Strictness.LENIENT);
+                .strictness(getSessionStrictness());
         initializeSession(builder);
-        mSession = builder.startMocking();
+        sHighlanderSession = mSession = builder.startMocking();
+    }
+
+    private void createSessionLocation() {
+        try {
+            sSessionCreationLocation = new Exception(getTestName());
+        } catch (Exception e) {
+            // Better safe than sorry...
+            Log.e(TAG, "Could not create sSessionCreationLocation with " + getTestName()
+                    + " on thread " + Thread.currentThread(), e);
+            sSessionCreationLocation = e;
+        }
+    }
+
+    /**
+     * Gets the session strictness.
+     *
+     * @return {@link Strictness.LENIENT} by default; subclasses can override.
+     */
+    protected Strictness getSessionStrictness() {
+        return Strictness.LENIENT;
     }
 
     /**
@@ -69,29 +118,127 @@
      * <p>Typically used to define which classes should have static methods mocked or spied.
      */
     protected void initializeSession(StaticMockitoSessionBuilder builder) {
-        if (DEBUG) {
-            Log.d(TAG, "initializeSession()");
+        if (VERBOSE) {
+            Log.v(TAG, "initializeSession()");
         }
     }
 
     @After
-    public final void finishSession() {
+    public final void finishSession() throws Exception {
+        if (false) { // For obvious reasons, should NEVER be merged as true
+            forceFailure(1, RuntimeException.class, "to simulate an unfinished session");
+        }
+
+        // mSession.finishMocking() must ALWAYS be called (hence the over-protective try/finally
+        // statements), otherwise it would cause failures on future tests as mockito
+        // cannot start a session when a previous one is not finished
+        try {
+            if (VERBOSE) {
+                Log.v(TAG, "finishSession() for " + getTestName() + " on thread "
+                        + Thread.currentThread() + "; sHighlanderSession=" + sHighlanderSession);
+
+            }
+        } finally {
+            sHighlanderSession = null;
+            finishSessionMocking();
+            afterSessionFinished();
+        }
+    }
+
+    /**
+     * Called after the mockito session was finished
+     *
+     * <p>This method should be used by subclasses that MUST do their cleanup after the session is
+     * finished (as methods marked with {@link After} in the subclasses would be called BEFORE
+     * that).
+     */
+    protected void afterSessionFinished() {
+        if (VERBOSE) {
+            Log.v(TAG, "afterSessionFinished()");
+        }
+    }
+
+    private void finishSessionMocking() {
         if (mSession == null) {
-            Log.w(TAG, "finishSession(): no session");
+            Log.w(TAG, getClass().getSimpleName() + ".finishSession(): no session");
             return;
         }
         try {
-            if (DEBUG) {
-                Log.d(TAG, "finishSession()");
+            mSession.finishMocking();
+        } finally {
+            // Shouldn't need to set mSession to null as JUnit always instantiate a new object,
+            // but it doesn't hurt....
+            mSession = null;
+            // When using inline mock maker, clean up inline mocks to prevent OutOfMemory
+            // errors. See https://github.com/mockito/mockito/issues/1614 and b/259280359.
+            Mockito.framework().clearInlineMocks();
+        }
+    }
+
+    private void finishHighlanderSessionIfNeeded(String where) {
+        if (sHighlanderSession == null) {
+            if (VERBOSE) {
+                Log.v(TAG, "finishHighlanderSessionIfNeeded(): sHighlanderSession already null");
+            }
+            return;
+        }
+
+        if (sSessionCreationLocation != null) {
+            if (VERBOSE) {
+                Log.e(TAG, where + ": There can be only one! Closing unfinished session, "
+                        + "created at", sSessionCreationLocation);
+            } else {
+                Log.e(TAG, where + ": There can be only one! Closing unfinished session, "
+                        + "created at " +  sSessionCreationLocation);
+            }
+        } else {
+            Log.e(TAG, where + ": There can be only one! Closing unfinished session created at "
+                    + "unknown location");
+        }
+        try {
+            sHighlanderSession.finishMocking();
+        } catch (Throwable t) {
+            if (VERBOSE) {
+                Log.e(TAG, "Failed to close unfinished session on " + getTestName(), t);
+            } else {
+                Log.e(TAG, "Failed to close unfinished session on " + getTestName() + ": " + t);
             }
         } finally {
-            // mSession.finishMocking() must ALWAYS be called (hence the over-protective try/finally
-            // statements), otherwise it would cause failures on future tests as mockito
-            // cannot start a session when a previous one is not finished
-            mSession.finishMocking();
+            if (VERBOSE) {
+                Log.v(TAG, "Resetting sHighlanderSession at finishHighlanderSessionIfNeeded()");
+            }
+            sHighlanderSession = null;
         }
     }
 
+    /**
+     * Forces a failure at the given invocation of a test method by throwing an exception.
+     */
+    protected final <T extends Throwable> void forceFailure(int invocationCount,
+            Class<T> failureClass, String reason) throws T {
+        if (sInvocationsCounter != invocationCount) {
+            Log.d(TAG, "forceFailure(" + invocationCount + "): no-op on invocation #"
+                    + sInvocationsCounter);
+            return;
+        }
+        String message = "Throwing on invocation #" + sInvocationsCounter + ": " + reason;
+        Log.e(TAG, message);
+        T throwable;
+        try {
+            Constructor<T> constructor = failureClass.getConstructor(String.class);
+            throwable = constructor.newInstance("Throwing on invocation #" + sInvocationsCounter
+                    + ": " + reason);
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Could not create exception of class " + failureClass
+                    + " using msg='" + message + "' as constructor");
+        }
+        throw throwable;
+    }
+
+    protected final @Nullable String getTestName() {
+        return mDumpableDumperRule.getTestName();
+    }
+
     protected final StandardSubjectBuilder expectWithMessage(String msg) {
         return mExpect.withMessage(msg);
     }
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index ef470fe..a1f4fdd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -48,7 +48,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
@@ -112,7 +111,6 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
 
 import android.Manifest;
 import android.app.ActivityManager;
@@ -160,6 +158,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.dx.mockito.inline.extended.MockedVoidMethod;
+import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
@@ -168,6 +167,7 @@
 import com.android.server.AppStateTracker;
 import com.android.server.AppStateTrackerImpl;
 import com.android.server.DeviceIdleInternal;
+import com.android.server.ExtendedMockitoTestCase;
 import com.android.server.LocalServices;
 import com.android.server.SystemClockTime.TimeConfidence;
 import com.android.server.SystemService;
@@ -180,7 +180,6 @@
 
 import libcore.util.EmptyArray;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -188,7 +187,6 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatchers;
 import org.mockito.Mock;
-import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
 import org.mockito.stubbing.Answer;
 
@@ -204,7 +202,7 @@
 
 @Presubmit
 @RunWith(AndroidJUnit4.class)
-public class AlarmManagerServiceTest {
+public final class AlarmManagerServiceTest extends ExtendedMockitoTestCase {
     private static final String TAG = AlarmManagerServiceTest.class.getSimpleName();
     private static final int SYSTEM_UI_UID = 12345;
     private static final int TEST_CALLING_USER = UserHandle.getUserId(TEST_CALLING_UID);
@@ -256,7 +254,6 @@
     DeviceConfig.Properties mDeviceConfigProperties;
     HashSet<String> mDeviceConfigKeys = new HashSet<>();
 
-    private MockitoSession mMockingSession;
     private Injector mInjector;
     private volatile long mNowElapsedTest;
     private volatile long mNowRtcTest;
@@ -409,26 +406,31 @@
         }
     }
 
+    @Override
+    protected Strictness getSessionStrictness() {
+        return Strictness.WARN;
+    }
+
+    @Override
+    protected void initializeSession(StaticMockitoSessionBuilder builder) {
+        builder
+            .spyStatic(ActivityManager.class)
+            .mockStatic(CompatChanges.class)
+            .spyStatic(DateFormat.class)
+            .spyStatic(DeviceConfig.class)
+            .mockStatic(LocalServices.class)
+            .spyStatic(Looper.class)
+            .mockStatic(MetricsHelper.class)
+            .mockStatic(PermissionChecker.class)
+            .mockStatic(PermissionManagerService.class)
+            .mockStatic(ServiceManager.class)
+            .mockStatic(Settings.Global.class)
+            .mockStatic(SystemProperties.class)
+            .spyStatic(UserHandle.class);
+    }
+
     @Before
     public final void setUp() {
-        mMockingSession = mockitoSession()
-                .initMocks(this)
-                .spyStatic(ActivityManager.class)
-                .mockStatic(CompatChanges.class)
-                .spyStatic(DateFormat.class)
-                .spyStatic(DeviceConfig.class)
-                .mockStatic(LocalServices.class)
-                .spyStatic(Looper.class)
-                .mockStatic(MetricsHelper.class)
-                .mockStatic(PermissionChecker.class)
-                .mockStatic(PermissionManagerService.class)
-                .mockStatic(ServiceManager.class)
-                .mockStatic(Settings.Global.class)
-                .mockStatic(SystemProperties.class)
-                .spyStatic(UserHandle.class)
-                .strictness(Strictness.WARN)
-                .startMocking();
-
         doReturn(mIActivityManager).when(ActivityManager::getService);
         doReturn(mDeviceIdleInternal).when(
                 () -> LocalServices.getService(DeviceIdleInternal.class));
@@ -1265,7 +1267,30 @@
         mService.interactiveStateChangedLocked(false);
         mService.interactiveStateChangedLocked(true);
         runnableCaptor.getValue().run();
-        verify(mMockContext).sendBroadcastAsUser(mService.mTimeTickIntent, UserHandle.ALL);
+        final ArgumentCaptor<Bundle> optionsCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mMockContext).sendBroadcastAsUser(eq(mService.mTimeTickIntent), eq(UserHandle.ALL),
+                isNull(), optionsCaptor.capture());
+        verifyTimeTickBroadcastOptions(optionsCaptor.getValue());
+    }
+
+    @Test
+    public void sendsTimeTickOnAlarmTrigger() throws Exception {
+        final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+        // Stubbing so the handler doesn't actually run the runnable.
+        doReturn(true).when(mService.mHandler).post(runnableCaptor.capture());
+        mService.mTimeTickTrigger.doAlarm(mock(IAlarmCompleteListener.class));
+        runnableCaptor.getValue().run();
+        final ArgumentCaptor<Bundle> optionsCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mMockContext).sendBroadcastAsUser(eq(mService.mTimeTickIntent), eq(UserHandle.ALL),
+                isNull(), optionsCaptor.capture());
+        verifyTimeTickBroadcastOptions(optionsCaptor.getValue());
+    }
+
+    private void verifyTimeTickBroadcastOptions(Bundle actualOptionsBundle) {
+        final BroadcastOptions actualOptions = new BroadcastOptions(actualOptionsBundle);
+        assertEquals(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT,
+                actualOptions.getDeliveryGroupPolicy());
+        assertTrue(actualOptions.isDeferUntilActive());
     }
 
     @Test
@@ -3728,11 +3753,8 @@
         testTemporaryQuota_bumpedBeforeDeferral(STANDBY_BUCKET_RARE);
     }
 
-    @After
-    public void tearDown() {
-        if (mMockingSession != null) {
-            mMockingSession.finishMocking();
-        }
+    @Override
+    public void afterSessionFinished() {
         LocalServices.removeServiceForTest(AlarmManagerInternal.class);
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index 4a40b5f..9c581f9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -711,8 +711,6 @@
                 null);                                // description
 
         // Case 8: App1 gets "remove task"
-        final String app1Description = "remove task";
-
         sleep(1);
         final int app1IsolatedUidUser2 = 1099002; // isolated uid
         final long app1Pss4 = 34343;
@@ -739,7 +737,7 @@
 
         mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(app1IsolatedUidUser2, app1UidUser2);
         noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
-                ApplicationExitInfo.SUBREASON_UNKNOWN, app1Description, now8);
+                ApplicationExitInfo.SUBREASON_REMOVE_TASK, null, now8);
 
         updateExitInfo(app, now8);
         list.clear();
@@ -749,21 +747,21 @@
         info = list.get(0);
 
         verifyApplicationExitInfo(
-                info,                                     // info
-                now8,                                     // timestamp
-                app1PidUser2,                             // pid
-                app1IsolatedUidUser2,                     // uid
-                app1UidUser2,                             // packageUid
-                null,                                     // definingUid
-                app1ProcessName,                          // processName
-                0,                                        // connectionGroup
-                ApplicationExitInfo.REASON_OTHER,         // reason
-                ApplicationExitInfo.SUBREASON_UNKNOWN,    // subReason
-                0,                                        // status
-                app1Pss4,                                 // pss
-                app1Rss4,                                 // rss
-                IMPORTANCE_CACHED,                        // importance
-                app1Description);                         // description
+                info,                                       // info
+                now8,                                       // timestamp
+                app1PidUser2,                               // pid
+                app1IsolatedUidUser2,                       // uid
+                app1UidUser2,                               // packageUid
+                null,                                       // definingUid
+                app1ProcessName,                            // processName
+                0,                                          // connectionGroup
+                ApplicationExitInfo.REASON_OTHER,           // reason
+                ApplicationExitInfo.SUBREASON_REMOVE_TASK,  // subReason
+                0,                                          // status
+                app1Pss4,                                   // pss
+                app1Rss4,                                   // rss
+                IMPORTANCE_CACHED,                          // importance
+                null);                                      // description
 
         // App1 gets "too many empty"
         final String app1Description2 = "too many empty";
@@ -1058,7 +1056,18 @@
         if (importance != null) {
             assertEquals(importance.intValue(), info.getImportance());
         }
-        if (description != null) {
+
+        // info.getDescription returns a combination of subReason & description
+        if ((subReason != null) && (subReason != ApplicationExitInfo.SUBREASON_UNKNOWN)
+                && (description != null)) {
+            assertTrue(TextUtils.equals(
+                    "[" + info.subreasonToString(subReason) + "] " + description,
+                    info.getDescription()));
+        } else if ((subReason != null) && (subReason != ApplicationExitInfo.SUBREASON_UNKNOWN)) {
+            assertTrue(TextUtils.equals(
+                    "[" + info.subreasonToString(subReason) + "]",
+                    info.getDescription()));
+        } else if (description != null) {
             assertTrue(TextUtils.equals(description, info.getDescription()));
         }
     }
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
new file mode 100644
index 0000000..ea14ffb
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
@@ -0,0 +1,282 @@
+/*
+ * 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.server.am;
+
+import static android.os.Process.myPid;
+import static android.os.Process.myUid;
+
+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.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;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManagerInternal;
+import android.app.IApplicationThread;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManagerInternal;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.SystemClock;
+import android.util.Log;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.DropBoxManagerInternal;
+import com.android.server.LocalServices;
+import com.android.server.am.ActivityManagerService.Injector;
+import com.android.server.appop.AppOpsService;
+import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.ActivityTaskManagerService;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.util.Arrays;
+
+
+/**
+ * Tests to verify process starts are completed or timeout correctly
+ */
+@MediumTest
+@SuppressWarnings("GuardedBy")
+public class AsyncProcessStartTest {
+    private static final String TAG = "AsyncProcessStartTest";
+
+    private static final String PACKAGE = "com.foo";
+
+    @Rule
+    public final ApplicationExitInfoTest.ServiceThreadRule
+            mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
+
+    private Context mContext;
+    private HandlerThread mHandlerThread;
+
+    @Mock
+    private AppOpsService mAppOpsService;
+    @Mock
+    private DropBoxManagerInternal mDropBoxManagerInt;
+    @Mock
+    private PackageManagerInternal mPackageManagerInt;
+    @Mock
+    private UsageStatsManagerInternal mUsageStatsManagerInt;
+    @Mock
+    private ActivityManagerInternal mActivityManagerInt;
+    @Mock
+    private ActivityTaskManagerInternal mActivityTaskManagerInt;
+    @Mock
+    private BatteryStatsService mBatteryStatsService;
+
+    private ActivityManagerService mRealAms;
+    private ActivityManagerService mAms;
+
+    private ProcessList mRealProcessList = new ProcessList();
+    private ProcessList mProcessList;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+
+        LocalServices.removeServiceForTest(DropBoxManagerInternal.class);
+        LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt);
+
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
+        LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
+
+        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+        LocalServices.addService(ActivityManagerInternal.class, mActivityManagerInt);
+
+        LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class);
+        LocalServices.addService(ActivityTaskManagerInternal.class, mActivityTaskManagerInt);
+
+        doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
+        doReturn(true).when(mActivityTaskManagerInt).attachApplication(any());
+        doNothing().when(mActivityTaskManagerInt).onProcessMapped(anyInt(), any());
+
+        mRealAms = new ActivityManagerService(
+                new TestInjector(mContext), mServiceThreadRule.getThread());
+        mRealAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
+        mRealAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
+        mRealAms.mAtmInternal = mActivityTaskManagerInt;
+        mRealAms.mPackageManagerInt = mPackageManagerInt;
+        mRealAms.mUsageStatsService = mUsageStatsManagerInt;
+        mRealAms.mProcessesReady = true;
+        mAms = spy(mRealAms);
+        mRealProcessList.mService = mAms;
+        mProcessList = spy(mRealProcessList);
+
+        doAnswer((invocation) -> {
+            Log.v(TAG, "Intercepting isProcStartValidLocked() for "
+                    + Arrays.toString(invocation.getArguments()));
+            return null;
+        }).when(mProcessList).isProcStartValidLocked(any(), anyLong());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mHandlerThread.quit();
+    }
+
+    private class TestInjector extends Injector {
+        TestInjector(Context context) {
+            super(context);
+        }
+
+        @Override
+        public AppOpsService getAppOpsService(File file, Handler handler) {
+            return mAppOpsService;
+        }
+
+        @Override
+        public Handler getUiHandler(ActivityManagerService service) {
+            return mHandlerThread.getThreadHandler();
+        }
+
+        @Override
+        public ProcessList getProcessList(ActivityManagerService service) {
+            return mRealProcessList;
+        }
+
+        @Override
+        public BatteryStatsService getBatteryStatsService() {
+            return mBatteryStatsService;
+        }
+    }
+
+    private ProcessRecord makeActiveProcessRecord(String packageName, boolean wedge)
+            throws Exception {
+        final ApplicationInfo ai = makeApplicationInfo(packageName);
+        return makeActiveProcessRecord(ai, wedge);
+    }
+
+    private ProcessRecord makeActiveProcessRecord(ApplicationInfo ai, boolean wedge)
+            throws Exception {
+        final IApplicationThread thread = mock(IApplicationThread.class);
+        final IBinder threadBinder = new Binder();
+        doReturn(threadBinder).when(thread).asBinder();
+        doAnswer((invocation) -> {
+            Log.v(TAG, "Intercepting bindApplication() for "
+                    + Arrays.toString(invocation.getArguments()));
+            if (!wedge) {
+                mRealAms.finishAttachApplication(0);
+            }
+            return null;
+        }).when(thread).bindApplication(
+                any(), any(),
+                any(), any(),
+                any(), any(),
+                any(), any(),
+                any(),
+                any(), anyInt(),
+                anyBoolean(), anyBoolean(),
+                anyBoolean(), anyBoolean(), any(),
+                any(), any(), any(),
+                any(), any(),
+                any(), any(),
+                any(),
+                anyLong(), anyLong());
+
+        final ProcessRecord r = spy(new ProcessRecord(mAms, ai, ai.processName, ai.uid));
+        r.setPid(myPid());
+        r.setStartUid(myUid());
+        r.setHostingRecord(new HostingRecord(HostingRecord.HOSTING_TYPE_BROADCAST));
+        r.makeActive(thread, mAms.mProcessStats);
+        doNothing().when(r).killLocked(any(), any(), anyInt(), anyInt(), anyBoolean(),
+                anyBoolean());
+
+        return r;
+    }
+
+    static ApplicationInfo makeApplicationInfo(String packageName) {
+        final ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = packageName;
+        ai.processName = packageName;
+        ai.uid = myUid();
+        return ai;
+    }
+
+    /**
+     * Verify that we don't kill a normal process
+     */
+    @Test
+    public void testNormal() throws Exception {
+        ProcessRecord app = startProcessAndWait(false);
+
+        verify(app, never()).killLocked(any(), anyInt(), anyBoolean());
+    }
+
+    /**
+     * Verify that we kill a wedged process after the process start timeout
+     */
+    @Test
+    public void testWedged() throws Exception {
+        ProcessRecord app = startProcessAndWait(true);
+
+        verify(app).killLocked(any(), anyInt(), anyBoolean());
+    }
+
+    private ProcessRecord startProcessAndWait(boolean wedge) throws Exception {
+        final ProcessRecord app = makeActiveProcessRecord(PACKAGE, wedge);
+        final ApplicationInfo appInfo = makeApplicationInfo(PACKAGE);
+
+        mProcessList.handleProcessStartedLocked(app, app.getPid(), /* usingWrapper */ false,
+                /* expectedStartSeq */ 0, /* procAttached */ false);
+
+        app.getThread().bindApplication(PACKAGE, appInfo,
+                null, null,
+                null,
+                null,
+                null, null,
+                null,
+                null, 0,
+                false, false,
+                true, false,
+                null,
+                null, null,
+                null,
+                null, null, null,
+                null, null,
+                0, 0);
+
+        // Sleep until timeout should have triggered
+        SystemClock.sleep(ActivityManagerService.PROC_START_TIMEOUT + 1000);
+
+        return app;
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 64e39ef..f0cd6cc 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -49,6 +49,7 @@
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -63,6 +64,8 @@
  */
 @Presubmit
 @RunWith(MockitoJUnitRunner.class)
+@Ignore("TODO(b/226641572): this test is broken and it cannot use ExtendedMockitoTestCase as it "
+        + "uses TestableDeviceConfigRule, which creates its own mockito session")
 public final class CachedAppOptimizerTest {
 
     private ServiceThread mThread;
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index c40017a..fb05699 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -17,7 +17,7 @@
 package com.android.server.am;
 
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
@@ -38,6 +38,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_TOP_SLEEPING;
 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
@@ -110,6 +111,7 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -225,6 +227,40 @@
         }
     }
 
+    private static void assertBfsl(ProcessRecord app) {
+        assertEquals(PROCESS_CAPABILITY_BFSL,
+                app.mState.getSetCapability() & PROCESS_CAPABILITY_BFSL);
+    }
+
+    private static void assertNoBfsl(ProcessRecord app) {
+        assertEquals(0, app.mState.getSetCapability() & PROCESS_CAPABILITY_BFSL);
+    }
+
+    /**
+     * Replace the process LRU with the given processes.
+     * @param apps
+     */
+    private void setProcessesToLru(ProcessRecord... apps) {
+        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
+        lru.clear();
+        Collections.addAll(lru, apps);
+    }
+
+    /**
+     * Run updateOomAdjLocked().
+     * - If there's only one process, then it calls updateOomAdjLocked(ProcessRecord, int).
+     * - Otherwise, sets the processes to the LRU and run updateOomAdjLocked(int).
+     */
+    private void updateOomAdj(ProcessRecord... apps) {
+        if (apps.length == 1) {
+            sService.mOomAdjuster.updateOomAdjLocked(apps[0], OomAdjuster.OOM_ADJ_REASON_NONE);
+        } else {
+            setProcessesToLru(apps);
+            sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+            sService.mProcessList.getLruProcessesLOSP().clear();
+        }
+    }
+
     @SuppressWarnings("GuardedBy")
     @Test
     public void testUpdateOomAdj_DoOne_Persistent_TopUi_Sleeping() {
@@ -233,11 +269,12 @@
         app.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         app.mState.setHasTopUi(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_ASLEEP);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
 
         assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERSISTENT_PROC_ADJ,
                 SCHED_GROUP_RESTRICTED);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -248,7 +285,7 @@
         app.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         app.mState.setHasTopUi(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_PERSISTENT_UI, PERSISTENT_PROC_ADJ,
                 SCHED_GROUP_TOP_APP);
@@ -262,7 +299,7 @@
         app.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         doReturn(app).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         doReturn(null).when(sService).getTopApp();
 
         assertProcStates(app, PROCESS_STATE_PERSISTENT_UI, PERSISTENT_PROC_ADJ,
@@ -277,7 +314,7 @@
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         doReturn(app).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         doReturn(null).when(sService).getTopApp();
 
         assertProcStates(app, PROCESS_STATE_TOP, FOREGROUND_APP_ADJ, SCHED_GROUP_TOP_APP);
@@ -291,7 +328,7 @@
         doReturn(PROCESS_STATE_TOP_SLEEPING).when(sService.mAtmInternal).getTopProcessState();
         app.mState.setRunningRemoteAnimation(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
 
         assertProcStates(app, PROCESS_STATE_TOP_SLEEPING, VISIBLE_APP_ADJ, SCHED_GROUP_TOP_APP);
@@ -304,11 +341,12 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
         doReturn(mock(ActiveInstrumentation.class)).when(app).getActiveInstrumentation();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         doCallRealMethod().when(app).getActiveInstrumentation();
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, FOREGROUND_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -319,7 +357,7 @@
         doReturn(true).when(sService).isReceivingBroadcastLocked(any(ProcessRecord.class),
                 any(int[].class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         doReturn(false).when(sService).isReceivingBroadcastLocked(any(ProcessRecord.class),
                 any(int[].class));
 
@@ -333,7 +371,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
         app.mServices.startExecutingService(mock(ServiceRecord.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_SERVICE, FOREGROUND_APP_ADJ, SCHED_GROUP_BACKGROUND);
     }
@@ -346,7 +384,7 @@
         doReturn(PROCESS_STATE_TOP_SLEEPING).when(sService.mAtmInternal).getTopProcessState();
         doReturn(app).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_ASLEEP);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         doReturn(null).when(sService).getTopApp();
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -363,7 +401,7 @@
         app.mState.setCurRawAdj(CACHED_APP_MIN_ADJ);
         doReturn(null).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, CACHED_APP_MIN_ADJ,
                 SCHED_GROUP_BACKGROUND);
@@ -389,7 +427,7 @@
         })).when(wpc).computeOomAdjFromActivities(
                 any(WindowProcessController.ComputeOomAdjCallback.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_TOP, VISIBLE_APP_ADJ, SCHED_GROUP_TOP_APP);
     }
@@ -403,7 +441,7 @@
         doReturn(true).when(wpc).hasRecentTasks();
         app.mState.setLastTopTime(SystemClock.uptimeMillis());
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         doCallRealMethod().when(wpc).hasRecentTasks();
 
         assertEquals(PROCESS_STATE_CACHED_RECENT, app.mState.getSetProcState());
@@ -417,10 +455,11 @@
         app.mServices.setHasForegroundServices(true, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION,
                 /* hasNoneType=*/false);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -430,10 +469,11 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
         app.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -445,7 +485,7 @@
         ServiceRecord s = ServiceRecord.newEmptyInstanceForTest(sService);
         s.startRequested = true;
         s.isForeground = true;
-        s.foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
+        s.foregroundServiceType = FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
         s.setShortFgsInfo(SystemClock.uptimeMillis());
 
         // SHORT_SERVICE FGS will get IMP_FG and a slightly different recent-adjustment.
@@ -454,16 +494,15 @@
                     MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
             app.mServices.startService(s);
             app.mServices.setHasForegroundServices(true,
-                    ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE, /* hasNoneType=*/false);
+                    FOREGROUND_SERVICE_TYPE_SHORT_SERVICE, /* hasNoneType=*/false);
             app.mState.setLastTopTime(SystemClock.uptimeMillis());
             sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
 
-            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+            updateOomAdj(app);
 
-            assertProcStates(app, PROCESS_STATE_IMPORTANT_FOREGROUND,
+            assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE,
                     PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 1, SCHED_GROUP_DEFAULT);
-            // Should get network access.
-            assertTrue((app.mState.getSetCapability() & PROCESS_CAPABILITY_NETWORK) != 0);
+            assertNoBfsl(app);
         }
 
         // SHORT_SERVICE, but no longer recent.
@@ -471,25 +510,24 @@
             ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                     MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
             app.mServices.setHasForegroundServices(true,
-                    ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE, /* hasNoneType=*/false);
+                    FOREGROUND_SERVICE_TYPE_SHORT_SERVICE, /* hasNoneType=*/false);
             app.mServices.startService(s);
             app.mState.setLastTopTime(SystemClock.uptimeMillis()
                     - sService.mConstants.TOP_TO_FGS_GRACE_DURATION);
             sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
 
-            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+            updateOomAdj(app);
 
-            assertProcStates(app, PROCESS_STATE_IMPORTANT_FOREGROUND,
+            assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE,
                     PERCEPTIBLE_MEDIUM_APP_ADJ + 1, SCHED_GROUP_DEFAULT);
-            // Still should get network access.
-            assertTrue((app.mState.getSetCapability() & PROCESS_CAPABILITY_NETWORK) != 0);
+            assertNoBfsl(app);
         }
 
         // SHORT_SERVICE, timed out already.
         s = ServiceRecord.newEmptyInstanceForTest(sService);
         s.startRequested = true;
         s.isForeground = true;
-        s.foregroundServiceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
+        s.foregroundServiceType = FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
         s.setShortFgsInfo(SystemClock.uptimeMillis()
                 - sService.mConstants.mShortFgsTimeoutDuration
                 - sService.mConstants.mShortFgsProcStateExtraWaitDuration);
@@ -497,19 +535,17 @@
             ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                     MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
             app.mServices.setHasForegroundServices(true,
-                    ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE, /* hasNoneType=*/false);
+                    FOREGROUND_SERVICE_TYPE_SHORT_SERVICE, /* hasNoneType=*/false);
             app.mServices.startService(s);
             app.mState.setLastTopTime(SystemClock.uptimeMillis()
                     - sService.mConstants.TOP_TO_FGS_GRACE_DURATION);
             sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
 
-            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+            updateOomAdj(app);
 
             // Procstate should be lower than FGS. (It should be SERVICE)
             assertEquals(app.mState.getSetProcState(), PROCESS_STATE_SERVICE);
-
-            // Shouldn't have the network capability now.
-            assertTrue((app.mState.getSetCapability() & PROCESS_CAPABILITY_NETWORK) == 0);
+            assertNoBfsl(app);
         }
     }
 
@@ -520,7 +556,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
         app.mState.setHasOverlayUi(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_IMPORTANT_FOREGROUND, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -534,10 +570,11 @@
         app.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         app.mState.setLastTopTime(SystemClock.uptimeMillis());
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE,
                 PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ, SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -558,7 +595,7 @@
             s.getConnections().clear();
             app.mServices.updateHasTopStartedAlmostPerceptibleServices();
             sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+            updateOomAdj(app);
 
             assertEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2, app.mState.getSetAdj());
         }
@@ -578,7 +615,7 @@
                     nowUptime - 2 * sService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs;
             app.mServices.updateHasTopStartedAlmostPerceptibleServices();
             sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+            updateOomAdj(app);
 
             assertEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2, app.mState.getSetAdj());
         }
@@ -599,11 +636,31 @@
             s.getConnections().clear();
             app.mServices.updateHasTopStartedAlmostPerceptibleServices();
             sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+            updateOomAdj(app);
 
             assertNotEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 2, app.mState.getSetAdj());
         }
     }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testUpdateOomAdj_DoOne_ImpFg_AlmostPerceptibleService() {
+        ProcessRecord system = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, true));
+        system.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+        system.mState.setHasTopUi(true);
+        // Simulate the system starting and binding to a service in the app.
+        ServiceRecord s = bindService(app, system,
+                null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+        assertProcStates(app, PROCESS_STATE_IMPORTANT_FOREGROUND,
+                PERCEPTIBLE_APP_ADJ + 1, SCHED_GROUP_DEFAULT);
+    }
+
     @SuppressWarnings("GuardedBy")
     @Test
     public void testUpdateOomAdj_DoOne_Toast() {
@@ -611,7 +668,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
         app.mState.setForcingToImportant(new Object());
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -625,7 +682,7 @@
         WindowProcessController wpc = app.getWindowProcessController();
         doReturn(true).when(wpc).isHeavyWeightProcess();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         doReturn(false).when(wpc).isHeavyWeightProcess();
 
         assertProcStates(app, PROCESS_STATE_HEAVY_WEIGHT, HEAVY_WEIGHT_APP_ADJ,
@@ -640,7 +697,7 @@
         WindowProcessController wpc = app.getWindowProcessController();
         doReturn(true).when(wpc).isHomeProcess();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_HOME, HOME_APP_ADJ, SCHED_GROUP_BACKGROUND);
     }
@@ -654,7 +711,7 @@
         doReturn(true).when(wpc).isPreviousProcess();
         doReturn(true).when(wpc).hasActivities();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, PREVIOUS_APP_ADJ,
                 SCHED_GROUP_BACKGROUND);
@@ -669,7 +726,7 @@
         backupTarget.app = app;
         doReturn(backupTarget).when(sService.mBackupTargets).get(anyInt());
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
         doReturn(null).when(sService.mBackupTargets).get(anyInt());
 
         assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, BACKUP_APP_ADJ,
@@ -683,7 +740,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
         app.mServices.setHasClientActivities(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertEquals(PROCESS_STATE_CACHED_ACTIVITY_CLIENT, app.mState.getSetProcState());
     }
@@ -695,7 +752,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
         app.mServices.setTreatLikeActivity(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertEquals(PROCESS_STATE_CACHED_ACTIVITY, app.mState.getSetProcState());
     }
@@ -712,7 +769,7 @@
         s.lastActivity = SystemClock.uptimeMillis();
         app.mServices.startService(s);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_B_ADJ, SCHED_GROUP_BACKGROUND);
     }
@@ -724,7 +781,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         app.mState.setMaxAdj(PERCEPTIBLE_LOW_APP_ADJ);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, PERCEPTIBLE_LOW_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -739,7 +796,7 @@
         app.mState.setCurRawAdj(SERVICE_ADJ);
         doReturn(null).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertTrue(ProcessList.CACHED_APP_MIN_ADJ <= app.mState.getSetAdj());
         assertTrue(ProcessList.CACHED_APP_MAX_ADJ >= app.mState.getSetAdj());
@@ -756,7 +813,7 @@
         s.lastActivity = SystemClock.uptimeMillis();
         app.mServices.startService(s);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND);
     }
@@ -774,7 +831,7 @@
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         doReturn(client).when(sService).getTopApp();
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
         doReturn(null).when(sService).getTopApp();
 
         assertProcStates(app, PROCESS_STATE_SERVICE, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
@@ -790,7 +847,7 @@
         bindService(app, client, null, Context.BIND_WAIVE_PRIORITY
                 | Context.BIND_TREAT_LIKE_ACTIVITY, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertEquals(PROCESS_STATE_CACHED_ACTIVITY, app.mState.getSetProcState());
     }
@@ -810,7 +867,7 @@
                 mock(ActivityServiceConnectionsHolder.class));
         doReturn(true).when(cr.activity).isActivityVisible();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
         assertEquals(SCHED_GROUP_TOP_APP_BOUND, app.mState.getSetSchedGroup());
@@ -822,11 +879,8 @@
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         bindService(app, app, null, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
     }
@@ -841,7 +895,7 @@
         client.mServices.setTreatLikeActivity(true);
         bindService(app, client, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertEquals(PROCESS_STATE_CACHED_EMPTY, app.mState.getSetProcState());
     }
@@ -861,7 +915,7 @@
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         doReturn(client).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
         doReturn(null).when(sService).getTopApp();
 
         assertEquals(PREVIOUS_APP_ADJ, app.mState.getSetAdj());
@@ -878,10 +932,11 @@
         client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         client.mState.setHasTopUi(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -894,9 +949,10 @@
         bindService(app, client, null, Context.BIND_IMPORTANT, mock(IBinder.class));
         client.mServices.startExecutingService(mock(ServiceRecord.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+        assertNoBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -910,7 +966,7 @@
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         doReturn(client).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
         doReturn(null).when(sService).getTopApp();
 
         assertProcStates(app, PROCESS_STATE_BOUND_TOP, VISIBLE_APP_ADJ, SCHED_GROUP_DEFAULT);
@@ -926,9 +982,12 @@
         bindService(app, client, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
         client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertEquals(PROCESS_STATE_BOUND_FOREGROUND_SERVICE, app.mState.getSetProcState());
+        assertEquals(PROCESS_STATE_PERSISTENT, client.mState.getSetProcState());
+        assertBfsl(client);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -941,9 +1000,10 @@
         bindService(app, client, null, Context.BIND_NOT_FOREGROUND, mock(IBinder.class));
         client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertEquals(PROCESS_STATE_TRANSIENT_BACKGROUND, app.mState.getSetProcState());
+        assertNoBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -956,9 +1016,94 @@
         bindService(app, client, null, 0, mock(IBinder.class));
         client.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
+        assertEquals(PROCESS_STATE_FOREGROUND_SERVICE, client.mState.getSetProcState());
+        assertBfsl(client);
         assertEquals(PROCESS_STATE_FOREGROUND_SERVICE, app.mState.getSetProcState());
+        assertBfsl(app);
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testUpdateOomAdj_DoOne_Service_ImportantFgService_ShortFgs() {
+        // Client has a SHORT_SERVICE FGS, which isn't allowed BFSL.
+        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+        ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+        bindService(app, client, null, 0, mock(IBinder.class));
+
+        // In order to trick OomAdjuster to think it has a short-service, we need this logic.
+        ServiceRecord s = ServiceRecord.newEmptyInstanceForTest(sService);
+        s.startRequested = true;
+        s.isForeground = true;
+        s.foregroundServiceType = FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
+        s.setShortFgsInfo(SystemClock.uptimeMillis());
+        client.mServices.startService(s);
+        client.mState.setLastTopTime(SystemClock.uptimeMillis());
+
+        client.mServices.setHasForegroundServices(true, FOREGROUND_SERVICE_TYPE_SHORT_SERVICE,
+                /* hasNoneType=*/false);
+        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+        updateOomAdj(client, app);
+
+        // Client only has a SHORT_FGS, so it doesn't have BFSL, and that's propagated.
+        assertEquals(PROCESS_STATE_FOREGROUND_SERVICE, client.mState.getSetProcState());
+        assertNoBfsl(client);
+        assertEquals(PROCESS_STATE_FOREGROUND_SERVICE, app.mState.getSetProcState());
+        assertNoBfsl(app);
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testUpdateOomAdj_DoOne_Service_BoundForegroundService_with_ShortFgs() {
+
+        // app2, which is bound by app1 (which makes it BFGS)
+        // but it also has a short-fgs.
+        ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+                MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+
+        // In order to trick OomAdjuster to think it has a short-service, we need this logic.
+        ServiceRecord s = ServiceRecord.newEmptyInstanceForTest(sService);
+        s.startRequested = true;
+        s.isForeground = true;
+        s.foregroundServiceType = FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
+        s.setShortFgsInfo(SystemClock.uptimeMillis());
+        app2.mServices.startService(s);
+        app2.mState.setLastTopTime(SystemClock.uptimeMillis());
+
+        app2.mServices.setHasForegroundServices(true, FOREGROUND_SERVICE_TYPE_SHORT_SERVICE,
+                /* hasNoneType=*/false);
+        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+        updateOomAdj(app2);
+
+        // Client only has a SHORT_FGS, so it doesn't have BFSL, and that's propagated.
+        assertEquals(PROCESS_STATE_FOREGROUND_SERVICE, app2.mState.getSetProcState());
+        assertNoBfsl(app2);
+
+        // Now, create a BFGS process (app1), and make it bind to app 2
+
+        // Persistent process
+        ProcessRecord pers = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+        pers.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+
+        // app1, which is bound by pers (which makes it BFGS)
+        ProcessRecord app1 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+
+        bindService(app1, pers, null, Context.BIND_FOREGROUND_SERVICE, mock(IBinder.class));
+        bindService(app2, app1, null, 0, mock(IBinder.class));
+
+        updateOomAdj(pers, app1, app2);
+
+        assertEquals(PROCESS_STATE_BOUND_FOREGROUND_SERVICE, app1.mState.getSetProcState());
+        assertBfsl(app1);
+
+        // Now, app2 gets BFSL from app1.
+        assertEquals(PROCESS_STATE_FOREGROUND_SERVICE, app2.mState.getSetProcState());
+        assertBfsl(app2);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -973,15 +1118,18 @@
         backupTarget.app = client;
         doReturn(backupTarget).when(sService.mBackupTargets).get(anyInt());
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
+
         doReturn(null).when(sService.mBackupTargets).get(anyInt());
 
         assertEquals(BACKUP_APP_ADJ, app.mState.getSetAdj());
+        assertNoBfsl(app);
 
         client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertEquals(PERSISTENT_SERVICE_ADJ, app.mState.getSetAdj());
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -994,7 +1142,7 @@
         bindService(app, client, null, Context.BIND_NOT_PERCEPTIBLE, mock(IBinder.class));
         client.mState.setRunningRemoteAnimation(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertEquals(PERCEPTIBLE_LOW_APP_ADJ, app.mState.getSetAdj());
     }
@@ -1009,7 +1157,7 @@
         bindService(app, client, null, Context.BIND_NOT_VISIBLE, mock(IBinder.class));
         client.mState.setRunningRemoteAnimation(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertEquals(PERCEPTIBLE_APP_ADJ, app.mState.getSetAdj());
     }
@@ -1024,23 +1172,25 @@
         bindService(app, client, null, 0, mock(IBinder.class));
         client.mState.setHasOverlayUi(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertEquals(PERCEPTIBLE_APP_ADJ, app.mState.getSetAdj());
     }
 
     @SuppressWarnings("GuardedBy")
     @Test
-    public void testUpdateOomAdj_DoOne_Service_MediumPerceptible() {
+    public void testUpdateOomAdj_DoOne_Service_AlmostPerceptible() {
         {
             ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                     MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
             ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                     MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
-            bindService(app, client, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+            bindService(app, client, null,
+                    Context.BIND_ALMOST_PERCEPTIBLE | Context.BIND_NOT_FOREGROUND,
+                    mock(IBinder.class));
             client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
             sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+            updateOomAdj(client, app);
 
             assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ + 2, app.mState.getSetAdj());
         }
@@ -1052,13 +1202,48 @@
                     MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
             WindowProcessController wpc = client.getWindowProcessController();
             doReturn(true).when(wpc).isHeavyWeightProcess();
-            bindService(app, client, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+            bindService(app, client, null,
+                    Context.BIND_ALMOST_PERCEPTIBLE | Context.BIND_NOT_FOREGROUND,
+                    mock(IBinder.class));
+            client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+            sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+            updateOomAdj(client, app);
+            doReturn(false).when(wpc).isHeavyWeightProcess();
+
+            assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ + 2, app.mState.getSetAdj());
+        }
+
+        {
+            ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                    MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+            ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                    MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+            bindService(app, client, null,
+                    Context.BIND_ALMOST_PERCEPTIBLE,
+                    mock(IBinder.class));
+            client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+            sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+            assertEquals(PERCEPTIBLE_APP_ADJ + 1, app.mState.getSetAdj());
+        }
+
+        {
+            ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                    MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+            ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                    MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+            WindowProcessController wpc = client.getWindowProcessController();
+            doReturn(true).when(wpc).isHeavyWeightProcess();
+            bindService(app, client, null,
+                    Context.BIND_ALMOST_PERCEPTIBLE,
+                    mock(IBinder.class));
             client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
             sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
             sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
             doReturn(false).when(wpc).isHeavyWeightProcess();
 
-            assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ + 2, app.mState.getSetAdj());
+            assertEquals(PERCEPTIBLE_APP_ADJ + 1, app.mState.getSetAdj());
         }
     }
 
@@ -1072,7 +1257,7 @@
         bindService(app, client, null, 0, mock(IBinder.class));
         client.mState.setRunningRemoteAnimation(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertEquals(VISIBLE_APP_ADJ, app.mState.getSetAdj());
     }
@@ -1087,9 +1272,10 @@
         bindService(app, client, null, Context.BIND_IMPORTANT_BACKGROUND, mock(IBinder.class));
         client.mState.setHasOverlayUi(true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertEquals(PROCESS_STATE_IMPORTANT_BACKGROUND, app.mState.getSetProcState());
+        assertNoBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1098,7 +1284,7 @@
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         bindProvider(app, app, null, null, false);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
     }
@@ -1112,12 +1298,8 @@
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         bindProvider(app, client, null, null, false);
         client.mServices.setTreatLikeActivity(true);
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client);
 
         assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
     }
@@ -1133,7 +1315,7 @@
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         doReturn(client).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
         doReturn(null).when(sService).getTopApp();
 
         assertProcStates(app, PROCESS_STATE_BOUND_TOP, FOREGROUND_APP_ADJ, SCHED_GROUP_DEFAULT);
@@ -1149,10 +1331,46 @@
         client.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindProvider(app, client, null, null, false);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testUpdateOomAdj_DoOne_Provider_FgService_ShortFgs() {
+        // Client has a SHORT_SERVICE FGS, which isn't allowed BFSL.
+        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+        ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+
+        // In order to trick OomAdjuster to think it has a short-service, we need this logic.
+        ServiceRecord s = ServiceRecord.newEmptyInstanceForTest(sService);
+        s.startRequested = true;
+        s.isForeground = true;
+        s.foregroundServiceType = FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
+        s.setShortFgsInfo(SystemClock.uptimeMillis());
+        client.mServices.startService(s);
+        client.mState.setLastTopTime(SystemClock.uptimeMillis());
+
+        client.mServices.setHasForegroundServices(true, FOREGROUND_SERVICE_TYPE_SHORT_SERVICE,
+                /* hasNoneType=*/false);
+        bindProvider(app, client, null, null, false);
+        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+        updateOomAdj(client, app);
+
+        // Client only has a SHORT_FGS, so it doesn't have BFSL, and that's propagated.
+        assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE,
+                PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 1,
+                SCHED_GROUP_DEFAULT);
+        assertNoBfsl(client);
+        assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE,
+                PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ + 1,
+                SCHED_GROUP_DEFAULT);
+        assertNoBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1164,7 +1382,7 @@
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         bindProvider(app, client, null, null, true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, app);
 
         assertProcStates(app, PROCESS_STATE_IMPORTANT_FOREGROUND, FOREGROUND_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1177,7 +1395,7 @@
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
         app.mProviders.setLastProviderTime(SystemClock.uptimeMillis());
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, PREVIOUS_APP_ADJ,
                 SCHED_GROUP_BACKGROUND);
@@ -1197,7 +1415,7 @@
         doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
         doReturn(client2).when(sService).getTopApp();
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, client2, app);
         doReturn(null).when(sService).getTopApp();
 
         assertProcStates(app, PROCESS_STATE_BOUND_TOP, VISIBLE_APP_ADJ,
@@ -1217,10 +1435,11 @@
         bindService(app, client2, null, 0, mock(IBinder.class));
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, client2, app);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1236,10 +1455,11 @@
         bindService(client, client2, null, 0, mock(IBinder.class));
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, client2, app);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1255,13 +1475,12 @@
         bindService(client, client2, null, 0, mock(IBinder.class));
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindService(client2, app, null, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
+
+        // Note: We add processes to LRU but still call updateOomAdjLocked() with a specific
+        // processes.
+        setProcessesToLru(app, client, client2);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1269,6 +1488,9 @@
                 SCHED_GROUP_DEFAULT);
         assertProcStates(client2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+        assertBfsl(client);
+        assertBfsl(client2);
 
         client2.mServices.setHasForegroundServices(false, 0, /* hasNoneType=*/false);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
@@ -1277,6 +1499,9 @@
         assertEquals(PROCESS_STATE_CACHED_EMPTY, client2.mState.getSetProcState());
         assertEquals(PROCESS_STATE_CACHED_EMPTY, client.mState.getSetProcState());
         assertEquals(PROCESS_STATE_CACHED_EMPTY, app.mState.getSetProcState());
+        assertNoBfsl(app);
+        assertNoBfsl(client);
+        assertNoBfsl(client2);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1292,13 +1517,8 @@
                 MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
         bindService(client2, client, null, 0, mock(IBinder.class));
         client.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1306,6 +1526,9 @@
                 SCHED_GROUP_DEFAULT);
         assertProcStates(client2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+        assertBfsl(client);
+        assertBfsl(client2);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1321,13 +1544,8 @@
         bindService(client, client2, null, 0, mock(IBinder.class));
         bindService(client2, client, null, 0, mock(IBinder.class));
         client.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1335,6 +1553,9 @@
                 SCHED_GROUP_DEFAULT);
         assertProcStates(client2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+        assertBfsl(client);
+        assertBfsl(client2);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1357,15 +1578,8 @@
         bindService(client3, client4, null, 0, mock(IBinder.class));
         bindService(client4, client3, null, 0, mock(IBinder.class));
         client.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
-        lru.add(client3);
-        lru.add(client4);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2, client3, client4);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1377,6 +1591,11 @@
                 SCHED_GROUP_DEFAULT);
         assertProcStates(client4, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+        assertBfsl(client);
+        assertBfsl(client2);
+        assertBfsl(client3);
+        assertBfsl(client4);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1396,17 +1615,12 @@
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         client3.mState.setForcingToImportant(new Object());
         bindService(app, client3, null, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
-        lru.add(client3);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2, client3);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1427,14 +1641,8 @@
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         client3.mState.setForcingToImportant(new Object());
         bindService(app, client3, null, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
-        lru.add(client3);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2, client3);
 
         assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1460,15 +1668,8 @@
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         client4.mState.setForcingToImportant(new Object());
         bindService(app, client4, null, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
-        lru.add(client3);
-        lru.add(client4);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2, client3, client4);
 
         assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1496,18 +1697,12 @@
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         client4.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindService(app, client4, null, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
-        lru.add(client3);
-        lru.add(client4);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2, client3, client4);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1529,10 +1724,11 @@
         client3.mState.setForcingToImportant(new Object());
         bindService(app, client3, null, 0, mock(IBinder.class));
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, client2, client3, app);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1548,10 +1744,11 @@
         bindProvider(client, client2, null, null, false);
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, client2, app);
 
         assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1567,16 +1764,12 @@
         bindProvider(client, client2, null, null, false);
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindService(client2, app, null, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2);
 
         assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1592,10 +1785,11 @@
         bindProvider(client, client2, null, null, false);
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client, client2, app);
 
         assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1611,17 +1805,12 @@
         bindProvider(client, client2, null, null, false);
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindProvider(client2, app, null, null, false);
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
-
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2);
 
         assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1643,18 +1832,18 @@
         client2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
 
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(app1, OomAdjuster.OOM_ADJ_REASON_NONE);
-        sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client1, client2, app1, app2);
 
         assertProcStates(app1, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
         assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app1);
+        assertBfsl(app2);
 
         bindService(app1, client1, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class));
         bindService(app2, client2, null, Context.BIND_SCHEDULE_LIKE_TOP_APP, mock(IBinder.class));
-        sService.mOomAdjuster.updateOomAdjLocked(app1, OomAdjuster.OOM_ADJ_REASON_NONE);
-        sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app1, app2);
 
         assertProcStates(app1, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
                 SCHED_GROUP_TOP_APP);
@@ -1662,12 +1851,12 @@
                 SCHED_GROUP_DEFAULT);
 
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_ASLEEP);
-        sService.mOomAdjuster.updateOomAdjLocked(app1, OomAdjuster.OOM_ADJ_REASON_NONE);
-        sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client1, client2, app1, app2);
         assertProcStates(app1, PROCESS_STATE_IMPORTANT_FOREGROUND, VISIBLE_APP_ADJ,
                 SCHED_GROUP_TOP_APP);
         assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app2);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1689,8 +1878,7 @@
         final ServiceRecord s2 = bindService(app2, client2, null,
                 Context.BIND_IMPORTANT, mock(IBinder.class));
 
-        sService.mOomAdjuster.updateOomAdjLocked(app1, OomAdjuster.OOM_ADJ_REASON_NONE);
-        sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client1, client2, app1, app2);
 
         assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1699,7 +1887,7 @@
 
         bindService(app2, client1, s2, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
                 mock(IBinder.class));
-        sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app2);
         assertProcStates(app2, PROCESS_STATE_PERSISTENT, PERSISTENT_SERVICE_ADJ,
                 SCHED_GROUP_DEFAULT);
 
@@ -1715,10 +1903,10 @@
         bindService(app2, client2, s2, Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
                 mock(IBinder.class));
 
-        sService.mOomAdjuster.updateOomAdjLocked(app1, OomAdjuster.OOM_ADJ_REASON_NONE);
-        sService.mOomAdjuster.updateOomAdjLocked(app2, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app1, app2);
 
-        assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+        // VISIBLE_APP_ADJ is the max oom-adj for BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE.
+        assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
         assertProcStates(app2, PROCESS_STATE_IMPORTANT_FOREGROUND, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1747,10 +1935,11 @@
 
         bindService(app1, client1, null, Context.BIND_NOT_PERCEPTIBLE, mock(IBinder.class));
 
-        sService.mOomAdjuster.updateOomAdjLocked(app1, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client1, app1);
 
         assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app1);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1767,10 +1956,11 @@
 
         bindService(app1, client1, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
 
-        sService.mOomAdjuster.updateOomAdjLocked(app1, OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(client1, app1);
 
         assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app1);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1798,13 +1988,7 @@
 
         client1.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         client2.mState.setForcingToImportant(new Object());
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app1);
-        lru.add(app2);
-        lru.add(app3);
-        lru.add(client1);
-        lru.add(client2);
+        setProcessesToLru(app1, app2, app3, client1, client2);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
 
         final ComponentName cn1 = ComponentName.unflattenFromString(
@@ -1891,18 +2075,15 @@
         ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         app2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(app2);
+
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
-        lru.clear();
+        updateOomAdj(app, app2);
 
         assertProcStates(app, PROCESS_STATE_TRANSIENT_BACKGROUND, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
         assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app2);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1915,18 +2096,15 @@
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         app2.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindService(app, app2, null, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(app2);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
-        lru.clear();
+        updateOomAdj(app, app2);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
         assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+        assertBfsl(app2);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1942,14 +2120,8 @@
         bindService(app2, app3, null, 0, mock(IBinder.class));
         app3.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindService(app3, app, null, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(app2);
-        lru.add(app3);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
-        lru.clear();
+        updateOomAdj(app, app2, app3);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -1966,6 +2138,9 @@
         assertEquals(false, app.mState.isEmpty());
         assertEquals(false, app2.mState.isEmpty());
         assertEquals(false, app3.mState.isEmpty());
+        assertBfsl(app);
+        assertBfsl(app2);
+        assertBfsl(app3);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -1990,16 +2165,8 @@
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         app5.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindService(app, app5, s, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(app2);
-        lru.add(app3);
-        lru.add(app4);
-        lru.add(app5);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
-        lru.clear();
+        updateOomAdj(app, app2, app3, app4, app5);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -2011,6 +2178,11 @@
                 SCHED_GROUP_DEFAULT);
         assertProcStates(app5, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+        assertBfsl(app2);
+        assertBfsl(app3);
+        // 4 is IMP_FG
+        assertBfsl(app5);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -2035,16 +2207,8 @@
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         app5.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindService(app, app5, s, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app5);
-        lru.add(app4);
-        lru.add(app3);
-        lru.add(app2);
-        lru.add(app);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
-        lru.clear();
+        updateOomAdj(app5, app4, app3, app2, app);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -2056,6 +2220,11 @@
                 SCHED_GROUP_DEFAULT);
         assertProcStates(app5, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+        assertBfsl(app2);
+        assertBfsl(app3);
+        // 4 is IMP_FG
+        assertBfsl(app5);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -2080,16 +2249,8 @@
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         app5.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindService(app, app5, s, 0, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app3);
-        lru.add(app4);
-        lru.add(app2);
-        lru.add(app);
-        lru.add(app5);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
-        lru.clear();
+        updateOomAdj(app3, app4, app2, app, app5);
 
         assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -2101,6 +2262,11 @@
                 SCHED_GROUP_DEFAULT);
         assertProcStates(app5, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+        assertBfsl(app2);
+        assertBfsl(app3);
+        // 4 is IMP_FG
+        assertBfsl(app5);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -2119,18 +2285,13 @@
                 MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
         client3.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
         bindService(app, client3, null, Context.BIND_INCLUDE_CAPABILITIES, mock(IBinder.class));
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(client);
-        lru.add(client2);
-        lru.add(client3);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+        updateOomAdj(app, client, client2, client3);
 
-        assertEquals(PROCESS_CAPABILITY_ALL, client.mState.getSetCapability());
-        assertEquals(PROCESS_CAPABILITY_ALL, client2.mState.getSetCapability());
-        assertEquals(PROCESS_CAPABILITY_ALL, app.mState.getSetCapability());
+        final int expected = PROCESS_CAPABILITY_ALL & ~PROCESS_CAPABILITY_BFSL;
+        assertEquals(expected, client.mState.getSetCapability());
+        assertEquals(expected, client2.mState.getSetCapability());
+        assertEquals(expected, app.mState.getSetCapability());
     }
 
     @SuppressWarnings("GuardedBy")
@@ -2155,16 +2316,8 @@
                 MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
         app5.mServices.setHasForegroundServices(true, 0, /* hasNoneType=*/true);
         bindProvider(app, app5, cr, null, false);
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app);
-        lru.add(app2);
-        lru.add(app3);
-        lru.add(app4);
-        lru.add(app5);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
-        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
-        lru.clear();
+        updateOomAdj(app, app2, app3, app4, app5);
 
         assertProcStates(app, PROCESS_STATE_BOUND_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
@@ -2176,6 +2329,11 @@
                 SCHED_GROUP_DEFAULT);
         assertProcStates(app5, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
                 SCHED_GROUP_DEFAULT);
+        assertBfsl(app);
+        assertBfsl(app2);
+        assertBfsl(app3);
+        // 4 is IMP_FG
+        assertBfsl(app5);
     }
 
     @SuppressWarnings("GuardedBy")
@@ -2202,15 +2360,9 @@
         doCallRealMethod().when(s).getConnections();
         s.startRequested = true;
         s.lastActivity = now;
-        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
-        lru.clear();
-        lru.add(app3);
-        lru.add(app2);
-        lru.add(app);
         sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
         sService.mOomAdjuster.mNumServiceProcs = 3;
-        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
-        lru.clear();
+        updateOomAdj(app3, app2, app);
 
         assertEquals(SERVICE_B_ADJ, app3.mState.getSetAdj());
         assertEquals(SERVICE_ADJ, app2.mState.getSetAdj());
@@ -2489,6 +2641,15 @@
         assertEquals(expectedProcState, state.getSetProcState());
         assertEquals(expectedAdj, state.getSetAdj());
         assertEquals(expectedSchedGroup, state.getSetSchedGroup());
+
+        // Below BFGS should never have BFSL.
+        if (expectedProcState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+            assertNoBfsl(app);
+        }
+        // Above FGS should always have BFSL.
+        if (expectedProcState < PROCESS_STATE_FOREGROUND_SERVICE) {
+            assertBfsl(app);
+        }
     }
 
     private void assertProcStates(ProcessRecord app, boolean expectedCached,
@@ -2498,5 +2659,14 @@
         assertEquals(expectedProcState, state.getSetProcState());
         assertEquals(expectedAdj, state.getSetAdj());
         assertEquals(expectedAdjType, state.getAdjType());
+
+        // Below BFGS should never have BFSL.
+        if (expectedProcState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+            assertNoBfsl(app);
+        }
+        // Above FGS should always have BFSL.
+        if (expectedProcState < PROCESS_STATE_FOREGROUND_SERVICE) {
+            assertBfsl(app);
+        }
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
index 9eed6ad..d1f7f93 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
@@ -42,6 +42,7 @@
 import android.content.res.AssetManager;
 import android.os.Handler;
 import android.os.UserHandle;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
@@ -51,12 +52,14 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.internal.util.ArrayUtils;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.server.LocalServices;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.PackageStateInternal;
 
 import org.junit.After;
 import org.junit.Before;
@@ -188,6 +191,11 @@
 
         // Stub out package calls to disable AppOpsService#updatePermissionRevokedCompat
         doReturn(null).when(mPackageManager).getPackagesForUid(anyInt());
+
+        doReturn(new ArrayMap<String, PackageStateInternal>()).when(mPackageManagerInternal)
+                .getPackageStates();
+
+        doReturn(new int[] {0}).when(mUserManagerInternal).getUserIds();
     }
 
     @After
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java
new file mode 100644
index 0000000..327fc19
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.annotation.NonNull;
+import android.app.backup.BackupHelper;
+import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
+
+import static org.mockito.Mockito.when;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Set;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class SystemBackupAgentTest {
+    private static final int NON_SYSTEM_USER_ID = 10;
+
+    private TestableSystemBackupAgent mSystemBackupAgent;
+
+    @Mock private Context mContextMock;
+    @Mock private UserManager mUserManagerMock;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mSystemBackupAgent = new TestableSystemBackupAgent();
+        when(mContextMock.getSystemService(UserManager.class)).thenReturn(mUserManagerMock);
+    }
+
+    @Test
+    public void onCreate_systemUser_addsAllHelpers() {
+        UserHandle userHandle = new UserHandle(UserHandle.USER_SYSTEM);
+        when(mUserManagerMock.isProfile()).thenReturn(false);
+
+        mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0);
+
+        assertThat(mSystemBackupAgent.mAddedHelpers)
+                .containsExactly(
+                        "account_sync_settings",
+                        "preferred_activities",
+                        "notifications",
+                        "permissions",
+                        "usage_stats",
+                        "shortcut_manager",
+                        "account_manager",
+                        "slices",
+                        "people",
+                        "app_locales",
+                        "app_gender");
+    }
+
+    @Test
+    public void onCreate_profileUser_addsProfileEligibleHelpers() {
+        UserHandle userHandle = new UserHandle(NON_SYSTEM_USER_ID);
+        when(mUserManagerMock.isProfile()).thenReturn(true);
+
+        mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0);
+
+        assertThat(mSystemBackupAgent.mAddedHelpers)
+                .containsExactly(
+                        "account_sync_settings",
+                        "notifications",
+                        "permissions",
+                        "app_locales");
+    }
+
+    @Test
+    public void onCreate_nonSystemUser_addsNonSystemEligibleHelpers() {
+        UserHandle userHandle = new UserHandle(NON_SYSTEM_USER_ID);
+        when(mUserManagerMock.isProfile()).thenReturn(false);
+
+        mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0);
+
+        assertThat(mSystemBackupAgent.mAddedHelpers)
+                .containsExactly(
+                        "account_sync_settings",
+                        "preferred_activities",
+                        "notifications",
+                        "permissions",
+                        "app_locales",
+                        "account_manager",
+                        "usage_stats",
+                        "shortcut_manager");
+    }
+
+    private class TestableSystemBackupAgent extends SystemBackupAgent {
+        final Set<String> mAddedHelpers = new ArraySet<>();
+
+        @Override
+        public void addHelper(String keyPrefix, BackupHelper helper) {
+            mAddedHelpers.add(keyPrefix);
+        }
+
+        @Override
+        public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) {
+            return mContextMock;
+        }
+
+        @Override
+        public Object getSystemService(@ServiceName @NonNull String name) {
+            return null;
+        }
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java
index 6093f4b..0306655 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/utils/BackupEligibilityRulesTest.java
@@ -25,6 +25,7 @@
 
 import android.app.backup.BackupAnnotations.BackupDestination;
 import android.compat.testing.PlatformCompatChangeRule;
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -35,6 +36,7 @@
 import android.content.pm.SigningInfo;
 import android.os.Process;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
@@ -64,11 +66,17 @@
     private static final Signature SIGNATURE_2 = generateSignature((byte) 2);
     private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
     private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
+    private static final int NON_SYSTEM_USER = 10;
 
     @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule();
 
     @Mock private PackageManagerInternal mMockPackageManagerInternal;
-    @Mock private PackageManager mPackageManager;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private Context mContext;
+    @Mock
+    private UserManager mUserManager;
 
     private BackupEligibilityRules mBackupEligibilityRules;
     private int mUserId;
@@ -78,6 +86,7 @@
         MockitoAnnotations.initMocks(this);
 
         mUserId = UserHandle.USER_SYSTEM;
+        mockContextForFullUser();
         mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD);
     }
 
@@ -95,6 +104,70 @@
     }
 
     @Test
+    public void appIsEligibleForBackup_systemUid_nonSystemUser_notAllowedPackage_returnsFalse()
+            throws Exception {
+        setUpForNonSystemUser();
+
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        applicationInfo.uid = Process.SYSTEM_UID;
+        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+        applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+        boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isFalse();
+    }
+
+    @Test
+    public void appIsEligibleForBackup_systemUid_nonSystemUser_allowedPackage_returnsTrue()
+            throws Exception {
+        setUpForNonSystemUser();
+
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        applicationInfo.uid = Process.SYSTEM_UID;
+        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+        applicationInfo.packageName = UserBackupManagerService.WALLPAPER_PACKAGE;
+
+        boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isTrue();
+    }
+
+    @Test
+    public void appIsEligibleForBackup_systemUid_profileUser_notAllowedPackage_returnsFalse()
+            throws Exception {
+        setUpForProfileUser();
+
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        applicationInfo.uid = Process.SYSTEM_UID;
+        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+        applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+        boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isFalse();
+    }
+
+    @Test
+    public void appIsEligibleForBackup_systemUid_profileUser_allowedPackage_returnsTrue()
+            throws Exception {
+        setUpForProfileUser();
+
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        applicationInfo.uid = Process.SYSTEM_UID;
+        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+        applicationInfo.packageName = UserBackupManagerService.PACKAGE_MANAGER_SENTINEL;
+
+        boolean isEligible = mBackupEligibilityRules.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isTrue();
+    }
+
+    @Test
     public void appIsEligibleForBackup_systemAppWithoutCustomBackupAgent_returnsFalse()
             throws Exception {
         ApplicationInfo applicationInfo = new ApplicationInfo();
@@ -790,7 +863,7 @@
     private BackupEligibilityRules getBackupEligibilityRules(
             @BackupDestination int backupDestination) {
         return new BackupEligibilityRules(mPackageManager, mMockPackageManagerInternal, mUserId,
-                backupDestination);
+                mContext, backupDestination);
     }
 
     private static Signature generateSignature(byte i) {
@@ -813,4 +886,26 @@
         return new Property(PackageManager.PROPERTY_ALLOW_ADB_BACKUP, allowAdbBackup,
                 TEST_PACKAGE_NAME, /* className */ "");
     }
+
+    private void setUpForNonSystemUser() {
+        mUserId = NON_SYSTEM_USER;
+        mockContextForFullUser();
+        mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD);
+    }
+
+    private void setUpForProfileUser() {
+        mUserId = NON_SYSTEM_USER;
+        mockContextForProfile();
+        mBackupEligibilityRules = getBackupEligibilityRules(BackupDestination.CLOUD);
+    }
+
+    private void mockContextForProfile() {
+        when(mUserManager.isProfile()).thenReturn(true);
+        when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
+    }
+
+    private void mockContextForFullUser() {
+        when(mUserManager.isProfile()).thenReturn(false);
+        when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
index 30c6975..3399565 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
@@ -149,7 +149,7 @@
                 fileMetadata);
         RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
                 mPackageManagerStub, false /* allowApks */, fileMetadata, signatures,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
         assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
@@ -163,7 +163,7 @@
                 fileMetadata);
         restorePolicy = tarBackupReader.chooseRestorePolicy(
                 mPackageManagerStub, false /* allowApks */, fileMetadata, signatures,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
         assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
@@ -226,7 +226,7 @@
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 true /* allowApks */, new FileMetadata(), null /* signatures */,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         verifyZeroInteractions(mBackupManagerMonitorMock);
@@ -247,7 +247,7 @@
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 true /* allowApks */, info, new Signature[0] /* signatures */,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -272,7 +272,7 @@
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 true /* allowApks */, info, new Signature[0] /* signatures */,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -298,7 +298,7 @@
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -323,7 +323,7 @@
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -350,7 +350,7 @@
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -385,7 +385,7 @@
 
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 false /* allowApks */, new FileMetadata(), signatures,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -424,7 +424,7 @@
                 packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 false /* allowApks */, new FileMetadata(), signatures,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -462,7 +462,7 @@
                 packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 false /* allowApks */, new FileMetadata(), signatures,
-                mMockPackageManagerInternal, mUserId);
+                mMockPackageManagerInternal, mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -504,7 +504,7 @@
                 packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 false /* allowApks */, info, signatures, mMockPackageManagerInternal,
-                mUserId);
+                mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -548,7 +548,7 @@
                 packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 true /* allowApks */, info, signatures, mMockPackageManagerInternal,
-                mUserId);
+                mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
         verifyNoMoreInteractions(mBackupManagerMonitorMock);
@@ -588,7 +588,7 @@
                 packageInfo.packageName);
         RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
                 false /* allowApks */, info, signatures, mMockPackageManagerInternal,
-                mUserId);
+                mUserId, mContext);
 
         assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index 3d36c1c..6e63315 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -16,13 +16,19 @@
 
 package com.android.server.display;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
@@ -37,6 +43,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PowerManager;
+import android.os.SystemProperties;
 import android.os.test.TestLooper;
 import android.util.FloatProperty;
 import android.view.Display;
@@ -46,8 +53,12 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.server.LocalServices;
+import com.android.server.am.BatteryStatsService;
 import com.android.server.display.RampAnimator.DualRampAnimator;
+import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.testutils.OffsettableClock;
 
@@ -58,7 +69,9 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
 
 import java.util.List;
 
@@ -66,14 +79,20 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public final class DisplayPowerController2Test {
-    private static final String UNIQUE_DISPLAY_ID = "unique_id_test123";
-    private static final int DISPLAY_ID = 42;
+    private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY;
+    private static final String UNIQUE_ID = "unique_id_test123";
+    private static final int FOLLOWER_DISPLAY_ID = DISPLAY_ID + 1;
+    private static final String FOLLOWER_UNIQUE_ID = "unique_id_456";
+    private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1;
+    private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789";
 
+    private MockitoSession mSession;
     private OffsettableClock mClock;
     private TestLooper mTestLooper;
     private Handler mHandler;
-    private DisplayPowerController2.Injector mInjector;
     private Context mContextSpy;
+    private DisplayPowerControllerHolder mHolder;
+    private Sensor mProxSensor;
 
     @Mock
     private DisplayPowerCallbacks mDisplayPowerCallbacksMock;
@@ -82,131 +101,106 @@
     @Mock
     private DisplayBlanker mDisplayBlankerMock;
     @Mock
-    private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock;
-    @Mock
-    private LogicalDisplay mLogicalDisplayMock;
-    @Mock
-    private DisplayDevice mDisplayDeviceMock;
-    @Mock
     private BrightnessTracker mBrightnessTrackerMock;
     @Mock
-    private BrightnessSetting mBrightnessSettingMock;
-    @Mock
     private WindowManagerPolicy mWindowManagerPolicyMock;
     @Mock
     private PowerManager mPowerManagerMock;
     @Mock
     private Resources mResourcesMock;
     @Mock
-    private DisplayDeviceConfig mDisplayDeviceConfigMock;
-    @Mock
-    private DisplayPowerState mDisplayPowerStateMock;
-    @Mock
-    private DualRampAnimator<DisplayPowerState> mDualRampAnimatorMock;
-    @Mock
-    private WakelockController mWakelockController;
+    private ColorDisplayService.ColorDisplayServiceInternal mCdsiMock;
 
     @Captor
     private ArgumentCaptor<SensorEventListener> mSensorEventListenerCaptor;
 
     @Before
     public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
+        mSession = ExtendedMockito.mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.LENIENT)
+                .spyStatic(SystemProperties.class)
+                .spyStatic(LocalServices.class)
+                .spyStatic(BatteryStatsService.class)
+                .startMocking();
         mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
         mClock = new OffsettableClock.Stopped();
         mTestLooper = new TestLooper(mClock::now);
         mHandler = new Handler(mTestLooper.getLooper());
-        mInjector = new DisplayPowerController2.Injector() {
-            @Override
-            DisplayPowerController2.Clock getClock() {
-                return mClock::now;
-            }
-
-            @Override
-            DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
-                    int displayId, int displayState) {
-                return mDisplayPowerStateMock;
-            }
-
-            @Override
-            DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
-                    FloatProperty<DisplayPowerState> firstProperty,
-                    FloatProperty<DisplayPowerState> secondProperty) {
-                return mDualRampAnimatorMock;
-            }
-
-            @Override
-            WakelockController getWakelockController(int displayId,
-                    DisplayPowerCallbacks displayPowerCallbacks) {
-                return mWakelockController;
-            }
-
-            @Override
-            DisplayPowerProximityStateController getDisplayPowerProximityStateController(
-                    WakelockController wakelockController, DisplayDeviceConfig displayDeviceConfig,
-                    Looper looper, Runnable nudgeUpdatePowerState, int displayId,
-                    SensorManager sensorManager) {
-                return new DisplayPowerProximityStateController(wakelockController,
-                        displayDeviceConfig, looper, nudgeUpdatePowerState, displayId,
-                        sensorManager, /* injector= */ null);
-            }
-        };
-
         addLocalServiceMock(WindowManagerPolicy.class, mWindowManagerPolicyMock);
 
         when(mContextSpy.getSystemService(eq(PowerManager.class))).thenReturn(mPowerManagerMock);
         when(mContextSpy.getResources()).thenReturn(mResourcesMock);
+
+        doAnswer((Answer<Void>) invocationOnMock -> null).when(() ->
+                SystemProperties.set(anyString(), any()));
+        doAnswer((Answer<ColorDisplayService.ColorDisplayServiceInternal>) invocationOnMock ->
+                mCdsiMock).when(() -> LocalServices.getService(
+                ColorDisplayService.ColorDisplayServiceInternal.class));
+        doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService);
+
+        mProxSensor = setUpProxSensor();
+
+        mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
     }
 
     @After
     public void tearDown() {
+        mSession.finishMocking();
         LocalServices.removeServiceForTest(WindowManagerPolicy.class);
     }
 
     @Test
     public void testReleaseProxSuspendBlockersOnExit() throws Exception {
-        setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID);
-
-        Sensor proxSensor = setUpProxSensor();
-
-        DisplayPowerController2 dpc = new DisplayPowerController2(
-                mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
-                mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
-                mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
-        }, mHighBrightnessModeMetadataMock);
-
-        when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
         // send a display power request
         DisplayPowerRequest dpr = new DisplayPowerRequest();
         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
         dpr.useProximitySensor = true;
-        dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
+        mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
 
         // Run updatePowerState to start listener for the prox sensor
         advanceTime(1);
 
-        SensorEventListener listener = getSensorEventListener(proxSensor);
+        SensorEventListener listener = getSensorEventListener(mProxSensor);
         assertNotNull(listener);
 
-        listener.onSensorChanged(TestUtils.createSensorEvent(proxSensor, 5 /* lux */));
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, 5 /* lux */));
         advanceTime(1);
 
         // two times, one for unfinished business and one for proximity
-        verify(mWakelockController).acquireWakelock(
+        verify(mHolder.wakelockController).acquireWakelock(
                 WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
-        verify(mWakelockController).acquireWakelock(
+        verify(mHolder.wakelockController).acquireWakelock(
                 WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE);
 
-
-        dpc.stop();
+        mHolder.dpc.stop();
         advanceTime(1);
         // two times, one for unfinished business and one for proximity
-        verify(mWakelockController).acquireWakelock(
+        verify(mHolder.wakelockController).acquireWakelock(
                 WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
-        verify(mWakelockController).acquireWakelock(
+        verify(mHolder.wakelockController).acquireWakelock(
                 WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE);
     }
 
+    @Test
+    public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() {
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+        // send a display power request
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+        dpr.useProximitySensor = true;
+        final DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
+        followerDpc.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
+
+        // Run updatePowerState
+        advanceTime(1);
+
+        verify(mSensorManagerMock, never()).registerListener(any(SensorEventListener.class),
+                eq(mProxSensor), anyInt(), any(Handler.class));
+    }
+
     /**
      * Creates a mock and registers it to {@link LocalServices}.
      */
@@ -234,56 +228,394 @@
         return mSensorEventListenerCaptor.getValue();
     }
 
-    private void setUpDisplay(int displayId, String uniqueId) {
+    private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock,
+            DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock) {
         DisplayInfo info = new DisplayInfo();
         DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
 
-        when(mLogicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
-        when(mLogicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(mDisplayDeviceMock);
-        when(mLogicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
-        when(mLogicalDisplayMock.isEnabledLocked()).thenReturn(true);
-        when(mLogicalDisplayMock.isInTransitionLocked()).thenReturn(false);
-        when(mDisplayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
-        when(mDisplayDeviceMock.getUniqueId()).thenReturn(uniqueId);
-        when(mDisplayDeviceMock.getDisplayDeviceConfig()).thenReturn(mDisplayDeviceConfigMock);
-        when(mDisplayDeviceConfigMock.getProximitySensor()).thenReturn(
+        when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
+        when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
+        when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
+        when(logicalDisplayMock.isEnabledLocked()).thenReturn(true);
+        when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+        when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
+        when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
+        when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
+        when(displayDeviceConfigMock.getProximitySensor()).thenReturn(
                 new DisplayDeviceConfig.SensorData() {
                     {
                         type = Sensor.STRING_TYPE_PROXIMITY;
                         name = null;
                     }
                 });
-        when(mDisplayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
+        when(displayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
+        when(displayDeviceConfigMock.isAutoBrightnessAvailable()).thenReturn(true);
+        when(displayDeviceConfigMock.getAmbientLightSensor()).thenReturn(
+                new DisplayDeviceConfig.SensorData());
+        when(displayDeviceConfigMock.getScreenOffBrightnessSensor()).thenReturn(
+                new DisplayDeviceConfig.SensorData());
     }
 
     @Test
-    public void testDisplayBrightnessFollowers() {
-        setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID);
+    public void testDisplayBrightnessFollowers_BothDpcsSupportNits() {
+        DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
 
-        DisplayPowerController2 defaultDpc = new DisplayPowerController2(
-                mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
-                mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
-                mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
-        }, mHighBrightnessModeMetadataMock);
-        DisplayPowerController2 followerDpc = new DisplayPowerController2(
-                mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
-                mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
-                mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
-        }, mHighBrightnessModeMetadataMock);
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
 
-        defaultDpc.addDisplayBrightnessFollower(followerDpc);
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
 
-        defaultDpc.setBrightness(0.3f);
-        assertEquals(defaultDpc.getBrightnessInfo().brightness,
-                followerDpc.getBrightnessInfo().brightness, 0);
+        mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
 
-        defaultDpc.setBrightness(0.6f);
-        assertEquals(defaultDpc.getBrightnessInfo().brightness,
-                followerDpc.getBrightnessInfo().brightness, 0);
+        // Test different float scale values
+        float leadBrightness = 0.3f;
+        float followerBrightness = 0.4f;
+        float nits = 300;
+        when(mHolder.automaticBrightnessController.convertToNits(leadBrightness)).thenReturn(nits);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(followerBrightness);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(leadBrightness);
+        listener.onBrightnessChanged(leadBrightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(leadBrightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(followerBrightness), anyFloat(),
+                anyFloat());
 
-        float brightness = 0.1f;
-        defaultDpc.clearDisplayBrightnessFollowers();
-        defaultDpc.setBrightness(brightness);
-        assertNotEquals(brightness, followerDpc.getBrightnessInfo().brightness, 0);
+        clearInvocations(mHolder.animator, followerDpc.animator);
+
+        // Test the same float scale value
+        float brightness = 0.6f;
+        nits = 600;
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+    @Test
+    public void testDisplayBrightnessFollowers_FollowerDoesNotSupportNits() {
+        DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
+
+        mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
+
+        float brightness = 0.3f;
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(300f);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat()))
+                .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+    @Test
+    public void testDisplayBrightnessFollowers_LeadDpcDoesNotSupportNits() {
+        DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
+
+        mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
+
+        float brightness = 0.3f;
+        when(mHolder.automaticBrightnessController.convertToNits(anyFloat())).thenReturn(-1f);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+    @Test
+    public void testDisplayBrightnessFollowers_NeitherDpcSupportsNits() {
+        DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_ID);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
+
+        mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
+
+        float brightness = 0.3f;
+        when(mHolder.automaticBrightnessController.convertToNits(anyFloat())).thenReturn(-1f);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat()))
+                .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+
+    @Test
+    public void testDisplayBrightnessFollowersRemoval() {
+        DisplayPowerControllerHolder followerDpc = createDisplayPowerController(FOLLOWER_DISPLAY_ID,
+                FOLLOWER_UNIQUE_ID);
+        DisplayPowerControllerHolder secondFollowerDpc = createDisplayPowerController(
+                SECOND_FOLLOWER_DISPLAY_ID, SECOND_FOLLOWER_UNIQUE_DISPLAY_ID);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        secondFollowerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
+
+        // Set the initial brightness on the DPC we're going to remove so we have a fixed value for
+        // it to return to.
+        listenerCaptor = ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(followerDpc.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener followerListener = listenerCaptor.getValue();
+        final float initialFollowerBrightness = 0.3f;
+        when(followerDpc.brightnessSetting.getBrightness()).thenReturn(initialFollowerBrightness);
+        followerListener.onBrightnessChanged(initialFollowerBrightness);
+        advanceTime(1);
+        verify(followerDpc.animator).animateTo(eq(initialFollowerBrightness),
+                anyFloat(), anyFloat());
+
+
+        mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
+        mHolder.dpc.addDisplayBrightnessFollower(secondFollowerDpc.dpc);
+        clearInvocations(followerDpc.animator);
+
+        // Validate both followers are correctly registered and receiving brightness updates
+        float brightness = 0.6f;
+        float nits = 600;
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(secondFollowerDpc.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+
+        clearInvocations(mHolder.animator, followerDpc.animator, secondFollowerDpc.animator);
+
+        // Remove the first follower and validate it goes back to its original brightness.
+        mHolder.dpc.removeDisplayBrightnessFollower(followerDpc.dpc);
+        advanceTime(1);
+        verify(followerDpc.animator).animateTo(eq(initialFollowerBrightness),
+                anyFloat(), anyFloat());
+        clearInvocations(followerDpc.animator);
+
+        // Change the brightness of the lead display and validate only the second follower responds
+        brightness = 0.7f;
+        nits = 700;
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(secondFollowerDpc.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator, never()).animateTo(anyFloat(), anyFloat(), anyFloat());
+        verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+    private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
+            String uniqueId) {
+        final DisplayPowerState displayPowerState = mock(DisplayPowerState.class);
+        final DualRampAnimator<DisplayPowerState> animator = mock(DualRampAnimator.class);
+        final AutomaticBrightnessController automaticBrightnessController =
+                mock(AutomaticBrightnessController.class);
+        final WakelockController wakelockController = mock(WakelockController.class);
+        final BrightnessMappingStrategy brightnessMappingStrategy =
+                mock(BrightnessMappingStrategy.class);
+        final HysteresisLevels hysteresisLevels = mock(HysteresisLevels.class);
+
+        TestInjector injector = new TestInjector(displayPowerState, animator,
+                automaticBrightnessController, wakelockController, brightnessMappingStrategy,
+                hysteresisLevels);
+
+        final LogicalDisplay display = mock(LogicalDisplay.class);
+        final DisplayDevice device = mock(DisplayDevice.class);
+        final HighBrightnessModeMetadata hbmMetadata = mock(HighBrightnessModeMetadata.class);
+        final BrightnessSetting brightnessSetting = mock(BrightnessSetting.class);
+        final DisplayDeviceConfig config = mock(DisplayDeviceConfig.class);
+
+        setUpDisplay(displayId, uniqueId, display, device, config);
+
+        final DisplayPowerController2 dpc = new DisplayPowerController2(
+                mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler,
+                mSensorManagerMock, mDisplayBlankerMock, display,
+                mBrightnessTrackerMock, brightnessSetting, () -> {},
+                hbmMetadata);
+
+        return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
+                automaticBrightnessController, wakelockController);
+    }
+
+    /**
+     * A class for holding a DisplayPowerController under test and all the mocks specifically
+     * related to it.
+     */
+    private static class DisplayPowerControllerHolder {
+        public final DisplayPowerController2 dpc;
+        public final DisplayPowerState displayPowerState;
+        public final BrightnessSetting brightnessSetting;
+        public final DualRampAnimator<DisplayPowerState> animator;
+        public final AutomaticBrightnessController automaticBrightnessController;
+        public final WakelockController wakelockController;
+
+        DisplayPowerControllerHolder(DisplayPowerController2 dpc,
+                DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
+                DualRampAnimator<DisplayPowerState> animator,
+                AutomaticBrightnessController automaticBrightnessController,
+                WakelockController wakelockController) {
+            this.dpc = dpc;
+            this.displayPowerState = displayPowerState;
+            this.brightnessSetting = brightnessSetting;
+            this.animator = animator;
+            this.automaticBrightnessController = automaticBrightnessController;
+            this.wakelockController = wakelockController;
+        }
+    }
+
+    private class TestInjector extends DisplayPowerController2.Injector {
+        private final DisplayPowerState mDisplayPowerState;
+        private final DualRampAnimator<DisplayPowerState> mAnimator;
+        private final AutomaticBrightnessController mAutomaticBrightnessController;
+        private final WakelockController mWakelockController;
+        private final BrightnessMappingStrategy mBrightnessMappingStrategy;
+        private final HysteresisLevels mHysteresisLevels;
+
+        TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> animator,
+                AutomaticBrightnessController automaticBrightnessController,
+                WakelockController wakelockController,
+                BrightnessMappingStrategy brightnessMappingStrategy,
+                HysteresisLevels hysteresisLevels) {
+            mDisplayPowerState = dps;
+            mAnimator = animator;
+            mAutomaticBrightnessController = automaticBrightnessController;
+            mWakelockController = wakelockController;
+            mBrightnessMappingStrategy = brightnessMappingStrategy;
+            mHysteresisLevels = hysteresisLevels;
+        }
+
+        @Override
+        DisplayPowerController2.Clock getClock() {
+            return mClock::now;
+        }
+
+        @Override
+        DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
+                int displayId, int displayState) {
+            return mDisplayPowerState;
+        }
+
+        @Override
+        DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
+                FloatProperty<DisplayPowerState> firstProperty,
+                FloatProperty<DisplayPowerState> secondProperty) {
+            return mAnimator;
+        }
+
+        @Override
+        WakelockController getWakelockController(int displayId,
+                DisplayPowerCallbacks displayPowerCallbacks) {
+            return mWakelockController;
+        }
+
+        @Override
+        DisplayPowerProximityStateController getDisplayPowerProximityStateController(
+                WakelockController wakelockController, DisplayDeviceConfig displayDeviceConfig,
+                Looper looper, Runnable nudgeUpdatePowerState, int displayId,
+                SensorManager sensorManager) {
+            return new DisplayPowerProximityStateController(wakelockController,
+                    displayDeviceConfig, looper, nudgeUpdatePowerState, displayId,
+                    sensorManager, /* injector= */ null);
+        }
+
+        @Override
+        AutomaticBrightnessController getAutomaticBrightnessController(
+                AutomaticBrightnessController.Callbacks callbacks, Looper looper,
+                SensorManager sensorManager, Sensor lightSensor,
+                BrightnessMappingStrategy interactiveModeBrightnessMapper,
+                int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
+                float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
+                long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
+                boolean resetAmbientLuxAfterWarmUpConfig,
+                HysteresisLevels ambientBrightnessThresholds,
+                HysteresisLevels screenBrightnessThresholds,
+                HysteresisLevels ambientBrightnessThresholdsIdle,
+                HysteresisLevels screenBrightnessThresholdsIdle, Context context,
+                HighBrightnessModeController hbmController,
+                BrightnessThrottler brightnessThrottler,
+                BrightnessMappingStrategy idleModeBrightnessMapper,
+                int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux,
+                float userBrightness) {
+            return mAutomaticBrightnessController;
+        }
+
+        @Override
+        BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
+                DisplayDeviceConfig displayDeviceConfig,
+                DisplayWhiteBalanceController displayWhiteBalanceController) {
+            return mBrightnessMappingStrategy;
+        }
+
+        @Override
+        HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
+                float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
+                float[] darkeningThresholdLevels, float minDarkeningThreshold,
+                float minBrighteningThreshold) {
+            return mHysteresisLevels;
+        }
+
+        @Override
+        HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
+                float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
+                float[] darkeningThresholdLevels, float minDarkeningThreshold,
+                float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
+            return mHysteresisLevels;
+        }
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
index b6388cc..a8c3e4e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -16,14 +16,19 @@
 
 package com.android.server.display;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
@@ -36,7 +41,9 @@
 import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.PowerManager;
+import android.os.SystemProperties;
 import android.os.test.TestLooper;
 import android.util.FloatProperty;
 import android.view.Display;
@@ -46,8 +53,12 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.server.LocalServices;
+import com.android.server.am.BatteryStatsService;
 import com.android.server.display.RampAnimator.DualRampAnimator;
+import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.testutils.OffsettableClock;
 
@@ -58,7 +69,9 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
 
 import java.util.List;
 
@@ -66,14 +79,20 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public final class DisplayPowerControllerTest {
-    private static final String UNIQUE_DISPLAY_ID = "unique_id_test123";
-    private static final int DISPLAY_ID = 42;
+    private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY;
+    private static final String UNIQUE_ID = "unique_id_test123";
+    private static final int FOLLOWER_DISPLAY_ID = DISPLAY_ID + 1;
+    private static final String FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_456";
+    private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1;
+    private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789";
 
+    private MockitoSession mSession;
     private OffsettableClock mClock;
     private TestLooper mTestLooper;
     private Handler mHandler;
-    private DisplayPowerController.Injector mInjector;
     private Context mContextSpy;
+    private DisplayPowerControllerHolder mHolder;
+    private Sensor mProxSensor;
 
     @Mock
     private DisplayPowerCallbacks mDisplayPowerCallbacksMock;
@@ -82,111 +101,107 @@
     @Mock
     private DisplayBlanker mDisplayBlankerMock;
     @Mock
-    private LogicalDisplay mLogicalDisplayMock;
-    @Mock
-    private DisplayDevice mDisplayDeviceMock;
-    @Mock
-    private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock;
-    @Mock
     private BrightnessTracker mBrightnessTrackerMock;
     @Mock
-    private BrightnessSetting mBrightnessSettingMock;
-    @Mock
     private WindowManagerPolicy mWindowManagerPolicyMock;
     @Mock
     private PowerManager mPowerManagerMock;
     @Mock
     private Resources mResourcesMock;
     @Mock
-    private DisplayDeviceConfig mDisplayDeviceConfigMock;
-    @Mock
-    private DisplayPowerState mDisplayPowerStateMock;
-    @Mock
-    private DualRampAnimator<DisplayPowerState> mDualRampAnimatorMock;
+    private ColorDisplayService.ColorDisplayServiceInternal mCdsiMock;
 
     @Captor
     private ArgumentCaptor<SensorEventListener> mSensorEventListenerCaptor;
 
     @Before
     public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
+        mSession = ExtendedMockito.mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.LENIENT)
+                .spyStatic(SystemProperties.class)
+                .spyStatic(LocalServices.class)
+                .spyStatic(BatteryStatsService.class)
+                .startMocking();
         mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
         mClock = new OffsettableClock.Stopped();
         mTestLooper = new TestLooper(mClock::now);
         mHandler = new Handler(mTestLooper.getLooper());
-        mInjector = new DisplayPowerController.Injector() {
-            @Override
-            DisplayPowerController.Clock getClock() {
-                return mClock::now;
-            }
-
-            @Override
-            DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
-                    int displayId, int displayState) {
-                return mDisplayPowerStateMock;
-            }
-
-            @Override
-            DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
-                    FloatProperty<DisplayPowerState> firstProperty,
-                    FloatProperty<DisplayPowerState> secondProperty) {
-                return mDualRampAnimatorMock;
-            }
-        };
 
         addLocalServiceMock(WindowManagerPolicy.class, mWindowManagerPolicyMock);
 
         when(mContextSpy.getSystemService(eq(PowerManager.class))).thenReturn(mPowerManagerMock);
         when(mContextSpy.getResources()).thenReturn(mResourcesMock);
+
+        doAnswer((Answer<Void>) invocationOnMock -> null).when(() ->
+                SystemProperties.set(anyString(), any()));
+        doAnswer((Answer<ColorDisplayService.ColorDisplayServiceInternal>) invocationOnMock ->
+                mCdsiMock).when(() -> LocalServices.getService(
+                ColorDisplayService.ColorDisplayServiceInternal.class));
+        doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService);
+
+        mProxSensor = setUpProxSensor();
+
+        mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
     }
 
     @After
     public void tearDown() {
+        mSession.finishMocking();
         LocalServices.removeServiceForTest(WindowManagerPolicy.class);
     }
 
     @Test
     public void testReleaseProxSuspendBlockersOnExit() throws Exception {
-        setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID);
-
-        Sensor proxSensor = setUpProxSensor();
-
-        DisplayPowerController dpc = new DisplayPowerController(
-                mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
-                mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
-                mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
-        }, mHighBrightnessModeMetadataMock);
-
-        when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
         // send a display power request
         DisplayPowerRequest dpr = new DisplayPowerRequest();
         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
         dpr.useProximitySensor = true;
-        dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
+        mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
 
         // Run updatePowerState to start listener for the prox sensor
         advanceTime(1);
 
-        SensorEventListener listener = getSensorEventListener(proxSensor);
+        SensorEventListener listener = getSensorEventListener(mProxSensor);
         assertNotNull(listener);
 
-        listener.onSensorChanged(TestUtils.createSensorEvent(proxSensor, 5 /* lux */));
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, 5 /* lux */));
         advanceTime(1);
 
         // two times, one for unfinished business and one for proximity
         verify(mDisplayPowerCallbacksMock).acquireSuspendBlocker(
-                dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
+                mHolder.dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
         verify(mDisplayPowerCallbacksMock).acquireSuspendBlocker(
-                dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
+                mHolder.dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
 
-        dpc.stop();
+        mHolder.dpc.stop();
         advanceTime(1);
 
         // two times, one for unfinished business and one for proximity
         verify(mDisplayPowerCallbacksMock).releaseSuspendBlocker(
-                dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
+                mHolder.dpc.getSuspendBlockerUnfinishedBusinessId(DISPLAY_ID));
         verify(mDisplayPowerCallbacksMock).releaseSuspendBlocker(
-                dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
+                mHolder.dpc.getSuspendBlockerProxDebounceId(DISPLAY_ID));
+    }
+
+    @Test
+    public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() {
+        DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID);
+
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+        // send a display power request
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+        dpr.useProximitySensor = true;
+        followerDpc.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
+
+        // Run updatePowerState
+        advanceTime(1);
+
+        verify(mSensorManagerMock, never()).registerListener(any(SensorEventListener.class),
+                eq(mProxSensor), anyInt(), any(Handler.class));
     }
 
     /**
@@ -216,56 +231,371 @@
         return mSensorEventListenerCaptor.getValue();
     }
 
-    private void setUpDisplay(int displayId, String uniqueId) {
+    private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock,
+            DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock) {
         DisplayInfo info = new DisplayInfo();
         DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
 
-        when(mLogicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
-        when(mLogicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(mDisplayDeviceMock);
-        when(mLogicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
-        when(mLogicalDisplayMock.isEnabledLocked()).thenReturn(true);
-        when(mLogicalDisplayMock.isInTransitionLocked()).thenReturn(false);
-        when(mDisplayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
-        when(mDisplayDeviceMock.getUniqueId()).thenReturn(uniqueId);
-        when(mDisplayDeviceMock.getDisplayDeviceConfig()).thenReturn(mDisplayDeviceConfigMock);
-        when(mDisplayDeviceConfigMock.getProximitySensor()).thenReturn(
+        when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
+        when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
+        when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
+        when(logicalDisplayMock.isEnabledLocked()).thenReturn(true);
+        when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+        when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
+        when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
+        when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
+        when(displayDeviceConfigMock.getProximitySensor()).thenReturn(
                 new DisplayDeviceConfig.SensorData() {
                     {
                         type = Sensor.STRING_TYPE_PROXIMITY;
                         name = null;
                     }
                 });
-        when(mDisplayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
+        when(displayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
+        when(displayDeviceConfigMock.isAutoBrightnessAvailable()).thenReturn(true);
+        when(displayDeviceConfigMock.getAmbientLightSensor()).thenReturn(
+                new DisplayDeviceConfig.SensorData());
+        when(displayDeviceConfigMock.getScreenOffBrightnessSensor()).thenReturn(
+                new DisplayDeviceConfig.SensorData());
     }
 
     @Test
-    public void testDisplayBrightnessFollowers() {
-        setUpDisplay(DISPLAY_ID, UNIQUE_DISPLAY_ID);
+    public void testDisplayBrightnessFollowers_BothDpcsSupportNits() {
+        DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID);
 
-        DisplayPowerController defaultDpc = new DisplayPowerController(
-                mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
-                mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
-                mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
-        }, mHighBrightnessModeMetadataMock);
-        DisplayPowerController followerDpc = new DisplayPowerController(
-                mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
-                mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
-                mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
-        }, mHighBrightnessModeMetadataMock);
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
 
-        defaultDpc.addDisplayBrightnessFollower(followerDpc);
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
 
-        defaultDpc.setBrightness(0.3f);
-        assertEquals(defaultDpc.getBrightnessInfo().brightness,
-                followerDpc.getBrightnessInfo().brightness, 0);
+        mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
 
-        defaultDpc.setBrightness(0.6f);
-        assertEquals(defaultDpc.getBrightnessInfo().brightness,
-                followerDpc.getBrightnessInfo().brightness, 0);
+        // Test different float scale values
+        float leadBrightness = 0.3f;
+        float followerBrightness = 0.4f;
+        float nits = 300;
+        when(mHolder.automaticBrightnessController.convertToNits(leadBrightness)).thenReturn(nits);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(followerBrightness);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(leadBrightness);
+        listener.onBrightnessChanged(leadBrightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(leadBrightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(followerBrightness), anyFloat(),
+                anyFloat());
 
-        float brightness = 0.1f;
-        defaultDpc.clearDisplayBrightnessFollowers();
-        defaultDpc.setBrightness(brightness);
-        assertNotEquals(brightness, followerDpc.getBrightnessInfo().brightness, 0);
+        clearInvocations(mHolder.animator, followerDpc.animator);
+
+        // Test the same float scale value
+        float brightness = 0.6f;
+        nits = 600;
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+    @Test
+    public void testDisplayBrightnessFollowers_FollowerDoesNotSupportNits() {
+        DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
+
+        mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
+
+        float brightness = 0.3f;
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(300f);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat()))
+                .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+    @Test
+    public void testDisplayBrightnessFollowers_LeadDpcDoesNotSupportNits() {
+        DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
+
+        mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
+
+        float brightness = 0.3f;
+        when(mHolder.automaticBrightnessController.convertToNits(anyFloat())).thenReturn(-1f);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+    @Test
+    public void testDisplayBrightnessFollowers_NeitherDpcSupportsNits() {
+        DisplayPowerControllerHolder followerDpc =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerDpc.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
+
+        mHolder.dpc.addDisplayBrightnessFollower(followerDpc.dpc);
+
+        float brightness = 0.3f;
+        when(mHolder.automaticBrightnessController.convertToNits(anyFloat())).thenReturn(-1f);
+        when(followerDpc.automaticBrightnessController.convertToFloatScale(anyFloat()))
+                .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+    @Test
+    public void testDisplayBrightnessFollowersRemoval() {
+        DisplayPowerControllerHolder followerHolder =
+                createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID);
+        DisplayPowerControllerHolder secondFollowerHolder =
+                createDisplayPowerController(SECOND_FOLLOWER_DISPLAY_ID,
+                        SECOND_FOLLOWER_UNIQUE_DISPLAY_ID);
+
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        followerHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        secondFollowerHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        ArgumentCaptor<BrightnessSetting.BrightnessSettingListener> listenerCaptor =
+                ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(mHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener listener = listenerCaptor.getValue();
+
+        // Set the initial brightness on the DPC we're going to remove so we have a fixed value for
+        // it to return to.
+        listenerCaptor = ArgumentCaptor.forClass(BrightnessSetting.BrightnessSettingListener.class);
+        verify(followerHolder.brightnessSetting).registerListener(listenerCaptor.capture());
+        BrightnessSetting.BrightnessSettingListener followerListener = listenerCaptor.getValue();
+        final float initialFollowerBrightness = 0.3f;
+        when(followerHolder.brightnessSetting.getBrightness()).thenReturn(
+                initialFollowerBrightness);
+        followerListener.onBrightnessChanged(initialFollowerBrightness);
+        advanceTime(1);
+        verify(followerHolder.animator).animateTo(eq(initialFollowerBrightness),
+                anyFloat(), anyFloat());
+
+
+        mHolder.dpc.addDisplayBrightnessFollower(followerHolder.dpc);
+        mHolder.dpc.addDisplayBrightnessFollower(secondFollowerHolder.dpc);
+        clearInvocations(followerHolder.animator);
+
+        // Validate both followers are correctly registered and receiving brightness updates
+        float brightness = 0.6f;
+        float nits = 600;
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
+        when(followerHolder.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(secondFollowerHolder.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(secondFollowerHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+
+        clearInvocations(mHolder.animator, followerHolder.animator, secondFollowerHolder.animator);
+
+        // Remove the first follower and validate it goes back to its original brightness.
+        mHolder.dpc.removeDisplayBrightnessFollower(followerHolder.dpc);
+        advanceTime(1);
+        verify(followerHolder.animator).animateTo(eq(initialFollowerBrightness),
+                anyFloat(), anyFloat());
+        clearInvocations(followerHolder.animator);
+
+        // Change the brightness of the lead display and validate only the second follower responds
+        brightness = 0.7f;
+        nits = 700;
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
+        when(followerHolder.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(secondFollowerHolder.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(brightness);
+        when(mHolder.brightnessSetting.getBrightness()).thenReturn(brightness);
+        listener.onBrightnessChanged(brightness);
+        advanceTime(1); // Send messages, run updatePowerState
+        verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+        verify(followerHolder.animator, never()).animateTo(anyFloat(), anyFloat(), anyFloat());
+        verify(secondFollowerHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+    }
+
+    private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
+            String uniqueId) {
+        final DisplayPowerState displayPowerState = mock(DisplayPowerState.class);
+        final DualRampAnimator<DisplayPowerState> animator = mock(DualRampAnimator.class);
+        final AutomaticBrightnessController automaticBrightnessController =
+                mock(AutomaticBrightnessController.class);
+        final BrightnessMappingStrategy brightnessMappingStrategy =
+                mock(BrightnessMappingStrategy.class);
+        final HysteresisLevels hysteresisLevels = mock(HysteresisLevels.class);
+
+        DisplayPowerController.Injector injector = new TestInjector(displayPowerState, animator,
+                automaticBrightnessController, brightnessMappingStrategy, hysteresisLevels);
+
+        final LogicalDisplay display = mock(LogicalDisplay.class);
+        final DisplayDevice device = mock(DisplayDevice.class);
+        final HighBrightnessModeMetadata hbmMetadata = mock(HighBrightnessModeMetadata.class);
+        final BrightnessSetting brightnessSetting = mock(BrightnessSetting.class);
+        final DisplayDeviceConfig config = mock(DisplayDeviceConfig.class);
+
+        setUpDisplay(displayId, uniqueId, display, device, config);
+
+        final DisplayPowerController dpc = new DisplayPowerController(
+                mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler,
+                mSensorManagerMock, mDisplayBlankerMock, display,
+                mBrightnessTrackerMock, brightnessSetting, () -> {},
+                hbmMetadata);
+
+        return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
+                automaticBrightnessController);
+    }
+
+    /**
+     * A class for holding a DisplayPowerController under test and all the mocks specifically
+     * related to it.
+     */
+    private static class DisplayPowerControllerHolder {
+        public final DisplayPowerController dpc;
+        public final DisplayPowerState displayPowerState;
+        public final BrightnessSetting brightnessSetting;
+        public final DualRampAnimator<DisplayPowerState> animator;
+        public final AutomaticBrightnessController automaticBrightnessController;
+
+        DisplayPowerControllerHolder(DisplayPowerController dpc,
+                DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
+                DualRampAnimator<DisplayPowerState> animator,
+                AutomaticBrightnessController automaticBrightnessController) {
+            this.dpc = dpc;
+            this.displayPowerState = displayPowerState;
+            this.brightnessSetting = brightnessSetting;
+            this.animator = animator;
+            this.automaticBrightnessController = automaticBrightnessController;
+        }
+    }
+
+    private class TestInjector extends DisplayPowerController.Injector {
+        private final DisplayPowerState mDisplayPowerState;
+        private final DualRampAnimator<DisplayPowerState> mAnimator;
+        private final AutomaticBrightnessController mAutomaticBrightnessController;
+        private final BrightnessMappingStrategy mBrightnessMappingStrategy;
+        private final HysteresisLevels mHysteresisLevels;
+
+        TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> animator,
+                AutomaticBrightnessController automaticBrightnessController,
+                BrightnessMappingStrategy brightnessMappingStrategy,
+                HysteresisLevels hysteresisLevels) {
+            mDisplayPowerState = dps;
+            mAnimator = animator;
+            mAutomaticBrightnessController = automaticBrightnessController;
+            mBrightnessMappingStrategy = brightnessMappingStrategy;
+            mHysteresisLevels = hysteresisLevels;
+        }
+
+        @Override
+        DisplayPowerController.Clock getClock() {
+            return mClock::now;
+        }
+
+        @Override
+        DisplayPowerState getDisplayPowerState(DisplayBlanker blanker, ColorFade colorFade,
+                int displayId, int displayState) {
+            return mDisplayPowerState;
+        }
+
+        @Override
+        DualRampAnimator<DisplayPowerState> getDualRampAnimator(DisplayPowerState dps,
+                FloatProperty<DisplayPowerState> firstProperty,
+                FloatProperty<DisplayPowerState> secondProperty) {
+            return mAnimator;
+        }
+
+        @Override
+        AutomaticBrightnessController getAutomaticBrightnessController(
+                AutomaticBrightnessController.Callbacks callbacks, Looper looper,
+                SensorManager sensorManager, Sensor lightSensor,
+                BrightnessMappingStrategy interactiveModeBrightnessMapper,
+                int lightSensorWarmUpTime, float brightnessMin, float brightnessMax,
+                float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
+                long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
+                boolean resetAmbientLuxAfterWarmUpConfig,
+                HysteresisLevels ambientBrightnessThresholds,
+                HysteresisLevels screenBrightnessThresholds,
+                HysteresisLevels ambientBrightnessThresholdsIdle,
+                HysteresisLevels screenBrightnessThresholdsIdle, Context context,
+                HighBrightnessModeController hbmController,
+                BrightnessThrottler brightnessThrottler,
+                BrightnessMappingStrategy idleModeBrightnessMapper,
+                int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux,
+                float userBrightness) {
+            return mAutomaticBrightnessController;
+        }
+
+        @Override
+        BrightnessMappingStrategy getInteractiveModeBrightnessMapper(Resources resources,
+                DisplayDeviceConfig displayDeviceConfig,
+                DisplayWhiteBalanceController displayWhiteBalanceController) {
+            return mBrightnessMappingStrategy;
+        }
+
+        @Override
+        HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
+                float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
+                float[] darkeningThresholdLevels, float minDarkeningThreshold,
+                float minBrighteningThreshold) {
+            return mHysteresisLevels;
+        }
+
+        @Override
+        HysteresisLevels getHysteresisLevels(float[] brighteningThresholdsPercentages,
+                float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels,
+                float[] darkeningThresholdLevels, float minDarkeningThreshold,
+                float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
+            return mHysteresisLevels;
+        }
     }
 }
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 ed78e72..c7bacbc 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -32,6 +32,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
@@ -470,6 +472,50 @@
     }
 
     /**
+     * Confirm that
+     * returns {@code null} when for user-visible jobs stopped by the user.
+     */
+    @Test
+    public void testGetRescheduleJobForFailure_userStopped() {
+        JobStatus uiJob = createJobStatus("testGetRescheduleJobForFailure",
+                createJobInfo().setUserInitiated(true));
+        JobStatus uvJob = createJobStatus("testGetRescheduleJobForFailure", createJobInfo());
+        spyOn(uvJob);
+        doReturn(true).when(uvJob).isUserVisibleJob();
+        JobStatus regJob = createJobStatus("testGetRescheduleJobForFailure", createJobInfo());
+
+        // Reschedule for a non-user reason
+        JobStatus rescheduledUiJob = mService.getRescheduleJobForFailureLocked(uiJob,
+                JobParameters.STOP_REASON_DEVICE_STATE,
+                JobParameters.INTERNAL_STOP_REASON_DEVICE_THERMAL);
+        JobStatus rescheduledUvJob = mService.getRescheduleJobForFailureLocked(uvJob,
+                JobParameters.STOP_REASON_DEVICE_STATE,
+                JobParameters.INTERNAL_STOP_REASON_DEVICE_THERMAL);
+        JobStatus rescheduledRegJob = mService.getRescheduleJobForFailureLocked(regJob,
+                JobParameters.STOP_REASON_DEVICE_STATE,
+                JobParameters.INTERNAL_STOP_REASON_DEVICE_THERMAL);
+        assertNotNull(rescheduledUiJob);
+        assertNotNull(rescheduledUvJob);
+        assertNotNull(rescheduledRegJob);
+
+        // Reschedule for a user reason. The user-visible jobs shouldn't be rescheduled.
+        spyOn(rescheduledUvJob);
+        doReturn(true).when(rescheduledUvJob).isUserVisibleJob();
+        rescheduledUiJob = mService.getRescheduleJobForFailureLocked(rescheduledUiJob,
+                JobParameters.STOP_REASON_USER,
+                JobParameters.INTERNAL_STOP_REASON_USER_UI_STOP);
+        rescheduledUvJob = mService.getRescheduleJobForFailureLocked(rescheduledUvJob,
+                JobParameters.STOP_REASON_USER,
+                JobParameters.INTERNAL_STOP_REASON_USER_UI_STOP);
+        rescheduledRegJob = mService.getRescheduleJobForFailureLocked(rescheduledRegJob,
+                JobParameters.STOP_REASON_USER,
+                JobParameters.INTERNAL_STOP_REASON_USER_UI_STOP);
+        assertNull(rescheduledUiJob);
+        assertNull(rescheduledUvJob);
+        assertNotNull(rescheduledRegJob);
+    }
+
+    /**
      * Confirm that {@link JobSchedulerService#getRescheduleJobForPeriodic(JobStatus)} returns a job
      * with the correct delay and deadline constraints if the periodic job is scheduled with the
      * minimum possible period.
@@ -1274,14 +1320,14 @@
         mService.getJobStore().add(job2a);
         mService.getJobStore().add(job2b);
 
-        mService.stopUserVisibleJobsInternal("pkg1", 1);
+        mService.notePendingUserRequestedAppStopInternal("pkg1", 1, "test");
         assertEquals(4, mService.getPendingJobQueue().size());
         assertTrue(mService.getPendingJobQueue().contains(job1a));
         assertTrue(mService.getPendingJobQueue().contains(job1b));
         assertTrue(mService.getPendingJobQueue().contains(job2a));
         assertTrue(mService.getPendingJobQueue().contains(job2b));
 
-        mService.stopUserVisibleJobsInternal("pkg1", 0);
+        mService.notePendingUserRequestedAppStopInternal("pkg1", 0, "test");
         assertEquals(2, mService.getPendingJobQueue().size());
         assertFalse(mService.getPendingJobQueue().contains(job1a));
         assertEquals(JobScheduler.PENDING_JOB_REASON_USER, mService.getPendingJobReason(job1a));
@@ -1290,7 +1336,7 @@
         assertTrue(mService.getPendingJobQueue().contains(job2a));
         assertTrue(mService.getPendingJobQueue().contains(job2b));
 
-        mService.stopUserVisibleJobsInternal("pkg2", 0);
+        mService.notePendingUserRequestedAppStopInternal("pkg2", 0, "test");
         assertEquals(0, mService.getPendingJobQueue().size());
         assertFalse(mService.getPendingJobQueue().contains(job1a));
         assertFalse(mService.getPendingJobQueue().contains(job1b));
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 2c47fd9..e6bc72f 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
@@ -225,6 +225,33 @@
     }
 
     @Test
+    public void testIsUserVisibleJob() {
+        JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
+                .setUserInitiated(false)
+                .build();
+        JobStatus job = createJobStatus(jobInfo);
+
+        assertFalse(job.isUserVisibleJob());
+
+        // User-initiated jobs are always user-visible unless they've been demoted.
+        jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
+                .setUserInitiated(true)
+                .build();
+        job = createJobStatus(jobInfo);
+
+        assertTrue(job.isUserVisibleJob());
+
+        job.addInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
+        assertFalse(job.isUserVisibleJob());
+
+        job.startedAsUserInitiatedJob = true;
+        assertTrue(job.isUserVisibleJob());
+
+        job.startedAsUserInitiatedJob = false;
+        assertFalse(job.isUserVisibleJob());
+    }
+
+    @Test
     public void testMediaBackupExemption_lateConstraint() {
         final JobInfo triggerContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
                 .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
index e0662c4..c197b34 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
@@ -55,7 +55,7 @@
 
         mPms = createPackageManagerService()
         doAnswer { false }.`when`(mPms).isPackageDeviceAdmin(any(), any())
-        doAnswer { null }.`when`(mPms).freezePackageForDelete(any(), any(), any(), any())
+        doAnswer { null }.`when`(mPms).freezePackageForDelete(any(), any(), any(), any(), any())
     }
 
     private fun createPackageManagerService(): PackageManagerService {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageFreezerTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageFreezerTest.kt
index 4d13981..d99af77 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageFreezerTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageFreezerTest.kt
@@ -37,6 +37,7 @@
     companion object {
         const val TEST_PACKAGE = "com.android.test.package"
         const val TEST_REASON = "test reason"
+        const val TEST_EXIT_REASON = 1
         const val TEST_USER_ID = 0
     }
 
@@ -82,14 +83,15 @@
     fun setup() {
         rule.system().stageNominalSystemState()
         pms = spy(createPackageManagerService(TEST_PACKAGE))
-        whenever(pms.killApplication(any(), any(), any(), any()))
+        whenever(pms.killApplication(any(), any(), any(), any(), any()))
     }
 
     @Test
     fun freezePackage() {
-        val freezer = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms)
+        val freezer = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms, TEST_EXIT_REASON)
         verify(pms, times(1))
-            .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON))
+            .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON),
+                    eq(TEST_EXIT_REASON))
 
         assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) {
             checkPackageStartable()
@@ -101,10 +103,13 @@
 
     @Test
     fun freezePackage_twice() {
-        val freezer1 = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms)
-        val freezer2 = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms)
+        val freezer1 = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms,
+                TEST_EXIT_REASON)
+        val freezer2 = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms,
+                TEST_EXIT_REASON)
         verify(pms, times(2))
-            .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON))
+            .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON),
+                    eq(TEST_EXIT_REASON))
 
         assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) {
             checkPackageStartable()
@@ -121,9 +126,11 @@
 
     @Test
     fun freezePackage_withoutClosing() {
-        var freezer: PackageFreezer? = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms)
+        var freezer: PackageFreezer? = PackageFreezer(TEST_PACKAGE, TEST_USER_ID, TEST_REASON, pms,
+                TEST_EXIT_REASON)
         verify(pms, times(1))
-            .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON))
+            .killApplication(eq(TEST_PACKAGE), any(), eq(TEST_USER_ID), eq(TEST_REASON),
+                    eq(TEST_EXIT_REASON))
 
         assertThrowContainsMessage(SecurityException::class, frozenMessage(TEST_PACKAGE)) {
             checkPackageStartable()
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
index d03d196..1ed2f78 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -20,6 +20,7 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assert.assertThrows;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
@@ -316,21 +317,10 @@
     }
 
     @Test
-    public void testGetBootUser_Headless_UserCreatedIfOnlySystemUserExists() throws Exception {
+    public void testGetBootUser_Headless_ThrowsIfOnlySystemUserExists() throws Exception {
         setSystemUserHeadless(true);
 
-        int bootUser = mUmi.getBootUser();
-
-        assertWithMessage("getStartingUser")
-                .that(bootUser).isNotEqualTo(UserHandle.USER_SYSTEM);
-
-        UserData newUser = mUsers.get(bootUser);
-        assertWithMessage("New boot user is a full user")
-                .that(newUser.info.isFull()).isTrue();
-        assertWithMessage("New boot user is an admin user")
-                .that(newUser.info.isAdmin()).isTrue();
-        assertWithMessage("New boot user is the main user")
-                .that(newUser.info.isMain()).isTrue();
+        assertThrows(UserManager.CheckedUserOperationException.class, () -> mUmi.getBootUser());
     }
 
     private void mockCurrentUser(@UserIdInt int userId) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
index 01ce696..38cf634 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
@@ -20,6 +20,8 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
+import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE;
+import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
 import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
 import static com.android.server.pm.UserVisibilityChangedEvent.onVisible;
@@ -126,4 +128,104 @@
 
         listener.verify();
     }
+  /* TODO: re-add
+
+    @Test
+    public void
+       testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnBgOnSecondaryDisplay()
+            throws Exception {
+        AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
+        startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
+                BG_VISIBLE, DEFAULT_DISPLAY);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
+
+        expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+        expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
+
+        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+        listener.verify();
+    }
+
+    @Test
+    public void
+        testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnBgOnDefaultDisplay()
+            throws Exception {
+        AsyncUserVisibilityListener listener = addListenerForEvents(
+                onVisible(PARENT_USER_ID),
+                onVisible(PROFILE_USER_ID));
+        startUserInSecondaryDisplay(PARENT_USER_ID, DEFAULT_DISPLAY);
+
+        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
+                BG_VISIBLE, DEFAULT_DISPLAY);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+
+        // Assert parent user visibility
+        expectUserIsVisible(PARENT_USER_ID);
+        expectUserIsVisibleOnDisplay(PARENT_USER_ID, DEFAULT_DISPLAY);
+        expectUserIsNotVisibleOnDisplay(PARENT_USER_ID, INVALID_DISPLAY);
+        expectDisplayAssignedToUser(PARENT_USER_ID, DEFAULT_DISPLAY);
+        expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
+        assertUserCanBeAssignedExtraDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+        // Assert profile user visibility
+        expectUserIsVisible(PROFILE_USER_ID);
+        expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+        expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
+        // Only full user (parent) is assigned to the display
+        expectDisplayAssignedToUser(PROFILE_USER_ID, INVALID_DISPLAY);
+        assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+        listener.verify();
+    }
+
+    @Test
+    public void testStartBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnBg()
+            throws Exception {
+        AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
+        startUserInSecondaryDisplay(PARENT_USER_ID, DEFAULT_DISPLAY);
+
+        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+                DEFAULT_DISPLAY);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+
+        // Assert parent user visibility
+        expectUserIsVisible(PARENT_USER_ID);
+        expectUserIsVisibleOnDisplay(PARENT_USER_ID, DEFAULT_DISPLAY);
+        expectUserIsNotVisibleOnDisplay(PARENT_USER_ID, INVALID_DISPLAY);
+        expectDisplayAssignedToUser(PARENT_USER_ID, DEFAULT_DISPLAY);
+        expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
+        assertUserCanBeAssignedExtraDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+        // Assert profile user visibility
+        expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+        assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+        listener.verify();
+    }
+
+    @Test
+    public void testStartVisibleBgUser_onDefaultDisplay_currentUserId() throws Exception {
+        int currentUserId = INITIAL_CURRENT_USER_ID;
+
+        AsyncUserVisibilityListener listener = addListenerForNoEvents();
+
+        int result = mMediator.assignUserToDisplayOnStart(currentUserId, currentUserId,
+                BG_VISIBLE, DEFAULT_DISPLAY);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE);
+
+        // Assert current user visibility
+        expectUserIsVisible(currentUserId);
+        expectUserIsVisibleOnDisplay(currentUserId, DEFAULT_DISPLAY);
+        expectUserIsNotVisibleOnDisplay(currentUserId, INVALID_DISPLAY);
+        expectDisplayAssignedToUser(currentUserId, DEFAULT_DISPLAY);
+
+        assertUserCanBeAssignedExtraDisplay(currentUserId, OTHER_SECONDARY_DISPLAY_ID);
+
+        listener.verify();
+    }
+  */
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/ThermalManagerServiceMockingTest.java b/services/tests/mockingservicestests/src/com/android/server/power/ThermalManagerServiceMockingTest.java
index c85ed26..0ae8dfd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/power/ThermalManagerServiceMockingTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/power/ThermalManagerServiceMockingTest.java
@@ -61,8 +61,7 @@
         mAidlBinder.attachInterface(mAidlHalMock, IThermal.class.getName());
         mTemperatureFuture = new CompletableFuture<>();
         mTemperatureCallback = temperature -> mTemperatureFuture.complete(temperature);
-        mAidlWrapper = new ThermalManagerService.ThermalHalAidlWrapper();
-        mAidlWrapper.setCallback(mTemperatureCallback);
+        mAidlWrapper = new ThermalManagerService.ThermalHalAidlWrapper(mTemperatureCallback);
         mAidlWrapper.initProxyAndRegisterCallback(mAidlBinder);
     }
 
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 9b48114..f8955ed 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -200,7 +200,6 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-
         ExtendedMockito.doAnswer(invocation -> {
             int userId = (invocation.getArgument(0));
             return getWallpaperTestDir(userId);
@@ -398,7 +397,8 @@
             TypedXmlSerializer serializer = Xml.newBinarySerializer();
             serializer.setOutput(new ByteArrayOutputStream(), StandardCharsets.UTF_8.name());
             serializer.startDocument(StandardCharsets.UTF_8.name(), true);
-            mService.writeWallpaperAttributes(serializer, "wp", systemWallpaperData);
+            mService.mWallpaperDataParser.writeWallpaperAttributes(
+                    serializer, "wp", systemWallpaperData);
         } catch (IOException e) {
             fail("exception occurred while writing system wallpaper attributes");
         }
@@ -409,7 +409,7 @@
                 systemWallpaperData.cropFile.getAbsolutePath());
         try {
             TypedXmlPullParser parser = Xml.newBinaryPullParser();
-            mService.parseWallpaperAttributes(parser, shouldMatchSystem, true);
+            mService.mWallpaperDataParser.parseWallpaperAttributes(parser, shouldMatchSystem, true);
         } catch (XmlPullParserException e) {
             fail("exception occurred while parsing wallpaper");
         }
diff --git a/services/tests/servicestests/src/com/android/server/BinaryTransparencyServiceTest.java b/services/tests/servicestests/src/com/android/server/BinaryTransparencyServiceTest.java
index 245db46..ae78dfe 100644
--- a/services/tests/servicestests/src/com/android/server/BinaryTransparencyServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/BinaryTransparencyServiceTest.java
@@ -40,7 +40,6 @@
 import android.hardware.fingerprint.FingerprintSensorProperties;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
-import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.SystemProperties;
@@ -166,36 +165,6 @@
     }
 
     @Test
-    public void getApexInfo_postInitialize_returnsValidEntries() throws RemoteException {
-        prepApexInfo();
-        List result = mTestInterface.getApexInfo();
-        Assert.assertNotNull("Apex info map should not be null", result);
-        // TODO(265244016): When PackageManagerInternal is a mock, it's harder to keep the
-        // `measurePackage` working in unit test. Disable it for now. We may need more refactoring
-        // or cover this in integration tests.
-        // Assert.assertFalse("Apex info map should not be empty", result.isEmpty());
-    }
-
-    @Test
-    public void getApexInfo_postInitialize_returnsActualApexs()
-            throws RemoteException, PackageManager.NameNotFoundException {
-        prepApexInfo();
-        List resultList = mTestInterface.getApexInfo();
-
-        PackageManager pm = mContext.getPackageManager();
-        Assert.assertNotNull(pm);
-        List<Bundle> castedResult = (List<Bundle>) resultList;
-        for (Bundle resultBundle : castedResult) {
-            String packageName = resultBundle.getString(
-                    BinaryTransparencyService.BUNDLE_PACKAGE_NAME);
-            Assert.assertNotNull("Package name for APEX should not be null", packageName);
-            Assert.assertTrue(packageName + "is not an APEX!",
-                    resultBundle.getBoolean(
-                            BinaryTransparencyService.BUNDLE_PACKAGE_IS_APEX));
-        }
-    }
-
-    @Test
     public void testCollectBiometricProperties_disablesFeature() {
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BIOMETRICS,
                 BinaryTransparencyService.KEY_ENABLE_BIOMETRIC_PROPERTY_VERIFICATION,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 4d1d2b2..32b9864 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -34,6 +34,7 @@
 
 import static org.junit.Assert.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
@@ -438,6 +439,42 @@
         verify(mMockMagnificationController).setMagnificationFollowTypingEnabled(false);
     }
 
+    @Test
+    public void testSettingsAlwaysOn_setEnabled_featureFlagDisabled_doNothing() {
+        when(mMockMagnificationController.isAlwaysOnMagnificationFeatureFlagEnabled())
+                .thenReturn(false);
+
+        final AccessibilityUserState userState = mA11yms.mUserStates.get(
+                mA11yms.getCurrentUserIdLocked());
+        Settings.Secure.putIntForUser(
+                mTestableContext.getContentResolver(),
+                // TODO: replace name with Settings Secure Key
+                "accessibility_magnification_always_on_enabled",
+                1, mA11yms.getCurrentUserIdLocked());
+
+        mA11yms.readAlwaysOnMagnificationLocked(userState);
+
+        verify(mMockMagnificationController, never()).setAlwaysOnMagnificationEnabled(anyBoolean());
+    }
+
+    @Test
+    public void testSettingsAlwaysOn_setEnabled_featureFlagEnabled_propagateToController() {
+        when(mMockMagnificationController.isAlwaysOnMagnificationFeatureFlagEnabled())
+                .thenReturn(true);
+
+        final AccessibilityUserState userState = mA11yms.mUserStates.get(
+                mA11yms.getCurrentUserIdLocked());
+        Settings.Secure.putIntForUser(
+                mTestableContext.getContentResolver(),
+                // TODO: replace name with Settings Secure Key
+                "accessibility_magnification_always_on_enabled",
+                1, mA11yms.getCurrentUserIdLocked());
+
+        mA11yms.readAlwaysOnMagnificationLocked(userState);
+
+        verify(mMockMagnificationController).setAlwaysOnMagnificationEnabled(eq(true));
+    }
+
     @SmallTest
     @Test
     public void testOnClientChange_magnificationEnabledAndCapabilityAll_requestConnection() {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
index df21ea3..eb6670e 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
@@ -113,6 +113,7 @@
             AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED,
             AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
             AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED,
+            AccessibilityEvent.TYPE_VIEW_TARGETED_BY_SCROLL,
     };
 
     private AccessibilitySecurityPolicy mA11ySecurityPolicy;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
index ed0336a..b4558b2 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
@@ -179,6 +179,7 @@
         assertEquals(mFocusStrokeWidthDefaultValue, mUserState.getFocusStrokeWidthLocked());
         assertEquals(mFocusColorDefaultValue, mUserState.getFocusColorLocked());
         assertTrue(mUserState.isMagnificationFollowTypingEnabled());
+        assertFalse(mUserState.isAlwaysOnMagnificationEnabled());
     }
 
     @Test
@@ -390,6 +391,15 @@
     }
 
     @Test
+    public void setAlwaysOnMagnificationEnabled_defaultFalseAndSetTrue_returnTrue() {
+        assertFalse(mUserState.isAlwaysOnMagnificationEnabled());
+
+        mUserState.setAlwaysOnMagnificationEnabled(true);
+
+        assertTrue(mUserState.isAlwaysOnMagnificationEnabled());
+    }
+
+    @Test
     public void setFocusAppearanceData_returnExpectedFocusAppearanceData() {
         final int focusStrokeWidthValue = 100;
         final int focusColorValue = Color.BLUE;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FlashNotificationsControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FlashNotificationsControllerTest.java
new file mode 100644
index 0000000..8a057df
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/FlashNotificationsControllerTest.java
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import static android.hardware.camera2.CameraCharacteristics.FLASH_INFO_AVAILABLE;
+import static android.hardware.camera2.CameraCharacteristics.LENS_FACING;
+import static android.hardware.camera2.CameraMetadata.LENS_FACING_BACK;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.server.accessibility.FlashNotificationsController.ACTION_FLASH_NOTIFICATION_START_PREVIEW;
+import static com.android.server.accessibility.FlashNotificationsController.ACTION_FLASH_NOTIFICATION_STOP_PREVIEW;
+import static com.android.server.accessibility.FlashNotificationsController.EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR;
+import static com.android.server.accessibility.FlashNotificationsController.EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE;
+import static com.android.server.accessibility.FlashNotificationsController.PREVIEW_TYPE_LONG;
+import static com.android.server.accessibility.FlashNotificationsController.PREVIEW_TYPE_SHORT;
+import static com.android.server.accessibility.FlashNotificationsController.SETTING_KEY_CAMERA_FLASH_NOTIFICATION;
+import static com.android.server.accessibility.FlashNotificationsController.SETTING_KEY_SCREEN_FLASH_NOTIFICATION;
+import static com.android.server.accessibility.FlashNotificationsController.SETTING_KEY_SCREEN_FLASH_NOTIFICATION_COLOR;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
+import static java.lang.Integer.max;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.AudioPlaybackConfiguration;
+import android.media.PlayerBase;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableContentResolver;
+import android.testing.TestableContext;
+import android.testing.TestableLooper;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.annotation.NonNull;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests for {@link FlashNotificationsController}.
+ */
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class FlashNotificationsControllerTest {
+    private static final String CALL_TAG = "com.android.server.telecom";
+    private static final String NOTI_TAG = "android";
+    private static final String NOTI_REASON_PKG = "noti.reason.pkg";
+    private static final int COLOR_YELLOW = 0x66FFFF00;
+    private static final int COLOR_BLUE = 0x4d0000fe;
+
+    @Rule
+    public final TestableContext mTestableContext = new TestableContext(
+            getInstrumentation().getTargetContext());
+
+    private final Map<String, CameraInfo> mCameraInfoMap = new HashMap<>();
+    private final Set<View> mViews = new HashSet<>();
+
+    @Mock
+    private IBinder mMockToken;
+    @Mock
+    private WindowManager mMockWindowManager;
+    @Mock
+    private AudioManager mMockAudioManager;
+
+    private final List<AudioPlaybackConfiguration> mAudioConfigsWithAlarm = getConfigWithAlarm();
+
+    private CameraManager mCameraManager;
+    private AudioManager.AudioPlaybackCallback mAudioPlaybackCallback;
+    private TestableContentResolver mTestableContentResolver;
+
+    private TestableLooper mTestableLooper;
+    private Handler mTestHandler;
+    private HandlerThread mFlashHandlerThread;
+    private Handler mFlashHandler;
+
+    private FlashNotificationsController mController;
+
+    private int mScreenFlashCount = 0;
+    private int mLastFlashedViewColor = Color.TRANSPARENT;
+
+    private final CameraManager.TorchCallback mTorchCallback = new CameraManager.TorchCallback() {
+        @Override
+        public void onTorchModeChanged(@NonNull String cameraId, boolean enabled) {
+            CameraInfo info = mCameraInfoMap.getOrDefault(cameraId,
+                    new CameraInfo(false));
+            info.setEnabled(enabled);
+            mCameraInfoMap.put(cameraId, info);
+        }
+    };
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mTestableLooper = TestableLooper.get(this);
+        mTestHandler = new Handler(mTestableLooper.getLooper());
+        mFlashHandlerThread = new HandlerThread("TestFlashHandlerThread");
+        mFlashHandlerThread.start();
+        mFlashHandler = mFlashHandlerThread.getThreadHandler();
+
+        doAnswer(invocation -> {
+            final View view = invocation.getArgument(0);
+            mLastFlashedViewColor = getBackgroundColor(view);
+            mViews.add(view);
+            return null;
+        }).when(mMockWindowManager).addView(any(View.class), any(ViewGroup.LayoutParams.class));
+        doAnswer(invocation -> {
+            final View view = invocation.getArgument(0);
+            final boolean isAnyViewAdded = !mViews.isEmpty();
+            mViews.remove(view);
+            if (isAnyViewAdded && mViews.isEmpty()) mScreenFlashCount++;
+            return null;
+        }).when(mMockWindowManager).removeView(any(View.class));
+        mTestableContext.addMockSystemService(Context.WINDOW_SERVICE, mMockWindowManager);
+
+        doAnswer(invocation -> {
+            mAudioPlaybackCallback = invocation.getArgument(0);
+            return null;
+        }).when(mMockAudioManager).registerAudioPlaybackCallback(
+                any(AudioManager.AudioPlaybackCallback.class), any(Handler.class));
+        mTestableContext.addMockSystemService(Context.AUDIO_SERVICE, mMockAudioManager);
+
+        mCameraManager = mTestableContext.getSystemService(CameraManager.class);
+        if (mCameraManager != null) {
+            try {
+                for (String id : mCameraManager.getCameraIdList()) {
+                    CameraCharacteristics value = mCameraManager.getCameraCharacteristics(id);
+                    Boolean available = value.get(FLASH_INFO_AVAILABLE);
+                    Integer facing = value.get(LENS_FACING);
+                    mCameraInfoMap.put(id, new CameraInfo(
+                            available != null && available
+                                    && facing != null && facing == LENS_FACING_BACK
+                    ));
+                }
+            } catch (CameraAccessException ignored) {
+            }
+            mCameraManager.registerTorchCallback(mTorchCallback, mTestHandler);
+        }
+
+        mTestableContentResolver = mTestableContext.getContentResolver();
+        putCameraFlash(false);
+        putScreenFlash(false);
+        putScreenColor(Color.TRANSPARENT);
+    }
+
+    @After
+    public void tearDown() {
+        mCameraManager.unregisterTorchCallback(mTorchCallback);
+        mFlashHandlerThread.quit();
+        mTestableLooper.processAllMessages();
+    }
+
+    @Test
+    public void testCallSequence_putCameraFlashTrue_assertCameraFlashedScreenNotFlashed()
+            throws InterruptedException {
+        assumeCameraTorchAvailable();
+        putCameraFlash(true);
+        initController(mFlashHandler);
+
+        simulateCallSequence();
+
+        assertThat(getCameraFlashedCount()).isGreaterThan(0);
+        assertThat(mScreenFlashCount).isEqualTo(0);
+    }
+
+    @Test
+    public void testCallSequence_putScreenFlashTrue_assertScreenFlashedCameraNotFlashed()
+            throws InterruptedException {
+        putScreenFlash(true);
+        putScreenColor(COLOR_YELLOW);
+        initController(mFlashHandler);
+
+        simulateCallSequence();
+
+        assertThat(mScreenFlashCount).isGreaterThan(0);
+        assertThat(getCameraFlashedCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void testAlarmSequence_putCameraFlashTrue_assertCameraFlashedScreenNotFlashed()
+            throws InterruptedException {
+        assumeCameraTorchAvailable();
+        putCameraFlash(true);
+        initController(mFlashHandler);
+
+        simulateAlarmSequence();
+
+        assertThat(getCameraFlashedCount()).isGreaterThan(0);
+        assertThat(mScreenFlashCount).isEqualTo(0);
+    }
+
+    @Test
+    public void testAlarmSequence_putScreenFlashTrue_assertScreenFlashedCameraNotFlashed()
+            throws InterruptedException {
+        putScreenFlash(true);
+        putScreenColor(COLOR_YELLOW);
+        initController(mFlashHandler);
+
+        simulateAlarmSequence();
+
+        assertThat(mScreenFlashCount).isGreaterThan(0);
+        assertThat(getCameraFlashedCount()).isEqualTo(0);
+
+    }
+
+    @Test
+    public void testEvent_putCameraFlashTrue_assertCameraFlashedScreenNotFlashed() {
+        assumeCameraTorchAvailable();
+        putCameraFlash(true);
+        initController(mTestHandler);
+
+        simulateNotificationEvent();
+
+        assertThat(getCameraFlashedCount()).isGreaterThan(0);
+        assertThat(mScreenFlashCount).isEqualTo(0);
+    }
+
+    @Test
+    public void testEvent_putScreenFlashTrue_assertScreenFlashedCameraNotFlashed() {
+        putScreenFlash(true);
+        putScreenColor(COLOR_YELLOW);
+        initController(mTestHandler);
+
+        simulateNotificationEvent();
+
+        assertThat(mScreenFlashCount).isGreaterThan(0);
+        assertThat(getCameraFlashedCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void testShortPreview_putCameraFlashTrue_assertCameraFlashedScreenNotFlashed() {
+        assumeCameraTorchAvailable();
+        putCameraFlash(true);
+        initController(mTestHandler);
+
+        simulateShortPreview();
+
+        assertThat(getCameraFlashedCount()).isGreaterThan(0);
+        assertThat(mScreenFlashCount).isEqualTo(0);
+    }
+
+    @Test
+    public void testShortPreview_putScreenFlashTrue_assertScreenFlashedCameraNotFlashed() {
+        putScreenFlash(true);
+        putScreenColor(COLOR_YELLOW);
+        initController(mTestHandler);
+
+        simulateShortPreview();
+
+        assertThat(mScreenFlashCount).isGreaterThan(0);
+        assertThat(getCameraFlashedCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void testLongPreview_assertScreenFlashed()
+            throws InterruptedException {
+        initController(mFlashHandler);
+
+        simulateLongPreview(COLOR_YELLOW);
+
+        assertThat(mScreenFlashCount).isGreaterThan(0);
+    }
+
+    @Test
+    public void testLongPreview_putScreenFlashColorBlue_assertScreenFlashedYellow()
+            throws InterruptedException {
+        putScreenColor(COLOR_YELLOW);
+        initController(mFlashHandler);
+
+        simulateLongPreview(COLOR_BLUE);
+
+        assertThat(mLastFlashedViewColor).isEqualTo(COLOR_BLUE);
+    }
+
+    @Test
+    public void testLongPreview_putCameraFlashTrue_assertNotCameraFlashed()
+            throws InterruptedException {
+        assumeCameraTorchAvailable();
+        putCameraFlash(true);
+        initController(mFlashHandler);
+
+        simulateLongPreview(COLOR_YELLOW);
+
+        assertThat(getCameraFlashedCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void testStartFlashNotificationSequence_invalidToken() {
+        initController(mTestHandler);
+
+        assertThat(mController.startFlashNotificationSequence(CALL_TAG,
+                AccessibilityManager.FLASH_REASON_CALL, null)).isFalse();
+    }
+
+    @Test
+    public void testOpenedCameraTest() {
+        assumeCameraTorchAvailable();
+        putCameraFlash(true);
+        putScreenFlash(true);
+        putScreenColor(COLOR_YELLOW);
+        initController(mTestHandler);
+
+        simulateCameraOpened();
+        simulateNotificationEvent();
+        simulateCameraClosed();
+
+        assertThat(getCameraFlashedCount()).isEqualTo(0);
+    }
+
+    private void initController(Handler flashHandler) {
+        mController = new FlashNotificationsController(mTestableContext,
+                flashHandler, mTestHandler);
+        mController.mFlashBroadcastReceiver.onReceive(mTestableContext,
+                new Intent(Intent.ACTION_BOOT_COMPLETED));
+    }
+
+    private void assumeCameraTorchAvailable() {
+        assumeTrue(mCameraManager != null);
+        assumeTrue(!mCameraInfoMap.isEmpty());
+    }
+
+    private void simulateCallSequence() throws InterruptedException {
+        mController.startFlashNotificationSequence(CALL_TAG,
+                AccessibilityManager.FLASH_REASON_CALL, mMockToken);
+        processLooper(2500);
+        Thread.sleep(2500);
+
+        mController.stopFlashNotificationSequence(CALL_TAG);
+        processLooper(500);
+        Thread.sleep(500);
+    }
+
+    private void simulateAlarmSequence() throws InterruptedException {
+        mAudioPlaybackCallback.onPlaybackConfigChanged(mAudioConfigsWithAlarm);
+        processLooper(2500);
+        Thread.sleep(2500);
+
+        mAudioPlaybackCallback.onPlaybackConfigChanged(Collections.emptyList());
+        processLooper(500);
+        Thread.sleep(500);
+    }
+
+    private void simulateNotificationEvent() {
+        mController.startFlashNotificationEvent(NOTI_TAG,
+                AccessibilityManager.FLASH_REASON_NOTIFICATION, NOTI_REASON_PKG);
+
+        processLooper(3000);
+    }
+
+    private void simulateShortPreview() {
+        Intent intent = new Intent(ACTION_FLASH_NOTIFICATION_START_PREVIEW);
+        intent.putExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, PREVIEW_TYPE_SHORT);
+        mController.mFlashBroadcastReceiver.onReceive(mTestableContext, intent);
+
+        processLooper(3000);
+    }
+
+    private void simulateLongPreview(int color) throws InterruptedException {
+        Intent startIntent = new Intent(ACTION_FLASH_NOTIFICATION_START_PREVIEW);
+        startIntent.putExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, PREVIEW_TYPE_LONG);
+        startIntent.putExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR, color);
+        mController.mFlashBroadcastReceiver.onReceive(mTestableContext, startIntent);
+        processLooper(2500);
+        Thread.sleep(2500);
+
+        Intent stopIntent = new Intent(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW);
+        mController.mFlashBroadcastReceiver.onReceive(mTestableContext, stopIntent);
+        processLooper(500);
+        Thread.sleep(500);
+    }
+
+    private void processLooper(long millis) {
+        mTestableLooper.moveTimeForward(millis);
+        mTestableLooper.processAllMessages();
+    }
+
+    private static List<AudioPlaybackConfiguration> getConfigWithAlarm() {
+        List<AudioPlaybackConfiguration> list = new ArrayList<>();
+
+        AudioPlaybackConfiguration config = new AudioPlaybackConfiguration(
+                mock(PlayerBase.PlayerIdCard.class), 0, 0, 0);
+        config.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_STARTED,
+                AudioPlaybackConfiguration.PLAYER_DEVICEID_INVALID);
+
+        AudioAttributes.Builder builder = new AudioAttributes.Builder();
+        builder.setUsage(AudioAttributes.USAGE_ALARM);
+        AudioAttributes attr = builder.build();
+
+        config.handleAudioAttributesEvent(attr);
+
+        list.add(config);
+        return list;
+    }
+
+    private int getCameraFlashedCount() {
+        int count = 0;
+        for (CameraInfo info : mCameraInfoMap.values()) {
+            count = max(count, info.mTorchFlashCount);
+        }
+        return count;
+    }
+
+    private int getBackgroundColor(View view) {
+        final Drawable background = view.getBackground();
+        if (background instanceof ColorDrawable) {
+            return ((ColorDrawable) background).getColor();
+        } else {
+            return Color.TRANSPARENT;
+        }
+    }
+
+    private void putCameraFlash(boolean value) {
+        Settings.System.putIntForUser(mTestableContentResolver,
+                SETTING_KEY_CAMERA_FLASH_NOTIFICATION,
+                value ? 1 : 0, UserHandle.USER_CURRENT);
+    }
+
+    private void putScreenFlash(boolean value) {
+        Settings.System.putIntForUser(mTestableContentResolver,
+                SETTING_KEY_SCREEN_FLASH_NOTIFICATION,
+                value ? 1 : 0, UserHandle.USER_CURRENT);
+    }
+
+    private void putScreenColor(int color) {
+        Settings.System.putIntForUser(mTestableContentResolver,
+                SETTING_KEY_SCREEN_FLASH_NOTIFICATION_COLOR,
+                color, UserHandle.USER_CURRENT);
+    }
+
+    private void simulateCameraOpened() {
+        for (String cameraId : mCameraInfoMap.keySet()) {
+            System.out.println("simulate open camera: " + cameraId);
+            mController.mTorchAvailabilityCallback.onCameraOpened(cameraId, "");
+        }
+        processLooper(200);
+    }
+
+    private void simulateCameraClosed() {
+        for (String cameraId : mCameraInfoMap.keySet()) {
+            System.out.println("simulate close camera: " + cameraId);
+            mController.mTorchAvailabilityCallback.onCameraClosed(cameraId);
+        }
+        processLooper(200);
+    }
+
+    private static class CameraInfo {
+        final boolean mIsValid;
+        boolean mEnabled = false;
+        int mTorchFlashCount = 0;
+
+        CameraInfo(boolean isValid) {
+            mIsValid = isValid;
+        }
+
+        void setEnabled(boolean enabled) {
+            if (mEnabled && !enabled) mTorchFlashCount++;
+            mEnabled = enabled;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
index 863dcb6..a02807f 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -70,7 +71,6 @@
     WindowMagnificationManagerStub mWindowMagnificationManagerStub;
 
     @Before
-
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mFullScreenMagnificationControllerStub = new FullScreenMagnificationControllerStub(
@@ -433,27 +433,60 @@
                 eq(newConfig), anyBoolean(), anyInt());
     }
 
+    @Test
+    public void setMagnificationConfigWithActivatedFalse_fullScreenEnabled_resetMagnification() {
+        setMagnificationActivated(TEST_DISPLAY, MAGNIFICATION_MODE_FULLSCREEN);
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setActivated(false).build();
+        mMagnificationProcessor.setMagnificationConfig(TEST_DISPLAY, config, false, SERVICE_ID);
+
+        verify(mMockFullScreenMagnificationController).reset(eq(TEST_DISPLAY), anyBoolean());
+    }
+
+    @Test
+    public void setMagnificationConfigWithActivatedFalse_windowEnabled_disableMagnification() {
+        setMagnificationActivated(TEST_DISPLAY, MAGNIFICATION_MODE_WINDOW);
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setActivated(false).build();
+        mMagnificationProcessor.setMagnificationConfig(TEST_DISPLAY, config, false, SERVICE_ID);
+
+        verify(mMockWindowMagnificationManager)
+                .disableWindowMagnification(eq(TEST_DISPLAY), anyBoolean());
+    }
+
+    @Test
+    public void setMagnificationConfigWithActivatedFalse_expectedReturnedValue() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setActivated(false).build();
+        assertFalse(mMagnificationProcessor.setMagnificationConfig(
+                        TEST_DISPLAY, config, false, SERVICE_ID));
+    }
+
     private void setMagnificationActivated(int displayId, int configMode) {
         setMagnificationActivated(displayId,
-                new MagnificationConfig.Builder().setMode(configMode).build());
+                new MagnificationConfig.Builder()
+                        .setMode(configMode)
+                        .setScale(TEST_SCALE).build());
     }
 
     private void setMagnificationActivated(int displayId, MagnificationConfig config) {
+        if (!config.isActivated()) {
+            fail("setMagnificationActivated method should be called with config activated true");
+        }
+
         when(mMockMagnificationController.isActivated(displayId, config.getMode())).thenReturn(
                 true);
         mMagnificationProcessor.setMagnificationConfig(displayId, config, false, SERVICE_ID);
         if (config.getMode() == MAGNIFICATION_MODE_FULLSCREEN) {
-            when(mMockMagnificationController.isActivated(displayId,
-                    MAGNIFICATION_MODE_WINDOW)).thenReturn(false);
             mFullScreenMagnificationControllerStub.resetAndStubMethods();
             mMockFullScreenMagnificationController.setScaleAndCenter(displayId, config.getScale(),
                     config.getCenterX(), config.getCenterY(), false, SERVICE_ID);
+            mWindowMagnificationManagerStub.deactivateIfNeed();
         } else if (config.getMode() == MAGNIFICATION_MODE_WINDOW) {
-            when(mMockMagnificationController.isActivated(displayId,
-                    MAGNIFICATION_MODE_FULLSCREEN)).thenReturn(false);
             mWindowMagnificationManagerStub.resetAndStubMethods();
             mMockWindowMagnificationManager.enableWindowMagnification(displayId, config.getScale(),
                     config.getCenterX(), config.getCenterY());
+            mFullScreenMagnificationControllerStub.deactivateIfNeed();
         }
     }
 
@@ -469,6 +502,7 @@
         private float mScale = 1.0f;
         private float mCenterX = 0;
         private float mCenterY = 0;
+        private boolean mIsActivated = false;
         private boolean mIsRegistered = false;
 
         FullScreenMagnificationControllerStub(
@@ -485,7 +519,11 @@
                     TEST_DISPLAY);
             doAnswer(invocation -> mIsRegistered).when(mScreenMagnificationController).isRegistered(
                     TEST_DISPLAY);
+            doAnswer(invocation -> mIsActivated).when(mScreenMagnificationController).isActivated(
+                    TEST_DISPLAY);
+
             Answer enableMagnificationStubAnswer = invocation -> {
+                mIsActivated = true;
                 mScale = invocation.getArgument(1);
                 mCenterX = invocation.getArgument(2);
                 mCenterY = invocation.getArgument(3);
@@ -495,6 +533,13 @@
                     mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), anyFloat(),
                     anyFloat(), anyFloat(), anyBoolean(), eq(SERVICE_ID));
 
+            Answer disableMagnificationStubAnswer = invocation -> {
+                deactivateIfNeed();
+                return true;
+            };
+            doAnswer(disableMagnificationStubAnswer).when(
+                    mScreenMagnificationController).reset(eq(TEST_DISPLAY), anyBoolean());
+
             Answer registerStubAnswer = invocation -> {
                 mIsRegistered = true;
                 return true;
@@ -508,14 +553,19 @@
             };
             doAnswer(unregisterStubAnswer).when(
                     mScreenMagnificationController).unregister(eq(TEST_DISPLAY));
-            doAnswer(unregisterStubAnswer).when(
-                    mScreenMagnificationController).reset(eq(TEST_DISPLAY), anyBoolean());
         }
 
         public void resetAndStubMethods() {
             Mockito.reset(mScreenMagnificationController);
             stubMethods();
         }
+
+        public void deactivateIfNeed() {
+            mScale = 1.0f;
+            mCenterX = 0;
+            mCenterY = 0;
+            mIsActivated = false;
+        }
     }
 
     private static class WindowMagnificationManagerStub {
@@ -523,6 +573,7 @@
         private float mScale = 1.0f;
         private float mCenterX = 0;
         private float mCenterY = 0;
+        private boolean mIsEnabled = false;
 
         WindowMagnificationManagerStub(
                 WindowMagnificationManager windowMagnificationManager) {
@@ -536,7 +587,11 @@
                     TEST_DISPLAY);
             doAnswer(invocation -> mCenterY).when(mWindowMagnificationManager).getCenterY(
                     TEST_DISPLAY);
+            doAnswer(invocation -> mIsEnabled).when(mWindowMagnificationManager)
+                    .isWindowMagnifierEnabled(TEST_DISPLAY);
+
             Answer enableWindowMagnificationStubAnswer = invocation -> {
+                mIsEnabled = true;
                 mScale = invocation.getArgument(1);
                 mCenterX = invocation.getArgument(2);
                 mCenterY = invocation.getArgument(3);
@@ -548,11 +603,29 @@
             doAnswer(enableWindowMagnificationStubAnswer).when(
                     mWindowMagnificationManager).enableWindowMagnification(eq(TEST_DISPLAY),
                     anyFloat(), anyFloat(), anyFloat(), any(), anyInt());
+
+            Answer disableWindowMagnificationStubAnswer = invocation -> {
+                deactivateIfNeed();
+                return true;
+            };
+            doAnswer(disableWindowMagnificationStubAnswer).when(
+                    mWindowMagnificationManager).disableWindowMagnification(eq(TEST_DISPLAY),
+                    anyBoolean());
+            doAnswer(disableWindowMagnificationStubAnswer).when(
+                    mWindowMagnificationManager).disableWindowMagnification(eq(TEST_DISPLAY),
+                    anyBoolean(), any());
         }
 
         public void resetAndStubMethods() {
             Mockito.reset(mWindowMagnificationManager);
             stubMethods();
         }
+
+        public void deactivateIfNeed() {
+            mScale = 1.0f;
+            mCenterX = Float.NaN;
+            mCenterY = Float.NaN;
+            mIsEnabled = false;
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index d996e37..2d036fe 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -19,6 +19,7 @@
 import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
 
 import static com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
+import static com.android.server.accessibility.magnification.MockWindowMagnificationConnection.TEST_DISPLAY;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -48,6 +49,9 @@
 import android.graphics.Region;
 import android.hardware.display.DisplayManagerInternal;
 import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
 import android.view.DisplayInfo;
 import android.view.MagnificationSpec;
 import android.view.accessibility.MagnificationAnimationCallback;
@@ -55,6 +59,7 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.LocalServices;
 import com.android.server.accessibility.AccessibilityTraceManager;
 import com.android.server.accessibility.test.MessageCapturingHandler;
@@ -71,6 +76,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 import org.mockito.stubbing.Answer;
+import org.testng.Assert;
 
 import java.util.Locale;
 
@@ -93,6 +99,7 @@
     static final int DISPLAY_1 = 1;
     static final int DISPLAY_COUNT = 2;
     static final int INVALID_DISPLAY = 2;
+    private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;
 
     final FullScreenMagnificationController.ControllerContext mMockControllerCtx =
             mock(FullScreenMagnificationController.ControllerContext.class);
@@ -105,8 +112,8 @@
             MagnificationInfoChangedCallback.class);
     private final MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(
             null);
-    private final MagnificationScaleProvider mScaleProvider = mock(
-            MagnificationScaleProvider.class);
+    private MagnificationScaleProvider mScaleProvider;
+    private MockContentResolver mResolver;
 
     private final ArgumentCaptor<MagnificationConfig> mConfigCaptor = ArgumentCaptor.forClass(
             MagnificationConfig.class);
@@ -129,6 +136,12 @@
         when(mMockControllerCtx.getWindowManager()).thenReturn(mMockWindowManager);
         when(mMockControllerCtx.getHandler()).thenReturn(mMessageCapturingHandler);
         when(mMockControllerCtx.getAnimationDuration()).thenReturn(1000L);
+        mResolver = new MockContentResolver();
+        mResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        when(mMockContext.getContentResolver()).thenReturn(mResolver);
+        Settings.Secure.putFloatForUser(mResolver,
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 2.0f,
+                CURRENT_USER_ID);
         initMockWindowManager();
 
         final DisplayInfo displayInfo = new DisplayInfo();
@@ -137,6 +150,7 @@
         LocalServices.removeServiceForTest(DisplayManagerInternal.class);
         LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
 
+        mScaleProvider = new MagnificationScaleProvider(mMockContext);
         mFullScreenMagnificationController = new FullScreenMagnificationController(
                 mMockControllerCtx, new Object(), mRequestObserver, mScaleProvider);
     }
@@ -1168,6 +1182,41 @@
         verify(mRequestObserver).onImeWindowVisibilityChanged(eq(DISPLAY_0), eq(true));
     }
 
+    @Test
+    public void persistScale_setValueWhenScaleIsOne_nothingChanged() {
+        final float persistedScale =
+                mFullScreenMagnificationController.getPersistedScale(TEST_DISPLAY);
+
+        PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+        mFullScreenMagnificationController.setScale(DISPLAY_0, 1.0f, pivotPoint.x, pivotPoint.y,
+                false, SERVICE_ID_1);
+        mFullScreenMagnificationController.persistScale(TEST_DISPLAY);
+
+        Assert.assertEquals(mFullScreenMagnificationController.getPersistedScale(TEST_DISPLAY),
+                persistedScale);
+    }
+
+    @Test
+    public void testOnContextChanged_alwaysOnFeatureDisabled_resetMagnification() {
+        setScaleToMagnifying();
+
+        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(false);
+        mFullScreenMagnificationController.onUserContextChanged(DISPLAY_0);
+
+        verify(mRequestObserver).onFullScreenMagnificationActivationState(eq(DISPLAY_0), eq(false));
+    }
+
+    @Test
+    public void testOnContextChanged_alwaysOnFeatureEnabled_setScaleTo1xAndStayActivated() {
+        setScaleToMagnifying();
+
+        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(true);
+        mFullScreenMagnificationController.onUserContextChanged(DISPLAY_0);
+
+        assertEquals(1.0f, mFullScreenMagnificationController.getScale(DISPLAY_0), 0);
+        assertTrue(mFullScreenMagnificationController.isActivated(DISPLAY_0));
+    }
+
     private void setScaleToMagnifying() {
         register(DISPLAY_0);
         float scale = 2.0f;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 5334e4c..a095760 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -81,23 +81,27 @@
  *          IDLE -> SHORTCUT_TRIGGERED [label="a11y\nbtn"]
  *          IDLE -> DOUBLE_TAP [label="2tap"]
  *          DOUBLE_TAP -> IDLE [label="timeout"]
- *          DOUBLE_TAP -> ZOOMED [label="tap"]
+ *          DOUBLE_TAP -> ACTIVATED [label="tap"]
  *          DOUBLE_TAP -> NON_ACTIVATED_ZOOMED_TMP [label="hold"]
  *          NON_ACTIVATED_ZOOMED_TMP -> IDLE [label="release"]
  *          SHORTCUT_TRIGGERED -> IDLE [label="a11y\nbtn"]
- *          SHORTCUT_TRIGGERED -> ZOOMED[label="tap"]
- *          SHORTCUT_TRIGGERED -> ACTIVATED_ZOOMED_TMP [label="hold"]
+ *          SHORTCUT_TRIGGERED -> ACTIVATED [label="tap"]
+ *          SHORTCUT_TRIGGERED -> SHORTCUT_TRIGGERED_ZOOMED_TMP [label="hold"]
  *          SHORTCUT_TRIGGERED -> PANNING [label="2hold]
- *          ZOOMED -> ZOOMED_DOUBLE_TAP [label="2tap"]
- *          ZOOMED -> IDLE [label="a11y\nbtn"]
- *          ZOOMED -> PANNING [label="2hold"]
- *          ZOOMED_DOUBLE_TAP -> ZOOMED [label="timeout"]
- *          ZOOMED_DOUBLE_TAP -> ACTIVATED_ZOOMED_TMP [label="hold"]
- *          ZOOMED_DOUBLE_TAP -> IDLE [label="tap"]
- *          ACTIVATED_ZOOMED_TMP -> ZOOMED [label="release"]
- *          PANNING -> ZOOMED [label="release"]
+ *          if always-on enabled:
+ *              SHORTCUT_TRIGGERED_ZOOMED_TMP -> ACTIVATED [label="release"]
+ *          else:
+ *              SHORTCUT_TRIGGERED_ZOOMED_TMP -> IDLE [label="release"]
+ *          ACTIVATED -> ACTIVATED_DOUBLE_TAP [label="2tap"]
+ *          ACTIVATED -> IDLE [label="a11y\nbtn"]
+ *          ACTIVATED -> PANNING [label="2hold"]
+ *          ACTIVATED_DOUBLE_TAP -> ACTIVATED [label="timeout"]
+ *          ACTIVATED_DOUBLE_TAP -> ACTIVATED_ZOOMED_TMP [label="hold"]
+ *          ACTIVATED_DOUBLE_TAP -> IDLE [label="tap"]
+ *          ACTIVATED_ZOOMED_TMP -> ACTIVATED [label="release"]
+ *          PANNING -> ACTIVATED [label="release"]
  *          PANNING -> PANNING_SCALING [label="pinch"]
- *          PANNING_SCALING -> ZOOMED [label="release"]
+ *          PANNING_SCALING -> ACTIVATED [label="release"]
  *      }
  * }
  */
@@ -105,14 +109,15 @@
 public class FullScreenMagnificationGestureHandlerTest {
 
     public static final int STATE_IDLE = 1;
-    public static final int STATE_ZOOMED = 2;
+    public static final int STATE_ACTIVATED = 2;
     public static final int STATE_2TAPS = 3;
-    public static final int STATE_ZOOMED_2TAPS = 4;
+    public static final int STATE_ACTIVATED_2TAPS = 4;
     public static final int STATE_SHORTCUT_TRIGGERED = 5;
     public static final int STATE_NON_ACTIVATED_ZOOMED_TMP = 6;
     public static final int STATE_ACTIVATED_ZOOMED_TMP = 7;
-    public static final int STATE_PANNING = 8;
-    public static final int STATE_SCALING_AND_PANNING = 9;
+    public static final int STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP = 8;
+    public static final int STATE_PANNING = 9;
+    public static final int STATE_SCALING_AND_PANNING = 10;
 
     public static final int FIRST_STATE = STATE_IDLE;
     public static final int LAST_STATE = STATE_SCALING_AND_PANNING;
@@ -167,6 +172,7 @@
             }
         };
         mFullScreenMagnificationController.register(DISPLAY_0);
+        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(true);
         mClock = new OffsettableClock.Stopped();
 
         boolean detectTripleTap = true;
@@ -267,22 +273,22 @@
         assertTransition(STATE_SHORTCUT_TRIGGERED, () -> {
             send(downEvent());
             fastForward1sec();
-        }, STATE_ACTIVATED_ZOOMED_TMP);
+        }, STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP);
 
-        // A11y button followed by a tap turns zoom on
-        assertTransition(STATE_SHORTCUT_TRIGGERED, () -> tap(), STATE_ZOOMED);
+        // A11y button followed by a tap turns magnifier on
+        assertTransition(STATE_SHORTCUT_TRIGGERED, () -> tap(), STATE_ACTIVATED);
 
         // A11y button pressed second time negates the 1st press
         assertTransition(STATE_SHORTCUT_TRIGGERED, () -> triggerShortcut(), STATE_IDLE);
 
-        // A11y button turns zoom off
-        assertTransition(STATE_ZOOMED, () -> triggerShortcut(), STATE_IDLE);
+        // A11y button turns magnifier off
+        assertTransition(STATE_ACTIVATED, () -> triggerShortcut(), STATE_IDLE);
 
-        // Double tap times out while zoomed
-        assertTransition(STATE_ZOOMED_2TAPS, () -> {
+        // Double tap times out while activated
+        assertTransition(STATE_ACTIVATED_2TAPS, () -> {
             allowEventDelegation();
             fastForward1sec();
-        }, STATE_ZOOMED);
+        }, STATE_ACTIVATED);
 
         // tap+tap+swipe doesn't get delegated
         assertTransition(STATE_2TAPS, () -> swipe(), STATE_IDLE);
@@ -290,8 +296,29 @@
         // tap+tap+swipe&hold initiates temporary viewport dragging zoom in immediately
         assertTransition(STATE_2TAPS, () -> swipeAndHold(), STATE_NON_ACTIVATED_ZOOMED_TMP);
 
-        // release when activated temporary zoom in back to zoomed
-        assertTransition(STATE_ACTIVATED_ZOOMED_TMP, () -> upEvent(), STATE_ZOOMED);
+        // release when activated temporary zoom in back to activated
+        assertTransition(STATE_ACTIVATED_ZOOMED_TMP, () -> send(upEvent()), STATE_ACTIVATED);
+    }
+
+    @Test
+    public void testRelease_shortcutTriggeredZoomedTmp_alwaysOnNotEnabled_shouldInIdle() {
+        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(false);
+        goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP);
+        send(upEvent());
+
+        assertIn(STATE_IDLE);
+    }
+
+    @Test
+    public void testRelease_shortcutTriggeredZoomedTmp_alwaysOnEnabled_shouldInActivated() {
+        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(true);
+        goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP);
+        send(upEvent());
+
+        assertIn(STATE_ACTIVATED);
+        assertTrue(!isZoomed());
+
+        returnToNormalFrom(STATE_ACTIVATED);
     }
 
     @Test
@@ -310,7 +337,7 @@
             longTap();
         };
         assertStaysIn(STATE_IDLE, tapAndLongTap);
-        assertStaysIn(STATE_ZOOMED, tapAndLongTap);
+        assertStaysIn(STATE_ACTIVATED, tapAndLongTap);
 
         // Triple tap with delays in between doesn't count
         Runnable slow3tap = () -> {
@@ -321,7 +348,7 @@
             tap();
         };
         assertStaysIn(STATE_IDLE, slow3tap);
-        assertStaysIn(STATE_ZOOMED, slow3tap);
+        assertStaysIn(STATE_ACTIVATED, slow3tap);
     }
 
     @Test
@@ -337,9 +364,9 @@
     @Test
     public void testTripleTapAndHold_zoomsImmediately() {
         assertZoomsImmediatelyOnSwipeFrom(STATE_2TAPS, STATE_NON_ACTIVATED_ZOOMED_TMP);
-        assertZoomsImmediatelyOnSwipeFrom(STATE_SHORTCUT_TRIGGERED, STATE_ACTIVATED_ZOOMED_TMP);
-        assertZoomsImmediatelyOnSwipeFrom(STATE_ZOOMED_2TAPS, STATE_ACTIVATED_ZOOMED_TMP);
-
+        assertZoomsImmediatelyOnSwipeFrom(STATE_SHORTCUT_TRIGGERED,
+                STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP);
+        assertZoomsImmediatelyOnSwipeFrom(STATE_ACTIVATED_2TAPS, STATE_ACTIVATED_ZOOMED_TMP);
     }
 
     @Test
@@ -361,8 +388,8 @@
     }
 
     @Test
-    public void testTwoFingersOneTap_zoomedState_dispatchMotionEvents() {
-        goFromStateIdleTo(STATE_ZOOMED);
+    public void testTwoFingersOneTap_activatedState_dispatchMotionEvents() {
+        goFromStateIdleTo(STATE_ACTIVATED);
         final EventCaptor eventCaptor = new EventCaptor();
         mMgh.setNext(eventCaptor);
 
@@ -371,7 +398,7 @@
         send(pointerEvent(ACTION_POINTER_UP, DEFAULT_X * 2, DEFAULT_Y));
         send(upEvent());
 
-        assertIn(STATE_ZOOMED);
+        assertIn(STATE_ACTIVATED);
         final List<Integer> expectedActions = new ArrayList();
         expectedActions.add(Integer.valueOf(ACTION_DOWN));
         expectedActions.add(Integer.valueOf(ACTION_POINTER_DOWN));
@@ -379,12 +406,12 @@
         expectedActions.add(Integer.valueOf(ACTION_UP));
         assertActionsInOrder(eventCaptor.mEvents, expectedActions);
 
-        returnToNormalFrom(STATE_ZOOMED);
+        returnToNormalFrom(STATE_ACTIVATED);
     }
 
     @Test
-    public void testThreeFingersOneTap_zoomedState_dispatchMotionEvents() {
-        goFromStateIdleTo(STATE_ZOOMED);
+    public void testThreeFingersOneTap_activatedState_dispatchMotionEvents() {
+        goFromStateIdleTo(STATE_ACTIVATED);
         final EventCaptor eventCaptor = new EventCaptor();
         mMgh.setNext(eventCaptor);
         PointF pointer1 = DEFAULT_POINT;
@@ -398,7 +425,7 @@
         send(pointerEvent(ACTION_POINTER_UP, new PointF[] {pointer1, pointer2, pointer3}, 2));
         send(upEvent());
 
-        assertIn(STATE_ZOOMED);
+        assertIn(STATE_ACTIVATED);
         final List<Integer> expectedActions = new ArrayList();
         expectedActions.add(Integer.valueOf(ACTION_DOWN));
         expectedActions.add(Integer.valueOf(ACTION_POINTER_DOWN));
@@ -408,12 +435,12 @@
         expectedActions.add(Integer.valueOf(ACTION_UP));
         assertActionsInOrder(eventCaptor.mEvents, expectedActions);
 
-        returnToNormalFrom(STATE_ZOOMED);
+        returnToNormalFrom(STATE_ACTIVATED);
     }
 
     @Test
-    public void testFirstFingerSwipe_twoPointerDownAndZoomedState_panningState() {
-        goFromStateIdleTo(STATE_ZOOMED);
+    public void testFirstFingerSwipe_twoPointerDownAndActivatedState_panningState() {
+        goFromStateIdleTo(STATE_ACTIVATED);
         PointF pointer1 = DEFAULT_POINT;
         PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
 
@@ -429,8 +456,8 @@
     }
 
     @Test
-    public void testSecondFingerSwipe_twoPointerDownAndZoomedState_panningState() {
-        goFromStateIdleTo(STATE_ZOOMED);
+    public void testSecondFingerSwipe_twoPointerDownAndActivatedState_panningState() {
+        goFromStateIdleTo(STATE_ACTIVATED);
         PointF pointer1 = DEFAULT_POINT;
         PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
 
@@ -463,8 +490,8 @@
     }
 
     @Test
-    public void testZoomedWithTripleTap_invokeShowWindowPromptAction() {
-        goFromStateIdleTo(STATE_ZOOMED);
+    public void testActivatedWithTripleTap_invokeShowWindowPromptAction() {
+        goFromStateIdleTo(STATE_ACTIVATED);
 
         verify(mWindowMagnificationPromptController).showNotificationIfNeeded();
     }
@@ -541,9 +568,8 @@
                 check(!isActivated(), state);
                 check(!isZoomed(), state);
             } break;
-            case STATE_ZOOMED: {
+            case STATE_ACTIVATED: {
                 check(isActivated(), state);
-                check(isZoomed(), state);
                 check(tapCount() < 2, state);
             } break;
             case STATE_2TAPS: {
@@ -551,7 +577,7 @@
                 check(!isZoomed(), state);
                 check(tapCount() == 2, state);
             } break;
-            case STATE_ZOOMED_2TAPS: {
+            case STATE_ACTIVATED_2TAPS: {
                 check(isActivated(), state);
                 check(isZoomed(), state);
                 check(tapCount() == 2, state);
@@ -561,14 +587,29 @@
                 check(isZoomed(), state);
                 check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
                         state);
-                check(!mMgh.mViewportDraggingState.mActivatedBeforeDrag, state);
+                check(Float.isNaN(mMgh.mViewportDraggingState.mScaleToRecoverAfterDraggingEnd),
+                        state);
             } break;
             case STATE_ACTIVATED_ZOOMED_TMP: {
                 check(isActivated(), state);
                 check(isZoomed(), state);
                 check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
                         state);
-                check(mMgh.mViewportDraggingState.mActivatedBeforeDrag, state);
+                check(mMgh.mViewportDraggingState.mScaleToRecoverAfterDraggingEnd >= 1.0f,
+                        state);
+            } break;
+            case STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP: {
+                check(isActivated(), state);
+                check(isZoomed(), state);
+                check(mMgh.mCurrentState == mMgh.mViewportDraggingState,
+                        state);
+                if (mFullScreenMagnificationController.isAlwaysOnMagnificationEnabled()) {
+                    check(mMgh.mViewportDraggingState.mScaleToRecoverAfterDraggingEnd >= 1.0f,
+                            state);
+                } else {
+                    check(Float.isNaN(mMgh.mViewportDraggingState.mScaleToRecoverAfterDraggingEnd),
+                            state);
+                }
             } break;
             case STATE_SHORTCUT_TRIGGERED: {
                 check(mMgh.mDetectingState.mShortcutTriggered, state);
@@ -605,7 +646,7 @@
                     tap();
                     tap();
                 } break;
-                case STATE_ZOOMED: {
+                case STATE_ACTIVATED: {
                     if (mMgh.mDetectTripleTap) {
                         goFromStateIdleTo(STATE_2TAPS);
                         tap();
@@ -614,8 +655,8 @@
                         tap();
                     }
                 } break;
-                case STATE_ZOOMED_2TAPS: {
-                    goFromStateIdleTo(STATE_ZOOMED);
+                case STATE_ACTIVATED_2TAPS: {
+                    goFromStateIdleTo(STATE_ACTIVATED);
                     tap();
                     tap();
                 } break;
@@ -625,7 +666,12 @@
                     fastForward1sec();
                 } break;
                 case STATE_ACTIVATED_ZOOMED_TMP: {
-                    goFromStateIdleTo(STATE_ZOOMED_2TAPS);
+                    goFromStateIdleTo(STATE_ACTIVATED_2TAPS);
+                    send(downEvent());
+                    fastForward1sec();
+                } break;
+                case STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP: {
+                    goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED);
                     send(downEvent());
                     fastForward1sec();
                 } break;
@@ -634,7 +680,7 @@
                     triggerShortcut();
                 } break;
                 case STATE_PANNING: {
-                    goFromStateIdleTo(STATE_ZOOMED);
+                    goFromStateIdleTo(STATE_ACTIVATED);
                     send(downEvent());
                     send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y));
                     fastForward(ViewConfiguration.getTapTimeout());
@@ -665,16 +711,16 @@
                 allowEventDelegation();
                 fastForward1sec();
             } break;
-            case STATE_ZOOMED: {
+            case STATE_ACTIVATED: {
                 if (mMgh.mDetectTripleTap) {
                     tap();
                     tap();
-                    returnToNormalFrom(STATE_ZOOMED_2TAPS);
+                    returnToNormalFrom(STATE_ACTIVATED_2TAPS);
                 } else {
                     triggerShortcut();
                 }
             } break;
-            case STATE_ZOOMED_2TAPS: {
+            case STATE_ACTIVATED_2TAPS: {
                 tap();
             } break;
             case STATE_NON_ACTIVATED_ZOOMED_TMP: {
@@ -682,7 +728,13 @@
             } break;
             case STATE_ACTIVATED_ZOOMED_TMP: {
                 send(upEvent());
-                returnToNormalFrom(STATE_ZOOMED);
+                returnToNormalFrom(STATE_ACTIVATED);
+            } break;
+            case STATE_SHORTCUT_TRIGGERED_ZOOMED_TMP: {
+                send(upEvent());
+                if (mFullScreenMagnificationController.isAlwaysOnMagnificationEnabled()) {
+                    returnToNormalFrom(STATE_ACTIVATED);
+                }
             } break;
             case STATE_SHORTCUT_TRIGGERED: {
                 triggerShortcut();
@@ -690,7 +742,7 @@
             case STATE_PANNING: {
                 send(pointerEvent(ACTION_POINTER_UP, DEFAULT_X * 2, DEFAULT_Y));
                 send(upEvent());
-                returnToNormalFrom(STATE_ZOOMED);
+                returnToNormalFrom(STATE_ACTIVATED);
             } break;
             case STATE_SCALING_AND_PANNING: {
                 returnToNormalFrom(STATE_PANNING);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index 231b2f32..b4a16c2 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -26,6 +26,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -404,6 +405,22 @@
     }
 
     @Test
+    public void
+            configTransitionToWindowModeAndActivatedFalse_fullScreenMagnifying_doNotEnableWindow()
+            throws RemoteException {
+        activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
+
+        MagnificationConfig config = (new MagnificationConfig.Builder())
+                .setMode(MODE_WINDOW).setActivated(false).build();
+        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
+                config, false, TEST_SERVICE_ID);
+
+        verify(mMockConnection.getConnection(), never()).enableWindowMagnification(anyInt(),
+                anyFloat(), anyFloat(), anyFloat(), anyFloat(), anyFloat(),
+                nullable(IRemoteMagnificationAnimationCallback.class));
+    }
+
+    @Test
     public void configTransitionToFullScreen_windowMagnifying_disableWindowAndEnableFullScreen()
             throws RemoteException {
         final boolean animate = true;
@@ -420,6 +437,49 @@
     }
 
     @Test
+    public void
+            configTransitionToFullScreenAndActivatedFalse_windowMagnifying_doNotEnableFullScreen()
+            throws RemoteException {
+        final boolean animate = true;
+        activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
+        MagnificationConfig config = (new MagnificationConfig.Builder())
+                .setMode(MODE_FULLSCREEN).setActivated(false).build();
+        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
+                config, animate, TEST_SERVICE_ID);
+        mMockConnection.invokeCallbacks();
+
+        verify(mScreenMagnificationController, never()).setScaleAndCenter(anyInt(),
+                anyFloat(), anyFloat(), anyFloat(),
+                anyBoolean(), anyInt());
+    }
+
+    @Test
+    public void configTransitionToActivatedFalse_fullScreenMagnifying_disableFullScreen()
+            throws RemoteException {
+        activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
+        MagnificationConfig config = (new MagnificationConfig.Builder())
+                .setMode(MODE_FULLSCREEN).setActivated(false).build();
+        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
+                config, false, TEST_SERVICE_ID);
+
+        verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY), eq(false));
+    }
+
+    @Test
+    public void configTransitionToActivatedFalse_windowMagnifying_disableWindow()
+            throws RemoteException {
+        final boolean animate = true;
+        activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
+        MagnificationConfig config = (new MagnificationConfig.Builder())
+                .setMode(MODE_WINDOW).setActivated(false).build();
+        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
+                config, animate, TEST_SERVICE_ID);
+
+        verify(mMockConnection.getConnection()).disableWindowMagnification(anyInt(),
+                nullable(IRemoteMagnificationAnimationCallback.class));
+    }
+
+    @Test
     public void configTransitionToFullScreen_userSettingsDisablingFullScreen_enableFullScreen()
             throws RemoteException {
         activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
@@ -679,6 +739,13 @@
     }
 
     @Test
+    public void setPreferenceAlwaysOnMagnificationEnabled_setPrefEnabled_enableOnFullScreen() {
+        mMagnificationController.setAlwaysOnMagnificationEnabled(true);
+
+        verify(mScreenMagnificationController).setAlwaysOnMagnificationEnabled(eq(true));
+    }
+
+    @Test
     public void onRectangleOnScreenRequested_fullScreenIsActivated_fullScreenDispatchEvent() {
         mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY,
                 true);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
index 8890070..7ea0754 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
@@ -63,11 +63,12 @@
     public static final int STATE_SHOW_MAGNIFIER_SHORTCUT = 2;
     public static final int STATE_TWO_FINGERS_DOWN = 3;
     public static final int STATE_SHOW_MAGNIFIER_TRIPLE_TAP = 4;
-    public static final int STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD = 5;
+    public static final int STATE_NOT_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD = 5;
+    public static final int STATE_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD = 6;
     //TODO: Test it after can injecting Handler to GestureMatcher is available.
 
     public static final int FIRST_STATE = STATE_IDLE;
-    public static final int LAST_STATE = STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD;
+    public static final int LAST_STATE = STATE_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD;
 
     // Co-prime x and y, to potentially catch x-y-swapped errors
     public static final float DEFAULT_TAP_X = 301;
@@ -164,15 +165,27 @@
     @Test
     public void testTripleTapAndHold_logSessionDuration() {
         // perform triple tap on spy gesture handler
-        goFromStateIdleTo(STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD);
+        goFromStateIdleTo(STATE_NOT_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD);
 
         // perform up event on spy gesture handler
-        returnToNormalFrom(STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD);
+        returnToNormalFrom(STATE_NOT_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD);
 
         verify(mMockWindowMagnificationGestureHandler)
                 .logMagnificationTripleTapAndHoldSession(anyLong());
     }
 
+    @Test
+    public void testTripleTapAndHold_enabled_releaseHold_expectedValue() {
+        goFromStateIdleTo(STATE_SHOW_MAGNIFIER_TRIPLE_TAP);
+        tap();
+        tap();
+        tapAndHold();
+        send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
+
+        assertIn(STATE_SHOW_MAGNIFIER_TRIPLE_TAP);
+        returnToNormalFrom(STATE_SHOW_MAGNIFIER_TRIPLE_TAP);
+    }
+
     private void forEachState(IntConsumer action) {
         for (int state = FIRST_STATE; state <= LAST_STATE; state++) {
             action.accept(state);
@@ -199,7 +212,8 @@
                         == mWindowMagnificationGestureHandler.mDetectingState, state);
             }
                 break;
-            case STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+            case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD:
+            case STATE_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
                 check(isWindowMagnifierEnabled(DISPLAY_0), state);
                 check(mWindowMagnificationGestureHandler.mCurrentState
                         == mWindowMagnificationGestureHandler.mViewportDraggingState, state);
@@ -256,13 +270,21 @@
                     tap();
                 }
                 break;
-                case STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+                case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
                     // Perform triple tap and hold gesture
                     tap();
                     tap();
                     tapAndHold();
                 }
                 break;
+                case STATE_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+                    // enabled then perform triple tap and hold gesture
+                    goFromStateIdleTo(STATE_SHOW_MAGNIFIER_SHORTCUT);
+                    tap();
+                    tap();
+                    tapAndHold();
+                }
+                break;
                 default:
                     throw new IllegalArgumentException("Illegal state: " + state);
             }
@@ -296,10 +318,15 @@
                 tap();
             }
             break;
-            case STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+            case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
                 send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
             }
             break;
+            case STATE_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+                send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
+                returnToNormalFrom(STATE_SHOW_MAGNIFIER_SHORTCUT);
+            }
+            break;
             default:
                 throw new IllegalArgumentException("Illegal state: " + state);
         }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
index 25ad2be..d841dfc 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
@@ -274,6 +274,19 @@
     }
 
     @Test
+    public void persistScale_setValueWhenScaleIsOne_nothingChanged() {
+        mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
+        final float persistedScale = mWindowMagnificationManager.getPersistedScale(TEST_DISPLAY);
+
+        mWindowMagnificationManager.setScale(TEST_DISPLAY, 1.0f);
+        mWindowMagnificationManager.persistScale(TEST_DISPLAY);
+
+        assertEquals(Settings.Secure.getFloatForUser(mResolver,
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 0f,
+                CURRENT_USER_ID), persistedScale);
+    }
+
+    @Test
     public void scaleSetterGetter_enabledOnTestDisplay_expectedValue() {
         mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
         mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2.0f, NaN, NaN);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index e9dc082..37ed4ac 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -69,6 +69,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.IProgressListener;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
@@ -848,7 +849,8 @@
         mInjector.secondaryDisplayIdsForStartingBackgroundUsers = new int[]{4, 8, 15, 16, 23, 42};
 
         assertThrows(IllegalArgumentException.class,
-                () -> mAms.startUserInBackgroundVisibleOnDisplay(USER_ID, 666));
+                () -> mAms.startUserInBackgroundVisibleOnDisplay(USER_ID, 666,
+                        /* unlockProgressListener= */ null));
 
         assertWithMessage("UserController.startUserOnSecondaryDisplay() calls")
                 .that(mInjector.usersStartedOnSecondaryDisplays).isEmpty();
@@ -859,7 +861,8 @@
         mInjector.secondaryDisplayIdsForStartingBackgroundUsers = new int[]{ 4, 8, 15, 16, 23, 42 };
         mInjector.returnValueForstartUserOnSecondaryDisplay = false;
 
-        boolean started = mAms.startUserInBackgroundVisibleOnDisplay(USER_ID, 42);
+        boolean started = mAms.startUserInBackgroundVisibleOnDisplay(USER_ID, 42,
+                /* unlockProgressListener= */ null);
         Log.v(TAG, "Started: " + started);
 
         assertWithMessage("mAms.startUserInBackgroundOnDisplay(%s, 42)", USER_ID)
@@ -874,7 +877,8 @@
         mInjector.secondaryDisplayIdsForStartingBackgroundUsers = new int[]{ 4, 8, 15, 16, 23, 42 };
         mInjector.returnValueForstartUserOnSecondaryDisplay = true;
 
-        boolean started = mAms.startUserInBackgroundVisibleOnDisplay(USER_ID, 42);
+        boolean started = mAms.startUserInBackgroundVisibleOnDisplay(USER_ID, 42,
+                /* unlockProgressListener= */ null);
         Log.v(TAG, "Started: " + started);
 
         assertWithMessage("mAms.startUserInBackgroundOnDisplay(%s, 42)", USER_ID)
@@ -1009,7 +1013,8 @@
         }
 
         @Override
-        public boolean startUserInBackgroundVisibleOnDisplay(int userId, int displayId) {
+        public boolean startUserInBackgroundVisibleOnDisplay(int userId, int displayId,
+                IProgressListener unlockProgressListener) {
             usersStartedOnSecondaryDisplays.add(new Pair<>(userId, displayId));
             return returnValueForstartUserOnSecondaryDisplay;
         }
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index b146c27..76dfe02 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -244,7 +244,8 @@
 
     @Test
     public void testStartUserVisibleOnDisplay() {
-        boolean started = mUserController.startUserVisibleOnDisplay(TEST_USER_ID, 42);
+        boolean started = mUserController.startUserVisibleOnDisplay(TEST_USER_ID, 42,
+                /* unlockProgressListener= */ null);
 
         assertWithMessage("startUserOnDisplay(%s, %s)", TEST_USER_ID, 42).that(started).isTrue();
         verifyUserAssignedToDisplay(TEST_USER_ID, 42);
@@ -412,7 +413,7 @@
         mInjector.mHandler.clearAllRecordedMessages();
         // Verify that continueUserSwitch worked as expected
         continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
-        verify(mInjector, times(0)).dismissKeyguard(any(), anyString());
+        verify(mInjector, times(0)).dismissKeyguard(any());
         verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
         continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false);
         verifySystemUserVisibilityChangesNeverNotified();
@@ -433,7 +434,7 @@
         mInjector.mHandler.clearAllRecordedMessages();
         // Verify that continueUserSwitch worked as expected
         continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
-        verify(mInjector, times(1)).dismissKeyguard(any(), anyString());
+        verify(mInjector, times(1)).dismissKeyguard(any());
         verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
         continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false);
         verifySystemUserVisibilityChangesNeverNotified();
@@ -1148,7 +1149,7 @@
         }
 
         @Override
-        protected void dismissKeyguard(Runnable runnable, String reason) {
+        protected void dismissKeyguard(Runnable runnable) {
             runnable.run();
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/audio/AbsoluteVolumeBehaviorTest.java b/services/tests/servicestests/src/com/android/server/audio/AbsoluteVolumeBehaviorTest.java
index 38093de..7c736c7 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AbsoluteVolumeBehaviorTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AbsoluteVolumeBehaviorTest.java
@@ -40,13 +40,20 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import libcore.junit.util.compat.CoreCompatChangeRule;
+
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 
 import java.util.Collections;
 import java.util.List;
 
 public class AbsoluteVolumeBehaviorTest {
+    @Rule
+    public TestRule compatChangeRule = new CoreCompatChangeRule();
+
     private static final String TAG = "AbsoluteVolumeBehaviorTest";
 
     private static final AudioDeviceAttributes DEVICE_SPEAKER_OUT = new AudioDeviceAttributes(
@@ -92,7 +99,30 @@
                 new VolumeInfo.Builder(AudioManager.STREAM_MUSIC).build());
 
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
-                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true);
+                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
+        mTestLooper.dispatchAll();
+
+        assertThat(mAudioService.getDeviceVolumeBehavior(DEVICE_SPEAKER_OUT))
+                .isEqualTo(AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
+    }
+
+    /**
+     * Tests that getDeviceVolumeBehavior returns the correct volume behavior, even if
+     * a different volume behavior was previously persisted via setDeviceVolumeBehavior
+     */
+    @Test
+    public void registerDispatcherAfterSetDeviceVolumeBehavior_setsVolumeBehaviorToAbsolute() {
+        List<VolumeInfo> volumes = Collections.singletonList(
+                new VolumeInfo.Builder(AudioManager.STREAM_MUSIC).build());
+
+        mAudioService.setDeviceVolumeBehavior(DEVICE_SPEAKER_OUT,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL, mPackageName);
+        mTestLooper.dispatchAll();
+
+        mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
+                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         assertThat(mAudioService.getDeviceVolumeBehavior(DEVICE_SPEAKER_OUT))
@@ -109,7 +139,8 @@
                         .build());
 
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
-                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true);
+                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         assertThat(mAudioService.getStreamVolume(AudioManager.STREAM_MUSIC))
@@ -124,11 +155,13 @@
                 new VolumeInfo.Builder(AudioManager.STREAM_MUSIC).build());
 
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
-                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true);
+                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(false,
-                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true);
+                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         assertThat(mAudioService.getDeviceVolumeBehavior(DEVICE_SPEAKER_OUT))
@@ -147,7 +180,8 @@
                 new VolumeInfo.Builder(AudioManager.STREAM_MUSIC).build());
 
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
-                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true);
+                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT, volumes, true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         mAudioService.setDeviceVolumeBehavior(DEVICE_SPEAKER_OUT,
@@ -171,7 +205,8 @@
 
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
                 mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT,
-                Collections.singletonList(volumeInfo), true);
+                Collections.singletonList(volumeInfo), true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         // Set stream volume without FLAG_ABSOLUTE_VOLUME
@@ -194,7 +229,8 @@
 
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
                 mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT,
-                Collections.singletonList(volumeInfo), true);
+                Collections.singletonList(volumeInfo), true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         // Set stream volume with FLAG_ABSOLUTE_VOLUME
@@ -218,7 +254,8 @@
         // Register dispatcher with handlesVolumeAdjustment = true
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
                 mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT,
-                Collections.singletonList(volumeInfo), true);
+                Collections.singletonList(volumeInfo), true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         // Adjust stream volume without FLAG_ABSOLUTE_VOLUME
@@ -247,7 +284,8 @@
         // Register dispatcher with handlesVolumeAdjustment = false
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
                 mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT,
-                Collections.singletonList(volumeInfo), false);
+                Collections.singletonList(volumeInfo), false,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         // Adjust stream volume without FLAG_ABSOLUTE_VOLUME
@@ -274,7 +312,8 @@
 
         mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
                 mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT,
-                Collections.singletonList(volumeInfo), true);
+                Collections.singletonList(volumeInfo), true,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
         mTestLooper.dispatchAll();
 
         // Adjust stream volume with FLAG_ABSOLUTE_VOLUME set
@@ -289,4 +328,38 @@
         verify(mMockDispatcher, never()).dispatchDeviceVolumeAdjusted(eq(DEVICE_SPEAKER_OUT), any(),
                 anyInt(), anyInt());
     }
+
+    @Test
+    public void switchAbsoluteVolumeBehaviorToAdjustOnly_onlyDispatchesVolumeChangeForNewListener()
+            throws RemoteException {
+        VolumeInfo volumeInfo = new VolumeInfo.Builder(AudioManager.STREAM_MUSIC)
+                .setMinVolumeIndex(0)
+                .setMaxVolumeIndex(250)
+                .setVolumeIndex(0)
+                .build();
+
+        mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
+                mMockDispatcher, mPackageName, DEVICE_SPEAKER_OUT,
+                Collections.singletonList(volumeInfo), false,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
+        mTestLooper.dispatchAll();
+
+        IAudioDeviceVolumeDispatcher.Stub mMockAdjustOnlyAbsoluteVolumeDispatcher =
+                mock(IAudioDeviceVolumeDispatcher.Stub.class);
+        mAudioService.registerDeviceVolumeDispatcherForAbsoluteVolume(true,
+                mMockAdjustOnlyAbsoluteVolumeDispatcher, mPackageName, DEVICE_SPEAKER_OUT,
+                Collections.singletonList(volumeInfo), false,
+                AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY);
+        mTestLooper.dispatchAll();
+
+        // Set stream volume without FLAG_ABSOLUTE_VOLUME
+        mAudioService.setStreamVolume(AudioManager.STREAM_MUSIC, 15, 0, mPackageName);
+        mTestLooper.dispatchAll();
+
+        // Volume change not dispatched for absolute volume listener
+        verify(mMockDispatcher, never()).dispatchDeviceVolumeChanged(eq(DEVICE_SPEAKER_OUT), any());
+        // Volume changed dispatched for adjust-only absolute volume listener
+        verify(mMockAdjustOnlyAbsoluteVolumeDispatcher).dispatchDeviceVolumeChanged(
+                DEVICE_SPEAKER_OUT, new VolumeInfo.Builder(volumeInfo).setVolumeIndex(150).build());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index 99f7905..e605a31 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -35,6 +35,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.content.ComponentName;
+import android.hardware.biometrics.BiometricFingerprintConstants;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.common.ICancellationSignal;
 import android.hardware.biometrics.common.OperationContext;
@@ -364,6 +365,16 @@
         showHideOverlay(c -> c.onLockoutPermanent());
     }
 
+    @Test
+    public void testPowerPressForwardsErrorMessage() throws RemoteException {
+        final FingerprintAuthenticationClient client = createClient();
+
+        client.onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR,
+                BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED);
+
+        verify(mClientMonitorCallbackConverter).onError(anyInt(), anyInt(),
+                eq(BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED), eq(0));
+    }
     private void showHideOverlay(Consumer<FingerprintAuthenticationClient> block)
             throws RemoteException {
         final FingerprintAuthenticationClient client = createClient();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
index 26524d7..a40d3fe 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -16,8 +16,6 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
-import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED;
-
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -29,6 +27,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.hardware.biometrics.BiometricFingerprintConstants;
 import android.hardware.biometrics.common.OperationContext;
 import android.hardware.biometrics.fingerprint.ISession;
 import android.hardware.biometrics.fingerprint.PointerContext;
@@ -276,11 +275,12 @@
     @Test
     public void testPowerPressForwardsAcquireMessage() throws RemoteException {
         final FingerprintEnrollClient client = createClient();
-        client.start(mCallback);
-        client.onPowerPressed();
+
+        client.onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR,
+                BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED);
 
         verify(mClientMonitorCallbackConverter).onAcquired(anyInt(),
-                eq(FINGERPRINT_ACQUIRED_POWER_PRESSED), anyInt());
+                eq(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED), eq(0));
     }
 
     private void showHideOverlay(Consumer<FingerprintEnrollClient> block)
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index 82f6493..4d06855 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -28,6 +28,7 @@
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertThrows;
 
+import android.app.ActivityManager;
 import android.hardware.devicestate.DeviceStateInfo;
 import android.hardware.devicestate.DeviceStateRequest;
 import android.hardware.devicestate.IDeviceStateManagerCallback;
@@ -541,7 +542,7 @@
     }
 
     @Test
-    public void requestState_flagCancelWhenRequesterNotOnTop_onTaskStackChanged()
+    public void requestState_flagCancelWhenRequesterNotOnTop_onTaskMovedToFront()
             throws RemoteException {
         requestState_flagCancelWhenRequesterNotOnTop_common(
                 // When the app is foreground, the state should not change
@@ -549,7 +550,8 @@
                     int pid = Binder.getCallingPid();
                     when(mWindowProcessController.getPid()).thenReturn(pid);
                     try {
-                        mService.mOverrideRequestTaskStackListener.onTaskStackChanged();
+                        mService.mOverrideRequestTaskStackListener.onTaskMovedToFront(
+                                new ActivityManager.RunningTaskInfo());
                     } catch (RemoteException e) {
                         throw new RuntimeException(e);
                     }
@@ -558,7 +560,8 @@
                 () -> {
                     when(mWindowProcessController.getPid()).thenReturn(FAKE_PROCESS_ID);
                     try {
-                        mService.mOverrideRequestTaskStackListener.onTaskStackChanged();
+                        mService.mOverrideRequestTaskStackListener.onTaskMovedToFront(
+                                new ActivityManager.RunningTaskInfo());
                     } catch (RemoteException e) {
                         throw new RuntimeException(e);
                     }
@@ -945,13 +948,15 @@
             }
 
             mListener = listener;
-            mListener.onSupportedDeviceStatesChanged(mSupportedDeviceStates);
+            mListener.onSupportedDeviceStatesChanged(mSupportedDeviceStates,
+                    SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED);
             mListener.onStateChanged(mSupportedDeviceStates[0].getIdentifier());
         }
 
         public void notifySupportedDeviceStates(DeviceState[] supportedDeviceStates) {
             mSupportedDeviceStates = supportedDeviceStates;
-            mListener.onSupportedDeviceStatesChanged(supportedDeviceStates);
+            mListener.onSupportedDeviceStatesChanged(supportedDeviceStates,
+                    SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED);
         }
 
         public void setState(int identifier) {
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateNotificationControllerTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateNotificationControllerTest.java
new file mode 100644
index 0000000..8196d6a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateNotificationControllerTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.devicestate;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+import android.platform.test.annotations.Presubmit;
+import android.util.SparseArray;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mockito;
+
+/**
+ * Unit tests for {@link DeviceStateNotificationController}.
+ * <p/>
+ * Run with <code>atest com.android.server.devicestate.DeviceStateNotificationControllerTest</code>.
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class DeviceStateNotificationControllerTest {
+
+    private static final int STATE_WITHOUT_NOTIFICATION = 1;
+    private static final int STATE_WITH_ACTIVE_NOTIFICATION = 2;
+    private static final int STATE_WITH_ACTIVE_AND_THERMAL_NOTIFICATION = 3;
+
+    private static final int VALID_APP_UID = 1000;
+    private static final int INVALID_APP_UID = 2000;
+    private static final String VALID_APP_NAME = "Valid app name";
+    private static final String INVALID_APP_NAME = "Invalid app name";
+    private static final String VALID_APP_LABEL = "Valid app label";
+
+    private static final String NAME_1 = "name1";
+    private static final String TITLE_1 = "title1";
+    private static final String CONTENT_1 = "content1:%1$s";
+    private static final String NAME_2 = "name2";
+    private static final String TITLE_2 = "title2";
+    private static final String CONTENT_2 = "content2:%1$s";
+    private static final String THERMAL_TITLE_2 = "thermal_title2";
+    private static final String THERMAL_CONTENT_2 = "thermal_content2";
+
+    private DeviceStateNotificationController mController;
+
+    private final ArgumentCaptor<Notification> mNotificationCaptor = ArgumentCaptor.forClass(
+            Notification.class);
+    private final NotificationManager mNotificationManager = mock(NotificationManager.class);
+
+    @Before
+    public void setup() throws Exception {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        Handler handler = mock(Handler.class);
+        PackageManager packageManager = mock(PackageManager.class);
+        Runnable cancelStateRunnable = mock(Runnable.class);
+        ApplicationInfo applicationInfo = mock(ApplicationInfo.class);
+
+        final SparseArray<DeviceStateNotificationController.NotificationInfo> notificationInfos =
+                new SparseArray<>();
+        notificationInfos.put(STATE_WITH_ACTIVE_NOTIFICATION,
+                new DeviceStateNotificationController.NotificationInfo(
+                        NAME_1, TITLE_1, CONTENT_1,
+                        "", ""));
+        notificationInfos.put(STATE_WITH_ACTIVE_AND_THERMAL_NOTIFICATION,
+                new DeviceStateNotificationController.NotificationInfo(
+                        NAME_2, TITLE_2, CONTENT_2,
+                        THERMAL_TITLE_2, THERMAL_CONTENT_2));
+
+        when(packageManager.getNameForUid(VALID_APP_UID)).thenReturn(VALID_APP_NAME);
+        when(packageManager.getNameForUid(INVALID_APP_UID)).thenReturn(INVALID_APP_NAME);
+        when(packageManager.getApplicationInfo(eq(VALID_APP_NAME), ArgumentMatchers.any()))
+                .thenReturn(applicationInfo);
+        when(packageManager.getApplicationInfo(eq(INVALID_APP_NAME), ArgumentMatchers.any()))
+                .thenThrow(new PackageManager.NameNotFoundException());
+        when(applicationInfo.loadLabel(eq(packageManager))).thenReturn(VALID_APP_LABEL);
+
+        mController = new DeviceStateNotificationController(
+                context, handler, cancelStateRunnable, notificationInfos,
+                packageManager, mNotificationManager);
+    }
+
+    @Test
+    public void test_activeNotification() {
+        mController.showStateActiveNotificationIfNeeded(
+                STATE_WITH_ACTIVE_NOTIFICATION, VALID_APP_UID);
+
+        // Verify that the notification manager is called with correct notification information.
+        verify(mNotificationManager).notify(
+                eq(DeviceStateNotificationController.NOTIFICATION_TAG),
+                eq(DeviceStateNotificationController.NOTIFICATION_ID),
+                mNotificationCaptor.capture());
+        Notification notification = mNotificationCaptor.getValue();
+        assertEquals(TITLE_1, notification.extras.getString(Notification.EXTRA_TITLE));
+        assertEquals(String.format(CONTENT_1, VALID_APP_LABEL),
+                notification.extras.getString(Notification.EXTRA_TEXT));
+        assertEquals(Notification.FLAG_ONGOING_EVENT,
+                notification.flags & Notification.FLAG_ONGOING_EVENT);
+
+        // Verify that the notification action is as expected.
+        Notification.Action[] actions = notification.actions;
+        assertEquals(1, actions.length);
+        Notification.Action action = actions[0];
+        assertEquals(DeviceStateNotificationController.INTENT_ACTION_CANCEL_STATE,
+                action.actionIntent.getIntent().getAction());
+
+        // Verify that the notification is properly canceled.
+        mController.cancelNotification(STATE_WITH_ACTIVE_NOTIFICATION);
+        verify(mNotificationManager).cancel(
+                DeviceStateNotificationController.NOTIFICATION_TAG,
+                DeviceStateNotificationController.NOTIFICATION_ID);
+    }
+
+    @Test
+    public void test_thermalNotification() {
+        // Verify that the active notification is created.
+        mController.showStateActiveNotificationIfNeeded(
+                STATE_WITH_ACTIVE_AND_THERMAL_NOTIFICATION, VALID_APP_UID);
+        verify(mNotificationManager).notify(
+                eq(DeviceStateNotificationController.NOTIFICATION_TAG),
+                eq(DeviceStateNotificationController.NOTIFICATION_ID),
+                mNotificationCaptor.capture());
+        Notification notification = mNotificationCaptor.getValue();
+        assertEquals(TITLE_2, notification.extras.getString(Notification.EXTRA_TITLE));
+        assertEquals(String.format(CONTENT_2, VALID_APP_LABEL),
+                notification.extras.getString(Notification.EXTRA_TEXT));
+        assertEquals(Notification.FLAG_ONGOING_EVENT,
+                notification.flags & Notification.FLAG_ONGOING_EVENT);
+        Mockito.clearInvocations(mNotificationManager);
+
+        // Verify that the thermal critical notification is created.
+        mController.showThermalCriticalNotificationIfNeeded(
+                STATE_WITH_ACTIVE_AND_THERMAL_NOTIFICATION);
+        verify(mNotificationManager).notify(
+                eq(DeviceStateNotificationController.NOTIFICATION_TAG),
+                eq(DeviceStateNotificationController.NOTIFICATION_ID),
+                mNotificationCaptor.capture());
+        notification = mNotificationCaptor.getValue();
+        assertEquals(THERMAL_TITLE_2, notification.extras.getString(Notification.EXTRA_TITLE));
+        assertEquals(THERMAL_CONTENT_2, notification.extras.getString(Notification.EXTRA_TEXT));
+        assertEquals(0, notification.flags & Notification.FLAG_ONGOING_EVENT);
+
+        // Verify that the notification is canceled.
+        mController.cancelNotification(STATE_WITH_ACTIVE_NOTIFICATION);
+        verify(mNotificationManager).cancel(
+                DeviceStateNotificationController.NOTIFICATION_TAG,
+                DeviceStateNotificationController.NOTIFICATION_ID);
+    }
+
+    @Test
+    public void test_deviceStateWithoutNotification() {
+        // Verify that no notification is created.
+        mController.showStateActiveNotificationIfNeeded(
+                STATE_WITHOUT_NOTIFICATION, VALID_APP_UID);
+        verify(mNotificationManager, Mockito.never()).notify(
+                eq(DeviceStateNotificationController.NOTIFICATION_TAG),
+                eq(DeviceStateNotificationController.NOTIFICATION_ID),
+                mNotificationCaptor.capture());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
index 430504c..fe37f42 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
@@ -58,7 +58,7 @@
 
     @Test
     public void addRequest() {
-        OverrideRequest request = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest request = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
         assertNull(mStatusListener.getLastStatus(request));
 
@@ -68,14 +68,14 @@
 
     @Test
     public void addRequest_cancelExistingRequestThroughNewRequest() {
-        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
         assertNull(mStatusListener.getLastStatus(firstRequest));
 
         mController.addRequest(firstRequest);
         assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
 
-        OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
         assertNull(mStatusListener.getLastStatus(secondRequest));
 
@@ -86,7 +86,7 @@
 
     @Test
     public void addRequest_cancelActiveRequest() {
-        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         mController.addRequest(firstRequest);
@@ -100,7 +100,7 @@
 
     @Test
     public void addBaseStateRequest() {
-        OverrideRequest request = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest request = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
         assertNull(mStatusListener.getLastStatus(request));
 
@@ -110,14 +110,14 @@
 
     @Test
     public void addBaseStateRequest_cancelExistingBaseStateRequestThroughNewRequest() {
-        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
         assertNull(mStatusListener.getLastStatus(firstRequest));
 
         mController.addBaseStateRequest(firstRequest);
         assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
 
-        OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
         assertNull(mStatusListener.getLastStatus(secondRequest));
 
@@ -128,7 +128,7 @@
 
     @Test
     public void addBaseStateRequest_cancelActiveBaseStateRequest() {
-        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
         mController.addBaseStateRequest(firstRequest);
@@ -142,12 +142,13 @@
 
     @Test
     public void handleBaseStateChanged() {
-        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 0 /* requestedState */,
                 DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES /* flags */,
                 OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+                0 /* uid */,
                 0 /* requestedState */,
                 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
@@ -167,10 +168,11 @@
 
     @Test
     public void handleProcessDied() {
-        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+                0 /* uid */,
                 1 /* requestedState */,
                 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
@@ -189,10 +191,11 @@
     public void handleProcessDied_stickyRequests() {
         mController.setStickyRequestsAllowed(true);
 
-        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+                0 /* uid */,
                 1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
         mController.addRequest(firstRequest);
@@ -211,10 +214,11 @@
 
     @Test
     public void handleNewSupportedStates() {
-        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+                0 /* uid */,
                 1 /* requestedState */,
                 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
@@ -224,18 +228,20 @@
         mController.addBaseStateRequest(baseStateRequest);
         assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_ACTIVE);
 
-        mController.handleNewSupportedStates(new int[]{0, 1});
+        mController.handleNewSupportedStates(new int[]{0, 1},
+                DeviceStateProvider.SUPPORTED_DEVICE_STATES_CHANGED_DEFAULT);
         assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
         assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_ACTIVE);
 
-        mController.handleNewSupportedStates(new int[]{0});
+        mController.handleNewSupportedStates(new int[]{0},
+                DeviceStateProvider.SUPPORTED_DEVICE_STATES_CHANGED_DEFAULT);
         assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
         assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_CANCELED);
     }
 
     @Test
     public void cancelOverrideRequestsTest() {
-        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
+        OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
                 1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         mController.addRequest(firstRequest);
@@ -250,7 +256,7 @@
         private Map<OverrideRequest, Integer> mLastStatusMap = new HashMap<>();
 
         @Override
-        public void onStatusChanged(@NonNull OverrideRequest request, int newStatus) {
+        public void onStatusChanged(@NonNull OverrideRequest request, int newStatus, int flags) {
             mLastStatusMap.put(request, newStatus);
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java b/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
index bcae50e..8f2a1e5 100644
--- a/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
@@ -19,6 +19,7 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.view.Display;
 import android.view.DisplayAddress;
 
 import androidx.test.filters.SmallTest;
@@ -64,10 +65,14 @@
         Layout testLayout = new Layout();
         testLayout.createDisplayLocked(
                 DisplayAddress.fromPhysicalDisplayId(123456L), /* isDefault= */ true,
-                /* isEnabled= */ true, mDisplayIdProducerMock);
+                /* isEnabled= */ true, mDisplayIdProducerMock,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         testLayout.createDisplayLocked(
                 DisplayAddress.fromPhysicalDisplayId(78910L), /* isDefault= */ false,
-                /* isEnabled= */ false, mDisplayIdProducerMock);
+                /* isEnabled= */ false, mDisplayIdProducerMock,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         assertEquals(testLayout, configLayout);
     }
 
@@ -78,10 +83,14 @@
         Layout testLayout = new Layout();
         testLayout.createDisplayLocked(
                 DisplayAddress.fromPhysicalDisplayId(78910L), /* isDefault= */ true,
-                /* isEnabled= */ true, mDisplayIdProducerMock);
+                /* isEnabled= */ true, mDisplayIdProducerMock,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         testLayout.createDisplayLocked(
                 DisplayAddress.fromPhysicalDisplayId(123456L), /* isDefault= */ false,
-                /* isEnabled= */ false, mDisplayIdProducerMock);
+                /* isEnabled= */ false, mDisplayIdProducerMock,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
 
         assertEquals(testLayout, configLayout);
     }
@@ -91,12 +100,48 @@
         Layout configLayout = mDeviceStateToLayoutMap.get(2);
 
         Layout testLayout = new Layout();
-        testLayout.createDisplayLocked(
+
+        Layout.Display display1 = testLayout.createDisplayLocked(
                 DisplayAddress.fromPhysicalDisplayId(345L), /* isDefault= */ true,
-                /* isEnabled= */ true, mDisplayIdProducerMock);
+                /* isEnabled= */ true, mDisplayIdProducerMock,
+                /* brightnessThrottlingMapId= */ "concurrent",
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        display1.setPosition(Layout.Display.POSITION_FRONT);
+
+        Layout.Display display2 = testLayout.createDisplayLocked(
+                DisplayAddress.fromPhysicalDisplayId(678L), /* isDefault= */ false,
+                /* isEnabled= */ true, mDisplayIdProducerMock,
+                /* brightnessThrottlingMapId= */ "concurrent",
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        display2.setPosition(Layout.Display.POSITION_REAR);
+
+        assertEquals(testLayout, configLayout);
+    }
+
+    @Test
+    public void testRearDisplayLayout() {
+        Layout configLayout = mDeviceStateToLayoutMap.get(2);
+
+        assertEquals(Layout.Display.POSITION_FRONT, configLayout.getAt(0).getPosition());
+        assertEquals(Layout.Display.POSITION_REAR, configLayout.getAt(1).getPosition());
+    }
+
+    @Test
+    public void testRefreshRateZoneId() {
+        Layout configLayout = mDeviceStateToLayoutMap.get(3);
+
+        Layout testLayout = new Layout();
+        Layout.Display display1 = testLayout.createDisplayLocked(
+                DisplayAddress.fromPhysicalDisplayId(345L), /* isDefault= */ true,
+                /* isEnabled= */ true, mDisplayIdProducerMock,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        display1.setRefreshRateZoneId("test1");
         testLayout.createDisplayLocked(
                 DisplayAddress.fromPhysicalDisplayId(678L), /* isDefault= */ false,
-                /* isEnabled= */ true, mDisplayIdProducerMock);
+                /* isEnabled= */ true, mDisplayIdProducerMock,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
 
         assertEquals(testLayout, configLayout);
     }
@@ -139,6 +184,21 @@
                 +      "<state>2</state> \n"
                 +      "<display enabled=\"true\" defaultDisplay=\"true\">\n"
                 +        "<address>345</address>\n"
+                +        "<position>front</position>\n"
+                +        "<brightnessThrottlingMapId>concurrent</brightnessThrottlingMapId>\n"
+                +      "</display>\n"
+                +      "<display enabled=\"true\">\n"
+                +        "<address>678</address>\n"
+                +        "<position>rear</position>\n"
+                +        "<brightnessThrottlingMapId>concurrent</brightnessThrottlingMapId>\n"
+                +      "</display>\n"
+                +    "</layout>\n"
+
+                +    "<layout>\n"
+                +      "<state>3</state> \n"
+                +      "<display enabled=\"true\" defaultDisplay=\"true\" "
+                +                                               "refreshRateZoneId=\"test1\">\n"
+                +        "<address>345</address>\n"
                 +      "</display>\n"
                 +      "<display enabled=\"true\">\n"
                 +        "<address>678</address>\n"
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
index 0ea20a8..0e9c171 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -53,6 +53,8 @@
 public final class DisplayDeviceConfigTest {
     private static final int DEFAULT_PEAK_REFRESH_RATE = 75;
     private static final int DEFAULT_REFRESH_RATE = 120;
+    private static final int DEFAULT_HIGH_BLOCKING_ZONE_REFRESH_RATE = 55;
+    private static final int DEFAULT_LOW_BLOCKING_ZONE_REFRESH_RATE = 95;
     private static final int[] LOW_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE = new int[]{10, 30};
     private static final int[] LOW_AMBIENT_THRESHOLD_OF_PEAK_REFRESH_RATE = new int[]{1, 21};
     private static final int[] HIGH_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE = new int[]{160};
@@ -149,8 +151,17 @@
         assertArrayEquals(new float[]{23, 24, 25},
                 mDisplayDeviceConfig.getAmbientDarkeningPercentagesIdle(), ZERO_DELTA);
 
-        assertEquals(75, mDisplayDeviceConfig.getDefaultLowRefreshRate());
-        assertEquals(90, mDisplayDeviceConfig.getDefaultHighRefreshRate());
+        assertEquals(75, mDisplayDeviceConfig.getDefaultLowBlockingZoneRefreshRate());
+        assertEquals(90, mDisplayDeviceConfig.getDefaultHighBlockingZoneRefreshRate());
+        assertEquals(85, mDisplayDeviceConfig.getDefaultPeakRefreshRate());
+        assertEquals(45, mDisplayDeviceConfig.getDefaultRefreshRate());
+
+        assertEquals(2, mDisplayDeviceConfig.getRefreshRangeProfiles().size());
+        assertEquals(60, mDisplayDeviceConfig.getRefreshRange("test1").min, SMALL_DELTA);
+        assertEquals(60, mDisplayDeviceConfig.getRefreshRange("test1").max, SMALL_DELTA);
+        assertEquals(80, mDisplayDeviceConfig.getRefreshRange("test2").min, SMALL_DELTA);
+        assertEquals(90, mDisplayDeviceConfig.getRefreshRange("test2").max, SMALL_DELTA);
+
         assertArrayEquals(new int[]{45, 55},
                 mDisplayDeviceConfig.getLowDisplayBrightnessThresholds());
         assertArrayEquals(new int[]{50, 60},
@@ -189,7 +200,7 @@
                 DisplayDeviceConfig.convertThermalStatus(ThermalStatus.shutdown), 0.025f
         ));
         assertEquals(new DisplayDeviceConfig.BrightnessThrottlingData(throttlingLevels),
-                mDisplayDeviceConfig.getBrightnessThrottlingData());
+                mDisplayDeviceConfig.getBrightnessThrottlingData("default"));
 
         throttlingLevels.clear();
         throttlingLevels.add(new DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel(
@@ -211,7 +222,7 @@
                 DisplayDeviceConfig.convertThermalStatus(ThermalStatus.shutdown), 0.0125f
         ));
         assertEquals(new DisplayDeviceConfig.BrightnessThrottlingData(throttlingLevels),
-                mDisplayDeviceConfig.getConcurrentDisplaysBrightnessThrottlingData());
+                mDisplayDeviceConfig.getBrightnessThrottlingData("concurrent"));
 
         assertNotNull(mDisplayDeviceConfig.getHostUsiVersion());
         assertEquals(mDisplayDeviceConfig.getHostUsiVersion().getMajorVersion(), 2);
@@ -278,8 +289,15 @@
                 mDisplayDeviceConfig.getAmbientDarkeningLevelsIdle(), ZERO_DELTA);
         assertArrayEquals(new float[]{29, 30, 31},
                 mDisplayDeviceConfig.getAmbientDarkeningPercentagesIdle(), ZERO_DELTA);
-        assertEquals(mDisplayDeviceConfig.getDefaultLowRefreshRate(), DEFAULT_REFRESH_RATE);
-        assertEquals(mDisplayDeviceConfig.getDefaultHighRefreshRate(), DEFAULT_PEAK_REFRESH_RATE);
+        assertEquals(mDisplayDeviceConfig.getDefaultLowBlockingZoneRefreshRate(),
+                DEFAULT_LOW_BLOCKING_ZONE_REFRESH_RATE);
+        assertEquals(mDisplayDeviceConfig.getDefaultHighBlockingZoneRefreshRate(),
+                DEFAULT_HIGH_BLOCKING_ZONE_REFRESH_RATE);
+        assertEquals(mDisplayDeviceConfig.getDefaultPeakRefreshRate(), DEFAULT_PEAK_REFRESH_RATE);
+        assertEquals(mDisplayDeviceConfig.getDefaultRefreshRate(), DEFAULT_REFRESH_RATE);
+
+        assertEquals(0, mDisplayDeviceConfig.getRefreshRangeProfiles().size());
+
         assertArrayEquals(mDisplayDeviceConfig.getLowDisplayBrightnessThresholds(),
                 LOW_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE);
         assertArrayEquals(mDisplayDeviceConfig.getLowAmbientBrightnessThresholds(),
@@ -509,7 +527,7 @@
                 +               "<brightness>0.025</brightness>\n"
                 +           "</brightnessThrottlingPoint>\n"
                 +       "</brightnessThrottlingMap>\n"
-                +       "<concurrentDisplaysBrightnessThrottlingMap>\n"
+                +       "<brightnessThrottlingMap id=\"concurrent\">\n"
                 +           "<brightnessThrottlingPoint>\n"
                 +               "<thermalStatus>light</thermalStatus>\n"
                 +               "<brightness>0.2</brightness>\n"
@@ -534,9 +552,25 @@
                 +               "<thermalStatus>shutdown</thermalStatus>\n"
                 +               "<brightness>0.0125</brightness>\n"
                 +           "</brightnessThrottlingPoint>\n"
-                +       "</concurrentDisplaysBrightnessThrottlingMap>\n"
+                +       "</brightnessThrottlingMap>\n"
                 +   "</thermalThrottling>\n"
                 +   "<refreshRate>\n"
+                +       "<defaultRefreshRate>45</defaultRefreshRate>\n"
+                +       "<defaultPeakRefreshRate>85</defaultPeakRefreshRate>\n"
+                +       "<refreshRateZoneProfiles>"
+                +           "<refreshRateZoneProfile id=\"test1\">"
+                +               "<refreshRateRange>\n"
+                +                   "<minimum>60</minimum>\n"
+                +                   "<maximum>60</maximum>\n"
+                +               "</refreshRateRange>\n"
+                +           "</refreshRateZoneProfile>\n"
+                +           "<refreshRateZoneProfile id=\"test2\">"
+                +               "<refreshRateRange>\n"
+                +                   "<minimum>80</minimum>\n"
+                +                   "<maximum>90</maximum>\n"
+                +               "</refreshRateRange>\n"
+                +           "</refreshRateZoneProfile>\n"
+                +       "</refreshRateZoneProfiles>"
                 +       "<lowerBlockingZoneConfigs>\n"
                 +           "<defaultRefreshRate>75</defaultRefreshRate>\n"
                 +           "<blockingZoneThreshold>\n"
@@ -642,10 +676,14 @@
                 .thenReturn(new int[]{370, 380, 390});
 
         // Configs related to refresh rates and blocking zones
-        when(mResources.getInteger(com.android.internal.R.integer.config_defaultPeakRefreshRate))
+        when(mResources.getInteger(R.integer.config_defaultPeakRefreshRate))
                 .thenReturn(DEFAULT_PEAK_REFRESH_RATE);
-        when(mResources.getInteger(com.android.internal.R.integer.config_defaultRefreshRate))
+        when(mResources.getInteger(R.integer.config_defaultRefreshRate))
                 .thenReturn(DEFAULT_REFRESH_RATE);
+        when(mResources.getInteger(R.integer.config_fixedRefreshRateInHighZone))
+            .thenReturn(DEFAULT_HIGH_BLOCKING_ZONE_REFRESH_RATE);
+        when(mResources.getInteger(R.integer.config_defaultRefreshRateInZone))
+            .thenReturn(DEFAULT_LOW_BLOCKING_ZONE_REFRESH_RATE);
         when(mResources.getIntArray(R.array.config_brightnessThresholdsOfPeakRefreshRate))
                 .thenReturn(LOW_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE);
         when(mResources.getIntArray(R.array.config_ambientThresholdsOfPeakRefreshRate))
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 2d252cb..1904671 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -56,6 +56,7 @@
 import android.hardware.display.DisplayViewport;
 import android.hardware.display.DisplayedContentSample;
 import android.hardware.display.DisplayedContentSamplingAttributes;
+import android.hardware.display.HdrConversionMode;
 import android.hardware.display.IDisplayManagerCallback;
 import android.hardware.display.IVirtualDisplayCallback;
 import android.hardware.display.VirtualDisplayConfig;
@@ -157,7 +158,7 @@
        VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
                Handler handler, DisplayAdapter.Listener displayAdapterListener) {
            return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
-                   (String name, boolean secure) -> mMockDisplayToken);
+                   (String name, boolean secure, float refreshRate) -> mMockDisplayToken);
        }
 
        @Override
@@ -171,6 +172,17 @@
                }
            });
        }
+
+        @Override
+        void setHdrConversionMode(int conversionMode, int preferredHdrOutputType,
+                int[] autoHdrTypes) {
+            return;
+        }
+
+        @Override
+        int[] getSupportedHdrOutputTypes() {
+            return new int[]{};
+        }
    }
 
     private final DisplayManagerService.Injector mBasicInjector = new BasicInjector();
@@ -240,8 +252,7 @@
         // the usage of SensorManager, which is available only after the PowerManagerService
         // is ready.
         resetConfigToIgnoreSensorManager(mContext);
-        DisplayManagerService displayManager =
-                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
         registerDefaultDisplays(displayManager);
         displayManager.systemReady(false /* safeMode */);
         displayManager.windowManagerAndInputReady();
@@ -316,8 +327,7 @@
         // the usage of SensorManager, which is available only after the PowerManagerService
         // is ready.
         resetConfigToIgnoreSensorManager(mContext);
-        DisplayManagerService displayManager =
-                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
         registerDefaultDisplays(displayManager);
         displayManager.systemReady(false /* safeMode */);
         displayManager.windowManagerAndInputReady();
@@ -1511,6 +1521,22 @@
 
     }
 
+    @Test
+    public void testHdrConversionModeEquals() {
+        assertEquals(
+                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2),
+                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2));
+        assertNotEquals(
+                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2),
+                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 3));
+        assertEquals(
+                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM),
+                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
+        assertNotEquals(
+                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2),
+                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
+    }
+
     private void testDisplayInfoFrameRateOverrideModeCompat(boolean compatChangeEnabled)
             throws Exception {
         DisplayManagerService displayManager =
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 3a3a507..0eff0da 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -754,7 +754,7 @@
 
     @Test
     public void testVotingWithSwitchingTypeRenderFrameRateOnlyRenderRateIsNotPhysicalRefreshRate() {
-        DisplayModeDirector director = createDirectorFromFpsRange(90, 120);
+        DisplayModeDirector director = createDirectorFromFpsRange(60, 120);
         SparseArray<Vote> votes = new SparseArray<>();
         SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
         votesByDisplay.put(DISPLAY_ID, votes);
@@ -775,23 +775,23 @@
         assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity();
         assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0);
         assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
-        assertThat(desiredSpecs.baseModeId).isEqualTo(90);
+        assertThat(desiredSpecs.baseModeId).isEqualTo(60);
 
         director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY);
         assertThat(director.getModeSwitchingType())
                 .isEqualTo(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY);
 
         desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
-        assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
-        assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+        assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+        assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
         assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
         assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
-        assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
-        assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+        assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+        assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
         assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0);
         assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
 
-        assertThat(desiredSpecs.baseModeId).isEqualTo(90);
+        assertThat(desiredSpecs.baseModeId).isEqualTo(60);
     }
 
     @Test
@@ -1732,6 +1732,31 @@
     }
 
     @Test
+    public void testRenderFrameRateIsAchievableWhenSwitchingTypeNone() {
+        Display.Mode[] modes = new Display.Mode[2];
+        modes[0] = new Display.Mode(
+                /*modeId=*/60, /*width=*/1000, /*height=*/1000, 60);
+        modes[1] = new Display.Mode(
+                /*modeId=*/90, /*width=*/1000, /*height=*/1000, 90);
+
+        DisplayModeDirector director = createDirectorFromModeArray(modes, modes[1]);
+        director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_NONE);
+
+        SparseArray<Vote> votes = new SparseArray<>();
+        SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
+        votesByDisplay.put(DISPLAY_ID, votes);
+        votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
+                Vote.forRenderFrameRates(0, 60));
+        director.injectVotesByDisplay(votesByDisplay);
+        DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+        assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+        assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+        assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90);
+        assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(90);
+        assertThat(desiredSpecs.baseModeId).isEqualTo(90);
+    }
+
+    @Test
     public void testProximitySensorVoting() {
         DisplayModeDirector director =
                 createDirectorFromRefreshRateArray(new float[]{60.f, 90.f}, 0);
@@ -2235,6 +2260,10 @@
             .thenReturn(75);
         when(resources.getInteger(R.integer.config_defaultRefreshRate))
             .thenReturn(45);
+        when(resources.getInteger(R.integer.config_fixedRefreshRateInHighZone))
+            .thenReturn(65);
+        when(resources.getInteger(R.integer.config_defaultRefreshRateInZone))
+            .thenReturn(85);
         when(resources.getIntArray(R.array.config_brightnessThresholdsOfPeakRefreshRate))
             .thenReturn(new int[]{5});
         when(resources.getIntArray(R.array.config_ambientThresholdsOfPeakRefreshRate))
@@ -2254,6 +2283,8 @@
         assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 45, 0.0);
         assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 75,
                 0.0);
+        assertEquals(director.getBrightnessObserver().getRefreshRateInHighZone(), 65);
+        assertEquals(director.getBrightnessObserver().getRefreshRateInLowZone(), 85);
         assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThreshold(),
                 new int[]{250});
         assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThreshold(),
@@ -2265,17 +2296,21 @@
 
         // Notify that the default display is updated, such that DisplayDeviceConfig has new values
         DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class);
-        when(displayDeviceConfig.getDefaultLowRefreshRate()).thenReturn(50);
-        when(displayDeviceConfig.getDefaultHighRefreshRate()).thenReturn(55);
+        when(displayDeviceConfig.getDefaultLowBlockingZoneRefreshRate()).thenReturn(50);
+        when(displayDeviceConfig.getDefaultHighBlockingZoneRefreshRate()).thenReturn(55);
+        when(displayDeviceConfig.getDefaultRefreshRate()).thenReturn(60);
+        when(displayDeviceConfig.getDefaultPeakRefreshRate()).thenReturn(65);
         when(displayDeviceConfig.getLowDisplayBrightnessThresholds()).thenReturn(new int[]{25});
         when(displayDeviceConfig.getLowAmbientBrightnessThresholds()).thenReturn(new int[]{30});
         when(displayDeviceConfig.getHighDisplayBrightnessThresholds()).thenReturn(new int[]{210});
         when(displayDeviceConfig.getHighAmbientBrightnessThresholds()).thenReturn(new int[]{2100});
         director.defaultDisplayDeviceUpdated(displayDeviceConfig);
 
-        assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 50, 0.0);
-        assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 55,
+        assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 60, 0.0);
+        assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 65,
                 0.0);
+        assertEquals(director.getBrightnessObserver().getRefreshRateInHighZone(), 55);
+        assertEquals(director.getBrightnessObserver().getRefreshRateInLowZone(), 50);
         assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThreshold(),
                 new int[]{210});
         assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThreshold(),
@@ -2288,6 +2323,8 @@
         // Notify that the default display is updated, such that DeviceConfig has new values
         FakeDeviceConfig config = mInjector.getDeviceConfig();
         config.setDefaultPeakRefreshRate(60);
+        config.setRefreshRateInHighZone(65);
+        config.setRefreshRateInLowZone(70);
         config.setLowAmbientBrightnessThresholds(new int[]{20});
         config.setLowDisplayBrightnessThresholds(new int[]{10});
         config.setHighDisplayBrightnessThresholds(new int[]{255});
@@ -2295,9 +2332,11 @@
 
         director.defaultDisplayDeviceUpdated(displayDeviceConfig);
 
-        assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 50, 0.0);
+        assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 60, 0.0);
         assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 60,
                 0.0);
+        assertEquals(director.getBrightnessObserver().getRefreshRateInHighZone(), 65);
+        assertEquals(director.getBrightnessObserver().getRefreshRateInLowZone(), 70);
         assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThreshold(),
                 new int[]{255});
         assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThreshold(),
@@ -2337,8 +2376,8 @@
                         any(Handler.class));
 
         DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class);
-        when(ddcMock.getDefaultLowRefreshRate()).thenReturn(50);
-        when(ddcMock.getDefaultHighRefreshRate()).thenReturn(55);
+        when(ddcMock.getDefaultLowBlockingZoneRefreshRate()).thenReturn(50);
+        when(ddcMock.getDefaultHighBlockingZoneRefreshRate()).thenReturn(55);
         when(ddcMock.getLowDisplayBrightnessThresholds()).thenReturn(new int[]{25});
         when(ddcMock.getLowAmbientBrightnessThresholds()).thenReturn(new int[]{30});
         when(ddcMock.getHighDisplayBrightnessThresholds()).thenReturn(new int[]{210});
@@ -2363,6 +2402,74 @@
                 eq(lightSensorTwo), anyInt(), any(Handler.class));
     }
 
+    @Test
+    public void testAuthenticationPossibleSetsPhysicalRateRangesToMax() throws RemoteException {
+        DisplayModeDirector director =
+                createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0);
+        // don't call director.start(createMockSensorManager());
+        // DisplayObserver will reset mSupportedModesByDisplay
+        director.onBootCompleted();
+        ArgumentCaptor<IUdfpsRefreshRateRequestCallback> captor =
+                ArgumentCaptor.forClass(IUdfpsRefreshRateRequestCallback.class);
+        verify(mStatusBarMock).setUdfpsRefreshRateCallback(captor.capture());
+
+        captor.getValue().onAuthenticationPossible(DISPLAY_ID, true);
+
+        Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE);
+        assertThat(vote.refreshRateRanges.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+        assertThat(vote.refreshRateRanges.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+    }
+
+    @Test
+    public void testAuthenticationPossibleUnsetsVote() throws RemoteException {
+        DisplayModeDirector director =
+                createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0);
+        director.start(createMockSensorManager());
+        director.onBootCompleted();
+        ArgumentCaptor<IUdfpsRefreshRateRequestCallback> captor =
+                ArgumentCaptor.forClass(IUdfpsRefreshRateRequestCallback.class);
+        verify(mStatusBarMock).setUdfpsRefreshRateCallback(captor.capture());
+        captor.getValue().onAuthenticationPossible(DISPLAY_ID, true);
+        captor.getValue().onAuthenticationPossible(DISPLAY_ID, false);
+
+        Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE);
+        assertNull(vote);
+    }
+
+    @Test
+    public void testUdfpsRequestSetsPhysicalRateRangesToMax() throws RemoteException {
+        DisplayModeDirector director =
+                createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0);
+        // don't call director.start(createMockSensorManager());
+        // DisplayObserver will reset mSupportedModesByDisplay
+        director.onBootCompleted();
+        ArgumentCaptor<IUdfpsRefreshRateRequestCallback> captor =
+                ArgumentCaptor.forClass(IUdfpsRefreshRateRequestCallback.class);
+        verify(mStatusBarMock).setUdfpsRefreshRateCallback(captor.capture());
+
+        captor.getValue().onRequestEnabled(DISPLAY_ID);
+
+        Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS);
+        assertThat(vote.refreshRateRanges.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+        assertThat(vote.refreshRateRanges.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+    }
+
+    @Test
+    public void testUdfpsRequestUnsetsUnsetsVote() throws RemoteException {
+        DisplayModeDirector director =
+                createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0);
+        director.start(createMockSensorManager());
+        director.onBootCompleted();
+        ArgumentCaptor<IUdfpsRefreshRateRequestCallback> captor =
+                ArgumentCaptor.forClass(IUdfpsRefreshRateRequestCallback.class);
+        verify(mStatusBarMock).setUdfpsRefreshRateCallback(captor.capture());
+        captor.getValue().onRequestEnabled(DISPLAY_ID);
+        captor.getValue().onRequestDisabled(DISPLAY_ID);
+
+        Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS);
+        assertNull(vote);
+    }
+
     private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) {
         return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
     }
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index a860387..488c533 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -19,6 +19,7 @@
 import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.DEFAULT_DISPLAY_GROUP;
+import static android.view.Display.FLAG_REAR;
 import static android.view.Display.TYPE_EXTERNAL;
 import static android.view.Display.TYPE_INTERNAL;
 import static android.view.Display.TYPE_VIRTUAL;
@@ -30,6 +31,8 @@
 import static com.android.server.display.DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED;
 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED;
+import static com.android.server.display.layout.Layout.Display.POSITION_REAR;
+import static com.android.server.display.layout.Layout.Display.POSITION_UNKNOWN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -296,9 +299,11 @@
 
         Layout layout1 = new Layout();
         layout1.createDisplayLocked(info(device1).address, /* isDefault= */ true,
-                /* isEnabled= */ true, mIdProducer);
+                /* isEnabled= */ true, mIdProducer, /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         layout1.createDisplayLocked(info(device2).address, /* isDefault= */ false,
-                /* isEnabled= */ true, mIdProducer);
+                /* isEnabled= */ true, mIdProducer, /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout1);
         assertThat(layout1.size()).isEqualTo(2);
         final int logicalId2 = layout1.getByAddress(info(device2).address).getLogicalDisplayId();
@@ -331,17 +336,20 @@
         add(device3);
 
         Layout layout1 = new Layout();
-        layout1.createDisplayLocked(info(device1).address,
-                /* isDefault= */ true, /* isEnabled= */ true, mIdProducer);
+        layout1.createDisplayLocked(info(device1).address, /* isDefault= */ true,
+                /* isEnabled= */ true, mIdProducer, /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout1);
 
         final int layoutState2 = 2;
         Layout layout2 = new Layout();
-        layout2.createDisplayLocked(info(device2).address,
-                /* isDefault= */ false, /* isEnabled= */ true, mIdProducer);
+        layout2.createDisplayLocked(info(device2).address, /* isDefault= */ false,
+                /* isEnabled= */ true, mIdProducer, /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         // Device3 is the default display.
-        layout2.createDisplayLocked(info(device3).address,
-                /* isDefault= */ true, /* isEnabled= */ true, mIdProducer);
+        layout2.createDisplayLocked(info(device3).address, /* isDefault= */ true,
+                /* isEnabled= */ true, mIdProducer, /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         when(mDeviceStateToLayoutMapSpy.get(layoutState2)).thenReturn(layout2);
         assertThat(layout2.size()).isEqualTo(2);
         final int logicalId2 = layout2.getByAddress(info(device2).address).getLogicalDisplayId();
@@ -563,16 +571,22 @@
 
         Layout layout = new Layout();
         layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address,
-                true, true, mIdProducer);
+                true, true, mIdProducer,
+                /* brightnessThrottlingMapId= */ "concurrent",
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address,
-                false, true, mIdProducer);
+                false, true, mIdProducer,
+                /* brightnessThrottlingMapId= */ "concurrent",
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(layout);
 
         layout = new Layout();
         layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address,
-                false, false, mIdProducer);
+                false, false, mIdProducer, /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address,
-                true, true, mIdProducer);
+                true, true, mIdProducer, /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(layout);
         when(mDeviceStateToLayoutMapSpy.get(2)).thenReturn(layout);
 
@@ -599,6 +613,14 @@
         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
+        assertEquals(-1, mLogicalDisplayMapper.getDisplayLocked(device1)
+                .getLeadDisplayIdLocked());
+        assertEquals(0, mLogicalDisplayMapper.getDisplayLocked(device2)
+                .getLeadDisplayIdLocked());
+        assertEquals("concurrent", mLogicalDisplayMapper.getDisplayLocked(device1)
+                .getBrightnessThrottlingDataIdLocked());
+        assertEquals("concurrent", mLogicalDisplayMapper.getDisplayLocked(device2)
+                .getBrightnessThrottlingDataIdLocked());
 
         mLogicalDisplayMapper.setDeviceStateLocked(1, false);
         advanceTime(1000);
@@ -606,6 +628,12 @@
         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
+        assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+                mLogicalDisplayMapper.getDisplayLocked(device1)
+                        .getBrightnessThrottlingDataIdLocked());
+        assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+                mLogicalDisplayMapper.getDisplayLocked(device2)
+                        .getBrightnessThrottlingDataIdLocked());
 
         mLogicalDisplayMapper.setDeviceStateLocked(2, false);
         advanceTime(1000);
@@ -613,6 +641,12 @@
         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
+        assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+                mLogicalDisplayMapper.getDisplayLocked(device1)
+                        .getBrightnessThrottlingDataIdLocked());
+        assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+                mLogicalDisplayMapper.getDisplayLocked(device2)
+                        .getBrightnessThrottlingDataIdLocked());
     }
 
     @Test
@@ -633,17 +667,23 @@
                 displayAddressOne,
                 /* isDefault= */ true,
                 /* isEnabled= */ true,
-                mIdProducer);
+                mIdProducer,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         threeDevicesEnabledLayout.createDisplayLocked(
                 displayAddressTwo,
                 /* isDefault= */ false,
                 /* isEnabled= */ true,
-                mIdProducer);
+                mIdProducer,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         threeDevicesEnabledLayout.createDisplayLocked(
                 displayAddressThree,
                 /* isDefault= */ false,
                 /* isEnabled= */ true,
-                mIdProducer);
+                mIdProducer,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
 
         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT))
                 .thenReturn(threeDevicesEnabledLayout);
@@ -678,17 +718,23 @@
                 displayAddressOne,
                 /* isDefault= */ true,
                 /* isEnabled= */ true,
-                mIdProducer);
+                mIdProducer,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         oneDeviceEnabledLayout.createDisplayLocked(
                 displayAddressTwo,
                 /* isDefault= */ false,
                 /* isEnabled= */ false,
-                mIdProducer);
+                mIdProducer,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
         oneDeviceEnabledLayout.createDisplayLocked(
                 displayAddressThree,
                 /* isDefault= */ false,
                 /* isEnabled= */ false,
-                mIdProducer);
+                mIdProducer,
+                /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
 
         when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(oneDeviceEnabledLayout);
         when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(threeDevicesEnabledLayout);
@@ -754,6 +800,46 @@
 
         assertFalse(display2.isEnabledLocked());
     }
+    @Test
+    public void testDisplayFlagRear() {
+        DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
+                FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+        DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
+                FLAG_REAR);
+
+        Layout layout = new Layout();
+        layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address,
+                true, true, mIdProducer, /* brightnessThrottlingMapId= */ null,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address,
+                false, true, mIdProducer, /* brightnessThrottlingMapId= */ null,
+                POSITION_REAR, Display.DEFAULT_DISPLAY);
+        when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(layout);
+
+        when(mDeviceStateToLayoutMapSpy.size()).thenReturn(1);
+
+        LogicalDisplay display1 = add(device1);
+        assertEquals(info(display1).address, info(device1).address);
+        assertEquals(DEFAULT_DISPLAY, id(display1));
+
+        LogicalDisplay display2 = add(device2);
+        assertEquals(info(display2).address, info(device2).address);
+        // We can only have one default display
+        assertEquals(DEFAULT_DISPLAY, id(display1));
+
+        mLogicalDisplayMapper.setDeviceStateLocked(0, false);
+        advanceTime(1000);
+        mLogicalDisplayMapper.onBootCompleted();
+        advanceTime(1000);
+
+        assertTrue(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked());
+        assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
+
+        assertEquals(POSITION_UNKNOWN,
+                mLogicalDisplayMapper.getDisplayLocked(device1).getDevicePositionLocked());
+        assertEquals(POSITION_REAR,
+                mLogicalDisplayMapper.getDisplayLocked(device2).getDevicePositionLocked());
+    }
 
     /////////////////
     // Helper Methods
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
index 1d70fc6..d28050d 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
@@ -26,12 +26,15 @@
 
 import android.app.PropertyInvalidatedCache;
 import android.graphics.Point;
+import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.SurfaceControl;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.display.layout.Layout;
+
 import org.junit.Before;
 import org.junit.Test;
 
@@ -47,6 +50,7 @@
 
     private LogicalDisplay mLogicalDisplay;
     private DisplayDevice mDisplayDevice;
+    private DisplayDeviceRepository mDeviceRepo;
     private final DisplayDeviceInfo mDisplayDeviceInfo = new DisplayDeviceInfo();
 
     @Before
@@ -66,7 +70,7 @@
         // Disable binder caches in this process.
         PropertyInvalidatedCache.disableForTestMode();
 
-        DisplayDeviceRepository repo = new DisplayDeviceRepository(
+        mDeviceRepo = new DisplayDeviceRepository(
                 new DisplayManagerService.SyncRoot(),
                 new PersistentDataStore(new PersistentDataStore.Injector() {
                     @Override
@@ -82,8 +86,8 @@
                     @Override
                     public void finishWrite(OutputStream os, boolean success) {}
                 }));
-        repo.onDisplayDeviceEvent(mDisplayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
-        mLogicalDisplay.updateLocked(repo);
+        mDeviceRepo.onDisplayDeviceEvent(mDisplayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
+        mLogicalDisplay.updateLocked(mDeviceRepo);
     }
 
     @Test
@@ -137,4 +141,29 @@
         verify(t).setDisplayFlags(any(), eq(SurfaceControl.DISPLAY_RECEIVES_INPUT));
         reset(t);
     }
+
+    @Test
+    public void testRearDisplaysArePresentationDisplaysThatDestroyContentOnRemoval() {
+        // Assert that the display isn't a presentation display by default, with a default remove
+        // mode
+        assertEquals(0, mLogicalDisplay.getDisplayInfoLocked().flags);
+        assertEquals(Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY,
+                mLogicalDisplay.getDisplayInfoLocked().removeMode);
+
+        // Update position and test to see that it's been updated to a rear, presentation display
+        // that destroys content on removal
+        mLogicalDisplay.setDevicePositionLocked(Layout.Display.POSITION_REAR);
+        mLogicalDisplay.updateLocked(mDeviceRepo);
+        assertEquals(Display.FLAG_REAR | Display.FLAG_PRESENTATION,
+                mLogicalDisplay.getDisplayInfoLocked().flags);
+        assertEquals(Display.REMOVE_MODE_DESTROY_CONTENT,
+                mLogicalDisplay.getDisplayInfoLocked().removeMode);
+
+        // And then check the unsetting the position resets both
+        mLogicalDisplay.setDevicePositionLocked(Layout.Display.POSITION_UNKNOWN);
+        mLogicalDisplay.updateLocked(mDeviceRepo);
+        assertEquals(0, mLogicalDisplay.getDisplayInfoLocked().flags);
+        assertEquals(Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY,
+                mLogicalDisplay.getDisplayInfoLocked().removeMode);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index d4ab794..ebd63a0 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -47,7 +47,7 @@
 @RunWith(AndroidJUnit4.class)
 public final class DisplayBrightnessControllerTest {
     private static final int DISPLAY_ID = 1;
-    private static final float DEFAULT_BRIGHTNESS = 0.4f;
+    private static final float DEFAULT_BRIGHTNESS = 0.15f;
 
     @Mock
     private DisplayBrightnessStrategySelector mDisplayBrightnessStrategySelector;
@@ -70,11 +70,18 @@
                 return mDisplayBrightnessStrategySelector;
             }
         };
+        when(mBrightnessSetting.getBrightness()).thenReturn(Float.NaN);
         mDisplayBrightnessController = new DisplayBrightnessController(mContext, injector,
                 DISPLAY_ID, DEFAULT_BRIGHTNESS, mBrightnessSetting, mOnBrightnessChangeRunnable);
     }
 
     @Test
+    public void testIfFirstScreenBrightnessIsDefault() {
+        assertEquals(mDisplayBrightnessController.getCurrentBrightness(), DEFAULT_BRIGHTNESS,
+                0.0f);
+    }
+
+    @Test
     public void testUpdateBrightness() {
         DisplayPowerRequest displayPowerRequest = mock(DisplayPowerRequest.class);
         DisplayBrightnessStrategy displayBrightnessStrategy = mock(DisplayBrightnessStrategy.class);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index 5ca695b..c9612cd 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -49,8 +49,8 @@
 import android.os.UserManager;
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
-import android.provider.Settings;
 import android.provider.DeviceConfig;
+import android.provider.Settings;
 import android.security.KeyStore;
 
 import androidx.test.InstrumentationRegistry;
@@ -83,16 +83,15 @@
     protected static final int MANAGED_PROFILE_USER_ID = 12;
     protected static final int TURNED_OFF_PROFILE_USER_ID = 17;
     protected static final int SECONDARY_USER_ID = 20;
+    protected static final int TERTIARY_USER_ID = 21;
 
-    private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER_ID, null, null,
-            UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY
-                    | UserInfo.FLAG_MAIN);
-    private static final UserInfo SECONDARY_USER_INFO = new UserInfo(SECONDARY_USER_ID, null, null,
-            UserInfo.FLAG_INITIALIZED);
+    protected UserInfo mPrimaryUserInfo;
+    protected UserInfo mSecondaryUserInfo;
+    protected UserInfo mTertiaryUserInfo;
 
     private ArrayList<UserInfo> mPrimaryUserProfiles = new ArrayList<>();
 
-    LockSettingsService mService;
+    LockSettingsServiceTestable mService;
     LockSettingsInternal mLocalService;
 
     MockLockSettingsContext mContext;
@@ -117,6 +116,7 @@
     FingerprintManager mFingerprintManager;
     FaceManager mFaceManager;
     PackageManager mPackageManager;
+    LockSettingsServiceTestable.MockInjector mInjector;
     @Rule
     public FakeSettingsProviderRule mSettingsRule = FakeSettingsProvider.rule();
 
@@ -162,22 +162,61 @@
         mSpManager = new MockSyntheticPasswordManager(mContext, mStorage, mGateKeeperService,
                 mUserManager, mPasswordSlotManager);
         mAuthSecretService = mock(IAuthSecret.class);
-        mService = new LockSettingsServiceTestable(mContext, mStorage,
-                mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager,
-                mSpManager, mAuthSecretService, mGsiService, mRecoverableKeyStoreManager,
-                mUserManagerInternal, mDeviceStateCache);
+        mInjector =
+                new LockSettingsServiceTestable.MockInjector(
+                        mContext,
+                        mStorage,
+                        mKeyStore,
+                        mActivityManager,
+                        setUpStorageManagerMock(),
+                        mSpManager,
+                        mGsiService,
+                        mRecoverableKeyStoreManager,
+                        mUserManagerInternal,
+                        mDeviceStateCache);
+        mService =
+                new LockSettingsServiceTestable(mInjector, mGateKeeperService, mAuthSecretService);
         mService.mHasSecureLockScreen = true;
-        when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO);
-        mPrimaryUserProfiles.add(PRIMARY_USER_INFO);
+        mPrimaryUserInfo =
+                new UserInfo(
+                        PRIMARY_USER_ID,
+                        null,
+                        null,
+                        UserInfo.FLAG_INITIALIZED
+                                | UserInfo.FLAG_ADMIN
+                                | UserInfo.FLAG_PRIMARY
+                                | UserInfo.FLAG_MAIN
+                                | UserInfo.FLAG_FULL);
+        mSecondaryUserInfo =
+                new UserInfo(
+                        SECONDARY_USER_ID,
+                        null,
+                        null,
+                        UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_FULL);
+        mTertiaryUserInfo =
+                new UserInfo(
+                        TERTIARY_USER_ID,
+                        null,
+                        null,
+                        UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_FULL);
+
+        when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(mPrimaryUserInfo);
+        when(mUserManagerInternal.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(mPrimaryUserInfo);
+        mPrimaryUserProfiles.add(mPrimaryUserInfo);
         installChildProfile(MANAGED_PROFILE_USER_ID);
         installAndTurnOffChildProfile(TURNED_OFF_PROFILE_USER_ID);
         for (UserInfo profile : mPrimaryUserProfiles) {
             when(mUserManager.getProfiles(eq(profile.id))).thenReturn(mPrimaryUserProfiles);
         }
-        when(mUserManager.getUserInfo(eq(SECONDARY_USER_ID))).thenReturn(SECONDARY_USER_INFO);
+        when(mUserManager.getUserInfo(eq(SECONDARY_USER_ID))).thenReturn(mSecondaryUserInfo);
+        when(mUserManagerInternal.getUserInfo(eq(SECONDARY_USER_ID)))
+                .thenReturn(mSecondaryUserInfo);
+        when(mUserManager.getUserInfo(eq(TERTIARY_USER_ID))).thenReturn(mTertiaryUserInfo);
+        when(mUserManagerInternal.getUserInfo(eq(TERTIARY_USER_ID))).thenReturn(mTertiaryUserInfo);
 
         final ArrayList<UserInfo> allUsers = new ArrayList<>(mPrimaryUserProfiles);
-        allUsers.add(SECONDARY_USER_INFO);
+        allUsers.add(mSecondaryUserInfo);
+        allUsers.add(mTertiaryUserInfo);
         when(mUserManager.getUsers()).thenReturn(allUsers);
 
         when(mActivityManager.unlockUser2(anyInt(), any())).thenAnswer(
@@ -227,9 +266,10 @@
         userInfo.profileGroupId = PRIMARY_USER_ID;
         mPrimaryUserProfiles.add(userInfo);
         when(mUserManager.getUserInfo(eq(profileId))).thenReturn(userInfo);
-        when(mUserManager.getProfileParent(eq(profileId))).thenReturn(PRIMARY_USER_INFO);
+        when(mUserManager.getProfileParent(eq(profileId))).thenReturn(mPrimaryUserInfo);
         when(mUserManager.isUserRunning(eq(profileId))).thenReturn(true);
         when(mUserManager.isUserUnlocked(eq(profileId))).thenReturn(true);
+        when(mUserManagerInternal.getUserInfo(eq(profileId))).thenReturn(userInfo);
         // TODO(b/258213147): Remove
         when(mUserManagerInternal.isUserManaged(eq(profileId))).thenReturn(true);
         when(mDeviceStateCache.isUserOrganizationManaged(eq(profileId)))
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index f0f0632..9686c38 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -30,6 +30,7 @@
 import android.os.storage.IStorageManager;
 import android.security.KeyStore;
 import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.service.gatekeeper.IGateKeeperService;
 
 import com.android.internal.widget.LockscreenCredential;
 import com.android.server.ServiceThread;
@@ -40,7 +41,7 @@
 
 public class LockSettingsServiceTestable extends LockSettingsService {
 
-    private static class MockInjector extends LockSettingsService.Injector {
+    public static class MockInjector extends LockSettingsService.Injector {
 
         private LockSettingsStorage mLockSettingsStorage;
         private KeyStore mKeyStore;
@@ -52,6 +53,9 @@
         private UserManagerInternal mUserManagerInternal;
         private DeviceStateCache mDeviceStateCache;
 
+        public boolean mIsHeadlessSystemUserMode = false;
+        public boolean mIsMainUserPermanentAdmin = false;
+
         public MockInjector(Context context, LockSettingsStorage storage, KeyStore keyStore,
                 IActivityManager activityManager,
                 IStorageManager storageManager, SyntheticPasswordManager spManager,
@@ -140,19 +144,22 @@
             return mock(ManagedProfilePasswordCache.class);
         }
 
+        @Override
+        public boolean isHeadlessSystemUserMode() {
+            return mIsHeadlessSystemUserMode;
+        }
+
+        @Override
+        public boolean isMainUserPermanentAdmin() {
+            return mIsMainUserPermanentAdmin;
+        }
     }
 
-    public MockInjector mInjector;
-
-    protected LockSettingsServiceTestable(Context context,
-            LockSettingsStorage storage, FakeGateKeeperService gatekeeper, KeyStore keystore,
-            IStorageManager storageManager, IActivityManager mActivityManager,
-            SyntheticPasswordManager spManager, IAuthSecret authSecretService,
-            FakeGsiService gsiService, RecoverableKeyStoreManager recoverableKeyStoreManager,
-            UserManagerInternal userManagerInternal, DeviceStateCache deviceStateCache) {
-        super(new MockInjector(context, storage, keystore, mActivityManager,
-                storageManager, spManager, gsiService, recoverableKeyStoreManager,
-                userManagerInternal, deviceStateCache));
+    protected LockSettingsServiceTestable(
+            LockSettingsService.Injector injector,
+            IGateKeeperService gatekeeper,
+            IAuthSecret authSecretService) {
+        super(injector);
         mGateKeeperService = gatekeeper;
         mAuthSecretService = authSecretService;
     }
@@ -199,4 +206,10 @@
         UserInfo userInfo = mUserManager.getUserInfo(userId);
         return userInfo.isCloneProfile() || userInfo.isManagedProfile();
     }
+
+    void clearAuthSecret() {
+        synchronized (mHeadlessAuthSecretLock) {
+            mAuthSecret = null;
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java b/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java
index a40cb06..e8ef398 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java
@@ -119,6 +119,5 @@
 
     public void enableWeaver() {
         mWeaverService = new MockWeaverService();
-        initWeaverService();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 57593cf..62d8a76 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -16,6 +16,10 @@
 
 package com.android.server.locksettings;
 
+import static android.content.pm.UserInfo.FLAG_FULL;
+import static android.content.pm.UserInfo.FLAG_MAIN;
+import static android.content.pm.UserInfo.FLAG_PRIMARY;
+
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
@@ -27,9 +31,9 @@
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -247,6 +251,15 @@
 
     @Test
     public void testUnlockUserKeyIfUnsecuredPassesPrimaryUserAuthSecret() throws RemoteException {
+        initSpAndSetCredential(PRIMARY_USER_ID, newPassword(null));
+        reset(mAuthSecretService);
+        mLocalService.unlockUserKeyIfUnsecured(PRIMARY_USER_ID);
+        verify(mAuthSecretService).setPrimaryUserCredential(any(byte[].class));
+    }
+
+    @Test
+    public void testUnlockUserKeyIfUnsecuredPassesPrimaryUserAuthSecretIfPasswordIsCleared()
+            throws RemoteException {
         LockscreenCredential password = newPassword("password");
         initSpAndSetCredential(PRIMARY_USER_ID, password);
         mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
@@ -256,6 +269,56 @@
         verify(mAuthSecretService).setPrimaryUserCredential(any(byte[].class));
     }
 
+    private void setupHeadlessTest() {
+        mInjector.mIsHeadlessSystemUserMode = true;
+        mInjector.mIsMainUserPermanentAdmin = true;
+        mPrimaryUserInfo.flags &= ~(FLAG_FULL | FLAG_PRIMARY);
+        mSecondaryUserInfo.flags |= FLAG_MAIN;
+        mService.initializeSyntheticPassword(PRIMARY_USER_ID);
+        mService.initializeSyntheticPassword(SECONDARY_USER_ID);
+        mService.initializeSyntheticPassword(TERTIARY_USER_ID);
+        reset(mAuthSecretService);
+    }
+
+    @Test
+    public void testHeadlessSystemUserDoesNotPassAuthSecret() throws RemoteException {
+        setupHeadlessTest();
+        mLocalService.unlockUserKeyIfUnsecured(PRIMARY_USER_ID);
+        verify(mAuthSecretService, never()).setPrimaryUserCredential(any(byte[].class));
+    }
+
+    @Test
+    public void testHeadlessSecondaryUserPassesAuthSecret() throws RemoteException {
+        setupHeadlessTest();
+        mLocalService.unlockUserKeyIfUnsecured(SECONDARY_USER_ID);
+        verify(mAuthSecretService).setPrimaryUserCredential(any(byte[].class));
+    }
+
+    @Test
+    public void testHeadlessTertiaryUserPassesSameAuthSecret() throws RemoteException {
+        setupHeadlessTest();
+        mLocalService.unlockUserKeyIfUnsecured(SECONDARY_USER_ID);
+        var captor = ArgumentCaptor.forClass(byte[].class);
+        verify(mAuthSecretService).setPrimaryUserCredential(captor.capture());
+        var value = captor.getValue();
+        reset(mAuthSecretService);
+        mLocalService.unlockUserKeyIfUnsecured(TERTIARY_USER_ID);
+        verify(mAuthSecretService).setPrimaryUserCredential(eq(value));
+    }
+
+    @Test
+    public void testHeadlessTertiaryUserPassesSameAuthSecretAfterReset() throws RemoteException {
+        setupHeadlessTest();
+        mLocalService.unlockUserKeyIfUnsecured(SECONDARY_USER_ID);
+        var captor = ArgumentCaptor.forClass(byte[].class);
+        verify(mAuthSecretService).setPrimaryUserCredential(captor.capture());
+        var value = captor.getValue();
+        mService.clearAuthSecret();
+        reset(mAuthSecretService);
+        mLocalService.unlockUserKeyIfUnsecured(TERTIARY_USER_ID);
+        verify(mAuthSecretService).setPrimaryUserCredential(eq(value));
+    }
+
     @Test
     public void testTokenBasedResetPassword() throws RemoteException {
         LockscreenCredential password = newPassword("password");
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java
index 966c047..50f3a88 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java
@@ -8,6 +8,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.locksettings.LockSettingsStorage.PersistentData;
+
 import com.google.android.collect.Sets;
 
 import org.junit.Before;
@@ -29,7 +30,7 @@
     // sequentially, starting at slot 0.
     @Test
     public void testFrpWeaverSlotNotReused() {
-        final int userId = 10;
+        final int userId = SECONDARY_USER_ID;
         final int frpWeaverSlot = 0;
 
         setDeviceProvisioned(false);
@@ -45,7 +46,7 @@
     // it's here as a control for testFrpWeaverSlotNotReused().
     @Test
     public void testFrpWeaverSlotReused() {
-        final int userId = 10;
+        final int userId = SECONDARY_USER_ID;
         final int frpWeaverSlot = 0;
 
         setDeviceProvisioned(true);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index bb79fd8..32cb8c4 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -40,6 +40,8 @@
 import android.Manifest;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
+import android.app.RemoteLockscreenValidationResult;
+import android.app.StartLockscreenValidationRequest;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Binder;
@@ -60,12 +62,16 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
+import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.security.SecureBox;
+import com.android.server.locksettings.LockSettingsService;
 import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage;
 import com.android.server.locksettings.recoverablekeystore.storage.CleanupManager;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
+import com.android.server.locksettings.recoverablekeystore.storage.RemoteLockscreenValidationSessionStorage;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -81,10 +87,12 @@
 
 import java.io.File;
 import java.nio.charset.StandardCharsets;
+import java.security.PublicKey;
 import java.security.cert.CertPath;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Map;
 import java.util.Random;
 import java.util.concurrent.ScheduledExecutorService;
@@ -152,6 +160,10 @@
             .setKeyDerivationParams(KeyDerivationParams.createSha256Params(TEST_SALT))
             .setSecret(TEST_SECRET)
             .build();
+    private static final byte[] VALID_GUESS = getUtf8Bytes("password123");
+    private static final byte[] INVALID_GUESS = getUtf8Bytes("not_password");
+    private static final byte[] GUESS_LOCKOUT = getUtf8Bytes("need_to_wait");
+    private static final int TIMEOUT_MILLIS = 30 * 1000;
 
     @Mock private Context mMockContext;
     @Mock private RecoverySnapshotListenersStorage mMockListenersStorage;
@@ -160,14 +172,17 @@
     @Mock private ApplicationKeyStorage mApplicationKeyStorage;
     @Mock private CleanupManager mCleanupManager;
     @Mock private ScheduledExecutorService mExecutorService;
+    @Mock private LockSettingsService mLockSettingsService;
     @Spy private TestOnlyInsecureCertificateHelper mTestOnlyInsecureCertificateHelper;
 
+    private int mUserId;
     private RecoverableKeyStoreDb mRecoverableKeyStoreDb;
     private File mDatabaseFile;
     private RecoverableKeyStoreManager mRecoverableKeyStoreManager;
     private RecoverySessionStorage mRecoverySessionStorage;
     private RecoverySnapshotStorage mRecoverySnapshotStorage;
     private PlatformEncryptionKey mPlatformEncryptionKey;
+    private RemoteLockscreenValidationSessionStorage mRemoteLockscreenValidationSessionStorage;
 
     @Before
     public void setUp() throws Exception {
@@ -177,7 +192,9 @@
         mDatabaseFile = context.getDatabasePath(DATABASE_FILE_NAME);
         mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context);
 
+        mUserId = UserHandle.getCallingUserId();
         mRecoverySessionStorage = new RecoverySessionStorage();
+        mRemoteLockscreenValidationSessionStorage = new RemoteLockscreenValidationSessionStorage();
 
         when(mMockContext.getSystemService(anyString())).thenReturn(mKeyguardManager);
         when(mMockContext.getSystemServiceName(any())).thenReturn("test");
@@ -198,11 +215,22 @@
                 mPlatformKeyManager,
                 mApplicationKeyStorage,
                 mTestOnlyInsecureCertificateHelper,
-                mCleanupManager);
+                mCleanupManager,
+                mRemoteLockscreenValidationSessionStorage);
+        when(mLockSettingsService.verifyCredential(
+                any(LockscreenCredential.class), anyInt(), anyInt())).thenAnswer(args -> {
+                    LockscreenCredential argument = (LockscreenCredential) args.getArguments()[0];
+                    if (Arrays.equals(argument.getCredential(), VALID_GUESS)) {
+                        return VerifyCredentialResponse.OK;
+                    } else if (Arrays.equals(argument.getCredential(), INVALID_GUESS)) {
+                        return VerifyCredentialResponse.ERROR;
+                    } else return VerifyCredentialResponse.fromTimeout(TIMEOUT_MILLIS);
+                });
     }
 
     @After
     public void tearDown() {
+        mRemoteLockscreenValidationSessionStorage.finishSession(mUserId);
         mRecoverableKeyStoreDb.close();
         mDatabaseFile.delete();
     }
@@ -1269,6 +1297,175 @@
         verify(mExecutorService).schedule(any(Runnable.class), anyLong(), any());
     }
 
+    @Test
+    public void startRemoteLockscreenValidation_credentialsNotSet() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_NONE);
+        try {
+            mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+            fail("should have thrown");
+        } catch (IllegalStateException e) {
+            assertThat(e.getMessage()).contains("not set");
+        }
+        verify(mLockSettingsService).getCredentialType(mUserId);
+    }
+    @Test
+    public void startRemoteLockscreenValidation_checksPermission() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PIN);
+
+        mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+
+        // TODO(b/254335492): Check new system permission
+        verify(mMockContext, times(1))
+                .enforceCallingOrSelfPermission(
+                        eq(Manifest.permission.RECOVER_KEYSTORE), any());
+    }
+    @Test
+    public void startRemoteLockscreenValidation_returnsCredentailsType() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PIN);
+
+        StartLockscreenValidationRequest request =
+                mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+
+        int credetialsType = request.getLockscreenUiType();
+        assertThat(credetialsType).isEqualTo(KeyguardManager.PIN);
+        assertThat(request.getRemainingAttempts()).isEqualTo(5);
+        verify(mLockSettingsService).getCredentialType(anyInt());
+    }
+    @Test
+    public void startRemoteLockscreenValidation_returnsRemainingAttempts() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PATTERN);
+        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 3);
+
+        StartLockscreenValidationRequest request =
+                mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+
+        int credetialsType = request.getLockscreenUiType();
+        assertThat(credetialsType).isEqualTo(KeyguardManager.PATTERN);
+        assertThat(request.getRemainingAttempts()).isEqualTo(2);
+    }
+    @Test
+    public void startRemoteLockscreenValidation_password() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
+        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 7);
+
+        StartLockscreenValidationRequest request =
+                mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+
+        int credetialsType = request.getLockscreenUiType();
+        assertThat(request.getRemainingAttempts()).isEqualTo(0);
+        assertThat(credetialsType).isEqualTo(KeyguardManager.PASSWORD);
+    }
+    @Test
+    public void validateRemoteLockscreen_noActiveSession() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_NONE);
+        try {
+            mRecoverableKeyStoreManager.validateRemoteLockscreen(INVALID_GUESS,
+                    mLockSettingsService);
+            fail("should have thrown");
+        } catch (IllegalStateException e) {
+            assertThat(e.getMessage()).contains("session");
+        }
+    }
+    @Test
+    public void validateRemoteLockscreen_decryptionError() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
+        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 4);
+
+        mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+
+        try {
+            mRecoverableKeyStoreManager.validateRemoteLockscreen(
+                        new byte[] {1, 2, 3},
+                        mLockSettingsService);
+            fail("should have thrown");
+        } catch (IllegalStateException e) {
+            // Decryption error
+        }
+    }
+    @Test
+    public void validateRemoteLockscreen_zeroRemainingAttempts() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
+        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 5);
+        mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+
+        RemoteLockscreenValidationResult result =
+                    mRecoverableKeyStoreManager.validateRemoteLockscreen(
+                    encryptCredentialsForNewSession(VALID_GUESS),
+                        mLockSettingsService);
+
+        assertThat(result.getResultCode()).isEqualTo(
+                RemoteLockscreenValidationResult.RESULT_NO_REMAINING_ATTEMPTS);
+    }
+    @Test
+    public void validateRemoteLockscreen_guessValid() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
+        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 4);
+        mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+
+        RemoteLockscreenValidationResult result =
+                mRecoverableKeyStoreManager.validateRemoteLockscreen(
+                        encryptCredentialsForNewSession(VALID_GUESS),
+                        mLockSettingsService);
+
+        assertThat(result.getResultCode()).isEqualTo(
+                RemoteLockscreenValidationResult.RESULT_GUESS_VALID);
+        // Valid guess resets counter
+        assertThat(mRecoverableKeyStoreDb.getBadRemoteGuessCounter(mUserId)).isEqualTo(0);
+    }
+    @Test
+    public void validateRemoteLockscreen_timeout() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
+        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 4);
+
+        RemoteLockscreenValidationResult result =
+                mRecoverableKeyStoreManager.validateRemoteLockscreen(
+                        encryptCredentialsForNewSession(GUESS_LOCKOUT),
+                        mLockSettingsService);
+
+        assertThat(result.getResultCode()).isEqualTo(
+                RemoteLockscreenValidationResult.RESULT_LOCKOUT);
+        assertThat(result.getTimeoutMillis()).isEqualTo((long) TIMEOUT_MILLIS);
+        // Counter was not changed
+        assertThat(mRecoverableKeyStoreDb.getBadRemoteGuessCounter(mUserId)).isEqualTo(4);
+    }
+    @Test
+    public void validateRemoteLockscreen_guessInvalid() throws Exception {
+        when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
+        mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 4);
+        mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+
+        RemoteLockscreenValidationResult result =
+                mRecoverableKeyStoreManager.validateRemoteLockscreen(
+                        encryptCredentialsForNewSession(INVALID_GUESS),
+                        mLockSettingsService);
+
+        assertThat(result.getResultCode()).isEqualTo(
+                RemoteLockscreenValidationResult.RESULT_GUESS_INVALID);
+        assertThat(mRecoverableKeyStoreDb.getBadRemoteGuessCounter(mUserId)).isEqualTo(5);
+    }
+
+    private byte[] encryptCredentialsForNewSession(byte[] credentials) throws Exception {
+        StartLockscreenValidationRequest request =
+                mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
+        PublicKey publicKey = SecureBox.decodePublicKey(request.getSourcePublicKey());
+        return SecureBox.encrypt(
+              publicKey,
+              /* sharedSecret= */ null,
+              RecoverableKeyStoreManager.ENCRYPTED_REMOTE_CREDENTIALS_HEADER,
+              credentials);
+    }
+
     private static byte[] encryptedApplicationKey(
             SecretKey recoveryKey, byte[] applicationKey) throws Exception {
         return KeySyncUtils.encryptKeysWithRecoveryKey(recoveryKey, ImmutableMap.of(
diff --git a/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
new file mode 100644
index 0000000..52c6777
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/os/BugreportManagerServiceImplTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.server.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.BugreportManager.BugreportCallback;
+import android.os.IBinder;
+import android.os.IDumpstateListener;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.util.Pair;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileDescriptor;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class BugreportManagerServiceImplTest {
+
+    Context mContext;
+    BugreportManagerServiceImpl mService;
+    BugreportManagerServiceImpl.BugreportFileManager mBugreportFileManager;
+
+    int mCallingUid = 1234;
+    String mCallingPackage  = "test.package";
+
+    String mBugreportFile = "bugreport-file.zip";
+    String mBugreportFile2 = "bugreport-file2.zip";
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        ArraySet<String> mAllowlistedPackages = new ArraySet<>();
+        mAllowlistedPackages.add(mContext.getPackageName());
+        mService = new BugreportManagerServiceImpl(
+                new BugreportManagerServiceImpl.Injector(mContext, mAllowlistedPackages));
+        mBugreportFileManager = new BugreportManagerServiceImpl.BugreportFileManager();
+    }
+
+    @Test
+    public void testBugreportFileManagerFileExists() {
+        Pair<Integer, String> callingInfo = new Pair<>(mCallingUid, mCallingPackage);
+        mBugreportFileManager.addBugreportFileForCaller(
+                callingInfo, mBugreportFile);
+
+        assertThrows(IllegalArgumentException.class, () ->
+                mBugreportFileManager.ensureCallerPreviouslyGeneratedFile(
+                        callingInfo, "unknown-file.zip"));
+
+        // No exception should be thrown.
+        mBugreportFileManager.ensureCallerPreviouslyGeneratedFile(callingInfo, mBugreportFile);
+    }
+
+    @Test
+    public void testBugreportFileManagerMultipleFiles() {
+        Pair<Integer, String> callingInfo = new Pair<>(mCallingUid, mCallingPackage);
+        mBugreportFileManager.addBugreportFileForCaller(
+                callingInfo, mBugreportFile);
+        mBugreportFileManager.addBugreportFileForCaller(
+                callingInfo, mBugreportFile2);
+
+        // No exception should be thrown.
+        mBugreportFileManager.ensureCallerPreviouslyGeneratedFile(callingInfo, mBugreportFile);
+        mBugreportFileManager.ensureCallerPreviouslyGeneratedFile(callingInfo, mBugreportFile2);
+    }
+
+    @Test
+    public void testBugreportFileManagerFileDoesNotExist() {
+        Pair<Integer, String> callingInfo = new Pair<>(mCallingUid, mCallingPackage);
+        assertThrows(IllegalArgumentException.class,
+                () -> mBugreportFileManager.ensureCallerPreviouslyGeneratedFile(
+                        callingInfo, "test-file.zip"));
+    }
+
+    @Test
+    public void testRetrieveBugreportWithoutFilesForCaller() throws Exception {
+        CountDownLatch latch = new CountDownLatch(1);
+        Listener listener = new Listener(latch);
+        mService.retrieveBugreport(Binder.getCallingUid(), mContext.getPackageName(),
+                new FileDescriptor(), mBugreportFile, listener);
+        assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(listener.getErrorCode()).isEqualTo(
+                BugreportCallback.BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE);
+    }
+
+    private static class Listener implements IDumpstateListener {
+        CountDownLatch mLatch;
+        int mErrorCode;
+
+        Listener(CountDownLatch latch) {
+            mLatch = latch;
+        }
+
+        @Override
+        public IBinder asBinder() {
+            return null;
+        }
+
+        @Override
+        public void onProgress(int progress) throws RemoteException {
+        }
+
+        @Override
+        public void onError(int errorCode) throws RemoteException {
+            mErrorCode = errorCode;
+            mLatch.countDown();
+        }
+
+        @Override
+        public void onFinished(String bugreportFile) throws RemoteException {
+            mLatch.countDown();
+        }
+
+        @Override
+        public void onScreenshotTaken(boolean success) throws RemoteException {
+        }
+
+        @Override
+        public void onUiIntensiveBugreportDumpsFinished() throws RemoteException {
+        }
+
+        int getErrorCode() {
+            return mErrorCode;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/os/OWNERS b/services/tests/servicestests/src/com/android/server/os/OWNERS
new file mode 100644
index 0000000..feb8011
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/os/OWNERS
@@ -0,0 +1,2 @@
+# Component 153446
+include /platform/frameworks/native:/cmds/dumpstate/OWNERS
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/os/TEST_MAPPING b/services/tests/servicestests/src/com/android/server/os/TEST_MAPPING
new file mode 100644
index 0000000..9902446
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/os/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "BugreportManagerServiceImplTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.os."
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
new file mode 100644
index 0000000..4434a32
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.pm;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import static java.io.FileDescriptor.err;
+import static java.io.FileDescriptor.in;
+import static java.io.FileDescriptor.out;
+
+import android.app.PropertyInvalidatedCache;
+import android.content.Context;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArrayMap;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.server.LocalServices;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * Test class for {@link UserManagerServiceShellCommand}.
+ *
+ * runtest atest UserManagerServiceShellCommandTest
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class UserManagerServiceShellCommandTest {
+
+    private UserManagerServiceShellCommand mCommand;
+    private UserManagerService mUserManagerService;
+    private @Mock LockPatternUtils mLockPatternUtils;
+    private final Binder mBinder = new Binder();
+    private final ShellCallback mShellCallback = new ShellCallback();
+    private final ResultReceiver mResultReceiver = new ResultReceiver(
+            new Handler(Looper.getMainLooper()));
+    private ByteArrayOutputStream mOutStream;
+    private PrintWriter mWriter;
+
+    @Before
+    public void setUp() throws Exception {
+        mOutStream = new ByteArrayOutputStream();
+        mWriter = new PrintWriter(new PrintStream(mOutStream));
+        MockitoAnnotations.initMocks(this);
+
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        // Disable binder caches in this process.
+        PropertyInvalidatedCache.disableForTestMode();
+
+        LocalServices.removeServiceForTest(UserManagerInternal.class);
+        final Context context = InstrumentationRegistry.getTargetContext();
+
+        UserManagerService serviceInstance = new UserManagerService(context);
+        mUserManagerService = spy(serviceInstance);
+
+        ArrayMap<String, UserTypeDetails> userTypes = UserTypeFactory.getUserTypes();
+        UserSystemPackageInstaller userSystemPackageInstaller =
+                new UserSystemPackageInstaller(mUserManagerService, userTypes);
+        UserManagerServiceShellCommand cmd = new UserManagerServiceShellCommand(mUserManagerService,
+                userSystemPackageInstaller, mLockPatternUtils, context);
+        mCommand = spy(cmd);
+    }
+
+    @Test
+    public void testMainUser() {
+        when(mUserManagerService.getMainUserId()).thenReturn(12);
+        doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+        assertEquals(0, mCommand.exec(mBinder, in, out, err,
+                new String[]{"get-main-user"}, mShellCallback, mResultReceiver));
+
+        mWriter.flush();
+        assertEquals("Main user id: 12", mOutStream.toString().trim());
+    }
+
+    @Test
+    public void testMainUserNull() {
+        when(mUserManagerService.getMainUserId()).thenReturn(UserHandle.USER_NULL);
+        doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+        assertEquals(1, mCommand.exec(mBinder, in, out, err,
+                new String[]{"get-main-user"}, mShellCallback, mResultReceiver));
+        mWriter.flush();
+        assertEquals("Couldn't get main user.", mOutStream.toString().trim());
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 00aa520..4af0323 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -16,7 +16,6 @@
 
 package com.android.server.pm;
 
-import static android.os.UserManager.DISALLOW_BLUETOOTH;
 import static android.os.UserManager.DISALLOW_USER_SWITCH;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -41,7 +40,6 @@
 import com.android.server.LocalServices;
 
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -188,13 +186,11 @@
         while (mUserManagerService.userExists(incorrectId)) {
             incorrectId++;
         }
-        try {
-            mUserManagerService.setUserRestriction(DISALLOW_BLUETOOTH, true, incorrectId);
-            Assert.fail();
-        } catch (IllegalArgumentException e) {
-            //Exception is expected to be thrown if user ID does not exist.
-            // IllegalArgumentException thrown means this test is successful.
-        }
+        assertThat(mUserManagerService.hasUserRestriction(DISALLOW_USER_SWITCH, incorrectId))
+                .isFalse();
+        mUserManagerService.setUserRestriction(DISALLOW_USER_SWITCH, true, incorrectId);
+        assertThat(mUserManagerService.hasUserRestriction(DISALLOW_USER_SWITCH, incorrectId))
+                .isFalse();
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index c760efd..b4dd631 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -72,6 +72,7 @@
     private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // 30 years
 
     private static final int SWITCH_USER_TIMEOUT_SECONDS = 40; // 40 seconds
+    private static final int REMOVE_USER_TIMEOUT_SECONDS = 40; // 40 seconds
 
     // Packages which are used during tests.
     private static final String[] PACKAGES = new String[] {
@@ -302,7 +303,7 @@
     @MediumTest
     @Test
     public void testRemoveUserByHandle_ThrowsException() {
-        assertThrows(IllegalArgumentException.class, () -> removeUser(null));
+        assertThrows(IllegalArgumentException.class, () -> mUserManager.removeUser(null));
     }
 
     @MediumTest
@@ -1464,6 +1465,12 @@
     }
 
     private void runThenWaitForUserRemoval(Runnable runnable, int userIdToWaitUntilDeleted) {
+        if (!hasUser(userIdToWaitUntilDeleted)) {
+            runnable.run();
+            mUsersToRemove.remove(userIdToWaitUntilDeleted);
+            return;
+        }
+
         Function<Intent, Boolean> checker = intent -> {
             UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER, UserHandle.class);
             return userHandle != null && userHandle.getIdentifier() == userIdToWaitUntilDeleted;
@@ -1472,6 +1479,7 @@
         BlockingBroadcastReceiver blockingBroadcastReceiver = BlockingBroadcastReceiver.create(
                 mContext, Intent.ACTION_USER_REMOVED, checker);
 
+        blockingBroadcastReceiver.setTimeout(REMOVE_USER_TIMEOUT_SECONDS);
         blockingBroadcastReceiver.register();
 
         try (blockingBroadcastReceiver) {
diff --git a/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
index 7fac9b6..7125796 100644
--- a/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
@@ -19,6 +19,9 @@
 
 import static android.content.Context.SENSOR_SERVICE;
 
+import static com.android.server.devicestate.DeviceStateProvider.SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED;
+import static com.android.server.devicestate.DeviceStateProvider.SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_CRITICAL;
+import static com.android.server.devicestate.DeviceStateProvider.SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_NORMAL;
 import static com.android.server.policy.DeviceStateProviderImpl.DEFAULT_DEVICE_STATE;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -124,7 +127,8 @@
         DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
         provider.setListener(listener);
 
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         assertArrayEquals(new DeviceState[]{DEFAULT_DEVICE_STATE},
                 mDeviceStateArrayCaptor.getValue());
 
@@ -151,7 +155,8 @@
         DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
         provider.setListener(listener);
 
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         final DeviceState[] expectedStates = new DeviceState[]{
                 new DeviceState(1, "", 0 /* flags */),
                 new DeviceState(2, "", 0 /* flags */) };
@@ -183,7 +188,8 @@
         DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
         provider.setListener(listener);
 
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         final DeviceState[] expectedStates = new DeviceState[]{
                 new DeviceState(1, "", DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS),
                 new DeviceState(2, "", 0 /* flags */) };
@@ -212,7 +218,8 @@
         DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
         provider.setListener(listener);
 
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         final DeviceState[] expectedStates = new DeviceState[]{
                 new DeviceState(1, "", 0 /* flags */),
                 new DeviceState(2, "", 0 /* flags */) };
@@ -247,7 +254,8 @@
         DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
         provider.setListener(listener);
 
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         final DeviceState[] expectedStates = new DeviceState[]{
                 new DeviceState(1, "", 0 /* flags */),
                 new DeviceState(2, "CLOSED", 0 /* flags */) };
@@ -265,7 +273,8 @@
         Mockito.clearInvocations(listener);
 
         provider.notifyLidSwitchChanged(1, true /* lidOpen */);
-        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         verify(listener).onStateChanged(mIntegerCaptor.capture());
         assertEquals(1, mIntegerCaptor.getValue().intValue());
     }
@@ -336,7 +345,8 @@
         DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
         provider.setListener(listener);
 
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         assertArrayEquals(
                 new DeviceState[]{
                         new DeviceState(1, "CLOSED", 0 /* flags */),
@@ -358,7 +368,8 @@
 
         provider.onSensorChanged(event0);
 
-        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         verify(listener).onStateChanged(mIntegerCaptor.capture());
         assertEquals(3, mIntegerCaptor.getValue().intValue());
 
@@ -370,7 +381,8 @@
 
         provider.onSensorChanged(event1);
 
-        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         verify(listener).onStateChanged(mIntegerCaptor.capture());
         assertEquals(2, mIntegerCaptor.getValue().intValue());
 
@@ -382,7 +394,8 @@
 
         provider.onSensorChanged(event2);
 
-        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         verify(listener).onStateChanged(mIntegerCaptor.capture());
         assertEquals(1, mIntegerCaptor.getValue().intValue());
     }
@@ -397,7 +410,8 @@
         DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
         provider.setListener(listener);
 
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         assertArrayEquals(
                 new DeviceState[]{
                         new DeviceState(1, "CLOSED", 0 /* flags */),
@@ -410,12 +424,14 @@
         Mockito.clearInvocations(listener);
 
         provider.onThermalStatusChanged(PowerManager.THERMAL_STATUS_MODERATE);
-        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         Mockito.clearInvocations(listener);
 
         // The THERMAL_TEST state should be disabled.
         provider.onThermalStatusChanged(PowerManager.THERMAL_STATUS_CRITICAL);
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_CRITICAL));
         assertArrayEquals(
                 new DeviceState[]{
                         new DeviceState(1, "CLOSED", 0 /* flags */),
@@ -426,7 +442,8 @@
 
         // The THERMAL_TEST state should be re-enabled.
         provider.onThermalStatusChanged(PowerManager.THERMAL_STATUS_LIGHT);
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_THERMAL_NORMAL));
         assertArrayEquals(
                 new DeviceState[]{
                         new DeviceState(1, "CLOSED", 0 /* flags */),
@@ -468,7 +485,8 @@
 
         provider.onSensorChanged(event2);
 
-        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         verify(listener, never()).onStateChanged(mIntegerCaptor.capture());
     }
 
@@ -513,7 +531,8 @@
         DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
         provider.setListener(listener);
 
-        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+        verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture(),
+                eq(SUPPORTED_DEVICE_STATES_CHANGED_INITIALIZED));
         assertArrayEquals(
                 new DeviceState[]{
                         new DeviceState(1, "CLOSED", 0 /* flags */),
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
index cff3bf8..b27ba88 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
@@ -38,7 +38,6 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -51,8 +50,8 @@
 
     private static final long POLL_INTERVAL_MS = 500;
     private static final long USER_REMOVE_TIMEOUT_MS = 5_000;
-    private static final long STOP_USER_TIMEOUT_MS = 10_000;
-    private static final long USER_UIDS_REMOVE_TIMEOUT_MS = 15_000;
+    private static final long STOP_USER_TIMEOUT_MS = 20_000;
+    private static final long USER_UIDS_REMOVE_TIMEOUT_MS = 20_000;
     private static final long BATTERYSTATS_POLLING_TIMEOUT_MS = 5_000;
 
     private static final String CPU_DATA_TAG = "cpu";
@@ -79,26 +78,29 @@
         batteryOnScreenOff();
     }
 
-    @Ignore("b/244349060")
     @Test
     public void testNoCpuDataForRemovedUser() throws Exception {
         mIam.startUserInBackground(mTestUserId);
         waitUntilTrue("No uids for started user " + mTestUserId,
                 () -> getNumberOfUidsInBatteryStats() > 0, BATTERYSTATS_POLLING_TIMEOUT_MS);
 
+        final boolean[] userStopped = new boolean[1];
         CountDownLatch stopUserLatch = new CountDownLatch(1);
         mIam.stopUser(mTestUserId, true, new IStopUserCallback.Stub() {
             @Override
             public void userStopped(int userId) throws RemoteException {
+                userStopped[0] = true;
                 stopUserLatch.countDown();
             }
 
             @Override
             public void userStopAborted(int userId) throws RemoteException {
+                stopUserLatch.countDown();
             }
         });
-        assertTrue("User " + mTestUserId + " could not be stopped",
+        assertTrue("User " + mTestUserId + " could not be stopped in " + STOP_USER_TIMEOUT_MS,
                 stopUserLatch.await(STOP_USER_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue("User " + mTestUserId + " could not be stopped", userStopped[0]);
 
         mUm.removeUser(mTestUserId);
         waitUntilTrue("Unable to remove user " + mTestUserId, () -> {
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index fc830a9..9facb4b 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -516,7 +516,7 @@
 
         long vibrationId = 1;
         VibrationEffect fallback = VibrationEffect.createOneShot(10, 100);
-        Vibration vibration = createVibration(vibrationId, CombinedVibration.createParallel(
+        HalVibration vibration = createVibration(vibrationId, CombinedVibration.createParallel(
                 VibrationEffect.get(VibrationEffect.EFFECT_CLICK)));
         vibration.addFallback(VibrationEffect.EFFECT_CLICK, fallback);
         startThreadAndDispatcher(vibration);
@@ -683,7 +683,7 @@
                 .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_TICK))
                 .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
                 .compose();
-        Vibration vib = createVibration(vibrationId, CombinedVibration.createParallel(effect));
+        HalVibration vib = createVibration(vibrationId, CombinedVibration.createParallel(effect));
         vib.addFallback(VibrationEffect.EFFECT_TICK, fallback);
         startThreadAndDispatcher(vib);
         waitForCompletion();
@@ -1592,7 +1592,7 @@
         return startThreadAndDispatcher(createVibration(vibrationId, effect));
     }
 
-    private VibrationStepConductor startThreadAndDispatcher(Vibration vib) {
+    private VibrationStepConductor startThreadAndDispatcher(HalVibration vib) {
         mControllers = createVibratorControllers();
         VibrationStepConductor conductor = new VibrationStepConductor(vib, mVibrationSettings,
                 mEffectAdapter, mControllers, mManagerHooks);
@@ -1624,8 +1624,8 @@
         mTestLooper.dispatchAll();  // Flush callbacks
     }
 
-    private Vibration createVibration(long id, CombinedVibration effect) {
-        return new Vibration(mVibrationToken, (int) id, effect, ATTRS, UID, DISPLAY_ID,
+    private HalVibration createVibration(long id, CombinedVibration effect) {
+        return new HalVibration(mVibrationToken, (int) id, effect, ATTRS, UID, DISPLAY_ID,
                 PACKAGE_NAME, "reason");
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index c83afb7..f040da8 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -2034,7 +2034,7 @@
 
     private void vibrateAndWaitUntilFinished(VibratorManagerService service,
             CombinedVibration effect, VibrationAttributes attrs) throws InterruptedException {
-        Vibration vib =
+        HalVibration vib =
                 service.vibrateInternal(UID, Display.DEFAULT_DISPLAY, PACKAGE_NAME, effect, attrs,
                         "some reason", service);
         if (vib != null) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 08c2c6e..9742384 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -1870,6 +1870,65 @@
         verifyVibrate(1);
     }
 
+    @Test
+    public void testStartFlashNotificationEvent_receiveBeepyNotification() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyBeepUnlooped();
+        verifyNeverVibrate();
+        verify(mAccessibilityService).startFlashNotificationEvent(any(), anyInt(),
+                eq(r.getSbn().getPackageName()));
+        assertTrue(r.isInterruptive());
+        assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+    }
+
+    @Test
+    public void testStartFlashNotificationEvent_receiveBuzzyNotification() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyNeverBeep();
+        verifyVibrate();
+        verify(mAccessibilityService).startFlashNotificationEvent(any(), anyInt(),
+                eq(r.getSbn().getPackageName()));
+        assertTrue(r.isInterruptive());
+        assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+    }
+
+    @Test
+    public void testStartFlashNotificationEvent_receiveBuzzyBeepyNotification() throws Exception {
+        NotificationRecord r = getBuzzyBeepyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyBeepUnlooped();
+        verifyDelayedVibrate(r.getVibration());
+        verify(mAccessibilityService).startFlashNotificationEvent(any(), anyInt(),
+                eq(r.getSbn().getPackageName()));
+        assertTrue(r.isInterruptive());
+        assertNotEquals(-1, r.getLastAudiblyAlertedMs());
+    }
+
+    @Test
+    public void testStartFlashNotificationEvent_receiveBuzzyBeepyNotification_ringerModeSilent()
+            throws Exception {
+        NotificationRecord r = getBuzzyBeepyNotification();
+        when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
+        when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyNeverBeep();
+        verifyNeverVibrate();
+        verify(mAccessibilityService).startFlashNotificationEvent(any(), anyInt(),
+                eq(r.getSbn().getPackageName()));
+        assertFalse(r.isInterruptive());
+        assertEquals(-1, r.getLastAudiblyAlertedMs());
+    }
+
     static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
         private final int mRepeatIndex;
 
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 20e8cd4..38c2f40 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -19,7 +19,6 @@
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.Notification.EXTRA_ALLOW_DURING_SETUP;
 import static android.app.Notification.FLAG_AUTO_CANCEL;
 import static android.app.Notification.FLAG_BUBBLE;
 import static android.app.Notification.FLAG_CAN_COLORIZE;
@@ -79,6 +78,7 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNotSame;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
@@ -218,7 +218,6 @@
 import com.android.server.notification.NotificationManagerService.NotificationListeners;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.UserManagerInternal;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.policy.PermissionPolicyInternal;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.uri.UriGrantsManagerInternal;
@@ -307,9 +306,6 @@
     ActivityManager mActivityManager;
     @Mock
     TelecomManager mTelecomManager;
-
-    @Mock
-    PermissionManagerServiceInternal mPermissionInternal;
     @Mock
     Resources mResources;
     @Mock
@@ -320,6 +316,8 @@
     private Looper mMainLooper;
     @Mock
     private NotificationManager mMockNm;
+    @Mock
+    private DevicePolicyManagerInternal mDevicePolicyManager;
 
     @Mock
     IIntentSender pi1;
@@ -519,11 +517,11 @@
         mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient,
                 mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr,
                 mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAtm,
-                mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
+                mAppUsageStats, mDevicePolicyManager, mUgm, mUgmInternal,
                 mAppOpsManager, mAppOpsService, mUm, mHistoryManager, mStatsManager,
                 mock(TelephonyManager.class),
                 mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class),
-                mTelecomManager, mLogger, mPermissionInternal);
+                mTelecomManager, mLogger);
         // Return first true for RoleObserver main-thread check
         when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
@@ -1651,6 +1649,46 @@
     }
 
     @Test
+    public void testEnqueueNotificationWithTag_nullAction_fixed() throws Exception {
+        Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .addAction(new Notification.Action.Builder(null, "one", null).build())
+                .addAction(new Notification.Action.Builder(null, "two", null).build())
+                .addAction(new Notification.Action.Builder(null, "three", null).build())
+                .build();
+        n.actions[1] = null;
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0);
+        waitForIdle();
+
+        StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG);
+        assertThat(posted).hasLength(1);
+        assertThat(posted[0].getNotification().actions).hasLength(2);
+        assertThat(posted[0].getNotification().actions[0].title.toString()).isEqualTo("one");
+        assertThat(posted[0].getNotification().actions[1].title.toString()).isEqualTo("three");
+    }
+
+    @Test
+    public void testEnqueueNotificationWithTag_allNullActions_fixed() throws Exception {
+        Notification n = new Notification.Builder(mContext, mTestNotificationChannel.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .addAction(new Notification.Action.Builder(null, "one", null).build())
+                .addAction(new Notification.Action.Builder(null, "two", null).build())
+                .build();
+        n.actions[0] = null;
+        n.actions[1] = null;
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, n, 0);
+        waitForIdle();
+
+        StatusBarNotification[] posted = mBinderService.getActiveNotifications(PKG);
+        assertThat(posted).hasLength(1);
+        assertThat(posted[0].getNotification().actions).isNull();
+    }
+
+    @Test
     public void testCancelNonexistentNotification() throws Exception {
         mBinderService.cancelNotificationWithTag(PKG, PKG,
                 "testCancelNonexistentNotification", 0, 0);
@@ -4173,35 +4211,8 @@
     }
 
     @Test
-    public void testNoNotificationDuringSetupPermission() throws Exception {
-        when(mPermissionInternal.checkPermission(any(), any(), anyInt()))
-                .thenReturn(PERMISSION_DENIED);
-        Bundle extras = new Bundle();
-        extras.putBoolean(EXTRA_ALLOW_DURING_SETUP, true);
-        Notification.Builder nb = new Notification.Builder(mContext,
-                mTestNotificationChannel.getId())
-                .setContentTitle("foo")
-                .addExtras(extras)
-                .setSmallIcon(android.R.drawable.sym_def_app_icon);
-        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
-                "testNoNotificationDuringSetupPermission", mUid, 0,
-                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
-        NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
-
-        mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
-                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
-        waitForIdle();
-
-        NotificationRecord posted = mService.findNotificationLocked(
-                PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());
-
-        assertFalse(posted.getNotification().extras.containsKey(EXTRA_ALLOW_DURING_SETUP));
-    }
-
-    @Test
     public void testNoFakeColorizedPermission() throws Exception {
-        when(mPermissionInternal.checkPermission(any(), any(), anyInt()))
-                .thenReturn(PERMISSION_DENIED);
+        when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
         Notification.Builder nb = new Notification.Builder(mContext,
                 mTestNotificationChannel.getId())
                 .setContentTitle("foo")
@@ -4226,7 +4237,7 @@
     @Test
     public void testMediaStyleRemote_hasPermission() throws RemoteException {
         String deviceName = "device";
-        when(mPermissionInternal.checkPermission(
+        when(mPackageManager.checkPermission(
                 eq(android.Manifest.permission.MEDIA_CONTENT_CONTROL), any(), anyInt()))
                 .thenReturn(PERMISSION_GRANTED);
         Notification.MediaStyle style = new Notification.MediaStyle();
@@ -4255,7 +4266,7 @@
     @Test
     public void testMediaStyleRemote_noPermission() throws RemoteException {
         String deviceName = "device";
-        when(mPermissionInternal.checkPermission(
+        when(mPackageManager.checkPermission(
                 eq(android.Manifest.permission.MEDIA_CONTENT_CONTROL), any(), anyInt()))
                 .thenReturn(PERMISSION_DENIED);
         Notification.MediaStyle style = new Notification.MediaStyle();
@@ -4283,7 +4294,7 @@
     @Test
     public void testSubstituteAppName_hasPermission() throws RemoteException {
         String subName = "Substitute Name";
-        when(mPermissionInternal.checkPermission(
+        when(mPackageManager.checkPermission(
                 eq(android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME), any(), anyInt()))
                 .thenReturn(PERMISSION_GRANTED);
         Bundle extras = new Bundle();
@@ -4310,7 +4321,7 @@
 
     @Test
     public void testSubstituteAppName_noPermission() throws RemoteException {
-        when(mPermissionInternal.checkPermission(
+        when(mPackageManager.checkPermission(
                 eq(android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME), any(), anyInt()))
                 .thenReturn(PERMISSION_DENIED);
         Bundle extras = new Bundle();
@@ -5820,7 +5831,7 @@
 
     @Test
     public void testCanUseManagedServices_hasPermission() throws Exception {
-        when(mPermissionInternal.checkPermission("perm", "pkg", 0))
+        when(mPackageManager.checkPermission("perm", "pkg", 0))
                 .thenReturn(PackageManager.PERMISSION_GRANTED);
 
         assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
@@ -5828,7 +5839,7 @@
 
     @Test
     public void testCanUseManagedServices_noPermission() throws Exception {
-        when(mPermissionInternal.checkPermission("perm", "pkg", 0))
+        when(mPackageManager.checkPermission("perm", "pkg", 0))
                 .thenReturn(PackageManager.PERMISSION_DENIED);
 
         assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
@@ -6783,7 +6794,7 @@
 
     private void setIfPackageHasPermissionToAvoidToastRateLimiting(
             String pkg, boolean hasPermission) throws Exception {
-        when(mPermissionInternal.checkPermission(android.Manifest.permission.UNLIMITED_TOASTS,
+        when(mPackageManager.checkPermission(android.Manifest.permission.UNLIMITED_TOASTS,
                 pkg, UserHandle.getUserId(mUid)))
                 .thenReturn(hasPermission ? PERMISSION_GRANTED : PERMISSION_DENIED);
     }
@@ -10075,4 +10086,281 @@
         mInternalService.sendReviewPermissionsNotification();
         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
     }
+
+    @Test
+    public void fixSystemNotification_withOnGoingFlag_shouldBeNonDismissible()
+            throws Exception {
+        // Given: a notification from an app on the system partition has the flag
+        // FLAG_ONGOING_EVENT set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(true)
+                .build();
+
+        final ApplicationInfo systemAppInfo = new ApplicationInfo();
+        systemAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+                .thenReturn(systemAppInfo);
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should be set
+        assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixMediaNotification_withOnGoingFlag_shouldBeNonDismissible()
+            throws Exception {
+        // Given: a media notification has the flag FLAG_ONGOING_EVENT set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(true)
+                .setStyle(new Notification.MediaStyle()
+                        .setMediaSession(mock(MediaSession.Token.class)))
+                .build();
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should be set
+        assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixNonExemptNotification_withOnGoingFlag_shouldBeDismissible() throws Exception {
+        // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(true)
+                .build();
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should not be set
+        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixNonExemptNotification_withNoDismissFlag_shouldBeDismissible()
+            throws Exception {
+        // Given: a non-exempt notification has the flag FLAG_NO_DISMISS set (even though this is
+        // not allowed)
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .build();
+        n.flags |= Notification.FLAG_NO_DISMISS;
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should be cleared
+        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixSystemNotification_withoutOnGoingFlag_shouldBeDismissible() throws Exception {
+        // Given: a notification from an app on the system partition doesn't have the flag
+        // FLAG_ONGOING_EVENT set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(false)
+                .build();
+
+        final ApplicationInfo systemAppInfo = new ApplicationInfo();
+        systemAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+                .thenReturn(systemAppInfo);
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should not be set
+        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixSystemNotification_withoutOnGoingFlag_withNoDismissFlag_shouldBeDismissible()
+            throws Exception {
+        // Given: a notification from an app on the system partition doesn't have the flag
+        // FLAG_ONGOING_EVENT set, but has the flag FLAG_NO_DISMISS set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(false)
+                .build();
+        n.flags |= Notification.FLAG_NO_DISMISS;
+
+        final ApplicationInfo systemAppInfo = new ApplicationInfo();
+        systemAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+                .thenReturn(systemAppInfo);
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should be cleared
+        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixMediaNotification_withoutOnGoingFlag_shouldBeDismissible() throws Exception {
+        // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(false)
+                .setStyle(new Notification.MediaStyle()
+                        .setMediaSession(mock(MediaSession.Token.class)))
+                .build();
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should not be set
+        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixMediaNotification_withoutOnGoingFlag_withNoDismissFlag_shouldBeDismissible()
+            throws Exception {
+        // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set,
+        // but has the flag FLAG_NO_DISMISS set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(false)
+                .setStyle(new Notification.MediaStyle()
+                        .setMediaSession(mock(MediaSession.Token.class)))
+                .build();
+        n.flags |= Notification.FLAG_NO_DISMISS;
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should be cleared
+        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixNonExempt_Notification_withoutOnGoingFlag_shouldBeDismissible()
+            throws Exception {
+        // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        mService.setOngoingDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(false)
+                .build();
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should not be set
+        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixOrganizationAdminNotification_withOnGoingFlag_shouldBeNonDismissible()
+            throws Exception {
+        when(mDevicePolicyManager.isActiveDeviceOwner(mUid)).thenReturn(true);
+        // Given: a notification has the flag FLAG_ONGOING_EVENT set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        mService.setSystemExemptFromDismissal(false);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(true)
+                .build();
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should be set
+        assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
+
+    @Test
+    public void fixSystemExemptAppOpNotification_withFlag_shouldBeNonDismissible()
+            throws Exception {
+        when(mAppOpsManager.checkOpNoThrow(
+                AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
+                PKG)).thenReturn(AppOpsManager.MODE_ALLOWED);
+        // Given: a notification has the flag FLAG_ONGOING_EVENT set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        mService.setSystemExemptFromDismissal(true);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(true)
+                .build();
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should be set
+        assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+        mService.setSystemExemptFromDismissal(false);
+    }
+
+    @Test
+    public void fixSystemExemptAppOpNotification_withoutFlag_shouldBeNonDismissible()
+            throws Exception {
+        when(mAppOpsManager.checkOpNoThrow(
+                AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
+                PKG)).thenReturn(AppOpsManager.MODE_ALLOWED);
+        // Given: a notification has the flag FLAG_ONGOING_EVENT set
+        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
+        mService.setOngoingDismissal(true);
+        mService.setSystemExemptFromDismissal(false);
+        Notification n = new Notification.Builder(mContext, "test")
+                .setOngoing(true)
+                .build();
+
+        // When: fix the notification with NotificationManagerService
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        // Then: the notification's flag FLAG_NO_DISMISS should not be set
+        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+
+        // Avoid affecting other tests
+        mService.setOngoingDismissal(false);
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java
index 0169a7d..beab107 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerTest.java
@@ -130,4 +130,29 @@
         p.r.getSbn().getNotification().flags |= FLAG_FOREGROUND_SERVICE;
         assertTrue(NotificationRecordLogger.isForegroundService(p.r));
     }
+
+
+    @Test
+    public void testIsNonDismissible_hasFlagNoDismiss_shouldReturnTrue() {
+        // Given: a notification pair's notification has flag FLAG_NO_DISMISS
+        NotificationRecordLogger.NotificationRecordPair p = getNotificationRecordPair(
+                0, null);
+        p.r.getNotification().flags |= Notification.FLAG_NO_DISMISS;
+
+        // When: check the value of isNonDismissible()
+        // Then: should return true
+        assertTrue(NotificationRecordLogger.isNonDismissible(p.r));
+    }
+
+    @Test
+    public void testIsNonDismissible_noFlagNoDismiss_shouldReturnFalse() {
+        // Given: a notification pair's notification doesn't have flag FLAG_NO_DISMISS
+        NotificationRecordLogger.NotificationRecordPair p = getNotificationRecordPair(
+                0, null);
+        p.r.getNotification().flags &= ~Notification.FLAG_NO_DISMISS;
+
+        // When: check the value of isNonDismissible()
+        // Then: should return false
+        assertFalse(NotificationRecordLogger.isNonDismissible(p.r));
+    }
 }
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 3a01c2d..98c156e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -72,7 +72,6 @@
 import com.android.server.lights.LightsManager;
 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
 import com.android.server.notification.NotificationManagerService.NotificationListeners;
-import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.utils.quota.MultiRateLimiter;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -169,9 +168,8 @@
                     mock(StatsManager.class), mock(TelephonyManager.class),
                     mock(ActivityManagerInternal.class),
                     mock(MultiRateLimiter.class), mock(PermissionHelper.class),
-                    mock(UsageStatsManagerInternal.class), mock(TelecomManager.class),
-                    mock(NotificationChannelLogger.class),
-                    mock(PermissionManagerServiceInternal.class));
+                    mock(UsageStatsManagerInternal.class), mock (TelecomManager.class),
+                    mock(NotificationChannelLogger.class));
         } catch (SecurityException e) {
             if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
                 throw e;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
index 61a6985..1306d57 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
@@ -36,6 +36,8 @@
     int countLogSmartSuggestionsVisible = 0;
     Set<Integer> mChannelToastsSent = new HashSet<>();
 
+    public boolean ONGOING_DISMISSAL = false;
+
     String stringArrayResourceValue;
     @Nullable
     NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
@@ -159,4 +161,13 @@
             return mGetStrongAuthForUserReturnValue;
         }
     }
+
+    // Mock SystemProperties
+    protected void setOngoingDismissal(boolean ongoingDismissal) {
+        ONGOING_DISMISSAL = ongoingDismissal;
+    }
+
+    protected void setSystemExemptFromDismissal(boolean isOn) {
+        mSystemExemptFromDismissal = isOn;
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 49edde5..12f124e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -525,6 +525,13 @@
 
     @Test
     public void testZenUpgradeNotification() {
+        /**
+         * Commit a485ec65b5ba947d69158ad90905abf3310655cf disabled DND status change
+         * notification on watches. So, assume that the device is not watch.
+         */
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)).thenReturn(false);
+
         // shows zen upgrade notification if stored settings says to shows,
         // zen has not been updated, boot is completed
         // and we're setting zen mode on
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 e663245..e5fe32a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -48,7 +48,7 @@
 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
 import static android.os.Process.NOBODY_UID;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -3177,18 +3177,18 @@
     public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
 
-        mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_IME).setWindowContainer(
+        mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer(
                 mImeWindow, null, null);
         mImeWindow.getControllableInsetProvider().setServerVisible(true);
 
-        InsetsSource imeSource = new InsetsSource(ITYPE_IME, ime());
+        InsetsSource imeSource = new InsetsSource(ID_IME, ime());
         app.mAboveInsetsState.addSource(imeSource);
         mDisplayContent.setImeLayeringTarget(app);
         mDisplayContent.updateImeInputAndControlTarget(app);
 
         InsetsState state = app.getInsetsState();
-        assertFalse(state.getSource(imeSource.getId()).isVisible());
-        assertTrue(state.getSource(imeSource.getId()).getFrame().isEmpty());
+        assertFalse(state.getOrCreateSource(imeSource.getId(), ime()).isVisible());
+        assertTrue(state.getOrCreateSource(imeSource.getId(), ime()).getFrame().isEmpty());
 
         // Simulate app is closing and expect IME insets is frozen.
         mDisplayContent.mOpeningApps.clear();
@@ -3211,8 +3211,8 @@
         // Verify when IME is visible and the app can receive the right IME insets from policy.
         makeWindowVisibleAndDrawn(app, mImeWindow);
         state = app.getInsetsState();
-        assertTrue(state.getSource(ITYPE_IME).isVisible());
-        assertEquals(state.getSource(ITYPE_IME).getFrame(), imeSource.getFrame());
+        assertTrue(state.peekSource(ID_IME).isVisible());
+        assertEquals(state.peekSource(ID_IME).getFrame(), imeSource.getFrame());
     }
 
     @SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD })
@@ -3222,7 +3222,7 @@
         final WindowState app1 = createWindow(null, TYPE_APPLICATION, "app1");
         final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
 
-        mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_IME).setWindowContainer(
+        mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer(
                 mImeWindow, null, null);
         mImeWindow.getControllableInsetProvider().setServerVisible(true);
 
@@ -3237,7 +3237,7 @@
         mDisplayContent.getInsetsStateController().onInsetsModified(app1);
 
         // Verify app1's IME insets is visible and app2's IME insets frozen flag set.
-        assertTrue(app1.getInsetsState().peekSource(ITYPE_IME).isVisible());
+        assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible());
         assertTrue(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);
 
         // Simulate switching to app2 to make it visible to be IME targets.
@@ -3256,7 +3256,7 @@
         verify(app2.mClient, atLeastOnce()).resized(any(), anyBoolean(), any(),
                 insetsStateCaptor.capture(), anyBoolean(), anyBoolean(), anyInt(), anyInt(),
                 anyBoolean());
-        assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @Test
@@ -3288,7 +3288,7 @@
         makeWindowVisibleAndDrawn(app1, app2);
 
         final InsetsStateController controller = mDisplayContent.getInsetsStateController();
-        controller.getSourceProvider(ITYPE_IME).setWindowContainer(
+        controller.getImeSourceProvider().setWindowContainer(
                 ime, null, null);
         ime.getControllableInsetProvider().setServerVisible(true);
 
@@ -3306,8 +3306,8 @@
         controller.onInsetsModified(app1);
 
         // Expect all activities in split-screen will get IME insets visible state
-        assertTrue(app1.getInsetsState().peekSource(ITYPE_IME).isVisible());
-        assertTrue(app2.getInsetsState().peekSource(ITYPE_IME).isVisible());
+        assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible());
+        assertTrue(app2.getInsetsState().peekSource(ID_IME).isVisible());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index ee8a988..ff5ede7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -34,7 +34,6 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
@@ -96,9 +95,7 @@
                 .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME));
 
         // verify if back animation would start.
-        verify(mBackNavigationController).scheduleAnimationLocked(
-                eq(BackNavigationInfo.TYPE_RETURN_TO_HOME), any(), eq(mBackAnimationAdapter),
-                any());
+        assertTrue("Animation scheduled", backNavigationInfo.isPrepareRemoteAnimation());
     }
 
     @Test
@@ -115,9 +112,7 @@
                 .isEqualTo(typeToString(BackNavigationInfo.TYPE_CROSS_TASK));
 
         // verify if back animation would start.
-        verify(mBackNavigationController).scheduleAnimationLocked(
-                eq(BackNavigationInfo.TYPE_CROSS_TASK), any(), eq(mBackAnimationAdapter),
-                any());
+        assertTrue("Animation scheduled", backNavigationInfo.isPrepareRemoteAnimation());
 
         // reset drawning status
         topTask.forAllWindows(w -> {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 3b34ba4..1ce8c61 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -105,6 +105,7 @@
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.when;
 
+import android.annotation.NonNull;
 import android.app.ActivityTaskManager;
 import android.app.WindowConfiguration;
 import android.content.res.Configuration;
@@ -123,6 +124,7 @@
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.view.ContentRecordingSession;
+import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 import android.view.Gravity;
@@ -1557,13 +1559,13 @@
         // If the visibility of insets state is changed, the rotated state should be updated too.
         final InsetsState rotatedState = app.getFixedRotationTransformInsetsState();
         final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
-        assertEquals(state.getSource(ITYPE_STATUS_BAR).isVisible(),
-                rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
-        state.getSource(ITYPE_STATUS_BAR).setVisible(
-                !rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
+        assertEquals(state.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()),
+                rotatedState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
+        state.setSourceVisible(ITYPE_STATUS_BAR,
+                !rotatedState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
         mDisplayContent.getInsetsStateController().notifyInsetsChanged();
-        assertEquals(state.getSource(ITYPE_STATUS_BAR).isVisible(),
-                rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
+        assertEquals(state.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()),
+                rotatedState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
 
         final Rect outFrame = new Rect();
         final Rect outInsets = new Rect();
@@ -1831,6 +1833,111 @@
     }
 
     @Test
+    public void testSecondaryInternalDisplayRotationFollowsDefaultDisplay() {
+        // Skip freezing so the unrelated conditions in updateRotationUnchecked won't disturb.
+        doNothing().when(mWm).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
+
+        final DisplayRotationCoordinator coordinator =
+                mRootWindowContainer.getDisplayRotationCoordinator();
+        final DisplayContent defaultDisplayContent = mDisplayContent;
+        final DisplayRotation defaultDisplayRotation = defaultDisplayContent.getDisplayRotation();
+        coordinator.removeDefaultDisplayRotationChangedCallback();
+
+        DeviceStateController deviceStateController = mock(DeviceStateController.class);
+        when(deviceStateController.shouldMatchBuiltInDisplayOrientationToReverseDefaultDisplay())
+                .thenReturn(true);
+
+        // Create secondary display
+        final DisplayContent secondaryDisplayContent =
+                createSecondaryDisplayContent(Display.TYPE_INTERNAL, deviceStateController);
+        final DisplayRotation secondaryDisplayRotation =
+                secondaryDisplayContent.getDisplayRotation();
+        try {
+            // TestDisplayContent bypasses this method but we need it for this test
+            doCallRealMethod().when(secondaryDisplayRotation).updateRotationUnchecked(anyBoolean());
+
+            // TestDisplayContent creates this as a mock. Lets set it up to test our use case.
+            when(secondaryDisplayContent.mDeviceStateController
+                    .shouldMatchBuiltInDisplayOrientationToReverseDefaultDisplay()).thenReturn(
+                    true);
+
+            // Check that secondary display registered callback
+            assertEquals(secondaryDisplayRotation.mDefaultDisplayRotationChangedCallback,
+                    coordinator.mDefaultDisplayRotationChangedCallback);
+
+            // Set the default display to a known orientation. This may be a zero or non-zero
+            // rotation since mDisplayInfo.logicalWidth/Height depends on the DUT's default display
+            defaultDisplayRotation.updateOrientation(SCREEN_ORIENTATION_PORTRAIT, false);
+            assertEquals(defaultDisplayRotation.mPortraitRotation,
+                    defaultDisplayRotation.getRotation());
+            assertEquals(defaultDisplayRotation.mPortraitRotation,
+                    coordinator.getDefaultDisplayCurrentRotation());
+
+            // Check that in the initial state, the secondary display is in the right rotation
+            assertRotationsAreCorrectlyReversed(defaultDisplayRotation.getRotation(),
+                    secondaryDisplayRotation.getRotation());
+
+            // Update primary display rotation, check display coordinator rotation is the default
+            // display's landscape rotation, and that the secondary display rotation is correct.
+            defaultDisplayRotation.updateOrientation(SCREEN_ORIENTATION_LANDSCAPE, false);
+            assertEquals(defaultDisplayRotation.mLandscapeRotation,
+                    defaultDisplayRotation.getRotation());
+            assertEquals(defaultDisplayRotation.mLandscapeRotation,
+                    coordinator.getDefaultDisplayCurrentRotation());
+            assertRotationsAreCorrectlyReversed(defaultDisplayRotation.getRotation(),
+                    secondaryDisplayRotation.getRotation());
+        } finally {
+            secondaryDisplayRotation.removeDefaultDisplayRotationChangedCallback();
+        }
+    }
+
+    @Test
+    public void testSecondaryNonInternalDisplayDoesNotFollowDefaultDisplay() {
+        // Skip freezing so the unrelated conditions in updateRotationUnchecked won't disturb.
+        doNothing().when(mWm).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
+
+        final DisplayRotationCoordinator coordinator =
+                mRootWindowContainer.getDisplayRotationCoordinator();
+        coordinator.removeDefaultDisplayRotationChangedCallback();
+
+        DeviceStateController deviceStateController = mock(DeviceStateController.class);
+        when(deviceStateController.shouldMatchBuiltInDisplayOrientationToReverseDefaultDisplay())
+                .thenReturn(true);
+
+        // Create secondary non-internal displays
+        createSecondaryDisplayContent(Display.TYPE_EXTERNAL, deviceStateController);
+        assertNull(coordinator.mDefaultDisplayRotationChangedCallback);
+        createSecondaryDisplayContent(Display.TYPE_VIRTUAL, deviceStateController);
+        assertNull(coordinator.mDefaultDisplayRotationChangedCallback);
+    }
+
+    private DisplayContent createSecondaryDisplayContent(int displayType,
+            @NonNull DeviceStateController deviceStateController) {
+        final DisplayInfo secondaryDisplayInfo = new DisplayInfo();
+        secondaryDisplayInfo.copyFrom(mDisplayInfo);
+        secondaryDisplayInfo.type = displayType;
+
+        return new TestDisplayContent.Builder(mAtm, secondaryDisplayInfo)
+                .setDeviceStateController(deviceStateController)
+                .build();
+    }
+
+    private static void assertRotationsAreCorrectlyReversed(@Surface.Rotation int rotation1,
+            @Surface.Rotation int rotation2) {
+        if (rotation1 == ROTATION_0) {
+            assertEquals(rotation1, rotation2);
+        } else if (rotation1 == ROTATION_180) {
+            assertEquals(rotation1, rotation2);
+        } else if (rotation1 == ROTATION_90) {
+            assertEquals(ROTATION_270, rotation2);
+        } else if (rotation1 == ROTATION_270) {
+            assertEquals(ROTATION_90, rotation2);
+        } else {
+            throw new IllegalArgumentException("Unknown rotation: " + rotation1 + ", " + rotation2);
+        }
+    }
+
+    @Test
     public void testRemoteRotation() {
         final DisplayContent dc = mDisplayContent;
         final DisplayRotation dr = dc.getDisplayRotation();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 6733470..6656f4c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -43,6 +43,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.view.DisplayInfo;
 import android.view.InsetsFrameProvider;
+import android.view.InsetsSource;
 import android.view.InsetsState;
 import android.view.PrivacyIndicatorBounds;
 import android.view.RoundedCorners;
@@ -162,19 +163,20 @@
         InsetsStateController controller = mDisplayContent.getInsetsStateController();
         controller.onPostLayout();
 
-        InsetsSourceProvider statusBarProvider = controller.getSourceProvider(ITYPE_STATUS_BAR);
+        InsetsSourceProvider statusBarProvider = controller.peekSourceProvider(ITYPE_STATUS_BAR);
         assertEquals(new Rect(0, 0, 500, 100), statusBarProvider.getSource().getFrame());
         assertEquals(Insets.of(0, 100, 0, 0),
                 statusBarProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
                         false /* ignoreVisibility */));
 
-        InsetsSourceProvider topGesturesProvider = controller.getSourceProvider(ITYPE_TOP_GESTURES);
+        InsetsSourceProvider topGesturesProvider = controller.peekSourceProvider(
+                ITYPE_TOP_GESTURES);
         assertEquals(new Rect(0, 0, 500, 100), topGesturesProvider.getSource().getFrame());
         assertEquals(Insets.of(0, 100, 0, 0),
                 topGesturesProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
                         false /* ignoreVisibility */));
 
-        InsetsSourceProvider navigationBarProvider = controller.getSourceProvider(
+        InsetsSourceProvider navigationBarProvider = controller.peekSourceProvider(
                 ITYPE_NAVIGATION_BAR);
         assertNotEquals(new Rect(0, 0, 500, 100), navigationBarProvider.getSource().getFrame());
     }
@@ -193,7 +195,7 @@
         mDisplayContent.getInsetsStateController().onPostLayout();
 
         InsetsSourceProvider provider =
-                mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR);
+                mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_STATUS_BAR);
         // In the new flexible insets setup, the insets frame should always respect the window
         // layout result.
         assertEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame());
@@ -255,7 +257,7 @@
                 mDisplayContent.getInsetsStateController().getRawInsetsState());
         // Exclude comparing IME insets because currently the simulated layout only focuses on the
         // insets from status bar and navigation bar.
-        realInsetsState.removeSource(InsetsState.ITYPE_IME);
+        realInsetsState.removeSource(InsetsSource.ID_IME);
         realInsetsState.removeSource(InsetsState.ITYPE_CAPTION_BAR);
 
         assertEquals(new ToStringComparatorWrapper<>(realInsetsState),
@@ -270,9 +272,9 @@
                 .rotationForActivityInDifferentOrientation(eq(mWindow.mActivityRecord));
         mWindow.mAboveInsetsState.set(
                 mDisplayContent.getInsetsStateController().getRawInsetsState());
-        final Rect frame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+        final Rect frame = mWindow.getInsetsState().peekSource(ITYPE_STATUS_BAR).getFrame();
         mDisplayContent.rotateInDifferentOrientationIfNeeded(mWindow.mActivityRecord);
-        final Rect rotatedFrame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+        final Rect rotatedFrame = mWindow.getInsetsState().peekSource(ITYPE_STATUS_BAR).getFrame();
 
         assertEquals(DISPLAY_WIDTH, frame.width());
         assertEquals(DISPLAY_HEIGHT, rotatedFrame.width());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index cf9ec81..6bb7769 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -17,8 +17,8 @@
 package com.android.server.wm;
 
 import static android.view.DisplayCutout.NO_CUTOUT;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
 import static android.view.Surface.ROTATION_0;
@@ -335,7 +335,7 @@
         displayPolicy.layoutWindowLw(mNavBarWindow, null, mDisplayContent.mDisplayFrames);
         displayPolicy.layoutWindowLw(mImeWindow, null, mDisplayContent.mDisplayFrames);
 
-        final InsetsSource imeSource = state.peekSource(ITYPE_IME);
+        final InsetsSource imeSource = state.peekSource(ID_IME);
         final InsetsSource navBarSource = state.peekSource(ITYPE_NAVIGATION_BAR);
 
         assertNotNull(imeSource);
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 45b30b2..4954e89 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
@@ -30,7 +31,9 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 
 import static org.junit.Assert.assertEquals;
@@ -58,6 +61,8 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.R;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -128,6 +133,69 @@
     }
 
     @Test
+    public void testOpenedCameraInSplitScreen_showToast() {
+        configureActivity(SCREEN_ORIENTATION_PORTRAIT);
+        spyOn(mTask);
+        spyOn(mDisplayRotationCompatPolicy);
+        doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mActivity).getWindowingMode();
+        doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mTask).getWindowingMode();
+
+        mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+
+        verify(mDisplayRotationCompatPolicy).showToast(
+                R.string.display_rotation_camera_compat_toast_in_split_screen);
+    }
+
+    @Test
+    public void testOnScreenRotationAnimationFinished_treatmentNotEnabled_doNotShowToast() {
+        when(mLetterboxConfiguration.isCameraCompatTreatmentEnabled(
+                    /* checkDeviceConfig */ anyBoolean()))
+                .thenReturn(false);
+        spyOn(mDisplayRotationCompatPolicy);
+
+        mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished();
+
+        verify(mDisplayRotationCompatPolicy, never()).showToast(
+                R.string.display_rotation_camera_compat_toast_after_rotation);
+    }
+
+    @Test
+    public void testOnScreenRotationAnimationFinished_noOpenCamera_doNotShowToast() {
+        spyOn(mDisplayRotationCompatPolicy);
+
+        mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished();
+
+        verify(mDisplayRotationCompatPolicy, never()).showToast(
+                R.string.display_rotation_camera_compat_toast_after_rotation);
+    }
+
+    @Test
+    public void testOnScreenRotationAnimationFinished_notFullscreen_doNotShowToast() {
+        configureActivity(SCREEN_ORIENTATION_PORTRAIT);
+        doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mActivity).getWindowingMode();
+        spyOn(mDisplayRotationCompatPolicy);
+
+        mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+
+        mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished();
+
+        verify(mDisplayRotationCompatPolicy, never()).showToast(
+                R.string.display_rotation_camera_compat_toast_after_rotation);
+    }
+
+    @Test
+    public void testOnScreenRotationAnimationFinished_showToast() {
+        configureActivity(SCREEN_ORIENTATION_PORTRAIT);
+        mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
+        spyOn(mDisplayRotationCompatPolicy);
+
+        mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished();
+
+        verify(mDisplayRotationCompatPolicy).showToast(
+                R.string.display_rotation_camera_compat_toast_after_rotation);
+    }
+
+    @Test
     public void testTreatmentNotEnabled_noForceRotationOrRefresh() throws Exception {
         when(mLetterboxConfiguration.isCameraCompatTreatmentEnabled(
                     /* checkDeviceConfig */ anyBoolean()))
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCoordinatorTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCoordinatorTests.java
new file mode 100644
index 0000000..4557df0
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCoordinatorTests.java
@@ -0,0 +1,95 @@
+/*
+ * 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.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.junit.Assert.assertEquals;
+
+import android.annotation.NonNull;
+import android.platform.test.annotations.Presubmit;
+import android.view.Surface;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Test class for {@link DisplayRotationCoordinator}
+ *
+ * Build/Install/Run:
+ *  atest DisplayRotationCoordinatorTests
+ */
+@SmallTest
+@Presubmit
+public class DisplayRotationCoordinatorTests {
+
+    @NonNull
+    private final DisplayRotationCoordinator mCoordinator = new DisplayRotationCoordinator();
+
+    @Test
+    public void testDefaultDisplayRotationChangedWhenNoCallbackRegistered() {
+        // Does not cause NPE
+        mCoordinator.onDefaultDisplayRotationChanged(Surface.ROTATION_90);
+    }
+
+    @Test (expected = UnsupportedOperationException.class)
+    public void testSecondRegistrationWithoutRemovingFirst() {
+        Runnable callback1 = mock(Runnable.class);
+        Runnable callback2 = mock(Runnable.class);
+        mCoordinator.setDefaultDisplayRotationChangedCallback(callback1);
+        mCoordinator.setDefaultDisplayRotationChangedCallback(callback2);
+        assertEquals(callback1, mCoordinator.mDefaultDisplayRotationChangedCallback);
+    }
+
+    @Test
+    public void testSecondRegistrationAfterRemovingFirst() {
+        Runnable callback1 = mock(Runnable.class);
+        mCoordinator.setDefaultDisplayRotationChangedCallback(callback1);
+        mCoordinator.removeDefaultDisplayRotationChangedCallback();
+
+        Runnable callback2 = mock(Runnable.class);
+        mCoordinator.setDefaultDisplayRotationChangedCallback(callback2);
+
+        mCoordinator.onDefaultDisplayRotationChanged(Surface.ROTATION_90);
+        verify(callback2).run();
+        verify(callback1, never()).run();
+    }
+
+    @Test
+    public void testRegisterThenDefaultDisplayRotationChanged() {
+        Runnable callback = mock(Runnable.class);
+        mCoordinator.setDefaultDisplayRotationChangedCallback(callback);
+        assertEquals(Surface.ROTATION_0, mCoordinator.getDefaultDisplayCurrentRotation());
+        verify(callback, never()).run();
+
+        mCoordinator.onDefaultDisplayRotationChanged(Surface.ROTATION_90);
+        verify(callback).run();
+        assertEquals(Surface.ROTATION_90, mCoordinator.getDefaultDisplayCurrentRotation());
+    }
+
+    @Test
+    public void testDefaultDisplayRotationChangedThenRegister() {
+        mCoordinator.onDefaultDisplayRotationChanged(Surface.ROTATION_90);
+        Runnable callback = mock(Runnable.class);
+        mCoordinator.setDefaultDisplayRotationChangedCallback(callback);
+        verify(callback).run();
+        assertEquals(Surface.ROTATION_90, mCoordinator.getDefaultDisplayCurrentRotation());
+    }
+}
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 ed2b0a3..21e8ec4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -1135,7 +1135,7 @@
             mDeviceStateController = mock(DeviceStateController.class);
             mTarget = new DisplayRotation(sMockWm, mMockDisplayContent, mMockDisplayAddress,
                     mMockDisplayPolicy, mMockDisplayWindowSettings, mMockContext, new Object(),
-                    mDeviceStateController) {
+                    mDeviceStateController, mock(DisplayRotationCoordinator.class)) {
                 @Override
                 DisplayRotationImmersiveAppCompatPolicy initImmersiveAppCompatPolicy(
                         WindowManagerService service, DisplayContent displayContent) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
index b2abd44..19d1d83 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
@@ -33,7 +33,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.os.UserHandle;
+import android.os.Process;
 import android.util.ArraySet;
 import android.view.Display;
 import android.window.DisplayWindowPolicyController;
@@ -101,7 +101,7 @@
         int uidAmount = (expectedUid0 && expectedUid1) ? 2 : (expectedUid0 || expectedUid1) ? 1 : 0;
         assertEquals(expectedTopActivity == null ? null :
                 expectedTopActivity.info.getComponentName(), mDwpc.mTopActivity);
-        assertEquals(expectedTopActivity == null ? UserHandle.USER_NULL :
+        assertEquals(expectedTopActivity == null ? Process.INVALID_UID :
                 expectedTopActivity.info.applicationInfo.uid, mDwpc.mTopActivityUid);
         assertEquals(uidAmount, mDwpc.mRunningUids.size());
         assertTrue(mDwpc.mRunningUids.contains(TEST_USER_0_ID) == expectedUid0);
@@ -224,7 +224,7 @@
                 new ComponentName("fake.package", "DisallowedActivity");
 
         ComponentName mTopActivity = null;
-        int mTopActivityUid = UserHandle.USER_NULL;
+        int mTopActivityUid = Process.INVALID_UID;
         ArraySet<Integer> mRunningUids = new ArraySet<>();
 
         @Override
@@ -254,8 +254,8 @@
         }
 
         @Override
-        public void onTopActivityChanged(ComponentName topActivity, int uid) {
-            super.onTopActivityChanged(topActivity, uid);
+        public void onTopActivityChanged(ComponentName topActivity, int uid, int userId) {
+            super.onTopActivityChanged(topActivity, uid, userId);
             mTopActivity = topActivity;
             mTopActivityUid = uid;
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
index 4eaae9f..d1a41ae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
@@ -552,7 +552,7 @@
         /** Please use the {@link Builder} to create. */
         DualDisplayContent(RootWindowContainer rootWindowContainer,
                 Display display) {
-            super(rootWindowContainer, display);
+            super(rootWindowContainer, display, mock(DeviceStateController.class));
 
             mFirstRoot = getGroupRoot(FEATURE_FIRST_ROOT);
             mSecondRoot = getGroupRoot(FEATURE_SECOND_ROOT);
diff --git a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java
index 0568b38..c0a90b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java
@@ -182,13 +182,11 @@
     @Test
     public void testApplicationNotInFocusWithModeId() {
         final WindowState appWindow = createWindow("appWindow");
-        assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
-        assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE);
-
-        final WindowState inFocusWindow = createWindow("inFocus");
-        appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow;
-
+        mDisplayContent.mCurrentFocus = appWindow;
         appWindow.updateFrameRateSelectionPriorityIfNeeded();
+        mDisplayContent.mCurrentFocus = null;
+        appWindow.updateFrameRateSelectionPriorityIfNeeded();
+
         // The window is not in focus.
         assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
         assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE);
@@ -211,13 +209,11 @@
     @Test
     public void testApplicationNotInFocusWithoutModeId() {
         final WindowState appWindow = createWindow("appWindow");
-        assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
-        assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE);
-
-        final WindowState inFocusWindow = createWindow("inFocus");
-        appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow;
-
+        mDisplayContent.mCurrentFocus = appWindow;
         appWindow.updateFrameRateSelectionPriorityIfNeeded();
+        mDisplayContent.mCurrentFocus = null;
+        appWindow.updateFrameRateSelectionPriorityIfNeeded();
+
         // The window is not in focus.
         assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
         assertEquals(appWindow.mFrameRateVote, FRAME_RATE_VOTE_NONE);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
index d4e860e..20bb549 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -39,7 +39,7 @@
 @RunWith(WindowTestRunner.class)
 public class ImeInsetsSourceProviderTest extends WindowTestsBase {
 
-    private InsetsSource mImeSource = new InsetsSource(ITYPE_IME, ime());
+    private InsetsSource mImeSource = new InsetsSource(ID_IME, ime());
     private ImeInsetsSourceProvider mImeProvider;
 
     @Before
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 9887839..1a126cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -276,12 +276,11 @@
         policy.updateBarControlTarget(mAppWindow);
         waitUntilWindowAnimatorIdle();
         assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
-                .getSource(ITYPE_STATUS_BAR).isVisible());
+                .isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
         assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
-                .getSource(ITYPE_NAVIGATION_BAR).isVisible());
+                .isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars()));
 
-        policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR},
-                true /* isGestureOnSystemBar */);
+        policy.showTransient(navigationBars() | statusBars(), true /* isGestureOnSystemBar */);
         waitUntilWindowAnimatorIdle();
         final InsetsSourceControl[] controls =
                 mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
@@ -293,9 +292,9 @@
         }
 
         assertTrue(mDisplayContent.getInsetsStateController().getRawInsetsState()
-                .getSource(ITYPE_STATUS_BAR).isVisible());
+                .isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
         assertTrue(mDisplayContent.getInsetsStateController().getRawInsetsState()
-                .getSource(ITYPE_NAVIGATION_BAR).isVisible());
+                .isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars()));
     }
 
     @SetupWindows(addWindows = W_ACTIVITY)
@@ -308,11 +307,11 @@
         spyOn(policy);
         doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(mAppWindow);
-        policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR},
+        policy.showTransient(navigationBars() | statusBars(),
                 true /* isGestureOnSystemBar */);
         waitUntilWindowAnimatorIdle();
-        assertTrue(policy.isTransient(ITYPE_STATUS_BAR));
-        assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR));
+        assertTrue(policy.isTransient(statusBars()));
+        assertFalse(policy.isTransient(navigationBars()));
         final InsetsSourceControl[] controls =
                 mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
 
@@ -344,7 +343,7 @@
         spyOn(policy);
         doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(mAppWindow);
-        policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR},
+        policy.showTransient(navigationBars() | statusBars(),
                 true /* isGestureOnSystemBar */);
         waitUntilWindowAnimatorIdle();
         InsetsSourceControl[] controls =
@@ -362,11 +361,11 @@
 
         final InsetsState clientState = mAppWindow.getInsetsState();
         // The transient bar states for client should be invisible.
-        assertFalse(clientState.getSource(ITYPE_STATUS_BAR).isVisible());
-        assertFalse(clientState.getSource(ITYPE_NAVIGATION_BAR).isVisible());
+        assertFalse(clientState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
+        assertFalse(clientState.isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars()));
         // The original state shouldn't be modified.
-        assertTrue(state.getSource(ITYPE_STATUS_BAR).isVisible());
-        assertTrue(state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
+        assertTrue(state.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
+        assertTrue(state.isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars()));
 
         mAppWindow.setRequestedVisibleTypes(
                 navigationBars() | statusBars(), navigationBars() | statusBars());
@@ -393,13 +392,13 @@
         spyOn(policy);
         doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(app);
-        policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR},
+        policy.showTransient(navigationBars() | statusBars(),
                 true /* isGestureOnSystemBar */);
         final InsetsSourceControl[] controls =
                 mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
         policy.updateBarControlTarget(app2);
-        assertFalse(policy.isTransient(ITYPE_STATUS_BAR));
-        assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR));
+        assertFalse(policy.isTransient(statusBars()));
+        assertFalse(policy.isTransient(navigationBars()));
     }
 
     private WindowState addNavigationBar() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 4d69979..74fde65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -19,12 +19,10 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_IME;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -48,6 +46,7 @@
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.util.SparseArray;
+import android.view.InsetsSource;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 
@@ -63,6 +62,15 @@
 @RunWith(WindowTestRunner.class)
 public class InsetsStateControllerTest extends WindowTestsBase {
 
+    private static final int ID_STATUS_BAR =
+            InsetsSource.createId(null /* owner */, 0 /* index */, statusBars());
+    private static final int ID_NAVIGATION_BAR =
+            InsetsSource.createId(null /* owner */, 0 /* index */, navigationBars());
+    private static final int ID_CLIMATE_BAR =
+            InsetsSource.createId(null /* owner */, 1 /* index */, statusBars());
+    private static final int ID_EXTRA_NAVIGATION_BAR =
+            InsetsSource.createId(null /* owner */, 1 /* index */, navigationBars());
+
     @Test
     public void testStripForDispatch_navBar() {
         final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
@@ -72,14 +80,15 @@
         // IME cannot be the IME target.
         ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
 
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
+        getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+                .setWindowContainer(navBar, null, null);
+        getController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(ime, null, null);
 
-        assertNull(navBar.getInsetsState().peekSource(ITYPE_IME));
-        assertNull(navBar.getInsetsState().peekSource(ITYPE_STATUS_BAR));
+        assertNull(navBar.getInsetsState().peekSource(ID_IME));
+        assertNull(navBar.getInsetsState().peekSource(ID_STATUS_BAR));
     }
 
     @Test
@@ -88,15 +97,15 @@
         final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
 
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
+        getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+                .setWindowContainer(navBar, null, null);
         app.setWindowingMode(WINDOWING_MODE_PINNED);
 
-        assertNull(app.getInsetsState().peekSource(ITYPE_STATUS_BAR));
-        assertNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
-        assertNull(app.getInsetsState().peekSource(ITYPE_IME));
+        assertNull(app.getInsetsState().peekSource(ID_STATUS_BAR));
+        assertNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
+        assertNull(app.getInsetsState().peekSource(ID_IME));
     }
 
     @Test
@@ -105,14 +114,14 @@
         final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
 
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
+        getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+                .setWindowContainer(navBar, null, null);
         app.setWindowingMode(WINDOWING_MODE_FREEFORM);
 
-        assertNull(app.getInsetsState().peekSource(ITYPE_STATUS_BAR));
-        assertNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
+        assertNull(app.getInsetsState().peekSource(ID_STATUS_BAR));
+        assertNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
     }
 
     @Test
@@ -121,57 +130,58 @@
         final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
 
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
+        getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+                .setWindowContainer(navBar, null, null);
         app.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         app.setAlwaysOnTop(true);
 
-        assertNull(app.getInsetsState().peekSource(ITYPE_STATUS_BAR));
-        assertNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
+        assertNull(app.getInsetsState().peekSource(ID_STATUS_BAR));
+        assertNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
     }
 
     @SetupWindows(addWindows = W_INPUT_METHOD)
     @Test
     public void testStripForDispatch_independentSources() {
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(mImeWindow, null, null);
+        getController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(mImeWindow, null, null);
 
         final WindowState app1 = createWindow(null, TYPE_APPLICATION, "app1");
         final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
 
-        app1.mAboveInsetsState.addSource(getController().getRawInsetsState().getSource(ITYPE_IME));
+        app1.mAboveInsetsState.addSource(getController().getRawInsetsState().peekSource(ID_IME));
 
-        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
-        assertFalse(app2.getInsetsState().getSource(ITYPE_IME)
-                .isVisible());
-        assertTrue(app1.getInsetsState().getSource(ITYPE_IME)
-                .isVisible());
+        getController().getRawInsetsState().setSourceVisible(ID_IME, true);
+        assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertTrue(app1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @SetupWindows(addWindows = W_INPUT_METHOD)
     @Test
     public void testStripForDispatch_belowIme() {
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(mImeWindow, null, null);
+        getController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(mImeWindow, null, null);
 
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        app.mAboveInsetsState.getSource(ITYPE_IME).setVisible(true);
-        app.mAboveInsetsState.getSource(ITYPE_IME).setFrame(mImeWindow.getFrame());
+        app.mAboveInsetsState.getOrCreateSource(ID_IME, ime())
+                .setVisible(true)
+                .setFrame(mImeWindow.getFrame());
 
-        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
+        getController().getRawInsetsState().setSourceVisible(ID_IME, true);
+        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @SetupWindows(addWindows = W_INPUT_METHOD)
     @Test
     public void testStripForDispatch_aboveIme() {
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(mImeWindow, null, null);
+        getController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(mImeWindow, null, null);
 
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
 
-        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
-        assertFalse(app.getInsetsState().getSource(ITYPE_IME)
-                .isVisible());
+        getController().getRawInsetsState().setSourceVisible(ID_IME, true);
+        assertFalse(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @SetupWindows(addWindows = W_INPUT_METHOD)
@@ -185,7 +195,8 @@
 
         // Make IME and stay visible during the test.
         mImeWindow.setHasSurface(true);
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(mImeWindow, null, null);
+        getController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(mImeWindow, null, null);
         getController().onImeControlTargetChanged(
                 mDisplayContent.getImeInputTarget().getWindowState());
         mDisplayContent.getImeInputTarget().getWindowState().setRequestedVisibleTypes(ime(), ime());
@@ -205,9 +216,8 @@
         mDisplayContent.applySurfaceChangesTransaction();
 
         // app won't get visible IME insets while above IME even when IME is visible.
-        assertTrue(getController().getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
-        assertFalse(app.getInsetsState().getSource(ITYPE_IME)
-                .isVisible());
+        assertTrue(getController().getRawInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertFalse(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
 
         // Reset invocation counter.
         clearInvocations(app);
@@ -216,20 +226,22 @@
         app.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
         mDisplayContent.computeImeTarget(true);
         mDisplayContent.applySurfaceChangesTransaction();
-        app.mAboveInsetsState.getSource(ITYPE_IME).setVisible(true);
-        app.mAboveInsetsState.getSource(ITYPE_IME).setFrame(mImeWindow.getFrame());
+        app.mAboveInsetsState.getOrCreateSource(ID_IME, ime())
+                .setVisible(true)
+                .setFrame(mImeWindow.getFrame());
 
         // Make sure app got notified.
         verify(app, atLeastOnce()).notifyInsetsChanged();
 
         // app will get visible IME insets while below IME.
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @SetupWindows(addWindows = W_INPUT_METHOD)
     @Test
     public void testStripForDispatch_childWindow_altFocusable() {
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(mImeWindow, null, null);
+        getController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(mImeWindow, null, null);
 
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
@@ -241,20 +253,20 @@
         mDisplayContent.setLayoutNeeded();
         mDisplayContent.applySurfaceChangesTransaction();
 
-        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
-        assertFalse(child.getInsetsState().getSource(ITYPE_IME)
-                .isVisible());
+        getController().getRawInsetsState().setSourceVisible(ID_IME, true);
+        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertFalse(child.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @SetupWindows(addWindows = W_INPUT_METHOD)
     @Test
     public void testStripForDispatch_childWindow_splitScreen() {
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(mImeWindow, null, null);
+        getController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(mImeWindow, null, null);
 
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
-        app.mAboveInsetsState.addSource(getController().getRawInsetsState().peekSource(ITYPE_IME));
+        app.mAboveInsetsState.addSource(getController().getRawInsetsState().peekSource(ID_IME));
         child.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
         child.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
 
@@ -262,10 +274,9 @@
         mDisplayContent.setLayoutNeeded();
         mDisplayContent.applySurfaceChangesTransaction();
 
-        getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
-        assertFalse(child.getInsetsState().getSource(ITYPE_IME)
-                .isVisible());
+        getController().getRawInsetsState().setSourceVisible(ID_IME, true);
+        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertFalse(child.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @Test
@@ -277,20 +288,21 @@
         ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
 
         WindowContainerInsetsSourceProvider statusBarProvider =
-                getController().getSourceProvider(ITYPE_STATUS_BAR);
+                getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars());
         final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> imeOverrideProviders =
                 new SparseArray<>();
         imeOverrideProviders.put(TYPE_INPUT_METHOD, ((displayFrames, windowState, rect) ->
                 rect.set(0, 1, 2, 3)));
         statusBarProvider.setWindowContainer(statusBar, null, imeOverrideProviders);
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null);
+        getController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(ime, null, null);
         statusBar.setControllableInsetProvider(statusBarProvider);
         statusBar.updateSourceFrame(statusBar.getFrame());
 
         statusBarProvider.onPostLayout();
 
         final InsetsState state = ime.getInsetsState();
-        assertEquals(new Rect(0, 1, 2, 3), state.getSource(ITYPE_STATUS_BAR).getFrame());
+        assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ID_STATUS_BAR).getFrame());
     }
 
     @Test
@@ -300,15 +312,14 @@
         final WindowState climateBar = createWindow(null, TYPE_APPLICATION, "climateBar");
         final WindowState extraNavBar = createWindow(null, TYPE_APPLICATION, "extraNavBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_CLIMATE_BAR).setWindowContainer(climateBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_EXTRA_NAVIGATION_BAR).setWindowContainer(
-                extraNavBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
+        getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+                .setWindowContainer(navBar, null, null);
+        getController().getOrCreateSourceProvider(ID_CLIMATE_BAR, statusBars())
+                .setWindowContainer(climateBar, null, null);
+        getController().getOrCreateSourceProvider(ID_EXTRA_NAVIGATION_BAR, navigationBars())
+                .setWindowContainer(extraNavBar, null, null);
         getController().onBarControlTargetChanged(app, null, app, null);
         InsetsSourceControl[] controls = getController().getControlsForDispatch(app);
         assertEquals(4, controls.length);
@@ -318,8 +329,8 @@
     public void testControlRevoked() {
         final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
         getController().onBarControlTargetChanged(app, null, null, null);
         assertNotNull(getController().getControlsForDispatch(app));
         getController().onBarControlTargetChanged(null, null, null, null);
@@ -330,8 +341,8 @@
     public void testControlRevoked_animation() {
         final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
         getController().onBarControlTargetChanged(app, null, null, null);
         assertNotNull(getController().getControlsForDispatch(app));
         statusBar.cancelAnimation();
@@ -343,21 +354,22 @@
         final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         final WindowContainerInsetsSourceProvider provider = getController()
-                .getSourceProvider(ITYPE_STATUS_BAR);
+                .getOrCreateSourceProvider(ID_STATUS_BAR, statusBars());
         provider.setWindowContainer(statusBar, null, null);
 
         final InsetsState rotatedState = new InsetsState(app.getInsetsState(),
                 true /* copySources */);
+        rotatedState.getOrCreateSource(ID_STATUS_BAR, statusBars());
         spyOn(app.mToken);
         doReturn(rotatedState).when(app.mToken).getFixedRotationTransformInsetsState();
-        assertTrue(rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
+        assertTrue(rotatedState.isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars()));
 
         provider.getSource().setVisible(false);
-        mDisplayContent.getInsetsPolicy().showTransient(new int[] { ITYPE_STATUS_BAR },
+        mDisplayContent.getInsetsPolicy().showTransient(statusBars(),
                 true /* isGestureOnSystemBar */);
 
-        assertTrue(mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR));
-        assertFalse(app.getInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
+        assertTrue(mDisplayContent.getInsetsPolicy().isTransient(statusBars()));
+        assertFalse(app.getInsetsState().isSourceOrDefaultVisible(ID_STATUS_BAR, statusBars()));
     }
 
     @Test
@@ -366,18 +378,18 @@
         final WindowState statusBar = createTestWindow("statusBar");
         final WindowState navBar = createTestWindow("navBar");
 
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
 
-        assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
-        assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
-        assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNull(app.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+        assertNull(statusBar.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+        assertNull(navBar.mAboveInsetsState.peekSource(ID_STATUS_BAR));
 
         getController().updateAboveInsetsState(true /* notifyInsetsChange */);
 
-        assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
-        assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
-        assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+        assertNotNull(app.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+        assertNull(statusBar.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+        assertNull(navBar.mAboveInsetsState.peekSource(ID_STATUS_BAR));
 
         verify(app, atLeastOnce()).notifyInsetsChanged();
     }
@@ -388,18 +400,18 @@
         final WindowState statusBar = createTestWindow("statusBar");
         final WindowState navBar = createTestWindow("navBar");
 
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
+        getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+                .setWindowContainer(navBar, null, null);
 
-        assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
-        assertNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+        assertNull(app.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+        assertNull(app.mAboveInsetsState.peekSource(ID_NAVIGATION_BAR));
 
         getController().updateAboveInsetsState(true /* notifyInsetsChange */);
 
-        assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
-        assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+        assertNotNull(app.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+        assertNotNull(app.mAboveInsetsState.peekSource(ID_NAVIGATION_BAR));
 
         verify(app, atLeastOnce()).notifyInsetsChanged();
     }
@@ -411,38 +423,40 @@
         final WindowState statusBar = createTestWindow("statusBar");
         final WindowState navBar = createTestWindow("navBar");
 
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null);
+        final InsetsSourceProvider imeSourceProvider =
+                getController().getOrCreateSourceProvider(ID_IME, ime());
+        imeSourceProvider.setWindowContainer(ime, null, null);
 
         waitUntilHandlersIdle();
         clearInvocations(mDisplayContent);
-        getController().getSourceProvider(ITYPE_IME).setClientVisible(true);
+        imeSourceProvider.setClientVisible(true);
         waitUntilHandlersIdle();
         // The visibility change should trigger a traversal to notify the change.
         verify(mDisplayContent).notifyInsetsChanged(any());
 
-        getController().getSourceProvider(ITYPE_STATUS_BAR).setWindowContainer(statusBar, null,
-                null);
-        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_STATUS_BAR, statusBars())
+                .setWindowContainer(statusBar, null, null);
+        getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+                .setWindowContainer(navBar, null, null);
 
         getController().updateAboveInsetsState(false /* notifyInsetsChange */);
 
         // ime is below others.
-        assertNull(app.mAboveInsetsState.peekSource(ITYPE_IME));
-        assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_IME));
-        assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_IME));
-        assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
-        assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+        assertNull(app.mAboveInsetsState.peekSource(ID_IME));
+        assertNull(statusBar.mAboveInsetsState.peekSource(ID_IME));
+        assertNull(navBar.mAboveInsetsState.peekSource(ID_IME));
+        assertNotNull(ime.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+        assertNotNull(ime.mAboveInsetsState.peekSource(ID_NAVIGATION_BAR));
 
         ime.getParent().positionChildAt(POSITION_TOP, ime, true /* includingParents */);
         getController().updateAboveInsetsState(true /* notifyInsetsChange */);
 
         // ime is above others.
-        assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_IME));
-        assertNotNull(statusBar.mAboveInsetsState.peekSource(ITYPE_IME));
-        assertNotNull(navBar.mAboveInsetsState.peekSource(ITYPE_IME));
-        assertNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
-        assertNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+        assertNotNull(app.mAboveInsetsState.peekSource(ID_IME));
+        assertNotNull(statusBar.mAboveInsetsState.peekSource(ID_IME));
+        assertNotNull(navBar.mAboveInsetsState.peekSource(ID_IME));
+        assertNull(ime.mAboveInsetsState.peekSource(ID_STATUS_BAR));
+        assertNull(ime.mAboveInsetsState.peekSource(ID_NAVIGATION_BAR));
 
         verify(ime, atLeastOnce()).notifyInsetsChanged();
         verify(app, atLeastOnce()).notifyInsetsChanged();
@@ -456,7 +470,8 @@
         final WindowState ime = createWindow(null,  TYPE_INPUT_METHOD, imeToken, "ime");
         final WindowState app = createTestWindow("app");
 
-        getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null);
+        getController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(ime, null, null);
         ime.getControllableInsetProvider().setServerVisible(true);
 
         app.mActivityRecord.setVisibility(true);
@@ -468,7 +483,7 @@
         assertTrue(ime.getControllableInsetProvider().getSource().isVisible());
 
         getController().updateAboveInsetsState(true /* notifyInsetsChange */);
-        assertNotNull(app.getInsetsState().peekSource(ITYPE_IME));
+        assertNotNull(app.getInsetsState().peekSource(ID_IME));
         verify(app, atLeastOnce()).notifyInsetsChanged();
 
         // Expect the app will still get IME insets even when the app was invisible.
@@ -476,7 +491,7 @@
         app.mActivityRecord.setVisible(false);
         app.setHasSurface(false);
         getController().updateAboveInsetsState(true /* notifyInsetsChange */);
-        assertNotNull(app.getInsetsState().peekSource(ITYPE_IME));
+        assertNotNull(app.getInsetsState().peekSource(ID_IME));
         verify(app, atLeastOnce()).notifyInsetsChanged();
 
         // Expect the app will get IME insets when the app is requesting visible.
@@ -484,19 +499,19 @@
         app.mActivityRecord.setVisibility(true);
         assertTrue(app.isVisibleRequested());
         getController().updateAboveInsetsState(true /* notifyInsetsChange */);
-        assertNotNull(app.getInsetsState().peekSource(ITYPE_IME));
+        assertNotNull(app.getInsetsState().peekSource(ID_IME));
         verify(app, atLeastOnce()).notifyInsetsChanged();
     }
 
     @Test
     public void testDispatchGlobalInsets() {
         final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
-        getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
-                null);
+        getController().getOrCreateSourceProvider(ID_NAVIGATION_BAR, navigationBars())
+                .setWindowContainer(navBar, null, null);
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
-        assertNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
+        assertNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
         app.mAttrs.receiveInsetsIgnoringZOrder = true;
-        assertNotNull(app.getInsetsState().peekSource(ITYPE_NAVIGATION_BAR));
+        assertNotNull(app.getInsetsState().peekSource(ID_NAVIGATION_BAR));
     }
 
     @SetupWindows(addWindows = W_INPUT_METHOD)
@@ -506,7 +521,8 @@
         final WindowState app2 = createTestWindow("app2");
 
         makeWindowVisible(mImeWindow);
-        final InsetsSourceProvider imeInsetsProvider = getController().getSourceProvider(ITYPE_IME);
+        final InsetsSourceProvider imeInsetsProvider =
+                getController().getOrCreateSourceProvider(ID_IME, ime());
         imeInsetsProvider.setWindowContainer(mImeWindow, null, null);
         imeInsetsProvider.updateSourceFrame(mImeWindow.getFrame());
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java
index ead1a86..e1fc0cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java
@@ -18,7 +18,6 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
-import static com.android.server.wm.LetterboxConfiguration.DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS;
 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
@@ -26,8 +25,6 @@
 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
 import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
@@ -37,7 +34,6 @@
 
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
-import android.provider.DeviceConfig;
 
 import androidx.test.filters.SmallTest;
 
@@ -51,7 +47,7 @@
  * Tests for the {@link LetterboxConfiguration} class.
  *
  * Build/Install/Run:
- *  atest WmTests:LetterboxConfigurationTests
+ *  atest WmTests:LetterboxConfigurationTest
  */
 @SmallTest
 @Presubmit
@@ -233,34 +229,6 @@
                 LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop);
     }
 
-    @Test
-    public void testIsCompatFakeFocusEnabledOnDevice() {
-        boolean wasFakeFocusEnabled = DeviceConfig
-                .getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, false);
-
-        // Set runtime flag to true and build time flag to false
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, "true", false);
-        mLetterboxConfiguration.setIsCompatFakeFocusEnabled(false);
-        assertFalse(mLetterboxConfiguration.isCompatFakeFocusEnabledOnDevice());
-
-        // Set runtime flag to false and build time flag to true
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, "false", false);
-        mLetterboxConfiguration.setIsCompatFakeFocusEnabled(true);
-        assertFalse(mLetterboxConfiguration.isCompatFakeFocusEnabledOnDevice());
-
-        // Set runtime flag to true so that both are enabled
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, "true", false);
-        assertTrue(mLetterboxConfiguration.isCompatFakeFocusEnabledOnDevice());
-
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-                DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, Boolean.toString(wasFakeFocusEnabled),
-                false);
-    }
-
     private void assertForHorizontalMove(int from, int expected, int expectedTime,
             boolean halfFoldPose, BiConsumer<LetterboxConfiguration, Boolean> move) {
         // We are in the current position
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 110ef89..d8037f6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -20,8 +20,10 @@
 import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION;
 import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH;
 import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
+import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS;
 import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
 import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
 import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
 import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT;
 import static android.content.pm.ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION;
@@ -37,6 +39,7 @@
 import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE;
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS;
 import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -71,6 +74,7 @@
 
 import com.android.internal.R;
 
+import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
 
 import org.junit.Before;
@@ -579,6 +583,42 @@
                 /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
     }
 
+    @Test
+    @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT,
+            OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA})
+    public void testOverrideOrientationIfNeeded_whenCameraNotActive_returnsUnchanged() {
+        doReturn(true).when(mLetterboxConfiguration).isCameraCompatTreatmentEnabled(anyBoolean());
+
+        // Recreate DisplayContent with DisplayRotationCompatPolicy
+        mActivity = setUpActivityWithComponent();
+        mController = new LetterboxUiController(mWm, mActivity);
+
+        spyOn(mDisplayContent.mDisplayRotationCompatPolicy);
+        doReturn(false).when(mDisplayContent.mDisplayRotationCompatPolicy)
+                .isActivityEligibleForOrientationOverride(eq(mActivity));
+
+        assertEquals(mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
+    }
+
+    @Test
+    @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT,
+            OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA})
+    public void testOverrideOrientationIfNeeded_whenCameraActive_returnsPortrait() {
+        doReturn(true).when(mLetterboxConfiguration).isCameraCompatTreatmentEnabled(anyBoolean());
+
+        // Recreate DisplayContent with DisplayRotationCompatPolicy
+        mActivity = setUpActivityWithComponent();
+        mController = new LetterboxUiController(mWm, mActivity);
+
+        spyOn(mDisplayContent.mDisplayRotationCompatPolicy);
+        doReturn(true).when(mDisplayContent.mDisplayRotationCompatPolicy)
+                .isActivityEligibleForOrientationOverride(eq(mActivity));
+
+        assertEquals(mController.overrideOrientationIfNeeded(
+                /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_PORTRAIT);
+    }
+
     // shouldUseDisplayLandscapeNaturalOrientation
 
     @Test
@@ -629,6 +669,72 @@
         assertFalse(mController.shouldUseDisplayLandscapeNaturalOrientation());
     }
 
+    @Test
+    @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
+    public void testShouldSendFakeFocus_overrideEnabled_returnsTrue() {
+        doReturn(true).when(mLetterboxConfiguration).isCompatFakeFocusEnabled();
+
+        mController = new LetterboxUiController(mWm, mActivity);
+
+        assertTrue(mController.shouldSendFakeFocus());
+    }
+
+    @Test
+    @DisableCompatChanges({OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
+    public void testShouldSendFakeFocus_overrideDisabled_returnsFalse() {
+        doReturn(true).when(mLetterboxConfiguration).isCompatFakeFocusEnabled();
+
+        mController = new LetterboxUiController(mWm, mActivity);
+
+        assertFalse(mController.shouldSendFakeFocus());
+    }
+
+    @Test
+    @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
+    public void testIsCompatFakeFocusEnabled_propertyDisabledAndOverrideEnabled_fakeFocusDisabled()
+            throws Exception {
+        doReturn(true).when(mLetterboxConfiguration).isCompatFakeFocusEnabled();
+        mockThatProperty(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS, /* value */ false);
+
+        mController = new LetterboxUiController(mWm, mActivity);
+
+        assertFalse(mController.shouldSendFakeFocus());
+    }
+
+    @Test
+    @DisableCompatChanges({OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
+    public void testIsCompatFakeFocusEnabled_propertyEnabled_noOverride_fakeFocusEnabled()
+            throws Exception {
+        doReturn(true).when(mLetterboxConfiguration).isCompatFakeFocusEnabled();
+        mockThatProperty(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS, /* value */ true);
+
+        mController = new LetterboxUiController(mWm, mActivity);
+
+        assertTrue(mController.shouldSendFakeFocus());
+    }
+
+    @Test
+    public void testIsCompatFakeFocusEnabled_propertyDisabled_fakeFocusDisabled()
+            throws Exception {
+        doReturn(true).when(mLetterboxConfiguration).isCompatFakeFocusEnabled();
+        mockThatProperty(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS, /* value */ false);
+
+        mController = new LetterboxUiController(mWm, mActivity);
+
+        assertFalse(mController.shouldSendFakeFocus());
+    }
+
+    @Test
+    public void testIsCompatFakeFocusEnabled_propertyEnabled_fakeFocusEnabled()
+            throws Exception {
+        doReturn(true).when(mLetterboxConfiguration).isCompatFakeFocusEnabled();
+        mockThatProperty(PROPERTY_COMPAT_ENABLE_FAKE_FOCUS, /* value */ true);
+
+        mController = new LetterboxUiController(mWm, mActivity);
+
+        assertTrue(mController.shouldSendFakeFocus());
+    }
+
     private void mockThatProperty(String propertyName, boolean value) throws Exception {
         Property property = new Property(propertyName, /* value */ value, /* packageName */ "",
                  /* className */ "");
diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
index bcaf886..0db983c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
@@ -24,7 +24,9 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.hardware.display.DisplayManager;
@@ -32,6 +34,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.view.Display.Mode;
 import android.view.Surface;
+import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 
 import androidx.test.filters.FlakyTest;
@@ -289,6 +292,22 @@
         assertEquals(FRAME_RATE_VOTE_NONE, overrideWindow.mFrameRateVote);
         assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE);
         assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE);
+
+        // Use default mode if it is animating by shell transition.
+        overrideWindow.mActivityRecord.mSurfaceAnimator.cancelAnimation();
+        registerTestTransitionPlayer();
+        final Transition transition = overrideWindow.mTransitionController.createTransition(
+                WindowManager.TRANSIT_OPEN);
+        transition.collect(overrideWindow.mActivityRecord);
+        assertEquals(0, mPolicy.getPreferredModeId(overrideWindow));
+
+        // If there will be display size change when switching from preferred mode to default mode,
+        // then keep the current preferred mode during animating.
+        mDisplayInfo = spy(mDisplayInfo);
+        final Mode defaultMode = new Mode(4321 /* width */, 1234 /* height */, LOW_REFRESH_RATE);
+        doReturn(defaultMode).when(mDisplayInfo).getDefaultMode();
+        mPolicy = new RefreshRatePolicy(mWm, mDisplayInfo, mDenylist);
+        assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow));
     }
 
     @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 1ab8c1f..74f492f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -16,8 +16,10 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 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.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
@@ -35,6 +37,7 @@
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -56,8 +59,6 @@
 import static com.android.server.wm.ActivityRecord.State.RESUMED;
 import static com.android.server.wm.ActivityRecord.State.STOPPED;
 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
-import static com.android.server.wm.LetterboxConfiguration.PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN;
-import static com.android.server.wm.LetterboxConfiguration.PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -259,6 +260,22 @@
     }
 
     @Test
+    public void testCheckOpaqueIsLetterboxedWhenStrategyIsApplied() {
+        mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
+        setUpDisplaySizeWithApp(2000, 1000);
+        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        // Translucent Activity
+        final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+                .setLaunchedFromUid(mActivity.getUid())
+                .build();
+        doReturn(false).when(translucentActivity).fillsParent();
+        spyOn(mActivity);
+        mTask.addChild(translucentActivity);
+        verify(mActivity).isFinishing();
+    }
+
+    @Test
     public void testRestartProcessIfVisible() {
         setUpDisplaySizeWithApp(1000, 2500);
         doNothing().when(mSupervisor).scheduleRestartTimeout(mActivity);
@@ -1440,7 +1457,7 @@
         // The activity doesn't fill the display, so the letterbox of the rotated activity is
         // overlapped with the rotated content frame of status bar. Hence the status bar shouldn't
         // be transparent.
-        assertFalse(displayPolicy.isFullyTransparentAllowed(w, ITYPE_STATUS_BAR));
+        assertFalse(displayPolicy.isFullyTransparentAllowed(w, statusBars()));
 
         // Activity is sandboxed.
         assertActivityMaxBoundsSandboxed();
@@ -1453,7 +1470,7 @@
 
         // The letterbox should only cover the notch area, so status bar can be transparent.
         assertEquals(new Rect(notchHeight, 0, 0, 0), mActivity.getLetterboxInsets());
-        assertTrue(displayPolicy.isFullyTransparentAllowed(w, ITYPE_STATUS_BAR));
+        assertTrue(displayPolicy.isFullyTransparentAllowed(w, statusBars()));
         assertActivityMaxBoundsSandboxed();
 
         // The insets state for metrics should be rotated (landscape).
@@ -1895,6 +1912,43 @@
     }
 
     @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_RESPECT_REQUESTED_ORIENTATION})
+    public void testOverrideRespectRequestedOrientationIsEnabled_orientationIsRespected() {
+        // Set up a display in landscape
+        setUpDisplaySizeWithApp(2800, 1400);
+
+        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */ false,
+                RESIZE_MODE_UNRESIZEABLE, SCREEN_ORIENTATION_PORTRAIT);
+        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+        // Display should be rotated.
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, activity.mDisplayContent.getOrientation());
+
+        // No size compat mode
+        assertFalse(activity.inSizeCompatMode());
+    }
+
+    @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_RESPECT_REQUESTED_ORIENTATION})
+    public void testOverrideRespectRequestedOrientationIsEnabled_multiWindow_orientationIgnored() {
+        // Set up a display in landscape
+        setUpDisplaySizeWithApp(2800, 1400);
+
+        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */ false,
+                RESIZE_MODE_UNRESIZEABLE, SCREEN_ORIENTATION_PORTRAIT);
+        TaskFragment taskFragment = activity.getTaskFragment();
+        spyOn(taskFragment);
+        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        doReturn(WINDOWING_MODE_MULTI_WINDOW).when(taskFragment).getWindowingMode();
+
+        // Display should not be rotated.
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, activity.mDisplayContent.getOrientation());
+
+        // No size compat mode
+        assertFalse(activity.inSizeCompatMode());
+    }
+
+    @Test
     public void testSplitAspectRatioForUnresizableLandscapeApps() {
         // Set up a display in portrait and ignoring orientation request.
         int screenWidth = 1400;
@@ -2332,6 +2386,29 @@
     }
 
     @Test
+    public void testDisplayIgnoreOrientationRequest_disabledViaDeviceConfig_orientationRespected() {
+        // Set up a display in landscape
+        setUpDisplaySizeWithApp(2800, 1400);
+
+        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */ false,
+                RESIZE_MODE_UNRESIZEABLE, SCREEN_ORIENTATION_PORTRAIT);
+        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+        spyOn(activity.mWmService.mLetterboxConfiguration);
+        doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
+                .isIgnoreOrientationRequestAllowed();
+
+        // Display should not be rotated.
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, activity.mDisplayContent.getOrientation());
+
+        doReturn(false).when(activity.mWmService.mLetterboxConfiguration)
+                .isIgnoreOrientationRequestAllowed();
+
+        // Display should be rotated.
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, activity.mDisplayContent.getOrientation());
+    }
+
+    @Test
     public void testSandboxDisplayApis_unresizableAppNotSandboxed() {
         // Set up a display in landscape with an unresizable app.
         setUpDisplaySizeWithApp(2500, 1000);
@@ -3631,7 +3708,8 @@
         assertEquals(newDensity, mActivity.getConfiguration().densityDpi);
     }
 
-    private ActivityRecord setUpActivityForCompatFakeFocusTest() {
+    @Test
+    public void testShouldSendFakeFocus_compatFakeFocusEnabled() {
         final ActivityRecord activity = new ActivityBuilder(mAtm)
                 .setCreateTask(true)
                 .setOnTop(true)
@@ -3640,69 +3718,40 @@
                         com.android.server.wm.SizeCompatTests.class.getName()))
                 .build();
         final Task task = activity.getTask();
+        spyOn(activity.mLetterboxUiController);
+        doReturn(true).when(activity.mLetterboxUiController).shouldSendFakeFocus();
+
         task.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
-        spyOn(activity.mWmService.mLetterboxConfiguration);
-        doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
-                .isCompatFakeFocusEnabledOnDevice();
-        return activity;
-    }
-
-    @Test
-    @EnableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
-    public void testShouldSendFakeFocus_overrideEnabled_returnsTrue() {
-        ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
-
         assertTrue(activity.shouldSendCompatFakeFocus());
-    }
 
-    @Test
-    @DisableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
-    public void testShouldSendFakeFocus_overrideDisabled_returnsFalse() {
-        ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
+        task.setWindowingMode(WINDOWING_MODE_PINNED);
+        assertFalse(activity.shouldSendCompatFakeFocus());
 
+        task.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertFalse(activity.shouldSendCompatFakeFocus());
     }
 
     @Test
-    @EnableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
-    public void testIsCompatFakeFocusEnabled_optOutPropertyAndOverrideEnabled_fakeFocusDisabled() {
-        ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
-        doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
-                .getPackageManagerProperty(any(), eq(PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT));
+    public void testShouldSendFakeFocus_compatFakeFocusDisabled() {
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setCreateTask(true)
+                .setOnTop(true)
+                // Set the component to be that of the test class in order to enable compat changes
+                .setComponent(ComponentName.createRelative(mContext,
+                        com.android.server.wm.SizeCompatTests.class.getName()))
+                .build();
+        final Task task = activity.getTask();
+        spyOn(activity.mLetterboxUiController);
+        doReturn(false).when(activity.mLetterboxUiController).shouldSendFakeFocus();
 
-        assertFalse(activity.mWmService.mLetterboxConfiguration
-                .isCompatFakeFocusEnabled(activity.info));
-    }
+        task.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+        assertFalse(activity.shouldSendCompatFakeFocus());
 
-    @Test
-    @DisableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
-    public void testIsCompatFakeFocusEnabled_optInPropertyEnabled_noOverride_fakeFocusEnabled() {
-        ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
-        doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
-                .getPackageManagerProperty(any(), eq(PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN));
+        task.setWindowingMode(WINDOWING_MODE_PINNED);
+        assertFalse(activity.shouldSendCompatFakeFocus());
 
-        assertTrue(activity.mWmService.mLetterboxConfiguration
-                .isCompatFakeFocusEnabled(activity.info));
-    }
-
-    @Test
-    public void testIsCompatFakeFocusEnabled_optOutPropertyEnabled_fakeFocusDisabled() {
-        ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
-        doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
-                .getPackageManagerProperty(any(), eq(PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT));
-
-        assertFalse(activity.mWmService.mLetterboxConfiguration
-                .isCompatFakeFocusEnabled(activity.info));
-    }
-
-    @Test
-    public void testIsCompatFakeFocusEnabled_optInPropertyEnabled_fakeFocusEnabled() {
-        ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
-        doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
-                .getPackageManagerProperty(any(), eq(PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN));
-
-        assertTrue(activity.mWmService.mLetterboxConfiguration
-                .isCompatFakeFocusEnabled(activity.info));
+        task.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertFalse(activity.shouldSendCompatFakeFocus());
     }
 
     private int getExpectedSplitSize(int dimensionToSplit) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java
index 22d72ed..c538727 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java
@@ -54,11 +54,11 @@
         final CountDownLatch finishedLatch = new CountDownLatch(1);
         SurfaceSyncGroup syncGroup = new SurfaceSyncGroup(TAG);
         syncGroup.addSyncCompleteCallback(mExecutor, finishedLatch::countDown);
-        SyncTarget syncTarget = new SyncTarget();
+        SurfaceSyncGroup syncTarget = new SurfaceSyncGroup("FakeSyncTarget");
         syncGroup.add(syncTarget, null /* runnable */);
         syncGroup.markSyncReady();
 
-        syncTarget.onBufferReady();
+        syncTarget.markSyncReady();
 
         finishedLatch.await(5, TimeUnit.SECONDS);
         assertEquals(0, finishedLatch.getCount());
@@ -69,22 +69,22 @@
         final CountDownLatch finishedLatch = new CountDownLatch(1);
         SurfaceSyncGroup syncGroup = new SurfaceSyncGroup(TAG);
         syncGroup.addSyncCompleteCallback(mExecutor, finishedLatch::countDown);
-        SyncTarget syncTarget1 = new SyncTarget();
-        SyncTarget syncTarget2 = new SyncTarget();
-        SyncTarget syncTarget3 = new SyncTarget();
+        SurfaceSyncGroup syncTarget1 = new SurfaceSyncGroup("FakeSyncTarget1");
+        SurfaceSyncGroup syncTarget2 = new SurfaceSyncGroup("FakeSyncTarget2");
+        SurfaceSyncGroup syncTarget3 = new SurfaceSyncGroup("FakeSyncTarget3");
 
         syncGroup.add(syncTarget1, null /* runnable */);
         syncGroup.add(syncTarget2, null /* runnable */);
         syncGroup.add(syncTarget3, null /* runnable */);
         syncGroup.markSyncReady();
 
-        syncTarget1.onBufferReady();
+        syncTarget1.markSyncReady();
         assertNotEquals(0, finishedLatch.getCount());
 
-        syncTarget3.onBufferReady();
+        syncTarget3.markSyncReady();
         assertNotEquals(0, finishedLatch.getCount());
 
-        syncTarget2.onBufferReady();
+        syncTarget2.markSyncReady();
 
         finishedLatch.await(5, TimeUnit.SECONDS);
         assertEquals(0, finishedLatch.getCount());
@@ -94,8 +94,8 @@
     public void testAddSyncWhenSyncComplete() {
         SurfaceSyncGroup syncGroup = new SurfaceSyncGroup(TAG);
 
-        SyncTarget syncTarget1 = new SyncTarget();
-        SyncTarget syncTarget2 = new SyncTarget();
+        SurfaceSyncGroup syncTarget1 = new SurfaceSyncGroup("FakeSyncTarget1");
+        SurfaceSyncGroup syncTarget2 = new SurfaceSyncGroup("FakeSyncTarget2");
 
         assertTrue(syncGroup.add(syncTarget1, null /* runnable */));
         syncGroup.markSyncReady();
@@ -114,21 +114,21 @@
         syncGroup1.addSyncCompleteCallback(mExecutor, finishedLatch1::countDown);
         syncGroup2.addSyncCompleteCallback(mExecutor, finishedLatch2::countDown);
 
-        SyncTarget syncTarget1 = new SyncTarget();
-        SyncTarget syncTarget2 = new SyncTarget();
+        SurfaceSyncGroup syncTarget1 = new SurfaceSyncGroup("FakeSyncTarget1");
+        SurfaceSyncGroup syncTarget2 = new SurfaceSyncGroup("FakeSyncTarget2");
 
         assertTrue(syncGroup1.add(syncTarget1, null /* runnable */));
         assertTrue(syncGroup2.add(syncTarget2, null /* runnable */));
         syncGroup1.markSyncReady();
         syncGroup2.markSyncReady();
 
-        syncTarget1.onBufferReady();
+        syncTarget1.markSyncReady();
 
         finishedLatch1.await(5, TimeUnit.SECONDS);
         assertEquals(0, finishedLatch1.getCount());
         assertNotEquals(0, finishedLatch2.getCount());
 
-        syncTarget2.onBufferReady();
+        syncTarget2.markSyncReady();
 
         finishedLatch2.await(5, TimeUnit.SECONDS);
         assertEquals(0, finishedLatch2.getCount());
@@ -144,8 +144,8 @@
         syncGroup1.addSyncCompleteCallback(mExecutor, finishedLatch1::countDown);
         syncGroup2.addSyncCompleteCallback(mExecutor, finishedLatch2::countDown);
 
-        SyncTarget syncTarget1 = new SyncTarget();
-        SyncTarget syncTarget2 = new SyncTarget();
+        SurfaceSyncGroup syncTarget1 = new SurfaceSyncGroup("FakeSyncTarget1");
+        SurfaceSyncGroup syncTarget2 = new SurfaceSyncGroup("FakeSyncTarget2");
 
         assertTrue(syncGroup1.add(syncTarget1, null /* runnable */));
         assertTrue(syncGroup2.add(syncTarget2, null /* runnable */));
@@ -155,12 +155,12 @@
 
         // Finish syncTarget2 first to test that the syncGroup is not complete until the merged sync
         // is also done.
-        syncTarget2.onBufferReady();
+        syncTarget2.markSyncReady();
         finishedLatch2.await(1, TimeUnit.SECONDS);
         // Sync did not complete yet
         assertNotEquals(0, finishedLatch2.getCount());
 
-        syncTarget1.onBufferReady();
+        syncTarget1.markSyncReady();
 
         // The first sync will still get a callback when it's sync requirements are done.
         finishedLatch1.await(5, TimeUnit.SECONDS);
@@ -180,13 +180,13 @@
         syncGroup1.addSyncCompleteCallback(mExecutor, finishedLatch1::countDown);
         syncGroup2.addSyncCompleteCallback(mExecutor, finishedLatch2::countDown);
 
-        SyncTarget syncTarget1 = new SyncTarget();
-        SyncTarget syncTarget2 = new SyncTarget();
+        SurfaceSyncGroup syncTarget1 = new SurfaceSyncGroup("FakeSyncTarget1");
+        SurfaceSyncGroup syncTarget2 = new SurfaceSyncGroup("FakeSyncTarget2");
 
         assertTrue(syncGroup1.add(syncTarget1, null /* runnable */));
         assertTrue(syncGroup2.add(syncTarget2, null /* runnable */));
         syncGroup1.markSyncReady();
-        syncTarget1.onBufferReady();
+        syncTarget1.markSyncReady();
 
         // The first sync will still get a callback when it's sync requirements are done.
         finishedLatch1.await(5, TimeUnit.SECONDS);
@@ -194,7 +194,7 @@
 
         syncGroup2.add(syncGroup1, null /* runnable */);
         syncGroup2.markSyncReady();
-        syncTarget2.onBufferReady();
+        syncTarget2.markSyncReady();
 
         // Verify that the second sync will receive complete since the merged sync was already
         // completed before the merge.
@@ -212,9 +212,9 @@
         syncGroup1.addSyncCompleteCallback(mExecutor, finishedLatch1::countDown);
         syncGroup2.addSyncCompleteCallback(mExecutor, finishedLatch2::countDown);
 
-        SyncTarget syncTarget1 = new SyncTarget();
-        SyncTarget syncTarget2 = new SyncTarget();
-        SyncTarget syncTarget3 = new SyncTarget();
+        SurfaceSyncGroup syncTarget1 = new SurfaceSyncGroup("FakeSyncTarget1");
+        SurfaceSyncGroup syncTarget2 = new SurfaceSyncGroup("FakeSyncTarget2");
+        SurfaceSyncGroup syncTarget3 = new SurfaceSyncGroup("FakeSyncTarget3");
 
         assertTrue(syncGroup1.add(syncTarget1, null /* runnable */));
         assertTrue(syncGroup1.add(syncTarget2, null /* runnable */));
@@ -228,8 +228,8 @@
 
         // Make target1 and target3 ready, but not target2. SyncGroup2 should not be ready since
         // SyncGroup2 also waits for all of SyncGroup1 to finish, which includes target2
-        syncTarget1.onBufferReady();
-        syncTarget3.onBufferReady();
+        syncTarget1.markSyncReady();
+        syncTarget3.markSyncReady();
 
         // Neither SyncGroup will be ready.
         finishedLatch1.await(1, TimeUnit.SECONDS);
@@ -238,7 +238,7 @@
         assertEquals(1, finishedLatch1.getCount());
         assertEquals(1, finishedLatch2.getCount());
 
-        syncTarget2.onBufferReady();
+        syncTarget2.markSyncReady();
 
         // Both sync groups should be ready after target2 completed.
         finishedLatch1.await(5, TimeUnit.SECONDS);
@@ -257,13 +257,13 @@
         syncGroup1.addSyncCompleteCallback(mExecutor, finishedLatch1::countDown);
         syncGroup2.addSyncCompleteCallback(mExecutor, finishedLatch2::countDown);
 
-        SyncTarget syncTarget1 = new SyncTarget();
-        SyncTarget syncTarget2 = new SyncTarget();
-        SyncTarget syncTarget3 = new SyncTarget();
+        SurfaceSyncGroup syncTarget1 = new SurfaceSyncGroup("FakeSyncTarget1");
+        SurfaceSyncGroup syncTarget2 = new SurfaceSyncGroup("FakeSyncTarget2");
+        SurfaceSyncGroup syncTarget3 = new SurfaceSyncGroup("FakeSyncTarget3");
 
         assertTrue(syncGroup1.add(syncTarget1, null /* runnable */));
         assertTrue(syncGroup1.add(syncTarget2, null /* runnable */));
-        syncTarget2.onBufferReady();
+        syncTarget2.markSyncReady();
 
         // Add syncTarget1 to syncGroup2 so it forces syncGroup1 into syncGroup2
         assertTrue(syncGroup2.add(syncTarget1, null /* runnable */));
@@ -272,7 +272,7 @@
         syncGroup1.markSyncReady();
         syncGroup2.markSyncReady();
 
-        syncTarget1.onBufferReady();
+        syncTarget1.markSyncReady();
 
         // Only SyncGroup1 will be ready, but SyncGroup2 still needs its own targets to be ready.
         finishedLatch1.await(1, TimeUnit.SECONDS);
@@ -281,7 +281,7 @@
         assertEquals(0, finishedLatch1.getCount());
         assertEquals(1, finishedLatch2.getCount());
 
-        syncTarget3.onBufferReady();
+        syncTarget3.markSyncReady();
 
         // SyncGroup2 is finished after target3 completed.
         finishedLatch2.await(1, TimeUnit.SECONDS);
@@ -302,7 +302,7 @@
         SurfaceControl.Transaction targetTransaction = spy(new StubTransaction());
         SurfaceSyncGroup.setTransactionFactory(() -> targetTransaction);
 
-        SyncTarget syncTarget = new SyncTarget();
+        SurfaceSyncGroup syncTarget = new SurfaceSyncGroup("FakeSyncTarget");
         assertTrue(
                 syncGroup.add(syncTarget.mISurfaceSyncGroup, true /* parentSyncGroupMerge */,
                         null /* runnable */));
@@ -329,7 +329,7 @@
         SurfaceControl.Transaction targetTransaction = spy(new StubTransaction());
         SurfaceSyncGroup.setTransactionFactory(() -> targetTransaction);
 
-        SyncTarget syncTarget = new SyncTarget();
+        SurfaceSyncGroup syncTarget = new SurfaceSyncGroup("FakeSyncTarget");
         assertTrue(syncGroup.add(syncTarget, null /* runnable */));
         syncTarget.markSyncReady();
 
@@ -344,13 +344,13 @@
         final CountDownLatch finishedLatch = new CountDownLatch(1);
         SurfaceSyncGroup syncGroup = new SurfaceSyncGroup(TAG);
         syncGroup.addSyncCompleteCallback(mExecutor, finishedLatch::countDown);
-        SyncTarget syncTarget = new SyncTarget();
+        SurfaceSyncGroup syncTarget = new SurfaceSyncGroup("FakeSyncTarget");
         syncGroup.add(syncTarget, null /* runnable */);
         // Add the syncTarget to the same syncGroup and ensure it doesn't crash.
         syncGroup.add(syncTarget, null /* runnable */);
         syncGroup.markSyncReady();
 
-        syncTarget.onBufferReady();
+        syncTarget.markSyncReady();
 
         try {
             finishedLatch.await(5, TimeUnit.SECONDS);
@@ -359,14 +359,4 @@
         }
         assertEquals(0, finishedLatch.getCount());
     }
-
-    private static class SyncTarget extends SurfaceSyncGroup {
-        SyncTarget() {
-            super("FakeSyncTarget");
-        }
-
-        void onBufferReady() {
-            markSyncReady();
-        }
-    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 42bbd2d..f4a266c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -352,6 +352,7 @@
         mAtmService.setWindowManager(mWmService);
         mWmService.mDisplayEnabled = true;
         mWmService.mDisplayReady = true;
+        mAtmService.getTransitionController().mIsWaitingForDisplayEnabled = false;
         // Set configuration for default display
         mWmService.getDefaultDisplayContentLocked().reconfigureDisplayLocked();
 
@@ -419,6 +420,7 @@
         LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
         LocalServices.removeServiceForTest(UserManagerInternal.class);
+        LocalServices.removeServiceForTest(ImeTargetVisibilityPolicy.class);
     }
 
     Description getDescription() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 40e8273..060f9d8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -352,6 +352,8 @@
         final int pid = Binder.getCallingPid();
         final int uid = Binder.getCallingUid();
         final ActivityRecord activity = createActivityRecord(mDisplayContent);
+        // Flush EVENT_APPEARED.
+        mController.dispatchPendingEvents();
         final Task task = activity.getTask();
         activity.info.applicationInfo.uid = uid;
         doReturn(pid).when(activity).getPid();
@@ -379,6 +381,8 @@
                 DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
         activity.reparent(taskFragment, POSITION_TOP);
         activity.mLastTaskFragmentOrganizerBeforePip = null;
+        // Flush EVENT_INFO_CHANGED.
+        mController.dispatchPendingEvents();
 
         // Clear invocations now because there will be another transaction for the TaskFragment
         // change above, triggered by the reparent. We only want to test onActivityReparentedToTask
@@ -400,6 +404,8 @@
         final Task task = createTask(mDisplayContent);
         task.addChild(mTaskFragment, POSITION_TOP);
         final ActivityRecord activity = createActivityRecord(task);
+        // Flush EVENT_APPEARED.
+        mController.dispatchPendingEvents();
 
         // Make sure the activity belongs to the same app, but it is in a different pid.
         activity.info.applicationInfo.uid = uid;
@@ -442,6 +448,8 @@
         final Task task = createTask(mDisplayContent);
         task.addChild(mTaskFragment, POSITION_TOP);
         final ActivityRecord activity = createActivityRecord(task);
+        // Flush EVENT_APPEARED.
+        mController.dispatchPendingEvents();
 
         // Make sure the activity is embedded in untrusted mode.
         activity.info.applicationInfo.uid = uid + 1;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 5099869..dab842c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -45,11 +45,13 @@
 import static org.mockito.Mockito.clearInvocations;
 
 import android.content.res.Configuration;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.os.Binder;
 import android.platform.test.annotations.Presubmit;
 import android.view.SurfaceControl;
 import android.window.ITaskFragmentOrganizer;
+import android.window.TaskFragmentAnimationParams;
 import android.window.TaskFragmentInfo;
 import android.window.TaskFragmentOrganizer;
 
@@ -299,35 +301,44 @@
 
     @Test
     public void testEmbeddedTaskFragmentEnterPip_singleActivity_resetOrganizerOverrideConfig() {
-        final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
-                .setOrganizer(mOrganizer)
-                .setFragmentToken(new Binder())
-                .setCreateParentTask()
-                .createActivityCount(1)
+        final Task task = createTask(mDisplayContent);
+        final TaskFragment taskFragment0 = createTaskFragmentWithEmbeddedActivity(task, mOrganizer);
+        final TaskFragment taskFragment1 = new TaskFragmentBuilder(mAtm)
+                .setParentTask(task)
                 .build();
-        final Task task = taskFragment.getTask();
-        final ActivityRecord activity = taskFragment.getTopMostActivity();
+        final ActivityRecord activity = taskFragment0.getTopMostActivity();
         final Rect taskFragmentBounds = new Rect(0, 0, 300, 1000);
         task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        taskFragment.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
-        taskFragment.setBounds(taskFragmentBounds);
+        taskFragment0.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+        taskFragment0.setBounds(taskFragmentBounds);
+        taskFragment0.setAdjacentTaskFragment(taskFragment1);
+        taskFragment0.setCompanionTaskFragment(taskFragment1);
+        taskFragment0.setAnimationParams(new TaskFragmentAnimationParams.Builder()
+                .setAnimationBackgroundColor(Color.GREEN)
+                .build());
 
         assertEquals(taskFragmentBounds, activity.getBounds());
         assertEquals(WINDOWING_MODE_MULTI_WINDOW, activity.getWindowingMode());
+        assertEquals(taskFragment1, taskFragment0.getAdjacentTaskFragment());
+        assertEquals(taskFragment1, taskFragment0.getCompanionTaskFragment());
+        assertNotEquals(TaskFragmentAnimationParams.DEFAULT, taskFragment0.getAnimationParams());
 
         // Move activity to pinned root task.
         mRootWindowContainer.moveActivityToPinnedRootTask(activity,
                 null /* launchIntoPipHostActivity */, "test");
 
         // Ensure taskFragment requested config is reset.
-        assertEquals(taskFragment, activity.getOrganizedTaskFragment());
+        assertEquals(taskFragment0, activity.getOrganizedTaskFragment());
         assertEquals(task, activity.getTask());
         assertTrue(task.inPinnedWindowingMode());
-        assertTrue(taskFragment.inPinnedWindowingMode());
+        assertTrue(taskFragment0.inPinnedWindowingMode());
         final Rect taskBounds = task.getBounds();
-        assertEquals(taskBounds, taskFragment.getBounds());
+        assertEquals(taskBounds, taskFragment0.getBounds());
         assertEquals(taskBounds, activity.getBounds());
-        assertEquals(Configuration.EMPTY, taskFragment.getRequestedOverrideConfiguration());
+        assertEquals(Configuration.EMPTY, taskFragment0.getRequestedOverrideConfiguration());
+        assertNull(taskFragment0.getAdjacentTaskFragment());
+        assertNull(taskFragment0.getCompanionTaskFragment());
+        assertEquals(TaskFragmentAnimationParams.DEFAULT, taskFragment0.getAnimationParams());
         // Because the whole Task is entering PiP, no need to record for future reparent.
         assertNull(activity.mLastTaskFragmentOrganizerBeforePip);
     }
@@ -335,18 +346,8 @@
     @Test
     public void testEmbeddedTaskFragmentEnterPip_multiActivities_notifyOrganizer() {
         final Task task = createTask(mDisplayContent);
-        final TaskFragment taskFragment0 = new TaskFragmentBuilder(mAtm)
-                .setParentTask(task)
-                .setOrganizer(mOrganizer)
-                .setFragmentToken(new Binder())
-                .createActivityCount(1)
-                .build();
-        final TaskFragment taskFragment1 = new TaskFragmentBuilder(mAtm)
-                .setParentTask(task)
-                .setOrganizer(mOrganizer)
-                .setFragmentToken(new Binder())
-                .createActivityCount(1)
-                .build();
+        final TaskFragment taskFragment0 = createTaskFragmentWithEmbeddedActivity(task, mOrganizer);
+        final TaskFragment taskFragment1 = createTaskFragmentWithEmbeddedActivity(task, mOrganizer);
         final ActivityRecord activity0 = taskFragment0.getTopMostActivity();
         final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
         activity0.setVisibility(true /* visible */, false /* deferHidingClient */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index e7813ff..2bfc5ec 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -56,6 +56,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.view.Gravity;
 import android.view.InsetsState;
+import android.view.WindowInsets;
 
 import androidx.test.filters.SmallTest;
 
@@ -1918,16 +1919,20 @@
 
         state.setDisplayFrame(displayFrame);
         if (sl > dl) {
-            state.getSource(ITYPE_CLIMATE_BAR).setFrame(dl, dt, sl, db);
+            state.getOrCreateSource(ITYPE_CLIMATE_BAR, WindowInsets.Type.statusBars())
+                    .setFrame(dl, dt, sl, db);
         }
         if (st > dt) {
-            state.getSource(ITYPE_STATUS_BAR).setFrame(dl, dt, dr, st);
+            state.getOrCreateSource(ITYPE_STATUS_BAR, WindowInsets.Type.statusBars())
+                    .setFrame(dl, dt, dr, st);
         }
         if (sr < dr) {
-            state.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(sr, dt, dr, db);
+            state.getOrCreateSource(ITYPE_EXTRA_NAVIGATION_BAR, WindowInsets.Type.navigationBars())
+                    .setFrame(sr, dt, dr, db);
         }
         if (sb < db) {
-            state.getSource(ITYPE_NAVIGATION_BAR).setFrame(dl, sb, dr, db);
+            state.getOrCreateSource(ITYPE_NAVIGATION_BAR, WindowInsets.Type.navigationBars())
+                    .setFrame(dl, sb, dr, db);
         }
         // Recompute config and push to children.
         display.onRequestedOverrideConfigurationChanged(display.getConfiguration());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index 83be4f0..fec079b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -27,8 +27,10 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -51,8 +53,9 @@
     public static final int DEFAULT_LOGICAL_DISPLAY_DENSITY = 300;
 
     /** Please use the {@link Builder} to create, visible for use in test builder overrides only. */
-    TestDisplayContent(RootWindowContainer rootWindowContainer, Display display) {
-        super(display, rootWindowContainer);
+    TestDisplayContent(RootWindowContainer rootWindowContainer, Display display,
+            @NonNull DeviceStateController deviceStateController) {
+        super(display, rootWindowContainer, deviceStateController);
         // Normally this comes from display-properties as exposed by WM. Without that, just
         // hard-code to FULLSCREEN for tests.
         setWindowingMode(WINDOWING_MODE_FULLSCREEN);
@@ -97,6 +100,8 @@
         private int mStatusBarHeight = 0;
         private SettingsEntry mOverrideSettings;
         private DisplayMetrics mDisplayMetrics;
+        @NonNull
+        private DeviceStateController mDeviceStateController = mock(DeviceStateController.class);
         @Mock
         Context mMockContext;
         @Mock
@@ -198,8 +203,13 @@
                         com.android.internal.R.dimen.default_minimal_size_resizable_task);
             return this;
         }
+        Builder setDeviceStateController(@NonNull DeviceStateController deviceStateController) {
+            mDeviceStateController = deviceStateController;
+            return this;
+        }
         TestDisplayContent createInternal(Display display) {
-            return new TestDisplayContent(mService.mRootWindowContainer, display);
+            return new TestDisplayContent(mService.mRootWindowContainer, display,
+                    mDeviceStateController);
         }
         TestDisplayContent build() {
             SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock);
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 9018138..95348a0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -106,10 +106,8 @@
     private BLASTSyncEngine mSyncEngine;
 
     private Transition createTestTransition(int transitType) {
-        TransitionTracer tracer = mock(TransitionTracer.class);
-        final TransitionController controller = new TransitionController(
-                mock(ActivityTaskManagerService.class), mock(TaskSnapshotController.class),
-                mock(TransitionTracer.class));
+        final TransitionController controller = new TestTransitionController(
+                mock(ActivityTaskManagerService.class));
 
         mSyncEngine = createTestBLASTSyncEngine();
         final Transition t = new Transition(transitType, 0 /* flags */, controller, mSyncEngine);
@@ -780,8 +778,7 @@
 
     @Test
     public void testTimeout() {
-        final TransitionController controller = new TransitionController(mAtm,
-                mock(TaskSnapshotController.class), mock(TransitionTracer.class));
+        final TransitionController controller = new TestTransitionController(mAtm);
         final BLASTSyncEngine sync = new BLASTSyncEngine(mWm);
         final CountDownLatch latch = new CountDownLatch(1);
         // When the timeout is reached, it will finish the sync-group and notify transaction ready.
@@ -1062,9 +1059,7 @@
 
     @Test
     public void testIntermediateVisibility() {
-        final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
-        final TransitionController controller = new TransitionController(mAtm, snapshotController,
-                mock(TransitionTracer.class));
+        final TransitionController controller = new TestTransitionController(mAtm);
         final ITransitionPlayer player = new ITransitionPlayer.Default();
         controller.registerTransitionPlayer(player, null /* playerProc */);
         final Transition openTransition = controller.createTransition(TRANSIT_OPEN);
@@ -1135,10 +1130,8 @@
 
     @Test
     public void testTransientLaunch() {
-        final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
         final ArrayList<ActivityRecord> enteringAnimReports = new ArrayList<>();
-        final TransitionController controller = new TransitionController(mAtm, snapshotController,
-                mock(TransitionTracer.class)) {
+        final TransitionController controller = new TestTransitionController(mAtm) {
             @Override
             protected void dispatchLegacyAppTransitionFinished(ActivityRecord ar) {
                 if (ar.mEnteringAnimation) {
@@ -1147,6 +1140,7 @@
                 super.dispatchLegacyAppTransitionFinished(ar);
             }
         };
+        final TaskSnapshotController snapshotController = controller.mTaskSnapshotController;
         final ITransitionPlayer player = new ITransitionPlayer.Default();
         controller.registerTransitionPlayer(player, null /* playerProc */);
         final Transition openTransition = controller.createTransition(TRANSIT_OPEN);
@@ -1211,9 +1205,7 @@
 
     @Test
     public void testNotReadyPushPop() {
-        final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
-        final TransitionController controller = new TransitionController(mAtm, snapshotController,
-                mock(TransitionTracer.class));
+        final TransitionController controller = new TestTransitionController(mAtm);
         final ITransitionPlayer player = new ITransitionPlayer.Default();
         controller.registerTransitionPlayer(player, null /* playerProc */);
         final Transition openTransition = controller.createTransition(TRANSIT_OPEN);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
index 19da718..7d13de8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.statusBars;
@@ -47,7 +47,7 @@
 
     private InsetsSource mSource = new InsetsSource(ITYPE_STATUS_BAR, statusBars());
     private WindowContainerInsetsSourceProvider mProvider;
-    private InsetsSource mImeSource = new InsetsSource(ITYPE_IME, ime());
+    private InsetsSource mImeSource = new InsetsSource(ID_IME, ime());
     private WindowContainerInsetsSourceProvider mImeProvider;
 
     @Before
@@ -170,10 +170,10 @@
         final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
         statusBar.getFrame().set(0, 0, 500, 100);
         mProvider.setWindowContainer(statusBar, null, null);
-        mProvider.updateControlForFakeTarget(target);
+        mProvider.updateFakeControlTarget(target);
         assertNotNull(mProvider.getControl(target));
         assertNull(mProvider.getControl(target).getLeash());
-        mProvider.updateControlForFakeTarget(null);
+        mProvider.updateFakeControlTarget(null);
         assertNull(mProvider.getControl(target));
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index cac7745..4dd5de3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -200,7 +200,7 @@
         final WindowSurfaceController surfaceController = mock(WindowSurfaceController.class);
         doReturn(true).when(surfaceController).hasSurface();
         spyOn(win);
-        doReturn(true).when(win).isExitAnimationRunningSelfOrParent();
+        doReturn(true).when(win).isAnimationRunningSelfOrParent();
         win.mWinAnimator.mSurfaceController = surfaceController;
         win.mViewVisibility = View.VISIBLE;
         win.mHasSurface = true;
@@ -500,6 +500,51 @@
                 virtualDisplay.getDisplay().getDisplayId());
     }
 
+    @Test
+    public void testSetInTouchModeOnAllDisplays_perDisplayFocusDisabled() {
+        testSetInTouchModeOnAllDisplays(/* perDisplayFocusEnabled= */ false);
+    }
+
+    @Test
+    public void testSetInTouchModeOnAllDisplays_perDisplayFocusEnabled() {
+        testSetInTouchModeOnAllDisplays(/* perDisplayFocusEnabled= */ true);
+    }
+
+    private void testSetInTouchModeOnAllDisplays(boolean perDisplayFocusEnabled) {
+        // Create a couple of extra displays.
+        // setInTouchModeOnAllDisplays should ignore the ownFocus setting.
+        final VirtualDisplay virtualDisplay = createVirtualDisplay(/* ownFocus= */ false);
+        final VirtualDisplay virtualDisplayOwnFocus = createVirtualDisplay(/* ownFocus= */ true);
+
+        // Enable or disable global touch mode (config_perDisplayFocusEnabled setting).
+        // setInTouchModeOnAllDisplays should ignore this value.
+        Resources mockResources = mock(Resources.class);
+        spyOn(mContext);
+        when(mContext.getResources()).thenReturn(mockResources);
+        doReturn(perDisplayFocusEnabled).when(mockResources).getBoolean(
+                com.android.internal.R.bool.config_perDisplayFocusEnabled);
+
+        int callingPid = Binder.getCallingPid();
+        int callingUid = Binder.getCallingUid();
+        doReturn(false).when(mWm).checkCallingPermission(anyString(), anyString(), anyBoolean());
+        when(mWm.mAtmService.instrumentationSourceHasPermission(callingPid,
+                android.Manifest.permission.MODIFY_TOUCH_MODE_STATE)).thenReturn(true);
+
+        for (boolean inTouchMode : new boolean[]{true, false}) {
+            mWm.setInTouchModeOnAllDisplays(inTouchMode);
+            for (int i = 0; i < mWm.mRoot.mChildren.size(); ++i) {
+                DisplayContent dc = mWm.mRoot.mChildren.get(i);
+                // All displays that are not already in the desired touch mode are requested to
+                // change their touch mode.
+                if (dc.isInTouchMode() != inTouchMode) {
+                    verify(mWm.mInputManager).setInTouchMode(
+                            true, callingPid, callingUid, /* hasPermission= */ true,
+                            dc.getDisplay().getDisplayId());
+                }
+            }
+        }
+    }
+
     private VirtualDisplay createVirtualDisplay(boolean ownFocus) {
         // Create virtual display
         Point surfaceSize = new Point(
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index b2761d1..169586e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -871,6 +871,7 @@
         lastReportedTiles.clear();
         called[0] = false;
         task1.positionChildAt(POSITION_TOP, rootTask, false /* includingParents */);
+        mAtm.mTaskOrganizerController.dispatchPendingEvents();
         assertTrue(called[0]);
         assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(0).topActivityType);
 
@@ -1124,11 +1125,11 @@
 
         final Task rootTask = createRootTask();
         final Task task = createTask(rootTask);
-        final ActivityRecord record = createActivityRecord(rootTask.mDisplayContent, task);
+        final ActivityRecord record = createActivityRecordAndDispatchPendingEvents(task);
 
         rootTask.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         record.setTaskDescription(new ActivityManager.TaskDescription("TestDescription"));
-        waitUntilHandlersIdle();
+        mAtm.mTaskOrganizerController.dispatchPendingEvents();
         assertEquals("TestDescription", o.mChangedInfo.taskDescription.getLabel());
     }
 
@@ -1288,6 +1289,8 @@
     public void testAppearDeferThenInfoChange() {
         final ITaskOrganizer organizer = registerMockOrganizer();
         final Task rootTask = createRootTask();
+        // Flush EVENT_APPEARED.
+        mAtm.mTaskOrganizerController.dispatchPendingEvents();
 
         // Assume layout defer
         mWm.mWindowPlacerLocked.deferLayout();
@@ -1310,6 +1313,8 @@
     public void testAppearDeferThenVanish() {
         final ITaskOrganizer organizer = registerMockOrganizer();
         final Task rootTask = createRootTask();
+        // Flush EVENT_APPEARED.
+        mAtm.mTaskOrganizerController.dispatchPendingEvents();
 
         // Assume layout defer
         mWm.mWindowPlacerLocked.deferLayout();
@@ -1328,7 +1333,7 @@
         final ITaskOrganizer organizer = registerMockOrganizer();
         final Task rootTask = createRootTask();
         final Task task = createTask(rootTask);
-        final ActivityRecord record = createActivityRecord(rootTask.mDisplayContent, task);
+        final ActivityRecord record = createActivityRecordAndDispatchPendingEvents(task);
 
         // Assume layout defer
         mWm.mWindowPlacerLocked.deferLayout();
@@ -1358,7 +1363,7 @@
         final ITaskOrganizer organizer = registerMockOrganizer();
         final Task rootTask = createRootTask();
         final Task task = createTask(rootTask);
-        final ActivityRecord record = createActivityRecord(rootTask.mDisplayContent, task);
+        final ActivityRecord record = createActivityRecordAndDispatchPendingEvents(task);
 
         // Assume layout defer
         mWm.mWindowPlacerLocked.deferLayout();
@@ -1381,7 +1386,7 @@
         final ITaskOrganizer organizer = registerMockOrganizer();
         final Task rootTask = createRootTask();
         final Task task = createTask(rootTask);
-        final ActivityRecord record = createActivityRecord(rootTask.mDisplayContent, task);
+        createActivityRecordAndDispatchPendingEvents(task);
 
         // Assume layout defer
         mWm.mWindowPlacerLocked.deferLayout();
@@ -1400,7 +1405,7 @@
         final ITaskOrganizer organizer = registerMockOrganizer();
         final Task rootTask = createRootTask();
         final Task task = createTask(rootTask);
-        final ActivityRecord record = createActivityRecord(rootTask.mDisplayContent, task);
+        final ActivityRecord record = createActivityRecordAndDispatchPendingEvents(task);
 
         // Assume layout defer
         mWm.mWindowPlacerLocked.deferLayout();
@@ -1465,13 +1470,12 @@
         final ITaskOrganizer organizer = registerMockOrganizer();
         final Task rootTask = createRootTask();
         final Task task = createTask(rootTask);
-        final ActivityRecord activity = createActivityRecord(rootTask.mDisplayContent, task);
+        final ActivityRecord activity = createActivityRecordAndDispatchPendingEvents(task);
         final ArgumentCaptor<RunningTaskInfo> infoCaptor =
                 ArgumentCaptor.forClass(RunningTaskInfo.class);
 
         assertTrue(rootTask.isOrganized());
 
-        spyOn(activity);
         doReturn(true).when(activity).inSizeCompatMode();
         doReturn(true).when(activity).isState(RESUMED);
 
@@ -1550,6 +1554,13 @@
         verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivities();
     }
 
+    private ActivityRecord createActivityRecordAndDispatchPendingEvents(Task task) {
+        final ActivityRecord record = createActivityRecord(task);
+        // Flush EVENT_APPEARED.
+        mAtm.mTaskOrganizerController.dispatchPendingEvents();
+        return record;
+    }
+
     /**
      * Verifies that task vanished is called for a specific task.
      */
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 1f60e79..b2d8fed 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -20,7 +20,7 @@
 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.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.Surface.ROTATION_0;
@@ -45,10 +45,8 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
@@ -103,7 +101,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -124,15 +121,6 @@
 @RunWith(WindowTestRunner.class)
 public class WindowStateTests extends WindowTestsBase {
 
-    @Before
-    public void setUp() {
-        // TODO: Let the insets source with new mode keep the visibility control, and remove this
-        // setup code. Now mTopFullscreenOpaqueWindowState will take back the control of insets
-        // visibility.
-        spyOn(mDisplayContent);
-        doNothing().when(mDisplayContent).layoutAndAssignWindowLayersIfNeeded();
-    }
-
     @Test
     public void testIsParentWindowHidden() {
         final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -437,13 +425,15 @@
         final WindowState app = mAppWindow;
         statusBar.mHasSurface = true;
         assertTrue(statusBar.isVisible());
-        mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
+        mDisplayContent.getInsetsStateController()
+                .getOrCreateSourceProvider(ITYPE_STATUS_BAR, statusBars())
                 .setWindowContainer(statusBar, null /* frameProvider */,
                         null /* imeFrameProvider */);
         mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
                 app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
         app.setRequestedVisibleTypes(0, statusBars());
-        mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
+        mDisplayContent.getInsetsStateController()
+                .getOrCreateSourceProvider(ITYPE_STATUS_BAR, statusBars())
                 .updateClientVisibility(app);
         waitUntilHandlersIdle();
         assertFalse(statusBar.isVisible());
@@ -986,19 +976,6 @@
         assertFalse(sameTokenWindow.needsRelativeLayeringToIme());
     }
 
-    @UseTestDisplay(addWindows = {W_ACTIVITY, W_INPUT_METHOD})
-    @Test
-    public void testNeedsRelativeLayeringToIme_systemDialog() {
-        WindowState systemDialogWindow = createWindow(null, TYPE_SECURE_SYSTEM_OVERLAY,
-                mDisplayContent,
-                "SystemDialog", true);
-        mDisplayContent.setImeLayeringTarget(mAppWindow);
-        mAppWindow.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
-        makeWindowVisible(mImeWindow);
-        systemDialogWindow.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
-        assertTrue(systemDialogWindow.needsRelativeLayeringToIme());
-    }
-
     @Test
     public void testSetFreezeInsetsState() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
@@ -1039,12 +1016,16 @@
         mAppWindow.mAboveInsetsState.addSource(navSource);
 
         navSource.setVisible(false);
-        assertTrue(mImeWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
-        assertFalse(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
+        assertTrue(mImeWindow.getInsetsState().isSourceOrDefaultVisible(
+                ITYPE_NAVIGATION_BAR, navigationBars()));
+        assertFalse(mAppWindow.getInsetsState().isSourceOrDefaultVisible(
+                ITYPE_NAVIGATION_BAR, navigationBars()));
 
         navSource.setVisible(true);
-        assertTrue(mImeWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
-        assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
+        assertTrue(mImeWindow.getInsetsState().isSourceOrDefaultVisible(
+                ITYPE_NAVIGATION_BAR, navigationBars()));
+        assertTrue(mAppWindow.getInsetsState().isSourceOrDefaultVisible(
+                ITYPE_NAVIGATION_BAR, navigationBars()));
     }
 
     @Test
@@ -1069,8 +1050,8 @@
         controller.updateAboveInsetsState(false);
 
         // Expect all app windows behind IME can receive IME insets visible.
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
-        assertTrue(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertTrue(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
 
         // Simulate app plays closing transition to app2.
         app.mActivityRecord.commitVisibility(false, false);
@@ -1078,8 +1059,8 @@
         assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
 
         // Verify the IME insets is visible on app, but not for app2 during app task switching.
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
-        assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @Test
@@ -1108,8 +1089,8 @@
 
         // Expect app windows behind IME can receive IME insets visible,
         // but not for app2 in background.
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
-        assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
 
         // Simulate app plays closing transition to app2.
         // And app2 is now IME layering target but not yet to be the IME input target.
@@ -1119,8 +1100,8 @@
         assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
 
         // Verify the IME insets is still visible on app, but not for app2 during task switching.
-        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
-        assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertTrue(app.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @SetupWindows(addWindows = W_ACTIVITY)
@@ -1145,7 +1126,9 @@
         spyOn(app.getDisplayContent());
         app.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
 
-        verify(app.getDisplayContent()).updateImeControlTarget();
+        // Expect updateImeParent will be invoked when the configuration of the IME control
+        // target has changed.
+        verify(app.getDisplayContent()).updateImeControlTarget(eq(true) /* updateImeParent */);
         assertEquals(mAppWindow, mDisplayContent.getImeTarget(IME_TARGET_CONTROL).getWindow());
     }
 
@@ -1163,18 +1146,18 @@
         mNotificationShadeWindow.setHasSurface(true);
         mNotificationShadeWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
         assertTrue(mNotificationShadeWindow.canBeImeTarget());
-        mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_IME).setWindowContainer(
-                mImeWindow, null, null);
+        mDisplayContent.getInsetsStateController().getOrCreateSourceProvider(ID_IME, ime())
+                .setWindowContainer(mImeWindow, null, null);
 
         mDisplayContent.computeImeTarget(true);
         assertEquals(mNotificationShadeWindow, mDisplayContent.getImeTarget(IME_TARGET_LAYERING));
         mDisplayContent.getInsetsStateController().getRawInsetsState()
-                .setSourceVisible(ITYPE_IME, true);
+                .setSourceVisible(ID_IME, true);
 
         // Verify notificationShade can still get IME insets even windowing mode is multi-window.
         InsetsState state = mNotificationShadeWindow.getInsetsState();
-        assertNotNull(state.peekSource(ITYPE_IME));
-        assertTrue(state.getSource(ITYPE_IME).isVisible());
+        assertNotNull(state.peekSource(ID_IME));
+        assertTrue(state.isSourceOrDefaultVisible(ID_IME, ime()));
     }
 
     @Test
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 e5efe05..323894ca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -79,6 +79,7 @@
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
 import android.hardware.display.DisplayManager;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -750,11 +751,11 @@
     }
 
     /**
-     * Creates a {@link TaskFragment} with {@link ActivityRecord} and attach it to the
+     * Creates a {@link TaskFragment} with {@link ActivityRecord}, and attaches it to the
      * {@code parentTask}.
      *
-     * @param parentTask the {@link Task} this TaskFragment is going to be attached
-     * @return the created TaskFragment
+     * @param parentTask the {@link Task} this {@link TaskFragment} is going to be attached.
+     * @return the created {@link TaskFragment}
      */
     static TaskFragment createTaskFragmentWithActivity(@NonNull Task parentTask) {
         return new TaskFragmentBuilder(parentTask.mAtmService)
@@ -763,13 +764,27 @@
                 .build();
     }
 
+    /**
+     * Creates an embedded {@link TaskFragment} organized by {@code organizer} with
+     * {@link ActivityRecord}, and attaches it to the {@code parentTask}.
+     *
+     * @param parentTask the {@link Task} this {@link TaskFragment} is going to be attached.
+     * @param organizer  the {@link TaskFragmentOrganizer} this {@link TaskFragment} is going to be
+     *                   organized by.
+     * @return the created {@link TaskFragment}
+     */
     static TaskFragment createTaskFragmentWithEmbeddedActivity(@NonNull Task parentTask,
-            TaskFragmentOrganizer organizer) {
-        return new TaskFragmentBuilder(parentTask.mAtmService)
+            @NonNull TaskFragmentOrganizer organizer) {
+        final IBinder fragmentToken = new Binder();
+        final TaskFragment taskFragment = new TaskFragmentBuilder(parentTask.mAtmService)
                 .setParentTask(parentTask)
                 .createActivityCount(1)
                 .setOrganizer(organizer)
+                .setFragmentToken(fragmentToken)
                 .build();
+        parentTask.mAtmService.mWindowOrganizerController.mLaunchTaskFragments
+                .put(fragmentToken, taskFragment);
+        return taskFragment;
     }
 
     /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
@@ -1728,6 +1743,14 @@
         }
     }
 
+    static class TestTransitionController extends TransitionController {
+        TestTransitionController(ActivityTaskManagerService atms) {
+            super(atms);
+            mTaskSnapshotController = mock(TaskSnapshotController.class);
+            mTransitionTracer = mock(TransitionTracer.class);
+        }
+    }
+
     static class TestTransitionPlayer extends ITransitionPlayer.Stub {
         final TransitionController mController;
         final WindowOrganizerController mOrganizer;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index 3ff791b..714eb4b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
@@ -39,6 +39,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
+import android.view.WindowInsets;
 import android.window.WindowContext;
 
 import androidx.test.filters.SmallTest;
@@ -262,8 +263,9 @@
     @Test
     public void testSetInsetsFrozen_notAffectImeWindowState() {
         // Pre-condition: make the IME window be controlled by IME insets provider.
-        mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_IME).setWindowContainer(
-                mDisplayContent.mInputMethodWindow, null, null);
+        mDisplayContent.getInsetsStateController()
+                .getOrCreateSourceProvider(ID_IME, WindowInsets.Type.ime())
+                .setWindowContainer(mDisplayContent.mInputMethodWindow, null, null);
 
         // Simulate an app window to be the IME layering target, assume the app window has no
         // frozen insets state by default.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 8c58158..6cf2b2d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -22,7 +22,6 @@
 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.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -32,7 +31,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
@@ -45,16 +43,21 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.os.Binder;
 import android.platform.test.annotations.Presubmit;
 import android.util.SparseBooleanArray;
 import android.view.IRecentsAnimationRunner;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
+import android.window.ScreenCapture;
 
 import androidx.test.filters.SmallTest;
 
@@ -547,26 +550,24 @@
     }
 
     @Test
-    public void testSystemDialogWindow_expectHigherThanIme_inMultiWindow() {
-        // Simulate the app window is in multi windowing mode and being IME target
-        mAppWindow.getConfiguration().windowConfiguration.setWindowingMode(
-                WINDOWING_MODE_MULTI_WINDOW);
-        mDisplayContent.setImeLayeringTarget(mAppWindow);
-        mDisplayContent.setImeInputTarget(mAppWindow);
-        makeWindowVisible(mImeWindow);
+    public void testImeScreenshotLayer() {
+        final Task task = createTask(mDisplayContent);
+        final WindowState imeAppTarget = createAppWindow(task, TYPE_APPLICATION, "imeAppTarget");
+        final Rect bounds = mImeWindow.getParentFrame();
+        final ScreenCapture.ScreenshotHardwareBuffer imeBuffer =
+                ScreenCapture.captureLayersExcluding(mImeWindow.getSurfaceControl(),
+                bounds, 1.0f, PixelFormat.RGB_565, null);
 
-        // Create a popupWindow
-        final WindowState systemDialogWindow = createWindow(null, TYPE_SECURE_SYSTEM_OVERLAY,
-                mDisplayContent, "SystemDialog", true);
-        systemDialogWindow.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
-        spyOn(systemDialogWindow);
+        spyOn(mDisplayContent.mWmService.mTaskSnapshotController);
+        doReturn(imeBuffer).when(mDisplayContent.mWmService.mTaskSnapshotController)
+                .snapshotImeFromAttachedTask(task);
 
-        mDisplayContent.assignChildLayers(mTransaction);
+        mDisplayContent.showImeScreenshot(imeAppTarget);
 
-        // Verify the surface layer of the popupWindow should higher than IME
-        verify(systemDialogWindow).needsRelativeLayeringToIme();
-        assertThat(systemDialogWindow.needsRelativeLayeringToIme()).isTrue();
-        assertZOrderGreaterThan(mTransaction, systemDialogWindow.getSurfaceControl(),
-                mDisplayContent.getImeContainer().getSurfaceControl());
+        assertEquals(imeAppTarget, mDisplayContent.mImeScreenshot.getImeTarget());
+        assertNotNull(mDisplayContent.mImeScreenshot);
+        assertZOrderGreaterThan(mTransaction,
+                mDisplayContent.mImeScreenshot.getImeScreenshotSurface(),
+                imeAppTarget.mSurfaceControl);
     }
 }
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index 133f924..9f3b52e 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -22,6 +22,10 @@
     libs: [
         "services.core",
         "android.hidl.manager-V1.0-java",
+        "android.hardware.usb.gadget-V1.0-java",
+        "android.hardware.usb.gadget-V1.1-java",
+        "android.hardware.usb.gadget-V1.2-java",
+        "android.hardware.usb.gadget-V1-java",
     ],
 
     static_libs: [
@@ -30,9 +34,5 @@
         "android.hardware.usb-V1.2-java",
         "android.hardware.usb-V1.3-java",
         "android.hardware.usb-V2-java",
-        "android.hardware.usb.gadget-V1.0-java",
-        "android.hardware.usb.gadget-V1.1-java",
-        "android.hardware.usb.gadget-V1.2-java",
-        "android.hardware.usb.gadget-V1-java",
     ],
 }
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 17c354a..aa1d556 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -23,7 +23,9 @@
 import android.media.IAudioService;
 import android.media.midi.MidiDeviceInfo;
 import android.os.Bundle;
+import android.os.FileObserver;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.service.usb.UsbAlsaManagerProto;
 import android.util.Slog;
@@ -34,9 +36,11 @@
 
 import libcore.io.IoUtils;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 
 /**
@@ -52,6 +56,11 @@
 
     private static final String ALSA_DIRECTORY = "/dev/snd/";
 
+    private static final int ALSA_DEVICE_TYPE_UNKNOWN = 0;
+    private static final int ALSA_DEVICE_TYPE_PLAYBACK = 1;
+    private static final int ALSA_DEVICE_TYPE_CAPTURE = 2;
+    private static final int ALSA_DEVICE_TYPE_MIDI = 3;
+
     private final Context mContext;
     private IAudioService mAudioService;
     private final boolean mHasMidiFeature;
@@ -110,11 +119,26 @@
     /**
      * List of connected MIDI devices
      */
-    private final HashMap<String, UsbMidiDevice>
-            mMidiDevices = new HashMap<String, UsbMidiDevice>();
+    private final HashMap<String, UsbAlsaMidiDevice>
+            mMidiDevices = new HashMap<String, UsbAlsaMidiDevice>();
 
-    // UsbMidiDevice for USB peripheral mode (gadget) device
-    private UsbMidiDevice mPeripheralMidiDevice = null;
+    // UsbAlsaMidiDevice for USB peripheral mode (gadget) device
+    private UsbAlsaMidiDevice mPeripheralMidiDevice = null;
+
+    private final HashSet<Integer> mAlsaCards = new HashSet<>();
+    private final FileObserver mAlsaObserver = new FileObserver(new File(ALSA_DIRECTORY),
+            FileObserver.CREATE | FileObserver.DELETE) {
+        public void onEvent(int event, String path) {
+            switch (event) {
+                case FileObserver.CREATE:
+                    alsaFileAdded(path);
+                    break;
+                case FileObserver.DELETE:
+                    alsaFileRemoved(path);
+                    break;
+            }
+        }
+    };
 
     /* package */ UsbAlsaManager(Context context) {
         mContext = context;
@@ -124,6 +148,7 @@
     public void systemReady() {
         mAudioService = IAudioService.Stub.asInterface(
                         ServiceManager.getService(Context.AUDIO_SERVICE));
+        mAlsaObserver.startWatching();
     }
 
     /**
@@ -224,6 +249,8 @@
             return;
         }
 
+        waitForAlsaDevice(cardRec.getCardNum(), true /*isAdded*/);
+
         // Add it to the devices list
         boolean hasInput = parser.hasInput()
                 && !isDeviceDenylisted(usbDevice.getVendorId(), usbDevice.getProductId(),
@@ -304,11 +331,11 @@
                 Slog.d(TAG, "numLegacyMidiOutputs:" + numLegacyMidiOutputs);
             }
 
-            UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties,
+            UsbAlsaMidiDevice midiDevice = UsbAlsaMidiDevice.create(mContext, properties,
                     cardRec.getCardNum(), 0 /*device*/, numLegacyMidiInputs,
                     numLegacyMidiOutputs);
-            if (usbMidiDevice != null) {
-                mMidiDevices.put(deviceAddress, usbMidiDevice);
+            if (midiDevice != null) {
+                mMidiDevices.put(deviceAddress, midiDevice);
             }
         }
     }
@@ -322,15 +349,16 @@
         UsbAlsaDevice alsaDevice = removeAlsaDeviceFromList(deviceAddress);
         Slog.i(TAG, "USB Audio Device Removed: " + alsaDevice);
         if (alsaDevice != null && alsaDevice == mSelectedDevice) {
+            waitForAlsaDevice(alsaDevice.getCardNum(), false /*isAdded*/);
             deselectAlsaDevice();
             selectDefaultDevice(); // if there any external devices left, select one of them
         }
 
         // MIDI
-        UsbMidiDevice usbMidiDevice = mMidiDevices.remove(deviceAddress);
-        if (usbMidiDevice != null) {
+        UsbAlsaMidiDevice midiDevice = mMidiDevices.remove(deviceAddress);
+        if (midiDevice != null) {
             Slog.i(TAG, "USB MIDI Device Removed: " + deviceAddress);
-            IoUtils.closeQuietly(usbMidiDevice);
+            IoUtils.closeQuietly(midiDevice);
         }
 
         logDevices("usbDeviceRemoved()");
@@ -353,7 +381,7 @@
                     com.android.internal.R.string.usb_midi_peripheral_product_name));
             properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
             properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
-            mPeripheralMidiDevice = UsbMidiDevice.create(mContext, properties, card, device,
+            mPeripheralMidiDevice = UsbAlsaMidiDevice.create(mContext, properties, card, device,
                     1 /* numInputs */, 1 /* numOutputs */);
         } else if (!enabled && mPeripheralMidiDevice != null) {
             IoUtils.closeQuietly(mPeripheralMidiDevice);
@@ -361,6 +389,89 @@
         }
    }
 
+    private boolean waitForAlsaDevice(int card, boolean isAdded) {
+        if (DEBUG) {
+            Slog.e(TAG, "waitForAlsaDevice(c:" + card + ")");
+        }
+
+        // This value was empirically determined.
+        final int kWaitTimeMs = 2500;
+
+        synchronized (mAlsaCards) {
+            long timeoutMs = SystemClock.elapsedRealtime() + kWaitTimeMs;
+            while ((isAdded ^ mAlsaCards.contains(card))
+                    && timeoutMs > SystemClock.elapsedRealtime()) {
+                long waitTimeMs = timeoutMs - SystemClock.elapsedRealtime();
+                if (waitTimeMs > 0) {
+                    try {
+                        mAlsaCards.wait(waitTimeMs);
+                    } catch (InterruptedException e) {
+                        Slog.d(TAG, "usb: InterruptedException while waiting for ALSA file.");
+                    }
+                }
+            }
+            final boolean cardFound = mAlsaCards.contains(card);
+            if ((isAdded ^ cardFound) && timeoutMs > SystemClock.elapsedRealtime()) {
+                Slog.e(TAG, "waitForAlsaDevice(" + card + ") timeout");
+            } else {
+                Slog.i(TAG, "waitForAlsaDevice for device card=" + card + ", isAdded=" + isAdded
+                        + ", found=" + cardFound);
+            }
+            return cardFound;
+        }
+    }
+
+    private int getCardNumberFromAlsaFilePath(String path) {
+        int type = ALSA_DEVICE_TYPE_UNKNOWN;
+        if (path.startsWith("pcmC")) {
+            if (path.endsWith("p")) {
+                type = ALSA_DEVICE_TYPE_PLAYBACK;
+            } else if (path.endsWith("c")) {
+                type = ALSA_DEVICE_TYPE_CAPTURE;
+            }
+        } else if (path.startsWith("midiC")) {
+            type = ALSA_DEVICE_TYPE_MIDI;
+        }
+
+        if (type == ALSA_DEVICE_TYPE_UNKNOWN) {
+            Slog.i(TAG, "Unknown type file(" + path + ") added.");
+            return -1;
+        }
+        try {
+            int c_index = path.indexOf('C');
+            int d_index = path.indexOf('D');
+            return Integer.parseInt(path.substring(c_index + 1, d_index));
+        } catch (Exception e) {
+            Slog.e(TAG, "Could not parse ALSA file name " + path, e);
+            return -1;
+        }
+    }
+
+    private void alsaFileAdded(String path) {
+        Slog.i(TAG, "alsaFileAdded(" + path + ")");
+        final int card = getCardNumberFromAlsaFilePath(path);
+        if (card == -1) {
+            return;
+        }
+        synchronized (mAlsaCards) {
+            if (!mAlsaCards.contains(card)) {
+                Slog.d(TAG, "Adding ALSA device card=" + card);
+                mAlsaCards.add(card);
+                mAlsaCards.notifyAll();
+            }
+        }
+    }
+
+    private void alsaFileRemoved(String path) {
+        final int card = getCardNumberFromAlsaFilePath(path);
+        if (card == -1) {
+            return;
+        }
+        synchronized (mAlsaCards) {
+            mAlsaCards.remove(card);
+        }
+    }
+
     //
     // Devices List
     //
@@ -389,9 +500,9 @@
         }
 
         for (String deviceAddr : mMidiDevices.keySet()) {
-            // A UsbMidiDevice does not have a handle to the UsbDevice anymore
-            mMidiDevices.get(deviceAddr).dump(deviceAddr, dump, "midi_devices",
-                    UsbAlsaManagerProto.MIDI_DEVICES);
+            // A UsbAlsaMidiDevice does not have a handle to the UsbDevice anymore
+            mMidiDevices.get(deviceAddr).dump(deviceAddr, dump, "alsa_midi_devices",
+                    UsbAlsaManagerProto.ALSA_MIDI_DEVICES);
         }
 
         dump.end(token);
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbAlsaMidiDevice.java
similarity index 91%
rename from services/usb/java/com/android/server/usb/UsbMidiDevice.java
rename to services/usb/java/com/android/server/usb/UsbAlsaMidiDevice.java
index d9ad703..e92c034 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaMidiDevice.java
@@ -10,7 +10,7 @@
  * 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 an
+ * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
@@ -24,7 +24,7 @@
 import android.media.midi.MidiManager;
 import android.media.midi.MidiReceiver;
 import android.os.Bundle;
-import android.service.usb.UsbMidiDeviceProto;
+import android.service.usb.UsbAlsaMidiDeviceProto;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -43,8 +43,12 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 
-public final class UsbMidiDevice implements Closeable {
-    private static final String TAG = "UsbMidiDevice";
+/**
+ * Opens device connections to MIDI 1.0 endpoints.
+ * These endpoints will use ALSA.
+ */
+public final class UsbAlsaMidiDevice implements Closeable {
+    private static final String TAG = "UsbAlsaMidiDevice";
 
     private final int mAlsaCard;
     private final int mAlsaDevice;
@@ -142,13 +146,13 @@
     }
 
     /**
-     * Creates an UsbMidiDevice based on the input parameters. Read/Write streams
+     * Creates an UsbAlsaMidiDevice based on the input parameters. Read/Write streams
      * will be created individually as some devices don't have the same number of
      * inputs and outputs.
      */
-    public static UsbMidiDevice create(Context context, Bundle properties, int card,
+    public static UsbAlsaMidiDevice create(Context context, Bundle properties, int card,
             int device, int numInputs, int numOutputs) {
-        UsbMidiDevice midiDevice = new UsbMidiDevice(card, device, numInputs, numOutputs);
+        UsbAlsaMidiDevice midiDevice = new UsbAlsaMidiDevice(card, device, numInputs, numOutputs);
         if (!midiDevice.register(context, properties)) {
             IoUtils.closeQuietly(midiDevice);
             Log.e(TAG, "createDeviceServer failed");
@@ -157,7 +161,7 @@
         return midiDevice;
     }
 
-    private UsbMidiDevice(int card, int device, int numInputs, int numOutputs) {
+    private UsbAlsaMidiDevice(int card, int device, int numInputs, int numOutputs) {
         mAlsaCard = card;
         mAlsaDevice = device;
         mNumInputs = numInputs;
@@ -217,7 +221,7 @@
 
         if (inputStreamCount > 0) {
             // Create input thread which will read from all output ports of the physical device
-            new Thread("UsbMidiDevice input thread") {
+            new Thread("UsbAlsaMidiDevice input thread") {
                 @Override
                 public void run() {
                     byte[] buffer = new byte[BUFFER_SIZE];
@@ -272,13 +276,13 @@
             final FileOutputStream outputStreamF = mOutputStreams[port];
             final int portF = port;
 
-            new Thread("UsbMidiDevice output thread " + port) {
+            new Thread("UsbAlsaMidiDevice output thread " + port) {
                 @Override
                 public void run() {
                     while (true) {
                         MidiEvent event;
                         try {
-                            event = (MidiEvent)eventSchedulerF.waitNextEvent();
+                            event = (MidiEvent) eventSchedulerF.waitNextEvent();
                         } catch (InterruptedException e) {
                             // try again
                             continue;
@@ -303,9 +307,9 @@
     }
 
     private boolean register(Context context, Bundle properties) {
-        MidiManager midiManager = (MidiManager)context.getSystemService(Context.MIDI_SERVICE);
+        MidiManager midiManager = context.getSystemService(MidiManager.class);
         if (midiManager == null) {
-            Log.e(TAG, "No MidiManager in UsbMidiDevice.register()");
+            Log.e(TAG, "No MidiManager in UsbAlsaMidiDevice.register()");
             return false;
         }
 
@@ -365,9 +369,9 @@
             long id) {
         long token = dump.start(idName, id);
 
-        dump.write("device_address", UsbMidiDeviceProto.DEVICE_ADDRESS, deviceAddr);
-        dump.write("card", UsbMidiDeviceProto.CARD, mAlsaCard);
-        dump.write("device", UsbMidiDeviceProto.DEVICE, mAlsaDevice);
+        dump.write("device_address", UsbAlsaMidiDeviceProto.DEVICE_ADDRESS, deviceAddr);
+        dump.write("card", UsbAlsaMidiDeviceProto.CARD, mAlsaCard);
+        dump.write("device", UsbAlsaMidiDeviceProto.DEVICE, mAlsaDevice);
 
         dump.end(token);
     }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index a480ebd..12e5ed9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -44,7 +44,6 @@
 import android.debug.AdbNotifications;
 import android.debug.AdbTransportType;
 import android.debug.IAdbTransport;
-import android.hardware.usb.IUsbOperationInternal;
 import android.hardware.usb.ParcelableUsbPort;
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbConfiguration;
@@ -57,7 +56,6 @@
 import android.hardware.usb.gadget.V1_0.GadgetFunction;
 import android.hardware.usb.gadget.V1_0.Status;
 import android.hardware.usb.gadget.V1_2.UsbSpeed;
-import android.hidl.manager.V1_0.IServiceManager;
 import android.hidl.manager.V1_0.IServiceNotification;
 import android.os.BatteryManager;
 import android.os.Environment;
@@ -1351,6 +1349,9 @@
                         || (mCurrentFunctions == UsbManager.FUNCTION_NCM)) {
                     titleRes = com.android.internal.R.string.usb_tether_notification_title;
                     id = SystemMessage.NOTE_USB_TETHER;
+                } else if (mCurrentFunctions == UsbManager.FUNCTION_UVC) {
+                    titleRes = com.android.internal.R.string.usb_uvc_notification_title;
+                    id = SystemMessage.NOTE_USB_UVC;
                 } else if (mCurrentFunctions == UsbManager.FUNCTION_ACCESSORY) {
                     titleRes = com.android.internal.R.string.usb_accessory_notification_title;
                     id = SystemMessage.NOTE_USB_ACCESSORY;
@@ -2403,6 +2404,9 @@
             MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_RNDIS);
         } else if (functions == UsbManager.FUNCTION_ACCESSORY) {
             MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_ACCESSORY);
+        } else if (functions == UsbManager.FUNCTION_UVC) {
+            // MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_UVC);
+            // TODO: Add MetricsEvent for UVC?
         }
         mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, operationId);
     }
diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp
index af0eca9..7332d2d 100644
--- a/services/voiceinteraction/Android.bp
+++ b/services/voiceinteraction/Android.bp
@@ -20,6 +20,7 @@
     srcs: [":services.voiceinteraction-sources"],
     libs: [
         "services.core",
+        "app-compat-annotations",
         "android.hardware.power-V1-java",
         "android.hardware.power-V1.0-java",
     ],
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 81717f4..7824c69 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -298,35 +298,33 @@
         }
 
         @Override
-        public int startRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback,
+        public int startRecognition(GenericSoundModel soundModel,
+                IRecognitionStatusCallback callback,
                 RecognitionConfig config, boolean runInBatterySaverMode) {
             try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                 enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+
+                if (soundModel == null) {
+                    Slog.e(TAG, "Null model passed to startRecognition");
+                    return STATUS_ERROR;
+                }
+
                 if (runInBatterySaverMode) {
                     enforceCallingPermission(Manifest.permission.SOUND_TRIGGER_RUN_IN_BATTERY_SAVER);
                 }
 
                 if (DEBUG) {
-                    Slog.i(TAG, "startRecognition(): Uuid : " + parcelUuid);
+                    Slog.i(TAG, "startRecognition(): Uuid : " + soundModel.toString());
                 }
 
                 sEventLogger.enqueue(new EventLogger.StringEvent(
-                        "startRecognition(): Uuid : " + parcelUuid));
+                        "startRecognition(): Uuid : " + soundModel.getUuid().toString()));
 
-                GenericSoundModel model = getSoundModel(parcelUuid);
-                if (model == null) {
-                    Slog.w(TAG, "Null model in database for id: " + parcelUuid);
-
-                    sEventLogger.enqueue(new EventLogger.StringEvent(
-                            "startRecognition(): Null model in database for id: " + parcelUuid));
-
-                    return STATUS_ERROR;
-                }
-
-                int ret = mSoundTriggerHelper.startGenericRecognition(parcelUuid.getUuid(), model,
+                int ret = mSoundTriggerHelper.startGenericRecognition(soundModel.getUuid(),
+                        soundModel,
                         callback, config, runInBatterySaverMode);
                 if (ret == STATUS_OK) {
-                    mSoundModelStatTracker.onStart(parcelUuid.getUuid());
+                    mSoundModelStatTracker.onStart(soundModel.getUuid());
                 }
                 return ret;
             }
@@ -379,8 +377,7 @@
 
                 sEventLogger.enqueue(new EventLogger.StringEvent("updateSoundModel(): model = "
                         + soundModel));
-
-                mDbHelper.updateGenericSoundModel(soundModel);
+               mDbHelper.updateGenericSoundModel(soundModel);
             }
         }
 
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 445446e..cc22847 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -51,7 +51,6 @@
 import android.os.ServiceManager;
 import android.os.SharedMemory;
 import android.provider.DeviceConfig;
-import android.service.voice.HotwordDetectedResult;
 import android.service.voice.HotwordDetectionService;
 import android.service.voice.HotwordDetector;
 import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
@@ -66,6 +65,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IHotwordRecognitionStatusCallback;
+import com.android.internal.app.IVisualQueryDetectionAttentionListener;
 import com.android.internal.infra.ServiceConnector;
 import com.android.server.LocalServices;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
@@ -88,19 +88,18 @@
     static final boolean DEBUG = false;
 
     /**
-     * For apps targeting Android API {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above,
-     * implementors of the {@link HotwordDetectionService} must not augment the phrase IDs which are
-     * supplied via {@link HotwordDetectionService
-     * #onDetect(AlwaysOnHotwordDetector.EventPayload, long, HotwordDetectionService.Callback)}.
+     * For apps targeting Android API Build.VERSION_CODES#UPSIDE_DOWN_CAKE and above,
+     * implementors of the HotwordDetectionService must not augment the phrase IDs which are
+     * supplied via HotwordDetectionService
+     * #onDetect(AlwaysOnHotwordDetector.EventPayload, long, HotwordDetectionService.Callback).
      *
-     * <p>The {@link HotwordDetectedResult#getHotwordPhraseId()} must match one of the phrase IDs
-     * from the {@link android.service.voice.AlwaysOnHotwordDetector
-     * .EventPayload#getKeyphraseRecognitionExtras()} list.
+     * <p>The HotwordDetectedResult#getHotwordPhraseId() must match one of the phrase IDs
+     * from the AlwaysOnHotwordDetector.EventPayload#getKeyphraseRecognitionExtras() list.
      * </p>
      *
-     * <p>This behavior change is made to ensure the {@link HotwordDetectionService} honors what
-     * it receives from the {@link android.hardware.soundtrigger.SoundTriggerModule}, and it
-     * cannot signal to the client application a phrase which was not origially detected.
+     * <p>This behavior change is made to ensure the HotwordDetectionService honors what
+     * it receives from the android.hardware.soundtrigger.SoundTriggerModule, and it
+     * cannot signal to the client application a phrase which was not originally detected.
      * </p>
      */
     @ChangeId
@@ -328,6 +327,15 @@
         session.startListeningFromMicLocked(audioFormat, callback);
     }
 
+    public void setVisualQueryDetectionAttentionListenerLocked(
+            @Nullable IVisualQueryDetectionAttentionListener listener) {
+        final VisualQueryDetectorSession session = getVisualQueryDetectorSessionLocked();
+        if (session == null) {
+            return;
+        }
+        session.setVisualQueryDetectionAttentionListenerLocked(listener);
+    }
+
     /**
      * This method is only used by VisualQueryDetector.
      */
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
index 621c3de..33150d8 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
@@ -33,6 +33,7 @@
 import android.util.Slog;
 
 import com.android.internal.app.IHotwordRecognitionStatusCallback;
+import com.android.internal.app.IVisualQueryDetectionAttentionListener;
 
 import java.io.PrintWriter;
 import java.util.Objects;
@@ -49,6 +50,7 @@
 final class VisualQueryDetectorSession extends DetectorSession {
 
     private static final String TAG = "VisualQueryDetectorSession";
+    private IVisualQueryDetectionAttentionListener mAttentionListener;
     private boolean mEgressingData;
     private boolean mQueryStreaming;
 
@@ -64,6 +66,7 @@
                 logging);
         mEgressingData = false;
         mQueryStreaming = false;
+        mAttentionListener = null;
     }
 
     @Override
@@ -74,6 +77,11 @@
         //TODO(b/261783819): Starts detection in VisualQueryDetectionService.
     }
 
+    void setVisualQueryDetectionAttentionListenerLocked(
+            @Nullable IVisualQueryDetectionAttentionListener listener) {
+        mAttentionListener = listener;
+    }
+
     @SuppressWarnings("GuardedBy")
     void startPerceivingLocked(IVisualQueryDetectionVoiceInteractionCallback callback) {
         if (DEBUG) {
@@ -86,15 +94,31 @@
             @Override
             public void onAttentionGained() {
                 Slog.v(TAG, "BinderCallback#onAttentionGained");
-                //TODO check to see if there is an active SysUI listener registered
                 mEgressingData = true;
+                if (mAttentionListener == null) {
+                    return;
+                }
+                try {
+                    mAttentionListener.onAttentionGained();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Error delivering attention gained event.", e);
+                    return;
+                }
             }
 
             @Override
             public void onAttentionLost() {
                 Slog.v(TAG, "BinderCallback#onAttentionLost");
-                //TODO check to see if there is an active SysUI listener registered
                 mEgressingData = false;
+                if (mAttentionListener == null) {
+                    return;
+                }
+                try {
+                    mAttentionListener.onAttentionLost();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Error delivering attention lost event.", e);
+                    return;
+                }
             }
 
             @Override
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 38bf9c2..0abed0b 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -87,6 +87,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IHotwordRecognitionStatusCallback;
+import com.android.internal.app.IVisualQueryDetectionAttentionListener;
 import com.android.internal.app.IVoiceActionCheckCallback;
 import com.android.internal.app.IVoiceInteractionManagerService;
 import com.android.internal.app.IVoiceInteractionSessionListener;
@@ -1338,6 +1339,39 @@
             }
         }
 
+        @android.annotation.EnforcePermission(
+                android.Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE)
+        @Override
+        public void enableVisualQueryDetection(
+                IVisualQueryDetectionAttentionListener listener) {
+            super.enableVisualQueryDetection_enforcePermission();
+            synchronized (this) {
+
+                if (mImpl == null) {
+                    Slog.w(TAG,
+                            "enableVisualQueryDetection without running voice interaction service");
+                    return;
+                }
+                this.mImpl.setVisualQueryDetectionAttentionListenerLocked(listener);
+            }
+        }
+
+        @android.annotation.EnforcePermission(
+                android.Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE)
+        @Override
+        public void disableVisualQueryDetection() {
+            super.disableVisualQueryDetection_enforcePermission();
+            synchronized (this) {
+                if (mImpl == null) {
+                    Slog.w(TAG,
+                            "disableVisualQueryDetection without running voice interaction"
+                                    + " service");
+                    return;
+                }
+                this.mImpl.setVisualQueryDetectionAttentionListenerLocked(null);
+            }
+        }
+
         @Override
         public void startPerceiving(
                 IVisualQueryDetectionVoiceInteractionCallback callback)
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 127195c..3dbd269 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -72,7 +72,9 @@
 import android.util.Slog;
 import android.view.IWindowManager;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IHotwordRecognitionStatusCallback;
+import com.android.internal.app.IVisualQueryDetectionAttentionListener;
 import com.android.internal.app.IVoiceActionCheckCallback;
 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
@@ -247,6 +249,7 @@
                 Context.RECEIVER_EXPORTED);
     }
 
+    @GuardedBy("this")
     public void grantImplicitAccessLocked(int grantRecipientUid, @Nullable Intent intent) {
         final int grantRecipientAppId = UserHandle.getAppId(grantRecipientUid);
         final int grantRecipientUserId = UserHandle.getUserId(grantRecipientUid);
@@ -256,6 +259,7 @@
                 /* direct= */ true);
     }
 
+    @GuardedBy("this")
     public boolean showSessionLocked(@Nullable Bundle args, int flags,
             @Nullable String attributionTag,
             @Nullable IVoiceInteractionSessionShowCallback showCallback,
@@ -328,6 +332,7 @@
         }
     }
 
+    @GuardedBy("this")
     public boolean hideSessionLocked() {
         if (mActiveSession != null) {
             return mActiveSession.hideLocked();
@@ -335,6 +340,7 @@
         return false;
     }
 
+    @GuardedBy("this")
     public boolean deliverNewSessionLocked(IBinder token,
             IVoiceInteractionSession session, IVoiceInteractor interactor) {
         if (mActiveSession == null || token != mActiveSession.mToken) {
@@ -345,6 +351,7 @@
         return true;
     }
 
+    @GuardedBy("this")
     public int startVoiceActivityLocked(@Nullable String callingFeatureId, int callingPid,
             int callingUid, IBinder token, Intent intent, String resolvedType) {
         try {
@@ -367,6 +374,7 @@
         }
     }
 
+    @GuardedBy("this")
     public int startAssistantActivityLocked(@Nullable String callingFeatureId, int callingPid,
             int callingUid, IBinder token, Intent intent, String resolvedType) {
         try {
@@ -389,6 +397,7 @@
         }
     }
 
+    @GuardedBy("this")
     public void requestDirectActionsLocked(@NonNull IBinder token, int taskId,
             @NonNull IBinder assistToken,  @Nullable RemoteCallback cancellationCallback,
             @NonNull RemoteCallback callback) {
@@ -444,6 +453,7 @@
         }
     }
 
+    @GuardedBy("this")
     void performDirectActionLocked(@NonNull IBinder token, @NonNull String actionId,
             @Nullable Bundle arguments, int taskId, IBinder assistToken,
             @Nullable RemoteCallback cancellationCallback,
@@ -470,6 +480,7 @@
         }
     }
 
+    @GuardedBy("this")
     public void setKeepAwakeLocked(IBinder token, boolean keepAwake) {
         try {
             if (mActiveSession == null || token != mActiveSession.mToken) {
@@ -482,6 +493,7 @@
         }
     }
 
+    @GuardedBy("this")
     public void closeSystemDialogsLocked(IBinder token) {
         try {
             if (mActiveSession == null || token != mActiveSession.mToken) {
@@ -494,6 +506,7 @@
         }
     }
 
+    @GuardedBy("this")
     public void finishLocked(IBinder token, boolean finishTask) {
         if (mActiveSession == null || (!finishTask && token != mActiveSession.mToken)) {
             Slog.w(TAG, "finish does not match active session");
@@ -503,6 +516,7 @@
         mActiveSession = null;
     }
 
+    @GuardedBy("this")
     public void setDisabledShowContextLocked(int callingUid, int flags) {
         int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
         if (callingUid != activeUid) {
@@ -512,6 +526,7 @@
         mDisabledShowContext = flags;
     }
 
+    @GuardedBy("this")
     public int getDisabledShowContextLocked(int callingUid) {
         int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
         if (callingUid != activeUid) {
@@ -521,6 +536,7 @@
         return mDisabledShowContext;
     }
 
+    @GuardedBy("this")
     public int getUserDisabledShowContextLocked(int callingUid) {
         int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
         if (callingUid != activeUid) {
@@ -534,6 +550,7 @@
         return mInfo.getSupportsLocalInteraction();
     }
 
+    @GuardedBy("this")
     public void startListeningVisibleActivityChangedLocked(@NonNull IBinder token) {
         if (DEBUG) {
             Slog.d(TAG, "startListeningVisibleActivityChangedLocked: token=" + token);
@@ -546,6 +563,7 @@
         mActiveSession.startListeningVisibleActivityChangedLocked();
     }
 
+    @GuardedBy("this")
     public void stopListeningVisibleActivityChangedLocked(@NonNull IBinder token) {
         if (DEBUG) {
             Slog.d(TAG, "stopListeningVisibleActivityChangedLocked: token=" + token);
@@ -558,6 +576,7 @@
         mActiveSession.stopListeningVisibleActivityChangedLocked();
     }
 
+    @GuardedBy("this")
     public void notifyActivityDestroyedLocked(@NonNull IBinder activityToken) {
         if (DEBUG) {
             Slog.d(TAG, "notifyActivityDestroyedLocked activityToken=" + activityToken);
@@ -572,6 +591,7 @@
         mActiveSession.notifyActivityDestroyedLocked(activityToken);
     }
 
+    @GuardedBy("this")
     public void notifyActivityEventChangedLocked(@NonNull IBinder activityToken, int type) {
         if (DEBUG) {
             Slog.d(TAG, "notifyActivityEventChangedLocked type=" + type);
@@ -586,6 +606,7 @@
         mActiveSession.notifyActivityEventChangedLocked(activityToken, type);
     }
 
+    @GuardedBy("this")
     public void updateStateLocked(
             @Nullable PersistableBundle options,
             @Nullable SharedMemory sharedMemory,
@@ -606,6 +627,7 @@
         }
     }
 
+    @GuardedBy("this")
     private void verifyDetectorForHotwordDetectionLocked(
             @Nullable SharedMemory sharedMemory,
             IHotwordRecognitionStatusCallback callback,
@@ -663,6 +685,7 @@
                 voiceInteractionServiceUid);
     }
 
+    @GuardedBy("this")
     private void verifyDetectorForVisualQueryDetectionLocked(@Nullable SharedMemory sharedMemory) {
         Slog.v(TAG, "verifyDetectorForVisualQueryDetectionLocked");
 
@@ -701,6 +724,7 @@
         }
     }
 
+    @GuardedBy("this")
     public void initAndVerifyDetectorLocked(
             @NonNull Identity voiceInteractorIdentity,
             @Nullable PersistableBundle options,
@@ -730,6 +754,7 @@
                 detectorType);
     }
 
+    @GuardedBy("this")
     public void destroyDetectorLocked(IBinder token) {
         Slog.v(TAG, "destroyDetectorLocked");
 
@@ -748,6 +773,7 @@
         }
     }
 
+    @GuardedBy("this")
     public void shutdownHotwordDetectionServiceLocked() {
         if (DEBUG) {
             Slog.d(TAG, "shutdownHotwordDetectionServiceLocked");
@@ -760,6 +786,16 @@
         mHotwordDetectionConnection = null;
     }
 
+    @GuardedBy("this")
+    public void setVisualQueryDetectionAttentionListenerLocked(
+            @Nullable IVisualQueryDetectionAttentionListener listener) {
+        if (mHotwordDetectionConnection == null) {
+            return;
+        }
+        mHotwordDetectionConnection.setVisualQueryDetectionAttentionListenerLocked(listener);
+    }
+
+    @GuardedBy("this")
     public void startPerceivingLocked(IVisualQueryDetectionVoiceInteractionCallback callback) {
         if (DEBUG) {
             Slog.d(TAG, "startPerceivingLocked");
@@ -773,6 +809,7 @@
         mHotwordDetectionConnection.startPerceivingLocked(callback);
     }
 
+    @GuardedBy("this")
     public void stopPerceivingLocked() {
         if (DEBUG) {
             Slog.d(TAG, "stopPerceivingLocked");
@@ -786,6 +823,7 @@
         mHotwordDetectionConnection.stopPerceivingLocked();
     }
 
+    @GuardedBy("this")
     public void startListeningFromMicLocked(
             AudioFormat audioFormat,
             IMicrophoneHotwordDetectionVoiceInteractionCallback callback) {
@@ -801,6 +839,7 @@
         mHotwordDetectionConnection.startListeningFromMicLocked(audioFormat, callback);
     }
 
+    @GuardedBy("this")
     public void startListeningFromExternalSourceLocked(
             ParcelFileDescriptor audioStream,
             AudioFormat audioFormat,
@@ -825,6 +864,7 @@
                 options, token, callback);
     }
 
+    @GuardedBy("this")
     public void stopListeningFromMicLocked() {
         if (DEBUG) {
             Slog.d(TAG, "stopListeningFromMicLocked");
@@ -838,6 +878,7 @@
         mHotwordDetectionConnection.stopListeningFromMicLocked();
     }
 
+    @GuardedBy("this")
     public void triggerHardwareRecognitionEventForTestLocked(
             SoundTrigger.KeyphraseRecognitionEvent event,
             IHotwordRecognitionStatusCallback callback) {
@@ -852,6 +893,7 @@
         mHotwordDetectionConnection.triggerHardwareRecognitionEventForTestLocked(event, callback);
     }
 
+    @GuardedBy("this")
     public IRecognitionStatusCallback createSoundTriggerCallbackLocked(
             IHotwordRecognitionStatusCallback callback) {
         if (DEBUG) {
@@ -876,6 +918,7 @@
         return null;
     }
 
+    @GuardedBy("this")
     boolean isIsolatedProcessLocked(@NonNull ServiceInfo serviceInfo) {
         return (serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
                 && (serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) == 0;
@@ -889,6 +932,7 @@
         mHotwordDetectionConnection.forceRestart();
     }
 
+    @GuardedBy("this")
     void setDebugHotwordLoggingLocked(boolean logging) {
         if (mHotwordDetectionConnection == null) {
             Slog.w(TAG, "Failed to set temporary debug logging: no hotword detection active");
@@ -897,6 +941,7 @@
         mHotwordDetectionConnection.setDebugHotwordLoggingLocked(logging);
     }
 
+    @GuardedBy("this")
     void resetHotwordDetectionConnectionLocked() {
         if (DEBUG) {
             Slog.d(TAG, "resetHotwordDetectionConnectionLocked");
@@ -911,6 +956,7 @@
         mHotwordDetectionConnection = null;
     }
 
+    @GuardedBy("this")
     public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!mValid) {
             pw.print("  NOT VALID: ");
@@ -947,6 +993,7 @@
         }
     }
 
+    @GuardedBy("this")
     void startLocked() {
         Intent intent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
         intent.setComponent(mComponent);
@@ -971,6 +1018,7 @@
         }
     }
 
+    @GuardedBy("this")
     void shutdownLocked() {
         // If there is an active session, cancel it to allow it to clean up its window and other
         // state.
@@ -998,6 +1046,7 @@
         }
     }
 
+    @GuardedBy("this")
     void notifySoundModelsChangedLocked() {
         if (mService == null) {
             Slog.w(TAG, "Not bound to voice interaction service " + mComponent);
diff --git a/telecomm/java/android/telecom/CallAttributes.java b/telecomm/java/android/telecom/CallAttributes.java
index 6d87981..1a0f192 100644
--- a/telecomm/java/android/telecom/CallAttributes.java
+++ b/telecomm/java/android/telecom/CallAttributes.java
@@ -116,13 +116,13 @@
      */
     public static final int SUPPORTS_STREAM = 1 << 2;
     /**
-     * The call can be completely transferred from one endpoint to another
+     * The call can be completely transferred from one endpoint to another.
      */
     public static final int SUPPORTS_TRANSFER = 1 << 3;
 
     /**
      * Build an instance of {@link CallAttributes}. In order to build a valid instance, a
-     * {@link PhoneAccountHandle}, call {@link Direction}, display name, and {@link Uri} address
+     * {@link PhoneAccountHandle}, call direction, display name, and {@link Uri} address
      * are required.
      *
      * <p>
@@ -165,7 +165,8 @@
         }
 
         /**
-         * @param callType see {@link CallType} for valid arguments
+         * Sets the type of call; uses to indicate if a call is a video call or audio call.
+         * @param callType The call type.
          * @return Builder
          */
         @NonNull
@@ -180,7 +181,9 @@
         }
 
         /**
-         * @param callCapabilities see {@link CallCapability} for valid arguments
+         * Sets the capabilities of this call.  Use this to indicate whether your app supports
+         * holding, streaming and call transfers.
+         * @param callCapabilities Bitmask of call capabilities.
          * @return Builder
          */
         @NonNull
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index 315ac67..f3c91f6 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -28,6 +28,7 @@
 import android.os.ParcelUuid;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.text.TextUtils;
 
 import com.android.internal.telecom.ClientTransactionalServiceRepository;
 import com.android.internal.telecom.ICallControl;
@@ -67,7 +68,7 @@
 
     /**
      * @return the callId Telecom assigned to this CallControl object which should be attached to
-     *  an individual call.
+     * an individual call.
      */
     @NonNull
     public ParcelUuid getCallId() {
@@ -78,9 +79,9 @@
      * Request Telecom set the call state to active.
      *
      * @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
-     *                will be called on.
+     *                 will be called on.
      * @param callback that will be completed on the Telecom side that details success or failure
-     *                of the requested operation.
+     *                 of the requested operation.
      *
      *                 {@link OutcomeReceiver#onResult} will be called if Telecom has successfully
      *                 switched the call state to active
@@ -109,9 +110,9 @@
      * but can be extended to setting a meeting to inactive.
      *
      * @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
-     *                will be called on.
+     *                 will be called on.
      * @param callback that will be completed on the Telecom side that details success or failure
-     *                of the requested operation.
+     *                 of the requested operation.
      *
      *                 {@link OutcomeReceiver#onResult} will be called if Telecom has successfully
      *                 switched the call state to inactive
@@ -136,23 +137,42 @@
     }
 
     /**
-     * Request Telecom set the call state to disconnect.
+     * Request Telecom disconnect the call and remove the call from telecom tracking.
      *
-     * @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
-     *                will be called on.
-     * @param callback that will be completed on the Telecom side that details success or failure
-     *                of the requested operation.
+     * @param disconnectCause represents the cause for disconnecting the call.  The only valid
+     *                        codes for the {@link  android.telecom.DisconnectCause} passed in are:
+     *                        <ul>
+     *                        <li>{@link DisconnectCause#LOCAL}</li>
+     *                        <li>{@link DisconnectCause#REMOTE}</li>
+     *                        <li>{@link DisconnectCause#REJECTED}</li>
+     *                        <li>{@link DisconnectCause#MISSED}</li>
+     *                        </ul>
      *
-     *                 {@link OutcomeReceiver#onResult} will be called if Telecom has successfully
-     *                 disconnected the call.
+     * @param executor        The {@link Executor} on which the {@link OutcomeReceiver} callback
+     *                        will be called on.
      *
-     *                 {@link OutcomeReceiver#onError} will be called if Telecom has failed to
-     *                 disconnect the call.  A {@link CallException} will be passed
-     *                 that details why the operation failed.
+     * @param callback        That will be completed on the Telecom side that details success or
+     *                        failure of the requested operation.
+     *
+     *                        {@link OutcomeReceiver#onResult} will be called if Telecom has
+     *                        successfully disconnected the call.
+     *
+     *                        {@link OutcomeReceiver#onError} will be called if Telecom has failed
+     *                        to disconnect the call.  A {@link CallException} will be passed
+     *                        that details why the operation failed.
+     *
+     * <p>
+     * Note: After the call has been successfully disconnected, calling any CallControl API will
+     * result in the {@link OutcomeReceiver#onError} with
+     * {@link CallException#CODE_CALL_IS_NOT_BEING_TRACKED}.
      */
     public void disconnect(@NonNull DisconnectCause disconnectCause,
             @CallbackExecutor @NonNull Executor executor,
             @NonNull OutcomeReceiver<Void, CallException> callback) {
+        Objects.requireNonNull(disconnectCause);
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+        validateDisconnectCause(disconnectCause);
         if (mServerInterface != null) {
             try {
                 mServerInterface.disconnect(mCallId, disconnectCause,
@@ -166,35 +186,6 @@
     }
 
     /**
-     * Request Telecom reject the incoming call.
-     *
-     * @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
-     *                will be called on.
-     * @param callback that will be completed on the Telecom side that details success or failure
-     *                of the requested operation.
-     *
-     *                 {@link OutcomeReceiver#onResult} will be called if Telecom has successfully
-     *                 rejected the incoming call.
-     *
-     *                 {@link OutcomeReceiver#onError} will be called if Telecom has failed to
-     *                 reject the incoming call.  A {@link CallException} will be passed
-     *                 that details why the operation failed.
-     */
-    public void rejectCall(@CallbackExecutor @NonNull Executor executor,
-            @NonNull OutcomeReceiver<Void, CallException> callback) {
-        if (mServerInterface != null) {
-            try {
-                mServerInterface.rejectCall(mCallId,
-                        new CallControlResultReceiver("rejectCall", executor, callback));
-            } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
-            }
-        } else {
-            throw new IllegalStateException(INTERFACE_ERROR_MSG);
-        }
-    }
-
-    /**
      * Request start a call streaming session. On receiving valid request, telecom will bind to
      * the {@link CallStreamingService} implemented by a general call streaming sender. So that the
      * call streaming sender can perform streaming local device audio to another remote device and
@@ -231,10 +222,10 @@
      * requesting a change. Instead, the new endpoint should be one of the valid endpoints provided
      * by {@link CallEventCallback#onAvailableCallEndpointsChanged(List)}.
      *
-     * @param callEndpoint ; The {@link CallEndpoint} to change to.
-     * @param executor     ; The {@link Executor} on which the {@link OutcomeReceiver} callback
+     * @param callEndpoint The {@link CallEndpoint} to change to.
+     * @param executor     The {@link Executor} on which the {@link OutcomeReceiver} callback
      *                     will be called on.
-     * @param callback     ; The {@link OutcomeReceiver} that will be completed on the Telecom side
+     * @param callback     The {@link OutcomeReceiver} that will be completed on the Telecom side
      *                     that details success or failure of the requested operation.
      *
      *                     {@link OutcomeReceiver#onResult} will be called if Telecom has
@@ -266,7 +257,9 @@
      * Since {@link OutcomeReceiver}s cannot be passed via AIDL, a ResultReceiver (which can) must
      * wrap the Clients {@link OutcomeReceiver} passed in and await for the Telecom Server side
      * response in {@link ResultReceiver#onReceiveResult(int, Bundle)}.
-     * @hide */
+     *
+     * @hide
+     */
     private class CallControlResultReceiver extends ResultReceiver {
         private final String mCallingMethod;
         private final Executor mExecutor;
@@ -308,4 +301,18 @@
         }
         return new CallException(message, CallException.CODE_ERROR_UNKNOWN);
     }
+
+    /** @hide */
+    private void validateDisconnectCause(DisconnectCause disconnectCause) {
+        final int code = disconnectCause.getCode();
+        if (code != DisconnectCause.LOCAL && code != DisconnectCause.REMOTE
+                && code != DisconnectCause.MISSED && code != DisconnectCause.REJECTED) {
+            throw new IllegalArgumentException(TextUtils.formatSimple(
+                    "The DisconnectCause code provided, %d , is not a valid Disconnect code. Valid "
+                            + "DisconnectCause codes are limited to [DisconnectCause.LOCAL, "
+                            + "DisconnectCause.REMOTE, DisconnectCause.MISSED, or "
+                            + "DisconnectCause.REJECTED]", disconnectCause.getCode()));
+        }
+    }
+
 }
diff --git a/telecomm/java/android/telecom/CallException.java b/telecomm/java/android/telecom/CallException.java
index 0b0de6b..d191593 100644
--- a/telecomm/java/android/telecom/CallException.java
+++ b/telecomm/java/android/telecom/CallException.java
@@ -116,17 +116,6 @@
     }
 
     /**
-     * Constructor for a new CallException when only message can be specified.
-     * {@code CODE_ERROR_UNKNOWN} will be default code returned when calling {@code getCode}
-     *
-     * @param message related to why the exception was created
-     */
-    public CallException(@Nullable String message) {
-        super(getMessage(message, CODE_ERROR_UNKNOWN));
-        mMessage = message;
-    }
-
-    /**
      * Constructor for a new CallException that has a defined error code in this class
      *
      * @param message related to why the exception was created
diff --git a/telecomm/java/android/telecom/CallStreamingService.java b/telecomm/java/android/telecom/CallStreamingService.java
index affa6b6..7f11128 100644
--- a/telecomm/java/android/telecom/CallStreamingService.java
+++ b/telecomm/java/android/telecom/CallStreamingService.java
@@ -79,7 +79,7 @@
                     break;
                 case MSG_CALL_STREAMING_CHANGED_CHANGED:
                     int state = (int) msg.obj;
-                    mCall.setStreamingState(state);
+                    mCall.requestStreamingState(state);
                     CallStreamingService.this.onCallStreamingStateChanged(state);
                     break;
                 default:
diff --git a/telecomm/java/android/telecom/StreamingCall.java b/telecomm/java/android/telecom/StreamingCall.java
index 985cccc..4b27dd6 100644
--- a/telecomm/java/android/telecom/StreamingCall.java
+++ b/telecomm/java/android/telecom/StreamingCall.java
@@ -172,7 +172,7 @@
      * to request holding, unholding and disconnecting this {@code StreamingCall}.
      * @param state The current streaming state of the call.
      */
-    public void setStreamingState(@StreamingCallState int state) {
+    public void requestStreamingState(@StreamingCallState int state) {
         mAdapter.setStreamingState(state);
     }
 }
diff --git a/telecomm/java/android/telecom/StreamingCallAdapter.java b/telecomm/java/android/telecom/StreamingCallAdapter.java
index bd8727d..54a3e24 100644
--- a/telecomm/java/android/telecom/StreamingCallAdapter.java
+++ b/telecomm/java/android/telecom/StreamingCallAdapter.java
@@ -25,7 +25,7 @@
  * Telecom. When Telecom binds to a {@link CallStreamingService}, an instance of this class is given
  * to the general streaming app through which it can manipulate the streaming calls. Whe the general
  * streaming app is notified of new ongoing streaming calls, it can execute
- * {@link StreamingCall#setStreamingState(int)} for the ongoing streaming calls the user on the
+ * {@link StreamingCall#requestStreamingState(int)} for the ongoing streaming calls the user on the
  * receiver side would like to hold, unhold and disconnect.
  *
  * @hide
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 7c86a75a..20564d6 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -951,6 +951,23 @@
     public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
 
     /**
+     * Intent action to trigger "switch to managed profile" dialog for call in SystemUI
+     *
+     * @hide
+     */
+    public static final String ACTION_SHOW_SWITCH_TO_WORK_PROFILE_FOR_CALL_DIALOG =
+            "android.telecom.action.SHOW_SWITCH_TO_WORK_PROFILE_FOR_CALL_DIALOG";
+
+    /**
+     * Extra specifying the managed profile user id.
+     * This is used with {@link TelecomManager#ACTION_SHOW_SWITCH_TO_WORK_PROFILE_FOR_CALL_DIALOG}
+     *
+     * @hide
+     */
+    public static final String EXTRA_MANAGED_PROFILE_USER_ID =
+            "android.telecom.extra.MANAGED_PROFILE_USER_ID";
+
+    /**
      * Indicating the call is initiated via emergency dialer's shortcut button.
      *
      * @hide
diff --git a/telecomm/java/com/android/internal/telecom/ICallControl.aidl b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
index a5c6e44..b78a77e 100644
--- a/telecomm/java/com/android/internal/telecom/ICallControl.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
@@ -28,7 +28,6 @@
     void setActive(String callId, in ResultReceiver callback);
     void setInactive(String callId, in ResultReceiver callback);
     void disconnect(String callId, in DisconnectCause disconnectCause, in ResultReceiver callback);
-    void rejectCall(String callId, in ResultReceiver callback);
     void startCallStreaming(String callId, in ResultReceiver callback);
     void requestCallEndpointChange(in CallEndpoint callEndpoint, in ResultReceiver callback);
 }
\ No newline at end of file
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index d4a8600..8662359 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -20,6 +20,7 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -859,7 +860,7 @@
             if ((subManager != null) &&
                     (!subManager.isSubscriptionAssociatedWithUser(subId, callerUserHandle))) {
                 // If subId is not associated with calling user, return false.
-                Log.e(LOG_TAG,"User[User ID:" + callerUserHandle.getIdentifier()
+                Log.e(LOG_TAG, "User[User ID:" + callerUserHandle.getIdentifier()
                         + "] is not associated with Subscription ID:" + subId);
                 return false;
 
@@ -869,4 +870,27 @@
         }
         return true;
     }
+
+    /**
+     * Ensure the caller (or self, if not processing an IPC) has
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
+     * {@link android.Manifest.permission#READ_PHONE_NUMBERS}.
+     *
+     * @throws SecurityException if the caller does not have the required permission/privileges
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PHONE_NUMBERS,
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE
+    })
+    public static boolean checkCallingOrSelfReadPrivilegedPhoneStatePermissionOrReadPhoneNumber(
+            Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+            String message) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            return false;
+        }
+        return (context.checkCallingOrSelfPermission(
+                Manifest.permission.READ_PRIVILEGED_PHONE_STATE) == PERMISSION_GRANTED
+                || checkCallingOrSelfReadPhoneNumber(context, subId, callingPackage,
+                callingFeatureId, message));
+    }
 }
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index 3dc7111..cbac34f 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -19,6 +19,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
@@ -26,10 +27,16 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.PersistableBundle;
+import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.telephony.ITelephony;
 
 import java.io.PrintWriter;
 import java.util.Collections;
@@ -43,6 +50,8 @@
  * This class provides various util functions
  */
 public final class TelephonyUtils {
+    private static final String LOG_TAG = "TelephonyUtils";
+
     public static boolean IS_USER = "user".equals(android.os.Build.TYPE);
     public static boolean IS_DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
 
@@ -240,4 +249,59 @@
         }
         return userHandle;
     }
+
+    /**
+     * Show switch to managed profile dialog if subscription is associated with managed profile.
+     *
+     * @param context Context object
+     * @param subId   subscription id
+     */
+    public static void showErrorIfSubscriptionAssociatedWithManagedProfile(Context context,
+            int subId) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            SubscriptionManager subscriptionManager = context.getSystemService(
+                    SubscriptionManager.class);
+            UserHandle associatedUserHandle = subscriptionManager.getSubscriptionUserHandle(subId);
+            UserManager um = context.getSystemService(UserManager.class);
+
+            if (associatedUserHandle != null && um.isManagedProfile(
+                    associatedUserHandle.getIdentifier())) {
+
+                ITelephony iTelephony = ITelephony.Stub.asInterface(
+                        TelephonyFrameworkInitializer
+                                .getTelephonyServiceManager()
+                                .getTelephonyServiceRegisterer()
+                                .get());
+                if (iTelephony != null) {
+                    try {
+                        iTelephony.showSwitchToManagedProfileDialog();
+                    } catch (RemoteException e) {
+                        Log.e(LOG_TAG, "Failed to launch switch to managed profile dialog.");
+                    }
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    /**
+     * Check if the process with given uid is foreground.
+     *
+     * @param context context
+     * @param uid     the caller uid
+     * @return true if the process with uid is foreground, false otherwise.
+     */
+    public static boolean isUidForeground(Context context, int uid) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ActivityManager am = context.getSystemService(ActivityManager.class);
+            boolean result = am != null && am.getUidImportance(uid)
+                    == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+            return result;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
 }
\ No newline at end of file
diff --git a/telephony/java/android/service/euicc/EuiccService.java b/telephony/java/android/service/euicc/EuiccService.java
index 2c0087e..b59e855 100644
--- a/telephony/java/android/service/euicc/EuiccService.java
+++ b/telephony/java/android/service/euicc/EuiccService.java
@@ -17,10 +17,12 @@
 
 import static android.telephony.euicc.EuiccCardManager.ResetOption;
 
+import android.Manifest;
 import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.app.PendingIntent;
@@ -132,13 +134,25 @@
      * @see android.telephony.euicc.EuiccManager#ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS
      * The difference is this one is used by system to bring up the LUI.
      */
+    @RequiresPermission(Manifest.permission.BIND_EUICC_SERVICE)
     public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
             "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
 
     /** @see android.telephony.euicc.EuiccManager#ACTION_PROVISION_EMBEDDED_SUBSCRIPTION */
+    @RequiresPermission(Manifest.permission.BIND_EUICC_SERVICE)
     public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION =
             "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
 
+    /** @see android.telephony.euicc.EuiccManager#ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS */
+    @RequiresPermission(Manifest.permission.BIND_EUICC_SERVICE)
+    public static final String ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS =
+            "android.service.euicc.action.TRANSFER_EMBEDDED_SUBSCRIPTIONS";
+
+    /** @see android.telephony.euicc.EuiccManager#ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION */
+    @RequiresPermission(Manifest.permission.BIND_EUICC_SERVICE)
+    public static final String ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION =
+            "android.service.euicc.action.CONVERT_TO_EMBEDDED_SUBSCRIPTION";
+
     /**
      * @see android.telephony.euicc.EuiccManager#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED. This is
      * a protected intent that can only be sent by the system, and requires the
diff --git a/telephony/java/android/telephony/CallState.java b/telephony/java/android/telephony/CallState.java
index 51ecfb0..836cb53 100644
--- a/telephony/java/android/telephony/CallState.java
+++ b/telephony/java/android/telephony/CallState.java
@@ -285,12 +285,12 @@
     /**
      * Builder of {@link CallState}
      *
-     * <p>The example below shows how you might create a new {@code CallState}:
+     * <p>The example below shows how you might create a new {@code CallState}. A precise call state
+     * {@link PreciseCallStates} is mandatory to build a CallState.
      *
      * <pre><code>
      *
-     * CallState = new CallState.Builder()
-     *     .setCallState(3)
+     * CallState = new CallState.Builder({@link PreciseCallStates})
      *     .setNetworkType({@link TelephonyManager#NETWORK_TYPE_LTE})
      *     .setCallQuality({@link CallQuality})
      *     .setImsCallSessionId({@link String})
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f0f230f..3bfbf03 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3866,13 +3866,12 @@
      * NR_SA - NR SA is unmetered for sub-6 frequencies
      * NR_SA_MMWAVE - NR SA is unmetered for mmwave frequencies
      *
-     * Note that this config only applies if an unmetered SubscriptionPlan is set via
-     * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set
+     * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link
+     * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set
      * via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)}
      * or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}.
      * If neither SubscriptionPlans nor an override are set, then no network types can be unmetered
      * regardless of the value of this config.
-     * TODO: remove other unmetered keys and replace with this
      * @hide
      */
     public static final String KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY =
@@ -3887,73 +3886,18 @@
      * NR_SA - NR SA is unmetered when roaming for sub-6 frequencies
      * NR_SA_MMWAVE - NR SA is unmetered when roaming for mmwave frequencies
      *
-     * Note that this config only applies if an unmetered SubscriptionPlan is set via
-     * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set
+     * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link
+     * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set
      * via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)}
      * or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}.
      * If neither SubscriptionPlans nor an override are set, then no network types can be unmetered
      * when roaming regardless of the value of this config.
-     * TODO: remove KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL and replace with this
      * @hide
      */
     public static final String KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY =
             "roaming_unmetered_network_types_string_array";
 
     /**
-     * Whether NR (non-standalone) should be unmetered for all frequencies.
-     * If either {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL} or
-     * {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL} are true, then this value will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_NSA_BOOL = "unmetered_nr_nsa_bool";
-
-    /**
-     * Whether NR (non-standalone) frequencies above 6GHz (millimeter wave) should be unmetered.
-     * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_NSA_MMWAVE_BOOL = "unmetered_nr_nsa_mmwave_bool";
-
-    /**
-     * Whether NR (non-standalone) frequencies below 6GHz (sub6) should be unmetered.
-     * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_NSA_SUB6_BOOL = "unmetered_nr_nsa_sub6_bool";
-
-    /**
-     * Whether NR (non-standalone) should be unmetered when the device is roaming.
-     * If false, then the values for {@link #KEY_UNMETERED_NR_NSA_BOOL},
-     * {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL}, {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL},
-     * and unmetered {@link SubscriptionPlan} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL =
-            "unmetered_nr_nsa_when_roaming_bool";
-
-    /**
-     * Whether NR (standalone) should be unmetered for all frequencies.
-     * If either {@link #KEY_UNMETERED_NR_SA_MMWAVE_BOOL} or
-     * {@link #KEY_UNMETERED_NR_SA_SUB6_BOOL} are true, then this value will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_SA_BOOL = "unmetered_nr_sa_bool";
-
-    /**
-     * Whether NR (standalone) frequencies above 6GHz (millimeter wave) should be unmetered.
-     * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_SA_MMWAVE_BOOL = "unmetered_nr_sa_mmwave_bool";
-
-    /**
-     * Whether NR (standalone) frequencies below 6GHz (sub6) should be unmetered.
-     * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored.
-     * @hide
-     */
-    public static final String KEY_UNMETERED_NR_SA_SUB6_BOOL = "unmetered_nr_sa_sub6_bool";
-
-    /**
      * Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable
      * this feature.
      * @hide
@@ -7046,11 +6990,11 @@
 
         /**
          * Maximum Retry Count for SMS over IMS on Failure, If the Retry Count exceeds this value,
-         * and if the retry count is less than KEY_SMS_MAX_RETRY_COUNT_INT
+         * and if the retry count is less than {@link #KEY_SMS_MAX_RETRY_COUNT_INT}
          * sending SMS should fallback to CS
          */
-        public static final String KEY_SMS_MAX_RETRY_COUNT_OVER_IMS_INT =
-                KEY_PREFIX + "sms_max_retry_count_over_ims_int";
+        public static final String KEY_SMS_MAX_RETRY_OVER_IMS_COUNT_INT =
+                KEY_PREFIX + "sms_max_retry_over_ims_count_int";
 
         /**
          * Delay Timer Value in milliseconds
@@ -7118,7 +7062,7 @@
             defaults.putInt(KEY_SMS_OVER_IMS_FORMAT_INT, SMS_FORMAT_3GPP);
 
             defaults.putInt(KEY_SMS_MAX_RETRY_COUNT_INT, 3);
-            defaults.putInt(KEY_SMS_MAX_RETRY_COUNT_OVER_IMS_INT, 3);
+            defaults.putInt(KEY_SMS_MAX_RETRY_OVER_IMS_COUNT_INT, 3);
             defaults.putInt(KEY_SMS_OVER_IMS_SEND_RETRY_DELAY_MILLIS_INT,
                     2000);
             defaults.putInt(KEY_SMS_TR1_TIMER_MILLIS_INT, 130000);
@@ -9045,8 +8989,9 @@
             "carrier_certificate_string_array";
 
     /**
-     * Flag specifying whether the incoming call number should be formatted to national number
-     * for Japan. @return {@code true} convert to the national format, {@code false} otherwise.
+     * Flag specifying whether the incoming call number and the conference participant number
+     * should be formatted to national number for Japan.
+     * @return {@code true} convert to the national format, {@code false} otherwise.
      * e.g. "+819012345678" -> "09012345678"
      * @hide
      */
@@ -10043,13 +9988,6 @@
         sDefaults.putStringArray(KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[] {
                 "NR_NSA", "NR_NSA_MMWAVE", "NR_SA", "NR_SA_MMWAVE"});
         sDefaults.putStringArray(KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[0]);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_SUB6_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_SA_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_SA_MMWAVE_BOOL, false);
-        sDefaults.putBoolean(KEY_UNMETERED_NR_SA_SUB6_BOOL, false);
         sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_WIFI_CALLING_ICON_IN_STATUS_BAR_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, false);
@@ -10122,7 +10060,7 @@
         sDefaults.putAll(Bsf.getDefaults());
         sDefaults.putAll(Iwlan.getDefaults());
         sDefaults.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, new String[0]);
-         sDefaults.putBoolean(KEY_FORMAT_INCOMING_NUMBER_TO_NATIONAL_FOR_JP_BOOL, false);
+        sDefaults.putBoolean(KEY_FORMAT_INCOMING_NUMBER_TO_NATIONAL_FOR_JP_BOOL, false);
         sDefaults.putIntArray(KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY,
                 new int[] {4 /* BUSY */});
         sDefaults.putBoolean(KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL, false);
diff --git a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
index 8308821..c2f5b8f 100644
--- a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
+++ b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
@@ -23,6 +23,7 @@
 import android.telephony.euicc.EuiccCardManager;
 import android.telephony.euicc.EuiccManager;
 import android.telephony.ims.ImsManager;
+import android.telephony.satellite.SatelliteManager;
 
 import com.android.internal.util.Preconditions;
 
@@ -98,6 +99,11 @@
                 context -> SmsManager.getSmsManagerForContextAndSubscriptionId(context,
                         SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
         );
+        SystemServiceRegistry.registerContextAwareService(
+                Context.SATELLITE_SERVICE,
+                SatelliteManager.class,
+                context -> new SatelliteManager(context)
+        );
     }
 
     /** @hide */
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0921834..819b0b2 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6000,6 +6000,7 @@
      * Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
      * @return the IMPI, or null if not present or not loaded
      * @hide
+     * @deprecated use {@link #getImsPrivateUserIdentity()}
      */
     @UnsupportedAppUsage
     public String getIsimImpi() {
@@ -6018,6 +6019,35 @@
     }
 
     /**
+     * Returns the IMS private user identity (IMPI) of the subscription that was loaded from the
+     * ISIM records {@link #APPTYPE_ISIM}. This value is fetched from the Elementary file EF_IMPI.
+     * The contents of the file is a <b>Ip Multimedia Service Private User Identity</b> of the user
+     * as defined in the section 4.2.2 of 3GPP TS 131 103.
+     *
+     * @return IMPI (IMS private user identity) of type string.
+     * @throws IllegalStateException in case the ISIM has’t been loaded
+     * @throws SecurityException if the caller does not have the required permission/privileges
+     * @hide
+     */
+    @NonNull
+    @RequiresPermission(android.Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER)
+    @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
+    public String getImsPrivateUserIdentity() {
+        try {
+            IPhoneSubInfo info = getSubscriberInfoService();
+            if (info == null) {
+                Rlog.e(TAG, "getImsPrivateUserIdentity(): IPhoneSubInfo instance is NULL");
+                throw new RuntimeException("IMPI error: Subscriber Info is null");
+            }
+            return info.getImsPrivateUserIdentity(getSubId(), getOpPackageName(),
+                    getAttributionTag());
+        } catch (RemoteException | NullPointerException | IllegalArgumentException ex) {
+            Rlog.e(TAG, "getImsPrivateUserIdentity() Exception = " + ex);
+            throw new RuntimeException(ex.getMessage());
+        }
+    }
+
+    /**
      * Returns the IMS home network domain name that was loaded from the ISIM {@see #APPTYPE_ISIM}.
      * @return the IMS domain name. Returns {@code null} if ISIM hasn't been loaded or IMS domain
      * hasn't been loaded or isn't present on the ISIM.
@@ -6050,6 +6080,7 @@
      * @return an array of IMPU strings, with one IMPU per string, or null if
      *      not present or not loaded
      * @hide
+     * @deprecated use {@link #getImsPublicUserIdentities()}
      */
     @UnsupportedAppUsage
     @Nullable
@@ -6070,6 +6101,39 @@
     }
 
     /**
+     * Returns the IMS public user identities (IMPU) of the subscription that was loaded from the
+     * ISIM records {@link #APPTYPE_ISIM}. This value is fetched from the Elementary file EF_IMPU.
+     * The contents of the file are <b>Ip Multimedia Service Public User Identities</b> of the user
+     * as defined in the section 4.2.4 of 3GPP TS 131 103. It contains one or more records.
+     *
+     * @return List of public user identities of type android.net.Uri or empty list  if
+     *         EF_IMPU is not available.
+     * @throws IllegalStateException in case the ISIM hasn’t been loaded
+     * @throws SecurityException if the caller does not have the required permission/privilege
+     * @hide
+     */
+    @NonNull
+    @RequiresPermission(anyOf = {android.Manifest.permission.READ_PHONE_NUMBERS,
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
+    @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
+    public List<Uri> getImsPublicUserIdentities() {
+        try {
+            IPhoneSubInfo info = getSubscriberInfoService();
+            if (info == null) {
+                throw new RuntimeException("IMPU error: Subscriber Info is null");
+            }
+            return info.getImsPublicUserIdentities(getSubId(), getOpPackageName(),
+                    getAttributionTag());
+        } catch (IllegalArgumentException | NullPointerException ex) {
+            Rlog.e(TAG, "getImsPublicUserIdentities Exception = " + ex);
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getImsPublicUserIdentities Exception = " + ex);
+            ex.rethrowAsRuntimeException();
+        }
+        return Collections.EMPTY_LIST;
+    }
+
+    /**
      * Device call state: No activity.
      */
     public static final int CALL_STATE_IDLE = 0;
@@ -9432,7 +9496,6 @@
             ALLOWED_NETWORK_TYPES_REASON_POWER,
             ALLOWED_NETWORK_TYPES_REASON_CARRIER,
             ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G,
-            ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface AllowedNetworkTypesReason {
@@ -9471,15 +9534,6 @@
     public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3;
 
     /**
-     * To indicate allowed network type change is requested by an update to the
-     * {@link android.os.UserManager.DISALLOW_CELLULAR_2G} user restriction.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS = 4;
-
-    /**
      * Set the allowed network types of the device and provide the reason triggering the allowed
      * network change.
      * <p>Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or
@@ -9503,7 +9557,6 @@
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE} permissions.
      * <ol>
      *     <li>{@code TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}</li>
-     *     <li>{@code TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS}</li>
      * </ol>
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -9578,7 +9631,6 @@
             case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER:
             case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER:
             case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G:
-            case ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS:
                 return true;
         }
         return false;
@@ -14842,7 +14894,10 @@
 
     /**
      * The extra used with an {@link #ACTION_NETWORK_COUNTRY_CHANGED} to specify the
-     * the country code in ISO-3166-1 alpha-2 format.
+     * the country code in ISO-3166-1 alpha-2 format. This is the same country code returned by
+     * {@link #getNetworkCountryIso()}. This might be an empty string when the country code is not
+     * available.
+     *
      * <p class="note">
      * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
      */
@@ -14851,11 +14906,11 @@
 
     /**
      * The extra used with an {@link #ACTION_NETWORK_COUNTRY_CHANGED} to specify the
-     * last known the country code in ISO-3166-1 alpha-2 format.
+     * last known the country code in ISO-3166-1 alpha-2 format. This might be an empty string when
+     * the country code was never available. The last known country code persists across reboot.
+     *
      * <p class="note">
      * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
-     *
-     * @hide
      */
     public static final String EXTRA_LAST_KNOWN_NETWORK_COUNTRY =
             "android.telephony.extra.LAST_KNOWN_NETWORK_COUNTRY";
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index cdb7d7c..ed46276 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -82,6 +82,47 @@
     public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
             "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
 
+
+    /**
+     * Intent action to transfer an embedded subscriptions.
+     *
+     * <p> Action sent by apps (such as the Settings app) to the Telephony framework to transfer an
+     * embedded subscription.
+     *
+     * <p> Requires that the calling app has the
+     * {@code android.Manifest.permission#MODIFY_PHONE_STATE} permission.
+     *
+     * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if
+     * {@link #isEnabled} is false.
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public static final String ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS =
+            "android.telephony.euicc.action.TRANSFER_EMBEDDED_SUBSCRIPTIONS";
+
+    /**
+     * Intent action to convert the physical subscription to an embedded subscription.
+     *
+     * <p> Action sent by apps (such as the Settings app) to the Telephony framework to convert
+     * physical sim to embedded sim.
+     *
+     * <p> Requires that the calling app has the
+     * {@code android.Manifest.permission#MODIFY_PHONE_STATE} permission.
+     *
+     * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if
+     * {@link #isEnabled} is false.
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public static final String ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION =
+            "android.telephony.euicc.action.CONVERT_TO_EMBEDDED_SUBSCRIPTION";
+
     /**
      * Broadcast Action: The eUICC OTA status is changed.
      * <p class="note">
@@ -841,6 +882,16 @@
     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public static final long SHOULD_RESOLVE_PORT_INDEX_FOR_APPS = 224562872L;
 
+    /**
+     * Starting with Android U, a port is available if it is active without an enabled profile
+     * on it or calling app can activate a new profile on the selected port without any user
+     * interaction.
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    public static final long INACTIVE_PORT_AVAILABILITY_CHECK = 240273417L;
+
     private final Context mContext;
     private int mCardId;
 
@@ -1570,8 +1621,12 @@
 
     /**
      * Returns whether the passing portIndex is available.
-     * A port is available if it is active without an enabled profile on it or calling app can
-     * activate a new profile on the selected port without any user interaction.
+     * A port is available if it is active without enabled profile on it or
+     * calling app has carrier privilege over the profile installed on the selected port.
+     *
+     * <p> From Android U, a port is available if it is active without an enabled profile on it or
+     * calling app can activate a new profile on the selected port without any user interaction.
+     *
      * Always returns false if the cardId is a physical card.
      *
      * @param portIndex is an enumeration of the ports available on the UICC.
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 1ea7fdc..d07edeb 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -27,6 +27,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telecom.VideoProfile;
+import android.telephony.CallState;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.emergency.EmergencyNumber.EmergencyCallRouting;
 import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
@@ -78,7 +79,9 @@
     public static final int SERVICE_TYPE_EMERGENCY = 2;
 
     /**
-     * Call type none
+     * This value is returned if there is no valid IMS call type defined for the call. For example,
+     * if an ongoing call is circuit-switched and {@link CallState#getImsCallType()} is called, this
+     * value will be returned.
      */
     public static final int CALL_TYPE_NONE = 0;
     /**
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
index 4836f86..5946535 100644
--- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -35,6 +35,7 @@
 import java.util.ArrayList;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 /**
  * Listener interface for notifying the Framework's {@link ImsCallSession} for updates to an ongoing
@@ -50,6 +51,7 @@
 public class ImsCallSessionListener {
     private static final String TAG = "ImsCallSessionListener";
     private final IImsCallSessionListener mListener;
+    private Executor mExecutor = null;
 
     /** @hide */
     public ImsCallSessionListener(IImsCallSessionListener l) {
@@ -247,6 +249,9 @@
     public void callSessionMergeStarted(ImsCallSessionImplBase newSession, ImsCallProfile profile)
     {
         try {
+            if (newSession != null && mExecutor != null) {
+                newSession.setDefaultExecutor(mExecutor);
+            }
             mListener.callSessionMergeStarted(newSession != null ?
                             newSession.getServiceImpl() : null, profile);
         } catch (RemoteException e) {
@@ -278,6 +283,9 @@
      */
     public void callSessionMergeComplete(ImsCallSessionImplBase newSession) {
         try {
+            if (newSession != null && mExecutor != null) {
+                newSession.setDefaultExecutor(mExecutor);
+            }
             mListener.callSessionMergeComplete(newSession != null ?
                     newSession.getServiceImpl() : null);
         } catch (RemoteException e) {
@@ -365,6 +373,9 @@
     public void callSessionConferenceExtended(ImsCallSessionImplBase newSession,
             ImsCallProfile profile) {
         try {
+            if (newSession != null && mExecutor != null) {
+                newSession.setDefaultExecutor(mExecutor);
+            }
             mListener.callSessionConferenceExtended(
                     newSession != null ? newSession.getServiceImpl() : null, profile);
         } catch (RemoteException e) {
@@ -410,6 +421,9 @@
     public void callSessionConferenceExtendReceived(ImsCallSessionImplBase newSession,
             ImsCallProfile profile) {
         try {
+            if (newSession != null && mExecutor != null) {
+                newSession.setDefaultExecutor(mExecutor);
+            }
             mListener.callSessionConferenceExtendReceived(newSession != null
                     ? newSession.getServiceImpl() : null, profile);
         } catch (RemoteException e) {
@@ -836,5 +850,19 @@
             e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor to use when executing the methods by the vendor
+     *                 implementation of {@link ImsCallSessionImplBase} for conference call.
+     *                 This executor is dedicated to set vendor CallSessionImpl
+     *                 only when conference call is established.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mExecutor == null) {
+            mExecutor = executor;
+        }
+    }
 }
 
diff --git a/telephony/java/android/telephony/ims/MediaQualityStatus.java b/telephony/java/android/telephony/ims/MediaQualityStatus.java
index 5038aac..76394fe 100644
--- a/telephony/java/android/telephony/ims/MediaQualityStatus.java
+++ b/telephony/java/android/telephony/ims/MediaQualityStatus.java
@@ -40,7 +40,7 @@
     private final int mMediaSessionType;
     private final int mTransportType;
     private final int mRtpPacketLossRate;
-    private final int mRtpJitter;
+    private final int mRtpJitterMillis;
     private final long mRtpInactivityTimeMillis;
 
     /** @hide */
@@ -52,23 +52,26 @@
     public @interface MediaSessionType {}
 
     /**
-     * Constructor for this
+     * The constructor for MediaQualityStatus, which represents the media quality for each session
+     * type ({@link #MEDIA_SESSION_TYPE_AUDIO} or {@link #MEDIA_SESSION_TYPE_VIDEO}) of the IMS call
      *
      * @param imsCallSessionId IMS call session id of this quality status
      * @param mediaSessionType media session type of this quality status
      * @param transportType transport type of this quality status
-     * @param rtpPacketLossRate measured RTP packet loss rate
-     * @param rtpJitter measured RTP jitter value
+     * @param rtpPacketLossRate measured RTP packet loss rate in percentage
+     * @param rtpJitterMillis measured RTP jitter(RFC3550) in milliseconds
      * @param rptInactivityTimeMillis measured RTP inactivity time in milliseconds
      */
-    private MediaQualityStatus(@NonNull String imsCallSessionId,
+    public MediaQualityStatus(@NonNull String imsCallSessionId,
             @MediaSessionType int mediaSessionType, @TransportType int transportType,
-            int rtpPacketLossRate, int rtpJitter, long rptInactivityTimeMillis) {
+            @IntRange(from = 0, to = 100) int rtpPacketLossRate,
+            @IntRange(from = 0) int rtpJitterMillis,
+            @IntRange(from = 0) long rptInactivityTimeMillis) {
         mImsCallSessionId = imsCallSessionId;
         mMediaSessionType = mediaSessionType;
         mTransportType = transportType;
         mRtpPacketLossRate = rtpPacketLossRate;
-        mRtpJitter = rtpJitter;
+        mRtpJitterMillis = rtpJitterMillis;
         mRtpInactivityTimeMillis = rptInactivityTimeMillis;
     }
 
@@ -106,13 +109,15 @@
     /**
      * Retrieves measured RTP jitter(RFC3550) value in milliseconds
      */
+    @IntRange(from = 0)
     public int getRtpJitterMillis() {
-        return mRtpJitter;
+        return mRtpJitterMillis;
     }
 
     /**
      * Retrieves measured RTP inactivity time in milliseconds
      */
+    @IntRange(from = 0)
     public long getRtpInactivityMillis() {
         return mRtpInactivityTimeMillis;
     }
@@ -126,7 +131,7 @@
         mMediaSessionType = in.readInt();
         mTransportType = in.readInt();
         mRtpPacketLossRate = in.readInt();
-        mRtpJitter = in.readInt();
+        mRtpJitterMillis = in.readInt();
         mRtpInactivityTimeMillis = in.readLong();
     }
 
@@ -136,7 +141,7 @@
         dest.writeInt(mMediaSessionType);
         dest.writeInt(mTransportType);
         dest.writeInt(mRtpPacketLossRate);
-        dest.writeInt(mRtpJitter);
+        dest.writeInt(mRtpJitterMillis);
         dest.writeLong(mRtpInactivityTimeMillis);
     }
 
@@ -167,14 +172,14 @@
                 && mMediaSessionType == that.mMediaSessionType
                 && mTransportType == that.mTransportType
                 && mRtpPacketLossRate == that.mRtpPacketLossRate
-                && mRtpJitter == that.mRtpJitter
+                && mRtpJitterMillis == that.mRtpJitterMillis
                 && mRtpInactivityTimeMillis == that.mRtpInactivityTimeMillis;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mImsCallSessionId, mMediaSessionType, mTransportType,
-                mRtpPacketLossRate, mRtpJitter, mRtpInactivityTimeMillis);
+                mRtpPacketLossRate, mRtpJitterMillis, mRtpInactivityTimeMillis);
     }
 
     @Override
@@ -188,100 +193,11 @@
         sb.append(mTransportType);
         sb.append(", mRtpPacketLossRate=");
         sb.append(mRtpPacketLossRate);
-        sb.append(", mRtpJitter=");
-        sb.append(mRtpJitter);
+        sb.append(", mRtpJitterMillis=");
+        sb.append(mRtpJitterMillis);
         sb.append(", mRtpInactivityTimeMillis=");
         sb.append(mRtpInactivityTimeMillis);
         sb.append("}");
         return sb.toString();
     }
-
-    /**
-     * Provides a convenient way to set the fields of an {@link MediaQualityStatus} when creating a
-     * new instance.
-     *
-     * <p>The example below shows how you might create a new {@code RtpQualityStatus}:
-     *
-     * <pre><code>
-     *
-     * MediaQualityStatus = new MediaQualityStatus.Builder(
-     *                                          callSessionId, mediaSessionType, transportType)
-     *     .setRtpPacketLossRate(packetLossRate)
-     *     .setRtpJitter(jitter)
-     *     .setRtpInactivityMillis(inactivityTimeMillis)
-     *     .build();
-     * </code></pre>
-     */
-    public static final class Builder {
-        private final String mImsCallSessionId;
-        private final int mMediaSessionType;
-        private final int mTransportType;
-        private int mRtpPacketLossRate;
-        private int mRtpJitter;
-        private long mRtpInactivityTimeMillis;
-
-        /**
-         * Default constructor for the Builder.
-         */
-        public Builder(
-                @NonNull String imsCallSessionId,
-                @MediaSessionType int mediaSessionType,
-                @TransportType int transportType) {
-            mImsCallSessionId = imsCallSessionId;
-            mMediaSessionType = mediaSessionType;
-            mTransportType = transportType;
-        }
-
-        /**
-         * Set RTP packet loss info.
-         *
-         * @param packetLossRate RTP packet loss rate in percentage
-         * @return The same instance of the builder.
-         */
-        @NonNull
-        public Builder setRtpPacketLossRate(@IntRange(from = 0, to = 100) int packetLossRate) {
-            this.mRtpPacketLossRate = packetLossRate;
-            return this;
-        }
-
-        /**
-         * Set calculated RTP jitter(RFC3550) value in milliseconds.
-         *
-         * @param jitter calculated RTP jitter value.
-         * @return The same instance of the builder.
-         */
-        @NonNull
-        public Builder setRtpJitterMillis(int jitter) {
-            this.mRtpJitter = jitter;
-            return this;
-        }
-
-        /**
-         * Set measured RTP inactivity time.
-         *
-         * @param inactivityTimeMillis RTP inactivity time in Milliseconds.
-         * @return The same instance of the builder.
-         */
-        @NonNull
-        public Builder setRtpInactivityMillis(long inactivityTimeMillis) {
-            this.mRtpInactivityTimeMillis = inactivityTimeMillis;
-            return this;
-        }
-
-        /**
-         * Build the {@link MediaQualityStatus}
-         *
-         * @return the {@link MediaQualityStatus} object
-         */
-        @NonNull
-        public MediaQualityStatus build() {
-            return new MediaQualityStatus(
-                    mImsCallSessionId,
-                    mMediaSessionType,
-                    mTransportType,
-                    mRtpPacketLossRate,
-                    mRtpJitter,
-                    mRtpInactivityTimeMillis);
-        }
-    }
 }
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 153a951..746246c 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -1141,6 +1141,7 @@
             throw new IllegalStateException("Session is not available.");
         }
         try {
+            c.setDefaultExecutor(MmTelFeature.this.mExecutor);
             listener.onIncomingCall(c.getServiceImpl(), null, extras);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
@@ -1175,7 +1176,9 @@
             IImsCallSessionListener isl =
                     listener.onIncomingCall(c.getServiceImpl(), callId, extras);
             if (isl != null) {
-                return new ImsCallSessionListener(isl);
+                ImsCallSessionListener iCSL = new ImsCallSessionListener(isl);
+                iCSL.setDefaultExecutor(MmTelFeature.this.mExecutor);
+                return iCSL;
             } else {
                 return null;
             }
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index 3ab4ee69..30a0684 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -220,8 +220,9 @@
 
         @Override
         public void setListener(IImsCallSessionListener listener) {
-            executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener(
-                    new ImsCallSessionListener(listener)), "setListener");
+            ImsCallSessionListener iCSL = new ImsCallSessionListener(listener);
+            iCSL.setDefaultExecutor(mExecutor);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener(iCSL), "setListener");
         }
 
         @Override
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
similarity index 60%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
index 497c272..5c3fa32 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package android.telephony.satellite;
+
+import android.telephony.satellite.PointingInfo;
 
 /**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
+ * Callback for position updates from the satellite service.
  * @hide
  */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+oneway interface ISatellitePositionUpdateCallback {
+    void onSatellitePositionUpdate(in PointingInfo pointingInfo);
+    void onMessageTransferStateUpdate(in int state);
+}
diff --git a/telephony/java/android/telephony/satellite/PointingInfo.aidl b/telephony/java/android/telephony/satellite/PointingInfo.aidl
new file mode 100644
index 0000000..7ff95cd
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/PointingInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.telephony.satellite;
+
+parcelable PointingInfo;
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
new file mode 100644
index 0000000..7a60c58
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
+import android.annotation.RequiresPermission;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyFrameworkInitializer;
+import android.util.ArrayMap;
+
+import com.android.internal.telephony.IIntegerConsumer;
+import com.android.internal.telephony.ITelephony;
+import com.android.telephony.Rlog;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+
+/**
+ * Manages satellite operations such as provisioning, pointing, messaging, location sharing, etc.
+ * To get the object, call {@link Context#getSystemService(Context.SATELLITE_SERVICE)}.
+ * To create an instance of {@link SatelliteManager} associated with a specific subscription ID,
+ * call {@link #createForSubscriptionId(int)}.
+ *
+ * @hide
+ */
+@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SATELLITE)
+public class SatelliteManager {
+    private static final String TAG = "SatelliteManager";
+
+    /**
+     * Map of all SatellitePositionUpdateCallback and their associated callback ids.
+     */
+    private final Map<SatellitePositionUpdateCallback, Integer> mSatellitePositionUpdateCallbacks =
+            new ArrayMap<>();
+
+    /**
+     * AtomicInteger for the id of the next SatellitePositionUpdateCallback.
+     */
+    private final AtomicInteger mSatellitePositionUpdateCallbackId = new AtomicInteger(0);
+
+    /**
+     * The subscription ID for this SatelliteManager.
+     */
+    private final int mSubId;
+
+    /**
+     * Context this SatelliteManager is for.
+     */
+    @Nullable private final Context mContext;
+
+    /**
+     * Create an instance of the SatelliteManager.
+     *
+     * @param context The context the SatelliteManager belongs to.
+     */
+    public SatelliteManager(@Nullable Context context) {
+        // TODO: replace DEFAULT_SUBSCRIPTION_ID with DEFAULT_SATELLITE_SUBSCRIPTION_ID
+        this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+    }
+
+    /**
+     * Create a new SatelliteManager associated with the given subscription ID.
+     *
+     * @param subId The subscription ID to create the SatelliteManager with.
+     * @return A SatelliteManager that uses the given subscription ID for all calls.
+     */
+    @NonNull public SatelliteManager createForSubscriptionId(int subId) {
+        return new SatelliteManager(mContext, subId);
+    }
+
+    /**
+     * Create an instance of the SatelliteManager associated with a particular subscription.
+     *
+     * @param context The context the SatelliteManager belongs to.
+     * @param subId The subscription ID associated with the SatelliteManager.
+     */
+    private SatelliteManager(@Nullable Context context, int subId) {
+        mContext = context;
+        mSubId = subId;
+    }
+
+    /**
+     * Successful response.
+     */
+    public static final int SATELLITE_SERVICE_SUCCESS = 0;
+    /**
+     * Satellite server is not reachable.
+     */
+    public static final int SATELLITE_SERVICE_SERVER_NOT_REACHABLE = 1;
+    /**
+     * Error received from the satellite server.
+     */
+    public static final int SATELLITE_SERVICE_SERVER_ERROR = 2;
+    /**
+     * Unexpected telephony internal error.
+     */
+    public static final int SATELLITE_SERVICE_TELEPHONY_INTERNAL_ERROR = 3;
+    /**
+     * Modem error received from the satellite service.
+     */
+    public static final int SATELLITE_SERVICE_MODEM_ERROR = 4;
+    /**
+     * System error received from the satellite service.
+     */
+    public static final int SATELLITE_SERVICE_SYSTEM_ERROR = 5;
+    /**
+     * Invalid arguments passed.
+     */
+    public static final int SATELLITE_SERVICE_INVALID_ARGUMENTS = 6;
+    /**
+     * Invalid modem state.
+     */
+    public static final int SATELLITE_SERVICE_INVALID_MODEM_STATE = 7;
+    /**
+     * Invalid SIM state.
+     */
+    public static final int SATELLITE_SERVICE_INVALID_SIM_STATE = 8;
+    /**
+     * Invalid state.
+     */
+    public static final int SATELLITE_SERVICE_INVALID_STATE = 9;
+    /**
+     * Satellite service is unavailable.
+     */
+    public static final int SATELLITE_SERVICE_NOT_AVAILABLE = 10;
+    /**
+     * Satellite service is not supported by the device or OS.
+     */
+    public static final int SATELLITE_SERVICE_NOT_SUPPORTED = 11;
+    /**
+     * Satellite service is rate limited.
+     */
+    public static final int SATELLITE_SERVICE_RATE_LIMITED = 12;
+    /**
+     * Satellite service has no memory available.
+     */
+    public static final int SATELLITE_SERVICE_NO_MEMORY = 13;
+    /**
+     * Satellite service has no resources available.
+     */
+    public static final int SATELLITE_SERVICE_NO_RESOURCES = 14;
+    /**
+     * Failed to send a request to the satellite service.
+     */
+    public static final int SATELLITE_SERVICE_REQUEST_FAILED = 15;
+    /**
+     * Failed to send a request to the satellite service for the given subscription ID.
+     */
+    public static final int SATELLITE_SERVICE_INVALID_SUBSCRIPTION_ID = 16;
+    /**
+     * Error received from satellite service.
+     */
+    public static final int SATELLITE_SERVICE_ERROR = 17;
+    /**
+     * Satellite service is disabled on the requested subscription.
+     */
+    public static final int SATELLITE_SERVICE_DISABLED = 18;
+
+    /** @hide */
+    @IntDef(prefix = {"SATELLITE_SERVICE_"}, value = {
+            SATELLITE_SERVICE_SUCCESS,
+            SATELLITE_SERVICE_SERVER_NOT_REACHABLE,
+            SATELLITE_SERVICE_SERVER_ERROR,
+            SATELLITE_SERVICE_TELEPHONY_INTERNAL_ERROR,
+            SATELLITE_SERVICE_MODEM_ERROR,
+            SATELLITE_SERVICE_SYSTEM_ERROR,
+            SATELLITE_SERVICE_INVALID_ARGUMENTS,
+            SATELLITE_SERVICE_INVALID_MODEM_STATE,
+            SATELLITE_SERVICE_INVALID_SIM_STATE,
+            SATELLITE_SERVICE_INVALID_STATE,
+            SATELLITE_SERVICE_NOT_AVAILABLE,
+            SATELLITE_SERVICE_NOT_SUPPORTED,
+            SATELLITE_SERVICE_RATE_LIMITED,
+            SATELLITE_SERVICE_NO_MEMORY,
+            SATELLITE_SERVICE_NO_RESOURCES,
+            SATELLITE_SERVICE_REQUEST_FAILED,
+            SATELLITE_SERVICE_INVALID_SUBSCRIPTION_ID,
+            SATELLITE_SERVICE_ERROR,
+            SATELLITE_SERVICE_DISABLED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SatelliteServiceResult {}
+
+    /**
+     * Message transfer is waiting to acquire.
+     */
+    public static final int SATELLITE_MESSAGE_TRANSFER_STATE_WAITING_TO_ACQUIRE = 0;
+    /**
+     * Message is being sent.
+     */
+    public static final int SATELLITE_MESSAGE_TRANSFER_STATE_SENDING = 1;
+    /**
+     * Message is being received.
+     */
+    public static final int SATELLITE_MESSAGE_TRANSFER_STATE_RECEIVING = 2;
+    /**
+     * Message transfer is being retried.
+     */
+    public static final int SATELLITE_MESSAGE_TRANSFER_STATE_RETRYING = 3;
+    /**
+     * Message transfer is complete.
+     */
+    public static final int SATELLITE_MESSAGE_TRANSFER_STATE_COMPLETE = 4;
+
+    /** @hide */
+    @IntDef(prefix = {"SATELLITE_MESSAGE_TRANSFER_STATE_"}, value = {
+            SATELLITE_MESSAGE_TRANSFER_STATE_WAITING_TO_ACQUIRE,
+            SATELLITE_MESSAGE_TRANSFER_STATE_SENDING,
+            SATELLITE_MESSAGE_TRANSFER_STATE_RECEIVING,
+            SATELLITE_MESSAGE_TRANSFER_STATE_RETRYING,
+            SATELLITE_MESSAGE_TRANSFER_STATE_COMPLETE
+    })
+    public @interface SatelliteMessageTransferState {}
+
+    /**
+     * Callback for position updates from the satellite service.
+     */
+    public interface SatellitePositionUpdateCallback {
+        /**
+         * Called when the satellite position changes.
+         *
+         * @param pointingInfo The pointing info containing the satellite location.
+         */
+        void onSatellitePositionUpdate(@NonNull PointingInfo pointingInfo);
+
+        /**
+         * Called when satellite message transfer state changes.
+         *
+         * @param state The new message transfer state.
+         */
+        void onMessageTransferStateUpdate(@SatelliteMessageTransferState int state);
+    }
+
+    /**
+     * Start receiving satellite position updates.
+     * This can be called by the pointing UI when the user starts pointing to the satellite.
+     * Modem should continue to report the pointing input as the device or satellite moves.
+     * Satellite position updates are started only on {@link #SATELLITE_SERVICE_SUCCESS}.
+     * All other results indicate that this operation failed.
+     *
+     * @param executor The executor to run callbacks on.
+     * @param callback The callback to notify of changes in satellite position.
+     * @return The result of the operation.
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    @SatelliteServiceResult public int startSatellitePositionUpdates(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull SatellitePositionUpdateCallback callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                int id;
+                if (mSatellitePositionUpdateCallbacks.containsKey(callback)) {
+                    id = mSatellitePositionUpdateCallbacks.get(callback);
+                } else {
+                    id = mSatellitePositionUpdateCallbackId.getAndIncrement();
+                }
+                int result = telephony.startSatellitePositionUpdates(mSubId, id,
+                        new ISatellitePositionUpdateCallback.Stub() {
+                            @Override
+                            public void onSatellitePositionUpdate(
+                                    @NonNull PointingInfo pointingInfo) {
+                                logd("onSatellitePositionUpdate: pointingInfo=" + pointingInfo);
+                                executor.execute(() -> Binder.withCleanCallingIdentity(
+                                        () -> callback.onSatellitePositionUpdate(pointingInfo)));
+                            }
+
+                            @Override
+                            public void onMessageTransferStateUpdate(
+                                    @SatelliteMessageTransferState int state) {
+                                logd("onMessageTransferStateUpdate: state=" + state);
+                                executor.execute(() -> Binder.withCleanCallingIdentity(
+                                        () -> callback.onMessageTransferStateUpdate(state)));
+                            }
+                        });
+                if (result == SATELLITE_SERVICE_SUCCESS) {
+                    mSatellitePositionUpdateCallbacks.put(callback, id);
+                }
+                return result;
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            loge("startSatellitePositionUpdates RemoteException: " + ex);
+            ex.rethrowFromSystemServer();
+        }
+        return SATELLITE_SERVICE_REQUEST_FAILED;
+    }
+
+    /**
+     * Stop receiving satellite position updates.
+     * This can be called by the pointing UI when the user stops pointing to the satellite.
+     * Satellite position updates are stopped only on {@link #SATELLITE_SERVICE_SUCCESS}.
+     * All other results indicate that this operation failed.
+     *
+     * @param callback The callback that was passed in {@link
+     *                 #startSatellitePositionUpdates(Executor, SatellitePositionUpdateCallback)}.
+     * @return The result of the operation.
+     * @throws IllegalArgumentException if the callback is invalid.
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    @SatelliteServiceResult public int stopSatellitePositionUpdates(
+            @NonNull SatellitePositionUpdateCallback callback) {
+        Objects.requireNonNull(callback);
+
+        if (!mSatellitePositionUpdateCallbacks.containsKey(callback)) {
+            throw new IllegalArgumentException(
+                    "startSatellitePositionUpdates was never called with the callback provided.");
+        }
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                int result = telephony.stopSatellitePositionUpdates(mSubId,
+                        mSatellitePositionUpdateCallbacks.get(callback));
+                if (result == SATELLITE_SERVICE_SUCCESS) {
+                    mSatellitePositionUpdateCallbacks.remove(callback);
+                    // TODO: Notify SmsHandler that pointing UI stopped
+                }
+                return result;
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            loge("stopSatellitePositionUpdates RemoteException: " + ex);
+            ex.rethrowFromSystemServer();
+        }
+        return SATELLITE_SERVICE_REQUEST_FAILED;
+    }
+
+    /**
+     * Get maximum number of characters per text message on satellite.
+     * @param executor - The executor on which the result listener will be called.
+     * @param resultListener - Listener that will be called when the operation is successful.
+     *                       If this method returns {@link #SATELLITE_SERVICE_SUCCESS}, listener
+     *                       will be called with maximum characters limit.
+     *
+     * @throws SecurityException if the caller doesn't have required permission.
+     *
+     * @return The result of the operation
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    @SatelliteServiceResult
+    public int getMaxCharactersPerSatelliteTextMessage(@NonNull @CallbackExecutor Executor executor,
+            @NonNull Consumer<Integer> resultListener) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(resultListener);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
+                    @Override
+                    public void accept(int result) {
+                        executor.execute(() -> Binder.withCleanCallingIdentity(
+                                () -> resultListener.accept(result)));
+                    }
+                };
+
+                return telephony.getMaxCharactersPerSatelliteTextMessage(mSubId, internalCallback);
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            loge("getMaxCharactersPerSatelliteTextMessage() RemoteException:" + ex);
+            ex.rethrowFromSystemServer();
+        }
+        return SATELLITE_SERVICE_REQUEST_FAILED;
+    }
+
+    private static ITelephony getITelephony() {
+        ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer
+                .getTelephonyServiceManager()
+                .getTelephonyServiceRegisterer()
+                .get());
+        if (binder == null) {
+            throw new RuntimeException("Could not find Telephony Service.");
+        }
+        return binder;
+    }
+
+    private static void logd(@NonNull String log) {
+        Rlog.d(TAG, log);
+    }
+
+    private static void loge(@NonNull String log) {
+        Rlog.e(TAG, log);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 3dfc81e..b4d93fd 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -180,6 +180,19 @@
     String getIsimImpi(int subId);
 
     /**
+     * Fetches the ISIM PrivateUserIdentity (EF_IMPI) based on subId
+     *
+     * @param subId subscriptionId
+     * @return IMPI (IMS private user identity) of type string or null if EF_IMPI is not available.
+     * @throws IllegalArgumentException if the subscriptionId is not valid
+     * @throws IllegalStateException in case the ISIM hasn’t been loaded.
+     * @throws SecurityException if the caller does not have the required permission
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+            + "android.Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER)")
+    String getImsPrivateUserIdentity(int subId, String callingPackage, String callingFeatureId);
+
+    /**
      * Returns the IMS home network domain name that was loaded from the ISIM.
      * @return the IMS domain name, or null if not present or not loaded
      */
@@ -193,6 +206,14 @@
     String[] getIsimImpu(int subId);
 
     /**
+     * Fetches the ISIM public user identities (EF_IMPU) from UICC based on subId
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" +
+    "anyOf={android.Manifest.permission.READ_PHONE_NUMBERS, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})")
+     List<Uri> getImsPublicUserIdentities(int subId, String callingPackage,
+                                           String callingFeatureId);
+
+    /**
      * Returns the IMS Service Table (IST) that was loaded from the ISIM.
      * @return IMS Service Table or null if not present or not loaded
      */
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 6099cb1..5486365 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -66,6 +66,7 @@
 import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.aidl.IRcsConfigCallback;
+import android.telephony.satellite.ISatellitePositionUpdateCallback;
 import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.telephony.CellNetworkScanResult;
 import com.android.internal.telephony.IBooleanConsumer;
@@ -2209,6 +2210,11 @@
         IIntegerConsumer subIdResult);
 
     /**
+     * Show error dialog to switch to managed profile.
+     */
+    oneway void showSwitchToManagedProfileDialog();
+
+    /**
      * Returns the MMS user agent.
      */
     String getMmsUserAgent(int subId);
@@ -2631,14 +2637,14 @@
      */
     boolean isRemovableEsimDefaultEuicc(String callingPackage);
 
-     /**
-      * Get the component name of the default app to direct respond-via-message intent for the
-      * user associated with this subscription, update the cache if there is no respond-via-message
-      * application currently configured for this user.
-      * @return component name of the app and class to direct Respond Via Message intent to, or
-      * {@code null} if the functionality is not supported.
-      * @hide
-      */
+    /**
+     * Get the component name of the default app to direct respond-via-message intent for the
+     * user associated with this subscription, update the cache if there is no respond-via-message
+     * application currently configured for this user.
+     * @return component name of the app and class to direct Respond Via Message intent to, or
+     * {@code null} if the functionality is not supported.
+     * @hide
+     */
     ComponentName getDefaultRespondViaMessageApplication(int subId, boolean updateIfNeeded);
 
     /**
@@ -2662,12 +2668,12 @@
     void setNullCipherAndIntegrityEnabled(boolean enabled);
 
     /**
-    * Get whether the radio is able to connect with null ciphering or integrity
-    * algorithms. Note that this retrieves the phone-global preference and not
-    * the state of the radio.
-    *
-    * @hide
-    */
+     * Get whether the radio is able to connect with null ciphering or integrity
+     * algorithms. Note that this retrieves the phone-global preference and not
+     * the state of the radio.
+     *
+     * @hide
+     */
     boolean isNullCipherAndIntegrityPreferenceEnabled();
 
     /**
@@ -2691,5 +2697,21 @@
     /**
      * Get the carrier restriction status of the device.
      */
-     void getCarrierRestrictionStatus(IIntegerConsumer internalCallback, String packageName);
-}
+    void getCarrierRestrictionStatus(IIntegerConsumer internalCallback, String packageName);
+
+    /**
+     * Start receiving satellite pointing updates.
+     */
+    int startSatellitePositionUpdates(int subId, int callbackId,
+            in ISatellitePositionUpdateCallback callback);
+
+    /**
+     * Stop receiving satellite pointing updates.
+     */
+    int stopSatellitePositionUpdates(int subId, int callbackId);
+
+    /**
+     * Get maximum number of characters per text message on satellite.
+     */
+    int getMaxCharactersPerSatelliteTextMessage(int subId, IIntegerConsumer internalCallback);
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 0f83a05..a9ebd5c 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -243,6 +243,13 @@
     /** The key to specify the selected domain for dialing calls. */
     public static final String EXTRA_DIAL_DOMAIN = "dial_domain";
 
+    /**
+     * Indicates that this call should be routed over Wi-Fi.
+     * An internal extension of NetworkRegistrationInfo's DOMAIN_* constants
+     * to also include NON_3GPP_PS routing for the domain selection service.
+     */
+    public static final int DOMAIN_NON_3GPP_PS = 4;
+
     /** The key to specify the emergency service category */
     public static final String EXTRA_EMERGENCY_SERVICE_CATEGORY = "emergency_service_category";
 }
diff --git a/tests/BinaryTransparencyHostTest/Android.bp b/tests/BinaryTransparencyHostTest/Android.bp
index 142e3dd..dc6bdff 100644
--- a/tests/BinaryTransparencyHostTest/Android.bp
+++ b/tests/BinaryTransparencyHostTest/Android.bp
@@ -35,6 +35,7 @@
     data: [
         ":BinaryTransparencyTestApp",
         ":EasterEgg",
+        ":com.android.apex.cts.shim.v2_rebootless_prebuilt",
     ],
     test_suites: [
         "general-tests",
diff --git a/tests/BinaryTransparencyHostTest/src/android/transparency/test/BaseInstallMultiple.java b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BaseInstallMultiple.java
new file mode 100644
index 0000000..3e94f25
--- /dev/null
+++ b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BaseInstallMultiple.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transparency.test;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Base class for invoking the install-multiple command via ADB. Subclass this for less typing:
+ *
+ * <code> private class InstallMultiple extends BaseInstallMultiple&lt;InstallMultiple&gt; { public
+ * InstallMultiple() { super(getDevice(), null); } } </code>
+ */
+/*package*/ class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
+
+    private final ITestDevice mDevice;
+    private final IBuildInfo mBuild;
+
+    private final List<String> mArgs = new ArrayList<>();
+    private final Map<File, String> mFileToRemoteMap = new HashMap<>();
+
+    /*package*/ BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo) {
+        mDevice = device;
+        mBuild = buildInfo;
+        addArg("-g");
+    }
+
+    T addArg(String arg) {
+        mArgs.add(arg);
+        return (T) this;
+    }
+
+    T addFile(String filename) throws FileNotFoundException {
+        return addFile(filename, filename);
+    }
+
+    T addFile(String filename, String remoteName) throws FileNotFoundException {
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
+        mFileToRemoteMap.put(buildHelper.getTestFile(filename), remoteName);
+        return (T) this;
+    }
+
+    T inheritFrom(String packageName) {
+        addArg("-r");
+        addArg("-p " + packageName);
+        return (T) this;
+    }
+
+    void run() throws DeviceNotAvailableException {
+        run(true);
+    }
+
+    void runExpectingFailure() throws DeviceNotAvailableException {
+        run(false);
+    }
+
+    private void run(boolean expectingSuccess) throws DeviceNotAvailableException {
+        final ITestDevice device = mDevice;
+
+        // Create an install session
+        final StringBuilder cmd = new StringBuilder();
+        cmd.append("pm install-create");
+        for (String arg : mArgs) {
+            cmd.append(' ').append(arg);
+        }
+
+        String result = device.executeShellCommand(cmd.toString());
+        TestCase.assertTrue(result, result.startsWith("Success"));
+
+        final int start = result.lastIndexOf("[");
+        final int end = result.lastIndexOf("]");
+        int sessionId = -1;
+        try {
+            if (start != -1 && end != -1 && start < end) {
+                sessionId = Integer.parseInt(result.substring(start + 1, end));
+            }
+        } catch (NumberFormatException e) {
+            throw new IllegalStateException("Failed to parse install session: " + result);
+        }
+        if (sessionId == -1) {
+            throw new IllegalStateException("Failed to create install session: " + result);
+        }
+
+        // Push our files into session. Ideally we'd use stdin streaming,
+        // but ddmlib doesn't support it yet.
+        for (final Map.Entry<File, String> entry : mFileToRemoteMap.entrySet()) {
+            final File file = entry.getKey();
+            final String remoteName  = entry.getValue();
+            final String remotePath = "/data/local/tmp/" + file.getName();
+            if (!device.pushFile(file, remotePath)) {
+                throw new IllegalStateException("Failed to push " + file);
+            }
+
+            cmd.setLength(0);
+            cmd.append("pm install-write");
+            cmd.append(' ').append(sessionId);
+            cmd.append(' ').append(remoteName);
+            cmd.append(' ').append(remotePath);
+
+            result = device.executeShellCommand(cmd.toString());
+            TestCase.assertTrue(result, result.startsWith("Success"));
+        }
+
+        // Everything staged; let's pull trigger
+        cmd.setLength(0);
+        cmd.append("pm install-commit");
+        cmd.append(' ').append(sessionId);
+
+        result = device.executeShellCommand(cmd.toString());
+        if (expectingSuccess) {
+            TestCase.assertTrue(result, result.contains("Success"));
+        } else {
+            TestCase.assertFalse(result, result.contains("Success"));
+        }
+    }
+}
diff --git a/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java
index 84bed92..b8e9a17 100644
--- a/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java
+++ b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java
@@ -16,27 +16,39 @@
 
 package android.transparency.test;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
 import com.android.tradefed.util.CommandResult;
 import com.android.tradefed.util.CommandStatus;
 
-import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.TimeUnit;
+
 // TODO: Add @Presubmit
 @RunWith(DeviceJUnit4ClassRunner.class)
 public final class BinaryTransparencyHostTest extends BaseHostJUnit4Test {
     private static final String PACKAGE_NAME = "android.transparency.test.app";
 
-    @After
-    public void tearDown() throws Exception {
-        uninstallPackage("com.android.egg");
+    private static final String JOB_ID = "1740526926";
+
+    /** Waiting time for the job to be scheduled */
+    private static final int JOB_CREATION_MAX_SECONDS = 30;
+
+    @Before
+    public void setUp() throws Exception {
+        cancelPendingJob();
     }
 
     @Test
@@ -59,13 +71,63 @@
 
     @Test
     public void testCollectAllUpdatedPreloadInfo() throws Exception {
-        installPackage("EasterEgg.apk");
-        runDeviceTest("testCollectAllUpdatedPreloadInfo");
+        try {
+            updatePreloadApp();
+            runDeviceTest("testCollectAllUpdatedPreloadInfo");
+        } finally {
+            // No need to wait until job complete, since we can't verifying very meaningfully.
+            cancelPendingJob();
+            uninstallPackage("com.android.egg");
+        }
     }
 
     @Test
-    public void testMeasureMbas() throws Exception {
-        // TODO(265244016): figure out a way to install an MBA
+    public void testCollectAllSilentInstalledMbaInfo() throws Exception {
+        try {
+            new InstallMultiple()
+                .addFile("ApkVerityTestApp.apk")
+                .addFile("ApkVerityTestAppSplit.apk")
+                .run();
+            updatePreloadApp();
+            assertNotNull(getDevice().getAppPackageInfo("com.android.apkverity"));
+            assertNotNull(getDevice().getAppPackageInfo("com.android.egg"));
+
+            assertTrue(getDevice().setProperty("debug.transparency.bg-install-apps",
+                        "com.android.apkverity,com.android.egg"));
+            runDeviceTest("testCollectAllSilentInstalledMbaInfo");
+        } finally {
+            // No need to wait until job complete, since we can't verifying very meaningfully.
+            cancelPendingJob();
+            uninstallPackage("com.android.apkverity");
+            uninstallPackage("com.android.egg");
+        }
+    }
+
+    @Test
+    public void testRebootlessApexUpdateTriggersJobScheduling() throws Exception {
+        try {
+            installRebootlessApex();
+
+            // Verify
+            expectJobToBeScheduled();
+        } finally {
+            // No need to wait until job complete, since we can't verifying very meaningfully.
+            uninstallRebootlessApexThenReboot();
+        }
+    }
+
+    @Test
+    public void testPreloadUpdateTriggersJobScheduling() throws Exception {
+        try {
+            updatePreloadApp();
+
+            // Verify
+            expectJobToBeScheduled();
+        } finally {
+            // No need to wait until job complete, since we can't verifying very meaningfully.
+            cancelPendingJob();
+            uninstallPackage("com.android.egg");
+        }
     }
 
     private void runDeviceTest(String method) throws DeviceNotAvailableException {
@@ -74,4 +136,71 @@
         options.setTestMethodName(method);
         runDeviceTests(options);
     }
+
+    private void cancelPendingJob() throws DeviceNotAvailableException {
+        CommandResult result = getDevice().executeShellV2Command(
+                "cmd jobscheduler cancel android " + JOB_ID);
+        if (result.getStatus() == CommandStatus.SUCCESS) {
+            CLog.d("Canceling, output: " + result.getStdout());
+        } else {
+            CLog.d("Something went wrong, error: " + result.getStderr());
+        }
+    }
+
+    private void expectJobToBeScheduled() throws Exception {
+        for (int i = 0; i < JOB_CREATION_MAX_SECONDS; i++) {
+            CommandResult result = getDevice().executeShellV2Command(
+                    "cmd jobscheduler get-job-state android " + JOB_ID);
+            String state = result.getStdout().toString();
+            CLog.i("Job status: " + state);
+            if (state.startsWith("unknown")) {
+                // The job hasn't been scheduled yet. So try again.
+                TimeUnit.SECONDS.sleep(1);
+            } else if (result.getExitCode() != 0) {
+                fail("Failing due to unexpected job state: " + result);
+            } else {
+                // The job exists, which is all we care about here
+                return;
+            }
+        }
+        fail("Timed out waiting for the job to be scheduled");
+    }
+
+    private void installRebootlessApex() throws Exception {
+        installPackage("com.android.apex.cts.shim.v2_rebootless.apex", "--force-non-staged");
+    }
+
+    private void uninstallRebootlessApexThenReboot() throws DeviceNotAvailableException {
+        // Reboot only if the APEX is not the pre-install one.
+        CommandResult result = getDevice().executeShellV2Command(
+                "pm list packages -f --apex-only |grep com.android.apex.cts.shim");
+        assertTrue(result.getStatus() == CommandStatus.SUCCESS);
+        if (result.getStdout().contains("/data/apex/active/")) {
+            uninstallPackage("com.android.apex.cts.shim");
+            getDevice().reboot();
+
+            // Reboot enforces SELinux. Make it permissive again.
+            CommandResult runResult = getDevice().executeShellV2Command("setenforce 0");
+            assertTrue(runResult.getStatus() == CommandStatus.SUCCESS);
+        }
+    }
+
+    private void updatePreloadApp() throws DeviceNotAvailableException {
+        CommandResult result = getDevice().executeShellV2Command("pm path com.android.egg");
+        assertTrue(result.getStatus() == CommandStatus.SUCCESS);
+        assertThat(result.getStdout()).startsWith("package:/system/app/");
+        String path = result.getStdout().replaceFirst("^package:", "");
+
+        result = getDevice().executeShellV2Command("pm install " + path);
+        assertTrue(result.getStatus() == CommandStatus.SUCCESS);
+    }
+
+    private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
+        InstallMultiple() {
+            super(getDevice(), getBuild());
+            // Needed since in getMockBackgroundInstalledPackages, getPackageInfo runs as the caller
+            // uid. This also makes it consistent with installPackage's behavior.
+            addArg("--force-queryable");
+        }
+    }
 }
diff --git a/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java b/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java
index aedb366..c087a85 100644
--- a/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java
+++ b/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java
@@ -33,8 +33,10 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.HexFormat;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 @RunWith(AndroidJUnit4.class)
@@ -56,11 +58,12 @@
         assertThat(args).isNotNull();
         int number = Integer.valueOf(args.getString("apex-number"));
         assertThat(number).isGreaterThan(0);
-        var expectedApexNames = new HashSet<String>();
+        var expectedApexNames = new ArrayList<String>();
         for (var i = 0; i < number; i++) {
             String moduleName = args.getString("apex-" + Integer.toString(i));
             expectedApexNames.add(moduleName);
         }
+        assertThat(expectedApexNames).containsNoDuplicates();
 
         // Action
         var apexInfoList = mBt.collectAllApexInfo(/* includeTestOnly */ true);
@@ -109,4 +112,35 @@
         assertThat(updatedPreload.mbaStatus).isEqualTo(/* MBA_STATUS_UPDATED_PRELOAD */ 2);
         assertThat(updatedPreload.signerDigests).asList().containsNoneOf(null, "");
     }
+
+    @Test
+    public void testCollectAllSilentInstalledMbaInfo() {
+        // Action
+        var appInfoList = mBt.collectAllSilentInstalledMbaInfo(new Bundle());
+
+        // Verify
+        assertThat(appInfoList).isNotEmpty();  // because we just installed from the host side
+
+        var expectedAppNames = Set.of("com.android.apkverity", "com.android.egg");
+        var actualAppNames = appInfoList.stream().map((appInfo) -> appInfo.packageName)
+                .collect(Collectors.toList());
+        assertThat(actualAppNames).containsAtLeastElementsIn(expectedAppNames);
+
+        var actualSplitNames = new ArrayList<String>();
+        for (var appInfo : appInfoList) {
+            Log.d(TAG, "Received " + appInfo.packageName + " as a silent install");
+            if (expectedAppNames.contains(appInfo.packageName)) {
+                assertThat(appInfo.longVersion).isGreaterThan(0);
+                assertThat(appInfo.digestAlgorithm).isGreaterThan(0);
+                assertThat(appInfo.digest).isNotEmpty();
+                assertThat(appInfo.mbaStatus).isEqualTo(/* MBA_STATUS_NEW_INSTALL */ 3);
+                assertThat(appInfo.signerDigests).asList().containsNoneOf(null, "");
+
+                if (appInfo.splitName != null) {
+                    actualSplitNames.add(appInfo.splitName);
+                }
+            }
+        }
+        assertThat(actualSplitNames).containsExactly("feature_x");  // Name of ApkVerityTestAppSplit
+    }
 }
diff --git a/tests/ChoreographerTests/Android.bp b/tests/ChoreographerTests/Android.bp
new file mode 100644
index 0000000..ff252f7
--- /dev/null
+++ b/tests/ChoreographerTests/Android.bp
@@ -0,0 +1,46 @@
+// 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "ChoreographerTests",
+    srcs: ["src/**/*.java"],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.ext.junit",
+        "androidx.test.rules",
+        "compatibility-device-util-axt",
+        "com.google.android.material_material",
+        "truth-prebuilt",
+    ],
+    resource_dirs: ["src/main/res"],
+    certificate: "platform",
+    platform_apis: true,
+    test_suites: ["device-tests"],
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/ChoreographerTests/AndroidManifest.xml b/tests/ChoreographerTests/AndroidManifest.xml
new file mode 100644
index 0000000..3283c90
--- /dev/null
+++ b/tests/ChoreographerTests/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.view.choreographertests">
+
+    <application android:debuggable="true" android:testOnly="true">
+        <uses-library android:name="android.test.runner"/>
+        <activity
+            android:name=".GraphicsActivity"
+            android:exported="false">
+        </activity>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.view.choreographertests"
+        android:label="Tests of android.view.ChoreographerTests">
+    </instrumentation>
+</manifest>
\ No newline at end of file
diff --git a/tests/ChoreographerTests/AndroidTest.xml b/tests/ChoreographerTests/AndroidTest.xml
new file mode 100644
index 0000000..e717699
--- /dev/null
+++ b/tests/ChoreographerTests/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<configuration description="Config for ChoreographerTests cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="test-tag" value="ChoreographerTests"/>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="install-arg" value="-t" />
+        <option name="test-file-name" value="ChoreographerTests.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.view.choreographertests" />
+        <option name="hidden-api-checks" value="false" />
+        <option name="isolated-storage" value="false" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/ChoreographerTests/OWNERS b/tests/ChoreographerTests/OWNERS
new file mode 100644
index 0000000..2b7de25
--- /dev/null
+++ b/tests/ChoreographerTests/OWNERS
@@ -0,0 +1,2 @@
+include platform/frameworks/base:/graphics/java/android/graphics/OWNERS
+include platform/frameworks/native:/services/surfaceflinger/OWNERS
\ No newline at end of file
diff --git a/tests/ChoreographerTests/TEST_MAPPING b/tests/ChoreographerTests/TEST_MAPPING
new file mode 100644
index 0000000..16a48ea
--- /dev/null
+++ b/tests/ChoreographerTests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "ChoreographerTests"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
new file mode 100644
index 0000000..3ea9651
--- /dev/null
+++ b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
@@ -0,0 +1,455 @@
+/*
+ * 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 android.view.choreographertests;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.Manifest;
+import android.app.compat.CompatChanges;
+import android.hardware.display.DisplayManager;
+import android.os.Looper;
+import android.support.test.uiautomator.UiDevice;
+import android.util.Log;
+import android.view.Choreographer;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class AttachedChoreographerTest {
+    private static final String TAG = "AttachedChoreographerTest";
+    private static final long DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID = 170503758;
+    private static final long THRESHOLD_MS = 10;
+    private static final int FRAME_ITERATIONS = 21;
+    private static final int CALLBACK_MISSED_THRESHOLD = 2;
+
+    private final CountDownLatch mTestCompleteSignal = new CountDownLatch(2);
+    private final CountDownLatch mSurfaceCreationCountDown = new CountDownLatch(1);
+    private final CountDownLatch mNoCallbackSignal = new CountDownLatch(1);
+
+    private ActivityScenario<GraphicsActivity> mScenario;
+    private int mInitialMatchContentFrameRate;
+    private DisplayManager mDisplayManager;
+    private SurfaceView mSurfaceView;
+    private SurfaceHolder mSurfaceHolder;
+    private boolean mIsFirstCallback = true;
+    private int mCallbackMissedCounter = 0;
+
+    @Before
+    public void setUp() throws Exception {
+        mScenario = ActivityScenario.launch(GraphicsActivity.class);
+        mScenario.moveToState(Lifecycle.State.CREATED);
+        mScenario.onActivity(activity -> {
+            mSurfaceView = activity.findViewById(R.id.surface);
+            mSurfaceHolder = mSurfaceView.getHolder();
+            mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
+
+                @Override
+                public void surfaceCreated(SurfaceHolder holder) {
+                    mSurfaceCreationCountDown.countDown();
+                }
+
+                @Override
+                public void surfaceChanged(SurfaceHolder holder, int format, int width,
+                        int height) {
+                }
+
+                @Override
+                public void surfaceDestroyed(SurfaceHolder holder) {
+                }
+            });
+        });
+
+        UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        uiDevice.wakeUp();
+        uiDevice.executeShellCommand("wm dismiss-keyguard");
+        mScenario.moveToState(Lifecycle.State.RESUMED);
+
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .adoptShellPermissionIdentity(Manifest.permission.LOG_COMPAT_CHANGE,
+                        Manifest.permission.READ_COMPAT_CHANGE_CONFIG,
+                        Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
+                        Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
+                        Manifest.permission.MANAGE_GAME_MODE);
+        mScenario.onActivity(activity -> {
+            mDisplayManager = activity.getSystemService(DisplayManager.class);
+            mInitialMatchContentFrameRate = toSwitchingType(
+                    mDisplayManager.getMatchContentFrameRateUserPreference());
+            mDisplayManager.setRefreshRateSwitchingType(
+                    DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY);
+            mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true);
+            boolean changeIsEnabled =
+                    CompatChanges.isChangeEnabled(
+                            DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID);
+            Log.i(TAG, "DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGE_ID is "
+                    + (changeIsEnabled ? "enabled" : "disabled"));
+        });
+    }
+
+    @After
+    public void tearDown() {
+        mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate);
+        mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .dropShellPermissionIdentity();
+    }
+
+    @Test
+    public void testCreateChoreographer() {
+        mScenario.onActivity(activity -> {
+            if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+                fail("Unable to create surface within 1 Second");
+            }
+            SurfaceControl sc = mSurfaceView.getSurfaceControl();
+            mTestCompleteSignal.countDown();
+            SurfaceControl sc1 = new SurfaceControl(sc, "AttachedChoreographerTests");
+            // Create attached choreographer with getChoreographer
+            sc1.getChoreographer();
+            assertTrue(sc1.hasChoreographer());
+            assertTrue(sc1.isValid());
+            sc1.release();
+
+            SurfaceControl sc2 = new SurfaceControl(sc, "AttachedChoreographerTests");
+            // Create attached choreographer with Looper.myLooper
+            sc2.getChoreographer(Looper.myLooper());
+            assertTrue(sc2.hasChoreographer());
+            assertTrue(sc2.isValid());
+            sc2.release();
+
+            SurfaceControl sc3 = new SurfaceControl(sc, "AttachedChoreographerTests");
+            // Create attached choreographer with Looper.myLooper
+            sc3.getChoreographer(Looper.getMainLooper());
+            assertTrue(sc3.hasChoreographer());
+            assertTrue(sc3.isValid());
+            sc3.release();
+            mTestCompleteSignal.countDown();
+        });
+        if (waitForCountDown(mTestCompleteSignal, /* timeoutInSeconds */ 2L)) {
+            fail("Test not finished in 2 Seconds");
+        }
+    }
+
+    @Test
+    public void testCopySurfaceControl() {
+        mScenario.onActivity(activity -> {
+            if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+                fail("Unable to create surface within 1 Second");
+            }
+            SurfaceControl sc = mSurfaceView.getSurfaceControl();
+            // Create attached choreographer
+            sc.getChoreographer();
+            assertTrue(sc.hasChoreographer());
+
+            // Use copy constructor
+            SurfaceControl copyConstructorSc = new SurfaceControl(sc, "AttachedChoreographerTests");
+            //Choreographer isn't copied over.
+            assertFalse(copyConstructorSc.hasChoreographer());
+            copyConstructorSc.getChoreographer();
+            assertTrue(copyConstructorSc.hasChoreographer());
+            mTestCompleteSignal.countDown();
+
+            // Use copyFrom
+            SurfaceControl copyFromSc = new SurfaceControl();
+            copyFromSc.copyFrom(sc, "AttachedChoreographerTests");
+            //Choreographer isn't copied over.
+            assertFalse(copyFromSc.hasChoreographer());
+            copyFromSc.getChoreographer();
+            assertTrue(copyFromSc.hasChoreographer());
+            mTestCompleteSignal.countDown();
+        });
+        if (waitForCountDown(mTestCompleteSignal, /* timeoutInSeconds */ 2L)) {
+            fail("Test not finished in 2 Seconds");
+        }
+    }
+
+    @Test
+    public void testMirrorSurfaceControl() {
+        mScenario.onActivity(activity -> {
+            if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+                fail("Unable to create surface within 1 Second");
+            }
+            SurfaceControl sc = mSurfaceView.getSurfaceControl();
+            // Create attached choreographer
+            sc.getChoreographer();
+            assertTrue(sc.hasChoreographer());
+            mTestCompleteSignal.countDown();
+
+            // Use mirrorSurface
+            SurfaceControl mirrorSc = SurfaceControl.mirrorSurface(sc);
+            //Choreographer isn't copied over.
+            assertFalse(mirrorSc.hasChoreographer());
+            mirrorSc.getChoreographer();
+            assertTrue(mirrorSc.hasChoreographer());
+            // make SurfaceControl invalid by releasing it.
+            mirrorSc.release();
+
+            assertTrue(sc.isValid());
+            assertFalse(mirrorSc.isValid());
+            assertFalse(mirrorSc.hasChoreographer());
+            assertThrows(NullPointerException.class, mirrorSc::getChoreographer);
+            mTestCompleteSignal.countDown();
+        });
+        if (waitForCountDown(mTestCompleteSignal, /* timeoutInSeconds */ 2L)) {
+            fail("Test not finished in 2 Seconds");
+        }
+    }
+
+    @Test
+    public void testPostFrameCallback() {
+        mScenario.onActivity(activity -> {
+            if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+                fail("Unable to create surface within 1 Second");
+            }
+            SurfaceControl sc = mSurfaceView.getSurfaceControl();
+            sc.getChoreographer().postFrameCallback(
+                    frameTimeNanos -> mTestCompleteSignal.countDown());
+
+            SurfaceControl copySc = new SurfaceControl(sc, "AttachedChoreographerTests");
+            Choreographer copyChoreographer = copySc.getChoreographer();
+            // make SurfaceControl invalid by releasing it.
+            copySc.release();
+
+            assertTrue(sc.isValid());
+            assertFalse(copySc.isValid());
+            copyChoreographer.postFrameCallback(frameTimeNanos -> mNoCallbackSignal.countDown());
+            assertDoesReceiveCallback();
+        });
+        if (waitForCountDown(mTestCompleteSignal, /* timeoutInSeconds */ 2L)) {
+            fail("Test not finished in 2 Seconds");
+        }
+    }
+
+    @Test
+    public void testPostFrameCallbackDelayed() {
+        mScenario.onActivity(activity -> {
+            if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+                fail("Unable to create surface within 1 Second");
+            }
+            SurfaceControl sc = mSurfaceView.getSurfaceControl();
+            sc.getChoreographer(Looper.getMainLooper()).postFrameCallbackDelayed(
+                    callback -> mTestCompleteSignal.countDown(),
+                    /* delayMillis */ 5);
+
+            SurfaceControl copySc = new SurfaceControl(sc, "AttachedChoreographerTests");
+            Choreographer copyChoreographer = copySc.getChoreographer();
+            // make SurfaceControl invalid by releasing it.
+            copySc.release();
+
+            assertTrue(sc.isValid());
+            assertFalse(copySc.isValid());
+            copyChoreographer.postFrameCallbackDelayed(
+                    frameTimeNanos -> mNoCallbackSignal.countDown(), /* delayMillis */5);
+            assertDoesReceiveCallback();
+        });
+        if (waitForCountDown(mTestCompleteSignal, /* timeoutInSeconds */ 2L)) {
+            fail("Test not finished in 2 Seconds");
+        }
+    }
+
+    @Test
+    public void testPostCallback() {
+        mScenario.onActivity(activity -> {
+            if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+                fail("Unable to create surface within 1 Second");
+            }
+            SurfaceControl sc = mSurfaceView.getSurfaceControl();
+            sc.getChoreographer().postCallback(Choreographer.CALLBACK_COMMIT,
+                    mTestCompleteSignal::countDown, /* token */ this);
+
+            SurfaceControl copySc = new SurfaceControl(sc, "AttachedChoreographerTests");
+            Choreographer copyChoreographer = copySc.getChoreographer();
+            // make SurfaceControl invalid by releasing it.
+            copySc.release();
+
+            assertTrue(sc.isValid());
+            assertFalse(copySc.isValid());
+            copyChoreographer.postCallback(Choreographer.CALLBACK_COMMIT,
+                    mNoCallbackSignal::countDown, /* token */ this);
+            assertDoesReceiveCallback();
+        });
+        if (waitForCountDown(mTestCompleteSignal, /* timeoutInSeconds */ 2L)) {
+            fail("Test not finished in 2 Seconds");
+        }
+    }
+
+    @Test
+    public void testPostCallbackDelayed() {
+        mScenario.onActivity(activity -> {
+            if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+                fail("Unable to create surface within 1 Second");
+            }
+            SurfaceControl sc = mSurfaceView.getSurfaceControl();
+            sc.getChoreographer().postCallbackDelayed(Choreographer.CALLBACK_COMMIT,
+                    mTestCompleteSignal::countDown, /* token */ this, /* delayMillis */ 5);
+
+            SurfaceControl copySc = new SurfaceControl(sc, "AttachedChoreographerTests");
+            Choreographer copyChoreographer = copySc.getChoreographer();
+            // make SurfaceControl invalid by releasing it.
+            copySc.release();
+
+            assertTrue(sc.isValid());
+            assertFalse(copySc.isValid());
+            copyChoreographer.postCallbackDelayed(Choreographer.CALLBACK_COMMIT,
+                    mNoCallbackSignal::countDown, /* token */ this, /* delayMillis */ 5);
+            assertDoesReceiveCallback();
+        });
+        if (waitForCountDown(mTestCompleteSignal, /* timeoutInSeconds */ 2L)) {
+            fail("Test not finished in 2 Seconds");
+        }
+    }
+
+    @Test
+    public void testPostVsyncCallback() {
+        mScenario.onActivity(activity -> {
+            if (waitForCountDown(mSurfaceCreationCountDown, /* timeout */ 1L)) {
+                fail("Unable to create surface within 1 Second");
+            }
+            SurfaceControl sc = mSurfaceView.getSurfaceControl();
+            sc.getChoreographer().postVsyncCallback(data -> mTestCompleteSignal.countDown());
+
+            SurfaceControl copySc = new SurfaceControl(sc, "AttachedChoreographerTests");
+            Choreographer copyChoreographer = copySc.getChoreographer();
+            // make SurfaceControl invalid by releasing it.
+            copySc.release();
+
+            assertTrue(sc.isValid());
+            assertFalse(copySc.isValid());
+            copyChoreographer.postVsyncCallback(data -> mNoCallbackSignal.countDown());
+            assertDoesReceiveCallback();
+        });
+        if (waitForCountDown(mTestCompleteSignal, /* timeoutInSeconds */ 2L)) {
+            fail("Test not finished in 2 Seconds");
+        }
+    }
+
+    @Test
+    public void testChoreographerDivisorRefreshRate() {
+        for (int divisor : new int[]{2, 3}) {
+            CountDownLatch continueLatch = new CountDownLatch(1);
+            mScenario.onActivity(activity -> {
+                if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+                    fail("Unable to create surface within 1 Second");
+                }
+                SurfaceControl sc = mSurfaceView.getSurfaceControl();
+                Choreographer choreographer = sc.getChoreographer();
+                SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+                float displayRefreshRate = activity.getDisplay().getMode().getRefreshRate();
+                float fps = displayRefreshRate / divisor;
+                long callbackDurationMs = Math.round(1000 / fps);
+                mCallbackMissedCounter = 0;
+                transaction.setFrameRate(sc, fps, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE)
+                        .addTransactionCommittedListener(Runnable::run,
+                                () -> verifyVsyncCallbacks(choreographer,
+                                        callbackDurationMs, continueLatch, FRAME_ITERATIONS))
+                        .apply();
+            });
+            // wait for the previous callbacks to finish before moving to the next divisor
+            if (waitForCountDown(continueLatch, /* timeoutInSeconds */ 5L)) {
+                fail("Test not finished in 5 Seconds");
+            }
+        }
+    }
+
+    private void verifyVsyncCallbacks(Choreographer choreographer, long callbackDurationMs,
+            CountDownLatch continueLatch, int frameCount) {
+        long callbackRequestedTimeNs = System.nanoTime();
+        choreographer.postVsyncCallback(frameData -> {
+            if (frameCount > 0) {
+                if (!mIsFirstCallback) {
+                    // Skip the first callback as it takes 1 frame
+                    // to reflect the new refresh rate
+                    long callbackDurationDiffMs = getCallbackDurationDiffInMs(
+                            frameData.getFrameTimeNanos(),
+                            callbackRequestedTimeNs, callbackDurationMs);
+                    if (callbackDurationDiffMs < 0 || callbackDurationDiffMs > THRESHOLD_MS) {
+                        mCallbackMissedCounter++;
+                        Log.e(TAG, "Frame #" + Math.abs(frameCount - FRAME_ITERATIONS)
+                                + " vsync callback failed, expected callback in "
+                                + callbackDurationMs
+                                + " With threshold of " + THRESHOLD_MS
+                                + " but actual duration difference is " + callbackDurationDiffMs);
+                    }
+                }
+                mIsFirstCallback = false;
+                verifyVsyncCallbacks(choreographer, callbackDurationMs,
+                        continueLatch, frameCount - 1);
+            } else {
+                assertTrue("Missed timeline for " + mCallbackMissedCounter + " callbacks, while "
+                                + CALLBACK_MISSED_THRESHOLD + " missed callbacks are allowed",
+                        mCallbackMissedCounter <= CALLBACK_MISSED_THRESHOLD);
+                continueLatch.countDown();
+            }
+        });
+    }
+
+    private long getCallbackDurationDiffInMs(long callbackTimeNs, long requestedTimeNs,
+            long expectedCallbackMs) {
+        long actualTimeMs = TimeUnit.NANOSECONDS.toMillis(callbackTimeNs)
+                - TimeUnit.NANOSECONDS.toMillis(requestedTimeNs);
+        return Math.abs(expectedCallbackMs - actualTimeMs);
+    }
+
+    private boolean waitForCountDown(CountDownLatch countDownLatch, long timeoutInSeconds) {
+        try {
+            return !countDownLatch.await(timeoutInSeconds, TimeUnit.SECONDS);
+        } catch (InterruptedException ex) {
+            throw new AssertionError("Test interrupted", ex);
+        }
+    }
+
+    private int toSwitchingType(int matchContentFrameRateUserPreference) {
+        switch (matchContentFrameRateUserPreference) {
+            case DisplayManager.MATCH_CONTENT_FRAMERATE_NEVER:
+                return DisplayManager.SWITCHING_TYPE_NONE;
+            case DisplayManager.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY:
+                return DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS;
+            case DisplayManager.MATCH_CONTENT_FRAMERATE_ALWAYS:
+                return DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS;
+            default:
+                return -1;
+        }
+    }
+
+    private void assertDoesReceiveCallback() {
+        try {
+            if (mNoCallbackSignal.await(/* timeout */ 50L, TimeUnit.MILLISECONDS)) {
+                fail("Callback not supposed to be generated");
+            } else {
+                mTestCompleteSignal.countDown();
+            }
+        } catch (InterruptedException e) {
+            fail("Callback wait is interrupted " + e);
+        }
+    }
+}
diff --git a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/GraphicsActivity.java b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/GraphicsActivity.java
new file mode 100644
index 0000000..50a6850
--- /dev/null
+++ b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/GraphicsActivity.java
@@ -0,0 +1,28 @@
+/*
+ * 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 android.view.choreographertests;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class GraphicsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_attached_choreographer);
+    }
+}
diff --git a/tests/ChoreographerTests/src/main/res/layout/activity_attached_choreographer.xml b/tests/ChoreographerTests/src/main/res/layout/activity_attached_choreographer.xml
new file mode 100644
index 0000000..d6c8212
--- /dev/null
+++ b/tests/ChoreographerTests/src/main/res/layout/activity_attached_choreographer.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/tests/ChoreographerTests/src/main/res/mipmap-hdpi/ic_launcher.png b/tests/ChoreographerTests/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
--- /dev/null
+++ b/tests/ChoreographerTests/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/ChoreographerTests/src/main/res/mipmap-mdpi/ic_launcher.png b/tests/ChoreographerTests/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
--- /dev/null
+++ b/tests/ChoreographerTests/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/ChoreographerTests/src/main/res/mipmap-xhdpi/ic_launcher.png b/tests/ChoreographerTests/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
--- /dev/null
+++ b/tests/ChoreographerTests/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/ChoreographerTests/src/main/res/mipmap-xxhdpi/ic_launcher.png b/tests/ChoreographerTests/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
--- /dev/null
+++ b/tests/ChoreographerTests/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/ChoreographerTests/src/main/res/values/strings.xml b/tests/ChoreographerTests/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e66b001
--- /dev/null
+++ b/tests/ChoreographerTests/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="app_name">ChoreographerTests</string>
+</resources>
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index 64ed453..87bfdeb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -22,7 +22,7 @@
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.launcher3.tapl.LauncherInstrumentation
 import com.android.server.wm.flicker.junit.FlickerBuilderProvider
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.Assume
 import org.junit.AssumptionViolatedException
 import org.junit.Test
@@ -184,12 +184,12 @@
     }
 
     open fun cujCompleted() {
-        entireScreenCovered()
-        statusBarLayerIsVisibleAtStartAndEnd()
-        statusBarLayerPositionAtStartAndEnd()
-        statusBarWindowIsAlwaysVisible()
-        visibleLayersShownMoreThanOneConsecutiveEntry()
-        visibleWindowsShownMoreThanOneConsecutiveEntry()
+        runAndIgnoreAssumptionViolation { entireScreenCovered() }
+        runAndIgnoreAssumptionViolation { statusBarLayerIsVisibleAtStartAndEnd() }
+        runAndIgnoreAssumptionViolation { statusBarLayerPositionAtStartAndEnd() }
+        runAndIgnoreAssumptionViolation { statusBarWindowIsAlwaysVisible() }
+        runAndIgnoreAssumptionViolation { visibleLayersShownMoreThanOneConsecutiveEntry() }
+        runAndIgnoreAssumptionViolation { visibleWindowsShownMoreThanOneConsecutiveEntry() }
         runAndIgnoreAssumptionViolation { taskBarLayerIsVisibleAtStartAndEnd() }
         runAndIgnoreAssumptionViolation { taskBarWindowIsAlwaysVisible() }
         runAndIgnoreAssumptionViolation { navBarLayerIsVisibleAtStartAndEnd() }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index f26ce25..e3dc699 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -20,8 +20,8 @@
 
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.traces.region.RegionSubject
-import com.android.server.wm.traces.common.ComponentNameMatcher
-import com.android.server.wm.traces.common.IComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.IComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import com.android.server.wm.traces.common.windowmanager.WindowManagerTrace
 
@@ -259,7 +259,7 @@
                     snapshotLayers
                         .mapNotNull { snapshotLayer -> snapshotLayer.layer?.visibleRegion }
                         .toTypedArray()
-                val snapshotRegion = RegionSubject.assertThat(visibleAreas, this, timestamp)
+                val snapshotRegion = RegionSubject(visibleAreas, this, timestamp)
                 val appVisibleRegion = it.visibleRegion(component)
                 if (snapshotRegion.region.isNotEmpty) {
                     snapshotRegion.coversExactly(appVisibleRegion.region)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
similarity index 63%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplit.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
index ea67729..7f2e057f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
@@ -33,13 +33,13 @@
  * Test opening an activity that will launch another activity as ActivityEmbedding placeholder in
  * split.
  *
- * To run this test: `atest FlickerTests:OpenActivityEmbeddingPlaceholderSplit`
+ * To run this test: `atest FlickerTests:OpenActivityEmbeddingPlaceholderSplitTest`
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenActivityEmbeddingPlaceholderSplit(flicker: FlickerTest) :
+class OpenActivityEmbeddingPlaceholderSplitTest(flicker: FlickerTest) :
     ActivityEmbeddingTestBase(flicker) {
 
     /** {@inheritDoc} */
@@ -55,9 +55,21 @@
         }
     }
 
+    /** Main activity should become invisible after launching the placeholder primary activity. */
     @Presubmit
     @Test
-    fun mainActivityBecomesInvisible() {
+    fun mainActivityWindowBecomesInvisible() {
+        flicker.assertWm {
+            isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+                .then()
+                .isAppWindowInvisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+        }
+    }
+
+    /** Main activity should become invisible after launching the placeholder primary activity. */
+    @Presubmit
+    @Test
+    fun mainActivityLayerBecomesInvisible() {
         flicker.assertLayers {
             isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
                 .then()
@@ -65,76 +77,41 @@
         }
     }
 
+    /**
+     * Placeholder primary and secondary should become visible after launch. The windows are not
+     * necessarily to become visible at the same time.
+     */
     @Presubmit
     @Test
-    fun placeholderSplitBecomesVisible() {
-        flicker.assertLayers {
-            isInvisible(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
+    fun placeholderSplitWindowsBecomeVisible() {
+        flicker.assertWm {
+            notContains(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
                 .then()
-                .isVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
+                .isAppWindowInvisible(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
+                .then()
+                .isAppWindowVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
         }
-        flicker.assertLayers {
-            isInvisible(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
+        flicker.assertWm {
+            notContains(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
                 .then()
-                .isVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
+                .isAppWindowInvisible(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
+                .then()
+                .isAppWindowVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
         }
     }
 
-    /** {@inheritDoc} */
-    @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
-
-    /** {@inheritDoc} */
+    /** Placeholder primary and secondary should become visible together after launch. */
     @Presubmit
     @Test
-    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun statusBarLayerIsVisibleAtStartAndEnd() =
-        super.statusBarLayerIsVisibleAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
-        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
-    /** {@inheritDoc} */
-    @Presubmit
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+    fun placeholderSplitLayersBecomeVisible() {
+        flicker.assertLayers {
+            isInvisible(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
+            isInvisible(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
+                .then()
+                .isVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
+                .isVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
+        }
+    }
 
     companion object {
         /**
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
new file mode 100644
index 0000000..20259a7
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
@@ -0,0 +1,124 @@
+/*
+ * 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.wm.flicker.activityembedding
+
+import android.platform.test.annotations.Presubmit
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerBuilder
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test opening a secondary activity that will split with the main activity.
+ *
+ * To run this test: `atest FlickerTests:OpenActivityEmbeddingSecondaryToSplitTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenActivityEmbeddingSecondaryToSplitTest(flicker: FlickerTest) :
+    ActivityEmbeddingTestBase(flicker) {
+
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit = {
+        setup {
+            tapl.setExpectedRotationCheckEnabled(false)
+            testApp.launchViaIntent(wmHelper)
+        }
+        transitions { testApp.launchSecondaryActivity(wmHelper) }
+        teardown {
+            tapl.goHome()
+            testApp.exit(wmHelper)
+        }
+    }
+
+    /** Main activity should remain visible when enter split from fullscreen. */
+    @Presubmit
+    @Test
+    fun mainActivityWindowIsAlwaysVisible() {
+        flicker.assertWm {
+            isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+        }
+    }
+
+    /**
+     * Main activity surface is animated from fullscreen to ActivityEmbedding split.
+     * During the transition, there is a period of time that it is covered by a snapshot of itself.
+     */
+    @Presubmit
+    @Test
+    fun mainActivityLayerIsAlwaysVisible() {
+        flicker.assertLayers {
+            isVisible(
+                ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT.or(
+                    ComponentNameMatcher.TRANSITION_SNAPSHOT
+                )
+            )
+        }
+        flicker.assertLayersEnd {
+            isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+                .isInvisible(ComponentNameMatcher.TRANSITION_SNAPSHOT)
+        }
+    }
+
+    /** Secondary activity should become visible after launching into split. */
+    @Presubmit
+    @Test
+    fun secondaryActivityWindowBecomesVisible() {
+        flicker.assertWm {
+            notContains(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+                .then()
+                .isAppWindowInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+                .then()
+                .isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+        }
+    }
+
+    /** Secondary activity should become visible after launching into split. */
+    @Presubmit
+    @Test
+    fun secondaryActivityLayerBecomesVisible() {
+        flicker.assertLayers {
+            isInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+                .then()
+                .isVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+        }
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests()
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index 23503d2..4d72729 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -24,7 +24,7 @@
 import com.android.server.wm.flicker.helpers.StandardAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.replacesLayer
-import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.LAUNCHER
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.LAUNCHER
 import org.junit.Test
 
 /** Base test class for transitions that close an app back to the launcher screen */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
index 368cc56..65d0fa9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
@@ -24,7 +24,7 @@
 import androidx.window.extensions.WindowExtensionsProvider
 import androidx.window.extensions.embedding.ActivityEmbeddingComponent
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.windowmanager.WindowManagerState.Companion.STATE_RESUMED
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
@@ -39,6 +39,25 @@
 ) : StandardAppHelper(instr, launcherName, component) {
 
     /**
+     * Clicks the button to launch the secondary activity, which should split with the main activity
+     * based on the split pair rule.
+     */
+    fun launchSecondaryActivity(wmHelper: WindowManagerStateHelper) {
+        val launchButton =
+            uiDevice.wait(
+                Until.findObject(By.res(getPackage(), "launch_secondary_activity_button")),
+                FIND_TIMEOUT
+            )
+        require(launchButton != null) { "Can't find launch secondary activity button on screen." }
+        launchButton.click()
+        wmHelper
+            .StateSyncBuilder()
+            .withActivityState(SECONDARY_ACTIVITY_COMPONENT, STATE_RESUMED)
+            .withActivityState(MAIN_ACTIVITY_COMPONENT, STATE_RESUMED)
+            .waitForAndVerify()
+    }
+
+    /**
      * Clicks the button to launch the placeholder primary activity, which should launch the
      * placeholder secondary activity based on the placeholder rule.
      */
@@ -63,6 +82,9 @@
         val MAIN_ACTIVITY_COMPONENT =
             ActivityOptions.ActivityEmbedding.MainActivity.COMPONENT.toFlickerComponent()
 
+        val SECONDARY_ACTIVITY_COMPONENT =
+            ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT.toFlickerComponent()
+
         val PLACEHOLDER_PRIMARY_COMPONENT =
             ActivityOptions.ActivityEmbedding.PlaceholderPrimaryActivity.COMPONENT
                 .toFlickerComponent()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
index 4ff4e31..73018a0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
@@ -17,7 +17,7 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 
 class AppPairsHelper(
     instrumentation: Instrumentation,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt
deleted file mode 100644
index a2d4d3a..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.helpers
-
-import android.app.Instrumentation
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.content.pm.ResolveInfo
-import android.provider.MediaStore
-import com.android.server.wm.traces.common.ComponentNameMatcher
-
-class CameraAppHelper
-@JvmOverloads
-constructor(
-    instrumentation: Instrumentation,
-    pkgManager: PackageManager = instrumentation.context.packageManager
-) :
-    StandardAppHelper(
-        instrumentation,
-        getCameraLauncherName(pkgManager),
-        getCameraComponent(pkgManager)
-    ) {
-    companion object {
-        private fun getCameraIntent(): Intent {
-            return Intent(MediaStore.ACTION_IMAGE_CAPTURE)
-        }
-
-        private fun getResolveInfo(pkgManager: PackageManager): ResolveInfo {
-            val intent = getCameraIntent()
-            return pkgManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY)
-                ?: error("unable to resolve camera activity")
-        }
-
-        private fun getCameraComponent(pkgManager: PackageManager): ComponentNameMatcher {
-            val resolveInfo = getResolveInfo(pkgManager)
-            return ComponentNameMatcher(
-                resolveInfo.activityInfo.packageName,
-                className = resolveInfo.activityInfo.name
-            )
-        }
-
-        private fun getCameraLauncherName(pkgManager: PackageManager): String {
-            val resolveInfo = getResolveInfo(pkgManager)
-            return resolveInfo.activityInfo.name
-        }
-    }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
index 05b50f0..cdf7ae5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
@@ -18,7 +18,7 @@
 
 import android.app.Instrumentation
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 
 class FixedOrientationAppHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
index d583bba..f5aed41 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
@@ -21,7 +21,7 @@
 import androidx.test.uiautomator.Direction
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index 3bb7f4e..a433b15 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -20,7 +20,7 @@
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
index 871b66e..fb0242e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
@@ -20,7 +20,7 @@
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
similarity index 81%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
index b7eea1b..fb04b32 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
@@ -23,15 +23,16 @@
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.Condition
 import com.android.server.wm.traces.common.DeviceStateDump
+import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import java.util.regex.Pattern
 
-class ImeAppAutoFocusHelper
+class ImeShownOnAppStartHelper
 @JvmOverloads
 constructor(
     instr: Instrumentation,
@@ -48,12 +49,13 @@
 
     override fun launchViaIntent(
         wmHelper: WindowManagerStateHelper,
-        expectedWindowName: String,
+        launchedAppComponentMatcherOverride: IComponentMatcher?,
         action: String?,
         stringExtras: Map<String, String>,
         waitConditions: Array<Condition<DeviceStateDump>>
     ) {
-        super.launchViaIntent(wmHelper, expectedWindowName, action, stringExtras, waitConditions)
+        super.launchViaIntent(
+            wmHelper, launchedAppComponentMatcherOverride, action, stringExtras, waitConditions)
         waitIMEShown(wmHelper)
     }
 
@@ -119,4 +121,20 @@
         }
         return false
     }
+
+    fun toggleFixPortraitOrientation(wmHelper: WindowManagerStateHelper) {
+        val button =
+            uiDevice.wait(
+                Until.findObject(By.res(getPackage(), "toggle_fixed_portrait_btn")),
+                FIND_TIMEOUT
+            )
+        require(button != null) {
+            "Button not found, this usually happens when the device " +
+                "was left in an unknown state (e.g. Screen turned off)"
+        }
+        button.click()
+        mInstrumentation.waitForIdleSync()
+        // Ensure app relaunching transition finish and the IME has shown
+        waitIMEShown(wmHelper)
+    }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
index 69d6a47..8a25e36 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
@@ -18,7 +18,7 @@
 
 import android.app.Instrumentation
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 
 class ImeStateInitializeHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
index d0935ef..d6ed24a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
@@ -22,7 +22,7 @@
 import androidx.test.uiautomator.UiObject2
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 
 class MailAppHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
index e0f6fb0..ae42232 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
@@ -21,7 +21,7 @@
 import android.provider.Settings
 import android.util.Log
 import com.android.compatibility.common.util.SystemUtil
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import java.io.IOException
 
 class MultiWindowUtils(
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
index 8b3fa18..5c1eca3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
@@ -21,7 +21,7 @@
 import androidx.test.uiautomator.UiDevice
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
index 992a1a1..58da2d8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
@@ -18,7 +18,7 @@
 
 import android.app.Instrumentation
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 
 class NonResizeableAppHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
index c29c752..d7f0830 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
@@ -20,7 +20,7 @@
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index 18792a8..0c8589d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -26,6 +26,7 @@
 import com.android.server.wm.flicker.testapp.ActivityOptions
 import com.android.server.wm.traces.common.Rect
 import com.android.server.wm.traces.common.WindowManagerConditionsFactory
+import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
 import com.android.server.wm.traces.common.region.Region
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
@@ -157,13 +158,13 @@
     @JvmOverloads
     fun launchViaIntentAndWaitForPip(
         wmHelper: WindowManagerStateHelper,
-        expectedWindowName: String = "",
+        launchedAppComponentMatcherOverride: IComponentMatcher? = null,
         action: String? = null,
         stringExtras: Map<String, String>
     ) {
         launchViaIntentAndWaitShown(
             wmHelper,
-            expectedWindowName,
+            launchedAppComponentMatcherOverride,
             action,
             stringExtras,
             waitConditions = arrayOf(WindowManagerConditionsFactory.hasPipWindow())
@@ -294,10 +295,10 @@
             .StateSyncBuilder()
             .add("pipWindowMinimized") {
                 val pipAppWindow =
-                        it.wmState.visibleWindows.firstOrNull { window ->
-                            this.windowMatchesAnyOf(window)
-                        }
-                                ?: return@add false
+                    it.wmState.visibleWindows.firstOrNull { window ->
+                        this.windowMatchesAnyOf(window)
+                    }
+                        ?: return@add false
                 val pipRegion = pipAppWindow.frameRegion
                 return@add windowRect.coversMoreThan(pipRegion)
             }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
index c51754c..8f54000 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
@@ -18,7 +18,7 @@
 
 import android.app.Instrumentation
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 
 class SeamlessRotationAppHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
index 9318f20..61dabfc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
@@ -18,7 +18,7 @@
 
 import android.app.Instrumentation
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 
 class ShowWhenLockedAppHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
index b46ff2c..9ed9d28e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
@@ -18,7 +18,7 @@
 
 import android.app.Instrumentation
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 
 class SimpleAppHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
index 720d962..8f7049a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
@@ -21,7 +21,7 @@
 import androidx.test.uiautomator.UiDevice
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTestCfArm.kt
deleted file mode 100644
index 70443d8..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTestCfArm.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.wm.flicker.ime
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeAutoOpenWindowToAppTestCfArm(flicker: FlickerTest) :
-    CloseImeAutoOpenWindowToAppTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTestCfArm.kt
deleted file mode 100644
index 2ffc757..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTestCfArm.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.wm.flicker.ime
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class CloseImeAutoOpenWindowToHomeTestCfArm(flicker: FlickerTest) :
-    CloseImeAutoOpenWindowToHomeTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
similarity index 94%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
index c72405c..092a4fd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
@@ -25,7 +25,7 @@
 import com.android.server.wm.flicker.helpers.ImeEditorPopupDialogAppHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.traces.region.RegionSubject
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -37,7 +37,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeEditorPopupDialogTest(flicker: FlickerTest) : BaseTest(flicker) {
+class CloseImeOnDismissPopupDialogTest(flicker: FlickerTest) : BaseTest(flicker) {
     private val imeTestApp = ImeEditorPopupDialogAppHelper(instrumentation)
 
     /** {@inheritDoc} */
@@ -90,7 +90,7 @@
                                 imeSnapshotLayer.layer?.visibleRegion
                             }
                             .toTypedArray()
-                    val imeVisibleRegion = RegionSubject.assertThat(visibleAreas, this, timestamp)
+                    val imeVisibleRegion = RegionSubject(visibleAreas, this, timestamp)
                     val appVisibleRegion = it.visibleRegion(imeTestApp)
                     if (imeVisibleRegion.region.isNotEmpty) {
                         imeVisibleRegion.coversAtMost(appVisibleRegion.region)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
similarity index 95%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
index 840575a..0870cec 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
@@ -25,7 +25,7 @@
 import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.helpers.ImeAppHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -41,7 +41,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class CloseImeWindowToHomeTest(flicker: FlickerTest) : BaseTest(flicker) {
+open class CloseImeOnGoHomeTest(flicker: FlickerTest) : BaseTest(flicker) {
     private val testApp = ImeAppHelper(instrumentation)
 
     /** {@inheritDoc} */
@@ -100,6 +100,7 @@
         flicker.assertLayers { this.isVisible(testApp).then().isInvisible(testApp) }
     }
 
+    @Presubmit
     @Test
     @IwTest(focusArea = "ime")
     override fun cujCompleted() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt
similarity index 92%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTestCfArm.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt
index 34bd455..96b23bc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt
@@ -26,4 +26,4 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenImeWindowTestCfArm(flicker: FlickerTest) : OpenImeWindowTest(flicker)
+class CloseImeOnGoHomeTestCfArm(flicker: FlickerTest) : CloseImeOnGoHomeTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
similarity index 90%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
index 2081424..48dbf25 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
@@ -22,9 +22,9 @@
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -48,8 +48,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class CloseImeAutoOpenWindowToHomeTest(flicker: FlickerTest) : BaseTest(flicker) {
-    private val testApp = ImeAppAutoFocusHelper(instrumentation, flicker.scenario.startRotation)
+open class CloseImeShownOnAppStartOnGoHomeTest(flicker: FlickerTest) : BaseTest(flicker) {
+    private val testApp = ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit = {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt
similarity index 90%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTestCfArm.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt
index 0e6cb53..ed5d309 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt
@@ -26,5 +26,5 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenImeWindowFromFixedOrientationAppTestCfArm(flicker: FlickerTest) :
-    OpenImeWindowFromFixedOrientationAppTest(flicker)
+open class CloseImeShownOnAppStartOnGoHomeTestCfArm(flicker: FlickerTest) :
+    CloseImeShownOnAppStartOnGoHomeTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
similarity index 89%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
index 522f9e7..7b935ff 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
@@ -22,9 +22,9 @@
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -48,8 +48,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class CloseImeAutoOpenWindowToAppTest(flicker: FlickerTest) : BaseTest(flicker) {
-    private val testApp = ImeAppAutoFocusHelper(instrumentation, flicker.scenario.startRotation)
+open class CloseImeShownOnAppStartToAppOnPressBackTest(flicker: FlickerTest) : BaseTest(flicker) {
+    private val testApp = ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit = {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt
similarity index 88%
copy from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
copy to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt
index 87d9abd..0a89991 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt
@@ -26,4 +26,5 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToHomeTestCfArm(flicker: FlickerTest) : CloseImeWindowToHomeTest(flicker)
+class CloseImeShownOnAppStartToAppOnPressBackTestCfArm(flicker: FlickerTest) :
+    CloseImeShownOnAppStartToAppOnPressBackTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
similarity index 95%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
index 13feeb1..1a0c959 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
@@ -27,7 +27,7 @@
 import com.android.server.wm.flicker.helpers.ImeAppHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -43,7 +43,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class CloseImeWindowToAppTest(flicker: FlickerTest) : BaseTest(flicker) {
+open class CloseImeToAppOnPressBackTest(flicker: FlickerTest) : BaseTest(flicker) {
     private val testApp = ImeAppHelper(instrumentation)
 
     /** {@inheritDoc} */
@@ -102,6 +102,7 @@
         flicker.assertWm { this.isAppWindowOnTop(testApp) }
     }
 
+    @Presubmit
     @Test
     @IwTest(focusArea = "ime")
     override fun cujCompleted() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt
similarity index 90%
copy from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
copy to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt
index 87d9abd..37e8c6b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt
@@ -26,4 +26,5 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToHomeTestCfArm(flicker: FlickerTest) : CloseImeWindowToHomeTest(flicker)
+class CloseImeToAppOnPressBackTestCfArm(flicker: FlickerTest) :
+    CloseImeToAppOnPressBackTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
similarity index 96%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
index 7d1f6cb..0b7b165 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
@@ -46,7 +46,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenImeWindowAndCloseTest(flicker: FlickerTest) : BaseTest(flicker) {
+open class CloseImeToHomeOnFinishActivityTest(flicker: FlickerTest) : BaseTest(flicker) {
     private val simpleApp = SimpleAppHelper(instrumentation)
     private val testApp = ImeAppHelper(instrumentation)
 
@@ -79,6 +79,7 @@
         super.visibleLayersShownMoreThanOneConsecutiveEntry()
     }
 
+    @Presubmit
     @Test
     @IwTest(focusArea = "ime")
     override fun cujCompleted() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt
similarity index 89%
copy from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
copy to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt
index 87d9abd..116bc1b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt
@@ -26,4 +26,5 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToHomeTestCfArm(flicker: FlickerTest) : CloseImeWindowToHomeTest(flicker)
+open class CloseImeToHomeOnFinishActivityTestCfArm(flicker: FlickerTest) :
+    CloseImeToHomeOnFinishActivityTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTestCfArm.kt
deleted file mode 100644
index f40f5e6..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTestCfArm.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.wm.flicker.ime
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToAppTestCfArm(flicker: FlickerTest) : CloseImeWindowToAppTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index 3edc15f..dcffa47 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -19,7 +19,7 @@
 package com.android.server.wm.flicker.ime
 
 import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 
 fun FlickerTest.imeLayerBecomesVisible() {
     assertLayers {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTestCfArm.kt
deleted file mode 100644
index 04cae53..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTestCfArm.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.wm.flicker.ime
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class LaunchAppShowImeOnStartTestCfArm(flicker: FlickerTest) :
-    LaunchAppShowImeOnStartTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTestCfArm.kt
deleted file mode 100644
index c40dfae..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTestCfArm.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.wm.flicker.ime
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenImeWindowAndCloseTestCfArm(flicker: FlickerTest) :
-    OpenImeWindowAndCloseTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
new file mode 100644
index 0000000..defb437
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
@@ -0,0 +1,117 @@
+/*
+ * 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.wm.flicker.ime
+
+import android.platform.test.annotations.Postsubmit
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.BaseTest
+import com.android.server.wm.flicker.FlickerBuilder
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.traces.region.RegionSubject
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test IME window shown on the app with fixing portrait orientation. To run this test: `atest
+ * FlickerTests:OpenImeWindowToFixedPortraitAppTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenImeWindowToFixedPortraitAppTest(flicker: FlickerTest) : BaseTest(flicker) {
+    private val testApp = ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
+
+    /** {@inheritDoc} */
+    override val transition: FlickerBuilder.() -> Unit = {
+        setup {
+            testApp.launchViaIntent(wmHelper)
+            testApp.openIME(wmHelper)
+            // Enable letterbox when the app calls setRequestedOrientation
+            device.executeShellCommand("cmd window set-ignore-orientation-request true")
+        }
+        transitions { testApp.toggleFixPortraitOrientation(wmHelper) }
+        teardown {
+            testApp.exit()
+            device.executeShellCommand("cmd window set-ignore-orientation-request false")
+        }
+    }
+
+    @Postsubmit
+    @Test
+    fun imeLayerVisibleStart() {
+        flicker.assertLayersStart { this.isVisible(ComponentNameMatcher.IME) }
+    }
+
+    @Postsubmit
+    @Test
+    fun imeLayerExistsEnd() {
+        flicker.assertLayersEnd { this.isVisible(ComponentNameMatcher.IME) }
+    }
+
+    @Postsubmit
+    @Test
+    fun imeLayerVisibleRegionKeepsTheSame() {
+        var imeLayerVisibleRegionBeforeTransition: RegionSubject? = null
+        flicker.assertLayersStart {
+            imeLayerVisibleRegionBeforeTransition = this.visibleRegion(ComponentNameMatcher.IME)
+        }
+        flicker.assertLayersEnd {
+            this.visibleRegion(ComponentNameMatcher.IME)
+                .coversExactly(imeLayerVisibleRegionBeforeTransition!!.region)
+        }
+    }
+
+    @Postsubmit
+    @Test
+    fun appWindowWithLetterboxCoversExactlyOnScreen() {
+        val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.startRotation)
+        flicker.assertLayersEnd {
+            this.visibleRegion(testApp.or(ComponentNameMatcher.LETTERBOX))
+                .coversExactly(displayBounds)
+        }
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedRotations =
+                    listOf(
+                        PlatformConsts.Rotation.ROTATION_90,
+                    ),
+                supportedNavigationModes =
+                    listOf(PlatformConsts.NavBar.MODE_3BUTTON, PlatformConsts.NavBar.MODE_GESTURAL)
+            )
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTestCfArm.kt
deleted file mode 100644
index 8e6d7dc..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTestCfArm.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.wm.flicker.ime
-
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenImeWindowToOverViewTestCfArm(flicker: FlickerTest) : OpenImeWindowToOverViewTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
similarity index 92%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
index d41843f..89d37db 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
@@ -23,7 +23,7 @@
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
@@ -45,8 +45,10 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenImeWindowFromFixedOrientationAppTest(flicker: FlickerTest) : BaseTest(flicker) {
-    private val imeTestApp = ImeAppAutoFocusHelper(instrumentation, flicker.scenario.startRotation)
+open class ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest(flicker: FlickerTest) :
+    BaseTest(flicker) {
+    private val imeTestApp =
+        ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit = {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt
similarity index 86%
copy from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
copy to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt
index 87d9abd..307821f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt
@@ -26,4 +26,5 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToHomeTestCfArm(flicker: FlickerTest) : CloseImeWindowToHomeTest(flicker)
+class ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm(flicker: FlickerTest) :
+    ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
similarity index 93%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
index 38791a2..c72e4e4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
@@ -22,11 +22,11 @@
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
 import com.android.server.wm.flicker.helpers.reopenAppFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -41,8 +41,9 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class ReOpenImeWindowTest(flicker: FlickerTest) : BaseTest(flicker) {
-    private val testApp = ImeAppAutoFocusHelper(instrumentation, flicker.scenario.startRotation)
+open class ShowImeOnAppStartWhenLaunchingAppFromOverviewTest(flicker: FlickerTest) :
+    BaseTest(flicker) {
+    private val testApp = ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit = {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
similarity index 93%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
index 477ddb3..167689c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
@@ -23,12 +23,12 @@
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.Before
@@ -47,9 +47,11 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @Presubmit
-open class SwitchImeWindowsFromGestureNavTest(flicker: FlickerTest) : BaseTest(flicker) {
+open class ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest(flicker: FlickerTest) :
+    BaseTest(flicker) {
     private val testApp = SimpleAppHelper(instrumentation)
-    private val imeTestApp = ImeAppAutoFocusHelper(instrumentation, flicker.scenario.startRotation)
+    private val imeTestApp =
+        ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
 
     @Before
     open fun before() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt
similarity index 87%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTestCfArm.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt
index 1d3658e..82c38a3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt
@@ -28,5 +28,5 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @Presubmit
-open class SwitchImeWindowsFromGestureNavTestCfArm(flicker: FlickerTest) :
-    SwitchImeWindowsFromGestureNavTest(flicker)
+open class ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm(flicker: FlickerTest) :
+    ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
similarity index 93%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
index e297e89..6c6003f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
@@ -38,8 +38,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class SwitchImeWindowsFromGestureNavTest_ShellTransit(flicker: FlickerTest) :
-    SwitchImeWindowsFromGestureNavTest(flicker) {
+class ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit(flicker: FlickerTest) :
+    ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest(flicker) {
     @Before
     override fun before() {
         Assume.assumeTrue(isShellTransitionsEnabled)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
similarity index 92%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
index 6685cf7..e7cfb9e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
@@ -22,11 +22,11 @@
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
 import com.android.server.wm.flicker.helpers.ImeStateInitializeHelper
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -72,8 +72,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class LaunchAppShowImeOnStartTest(flicker: FlickerTest) : BaseTest(flicker) {
-    private val testApp = ImeAppAutoFocusHelper(instrumentation, flicker.scenario.startRotation)
+open class ShowImeOnAppStartWhenLaunchingAppTest(flicker: FlickerTest) : BaseTest(flicker) {
+    private val testApp = ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
     private val initializeApp = ImeStateInitializeHelper(instrumentation)
 
     /** {@inheritDoc} */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
similarity index 89%
copy from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
copy to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
index 87d9abd..e7ecb87 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
@@ -26,4 +26,5 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToHomeTestCfArm(flicker: FlickerTest) : CloseImeWindowToHomeTest(flicker)
+class ShowImeOnStartWhenLaunchingAppCfArmTest(flicker: FlickerTest) :
+    ShowImeOnAppStartWhenLaunchingAppTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
similarity index 96%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
index 5b830e5..851651e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
@@ -37,7 +37,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenImeWindowTest(flicker: FlickerTest) : BaseTest(flicker) {
+open class ShowImeWhenFocusingOnInputFieldTest(flicker: FlickerTest) : BaseTest(flicker) {
     private val testApp = ImeAppHelper(instrumentation)
 
     /** {@inheritDoc} */
@@ -50,6 +50,7 @@
         }
     }
 
+    @Presubmit
     @Test
     @IwTest(focusArea = "ime")
     override fun cujCompleted() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt
similarity index 89%
copy from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
copy to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt
index 87d9abd..0c53155 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt
@@ -26,4 +26,5 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToHomeTestCfArm(flicker: FlickerTest) : CloseImeWindowToHomeTest(flicker)
+class ShowImeWhenFocusingOnInputFieldTestCfArm(flicker: FlickerTest) :
+    ShowImeWhenFocusingOnInputFieldTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
similarity index 91%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
index cb530da..6058212 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
@@ -25,9 +25,9 @@
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -45,8 +45,8 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class LaunchAppShowImeAndDialogThemeAppTest(flicker: FlickerTest) : BaseTest(flicker) {
-    private val testApp = ImeAppAutoFocusHelper(instrumentation, flicker.scenario.startRotation)
+class ShowImeWhileDismissingThemedPopupDialogTest(flicker: FlickerTest) : BaseTest(flicker) {
+    private val testApp = ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit = {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
similarity index 96%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
index d95af9d..5d96346 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
@@ -22,12 +22,12 @@
 import com.android.server.wm.flicker.FlickerBuilder
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd
 import com.android.server.wm.flicker.statusBarLayerIsVisibleAtStartAndEnd
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.WindowManagerConditionsFactory
 import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import org.junit.Assume
@@ -46,8 +46,9 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenImeWindowToOverViewTest(flicker: FlickerTest) : BaseTest(flicker) {
-    private val imeTestApp = ImeAppAutoFocusHelper(instrumentation, flicker.scenario.startRotation)
+open class ShowImeWhileEnteringOverviewTest(flicker: FlickerTest) : BaseTest(flicker) {
+    private val imeTestApp =
+        ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit = {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt
similarity index 90%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt
index 87d9abd..9308fbb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt
@@ -26,4 +26,5 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeWindowToHomeTestCfArm(flicker: FlickerTest) : CloseImeWindowToHomeTest(flicker)
+class ShowImeWhileEnteringOverviewTestCfArm(flicker: FlickerTest) :
+    ShowImeWhileEnteringOverviewTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
index 1baff37..7979cf9b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
@@ -25,7 +25,7 @@
 import com.android.server.wm.flicker.helpers.TwoActivitiesAppHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 import org.junit.FixMethodOrder
 import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
index baa2750..0942287 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
@@ -49,8 +49,9 @@
                 // 1. Open camera - cold -> close it first
                 cameraApp.exit(wmHelper)
                 cameraApp.launchViaIntent(wmHelper)
-                // 2. Press home button (button nav mode) / swipe up to home (gesture nav mode)
-                tapl.goHome()
+                // Can't use TAPL due to Recents not showing in 3 Button Nav in full screen mode
+                device.pressHome()
+                tapl.getWorkspace()
             }
             teardown { testApp.exit(wmHelper) }
             transitions { testApp.launchViaIntent(wmHelper) }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
index b234ec7..2f0e56f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
@@ -19,7 +19,7 @@
 import android.platform.test.annotations.Presubmit
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.replacesLayer
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.Test
 
 /** Base class for app launch tests */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
index 991cd1c..08786d3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
@@ -24,7 +24,7 @@
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Ignore
 import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
index 60b0f9b..a5d85cc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
@@ -24,7 +24,7 @@
 import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Ignore
 import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
index 75de476..ff39611 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
@@ -26,7 +26,7 @@
 import com.android.server.wm.flicker.helpers.ShowWhenLockedAppHelper
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
index 718c6e9..aa054a9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
@@ -22,7 +22,7 @@
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.navBarLayerPositionAtEnd
 import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.Assume
 import org.junit.Ignore
 import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
index 90c18c4..0ed3bba 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
@@ -24,7 +24,7 @@
 import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Ignore
 import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
index efca6ab..af6c81d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
@@ -35,7 +35,7 @@
 import com.android.server.wm.flicker.navBarWindowIsVisibleAtEnd
 import com.android.server.wm.flicker.taskBarLayerIsVisibleAtEnd
 import com.android.server.wm.flicker.taskBarWindowIsVisibleAtEnd
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Ignore
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index 7cfe879..55e7a99 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -25,7 +25,7 @@
 import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
 import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
index 2adb0b4..618fb8a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
@@ -24,7 +24,7 @@
 import com.android.server.wm.flicker.helpers.StandardAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.Test
 
 /** Base class for app launch tests */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
index b9594a1..c78d0e9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
@@ -33,7 +33,7 @@
 import com.android.server.wm.flicker.junit.FlickerBuilderProvider
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.WindowManagerConditionsFactory
 import org.junit.FixMethodOrder
 import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
index 959ab3d..94afd81 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
@@ -31,12 +31,12 @@
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
-import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.DEFAULT_TASK_DISPLAY_AREA
-import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.SPLASH_SCREEN
-import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
-import com.android.server.wm.traces.common.ComponentSplashScreenMatcher
-import com.android.server.wm.traces.common.IComponentMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.DEFAULT_TASK_DISPLAY_AREA
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.SPLASH_SCREEN
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
+import com.android.server.wm.traces.common.component.matchers.ComponentSplashScreenMatcher
+import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
 import com.android.server.wm.traces.parser.toFlickerComponent
 import org.junit.Assume
 import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index be3b0bf..b7faf83 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -26,7 +26,7 @@
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.Rect
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index 18d1d3c..6294761 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -26,7 +26,7 @@
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.Rect
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index e06a8d6..c03cd29 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -26,8 +26,8 @@
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
 import com.android.server.wm.traces.common.Rect
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 8b250c3..e7e39c6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -24,7 +24,7 @@
 import com.android.server.wm.flicker.FlickerTestFactory
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index 4ef9eaf..74ecdde 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -22,7 +22,7 @@
 import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.helpers.StandardAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.Test
 
 /** Base class for app rotation tests */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index d76c94d..1a69344 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -27,7 +27,7 @@
 import com.android.server.wm.flicker.helpers.SeamlessRotationAppHelper
 import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.ComponentNameMatcher
+import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Ignore
 import org.junit.Test
@@ -111,9 +111,9 @@
                 val appWindow = it.windowState(testApp.`package`)
                 val flags = appWindow.windowState?.attributes?.flags ?: 0
                 appWindow
-                    .verify("isFullScreen")
+                    .check { "isFullScreen" }
                     .that(flags.and(WindowManager.LayoutParams.FLAG_FULLSCREEN))
-                    .isGreaterThan(0)
+                    .isGreater(0)
             }
         }
     }
@@ -127,13 +127,13 @@
                 val appWindow = it.windowState(testApp.`package`)
                 val rotationAnimation = appWindow.windowState?.attributes?.rotationAnimation ?: 0
                 appWindow
-                    .verify("isRotationSeamless")
+                    .check { "isRotationSeamless" }
                     .that(
                         rotationAnimation.and(
                             WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
                         )
                     )
-                    .isGreaterThan(0)
+                    .isGreater(0)
             }
         }
     }
diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
index 83823ea..5361d73f 100644
--- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
@@ -47,7 +47,7 @@
                   android:theme="@style/CutoutShortEdges"
                   android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivityAutoFocus"
                   android:windowSoftInputMode="stateVisible"
-                  android:configChanges="orientation|screenSize"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
                   android:label="ImeAppAutoFocus"
                   android:exported="true">
             <intent-filter>
@@ -179,6 +179,13 @@
             </intent-filter>
         </activity>
         <activity
+            android:name=".ActivityEmbeddingSecondaryActivity"
+            android:label="ActivityEmbedding Secondary"
+            android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
+            android:theme="@style/CutoutShortEdges"
+            android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+            android:exported="false"/>
+        <activity
             android:name=".ActivityEmbeddingPlaceholderPrimaryActivity"
             android:label="ActivityEmbedding Placeholder Primary"
             android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
index 19c81a8..d78b9a8 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml
@@ -22,6 +22,14 @@
     android:background="@android:color/holo_orange_light">
 
     <Button
+        android:id="@+id/launch_secondary_activity_button"
+        android:layout_width="wrap_content"
+        android:layout_height="48dp"
+        android:layout_centerHorizontal="true"
+        android:onClick="launchSecondaryActivity"
+        android:text="Launch Secondary Activity" />
+
+    <Button
         android:id="@+id/launch_placeholder_split_button"
         android:layout_width="wrap_content"
         android:layout_height="48dp"
diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml
index baaf707..fa73e2c 100644
--- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_ime.xml
@@ -26,14 +26,27 @@
               android:layout_width="match_parent"
 	      android:imeOptions="flagNoExtractUi"
               android:inputType="text"/>
-    <Button
-        android:id="@+id/finish_activity_btn"
+    <LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="Finish activity" />
-    <Button
-        android:id="@+id/start_dialog_themed_activity_btn"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="Start dialog themed activity" />
+        android:layout_height="match_parent"
+        android:orientation="horizontal">
+        <Button
+            android:id="@+id/finish_activity_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Finish activity" />
+        <Button
+            android:id="@+id/start_dialog_themed_activity_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Dialog themed activity" />
+        <ToggleButton
+            android:id="@+id/toggle_fixed_portrait_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textOn="Portrait (On)"
+            android:textOff="Portrait (Off)"
+        />
+    </LinearLayout>
 </LinearLayout>
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
index 04a590d..6a7a2cc 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java
@@ -25,6 +25,7 @@
 
 import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
 import androidx.window.extensions.embedding.EmbeddingRule;
+import androidx.window.extensions.embedding.SplitPairRule;
 import androidx.window.extensions.embedding.SplitPlaceholderRule;
 
 import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper;
@@ -40,20 +41,23 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_embedding_main_layout);
+    }
 
-        initializeSplitRules();
+    /** R.id.launch_secondary_activity_button onClick */
+    public void launchSecondaryActivity(View view) {
+        initializeSplitRules(createSplitPairRules());
+        startActivity(new Intent().setComponent(
+                ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT));
     }
 
     /** R.id.launch_placeholder_split_button onClick */
     public void launchPlaceholderSplit(View view) {
-        startActivity(
-                new Intent().setComponent(
-                        ActivityOptions.ActivityEmbedding.PlaceholderPrimaryActivity.COMPONENT
-                )
-        );
+        initializeSplitRules(createSplitPlaceholderRules());
+        startActivity(new Intent().setComponent(
+                ActivityOptions.ActivityEmbedding.PlaceholderPrimaryActivity.COMPONENT));
     }
 
-    private void initializeSplitRules() {
+    private void initializeSplitRules(Set<EmbeddingRule> rules) {
         ActivityEmbeddingComponent embeddingComponent =
                 ActivityEmbeddingAppHelper.getActivityEmbeddingComponent();
         if (embeddingComponent == null) {
@@ -62,14 +66,28 @@
             finish();
             return;
         }
-
-        embeddingComponent.setEmbeddingRules(getSplitRules());
+        embeddingComponent.setEmbeddingRules(rules);
     }
 
-    private Set<EmbeddingRule> getSplitRules() {
+    private Set<EmbeddingRule> createSplitPairRules() {
         final Set<EmbeddingRule> rules = new ArraySet<>();
+        final SplitPairRule rule = new SplitPairRule.Builder(
+                activitiesPair -> activitiesPair.first instanceof ActivityEmbeddingMainActivity
+                        && activitiesPair.second instanceof ActivityEmbeddingSecondaryActivity,
+                activityIntentPair ->
+                        activityIntentPair.first instanceof ActivityEmbeddingMainActivity
+                                && activityIntentPair.second.getComponent().equals(ActivityOptions
+                                .ActivityEmbedding.SecondaryActivity.COMPONENT),
+                windowMetrics -> true)
+                .setSplitRatio(DEFAULT_SPLIT_RATIO)
+                .build();
+        rules.add(rule);
+        return rules;
+    }
 
-        final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule.Builder(
+    private Set<EmbeddingRule> createSplitPlaceholderRules() {
+        final Set<EmbeddingRule> rules = new ArraySet<>();
+        final SplitPlaceholderRule rule = new SplitPlaceholderRule.Builder(
                 new Intent().setComponent(
                         ActivityOptions.ActivityEmbedding.PlaceholderSecondaryActivity.COMPONENT),
                 activity -> activity instanceof ActivityEmbeddingPlaceholderPrimaryActivity,
@@ -78,7 +96,7 @@
                 windowMetrics -> true)
                 .setSplitRatio(DEFAULT_SPLIT_RATIO)
                 .build();
-        rules.add(placeholderRule);
+        rules.add(rule);
         return rules;
     }
 }
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java
new file mode 100644
index 0000000..00f4c25
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java
@@ -0,0 +1,30 @@
+/*
+ * 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.wm.flicker.testapp;
+
+import android.graphics.Color;
+
+/**
+ * Activity to be used as the secondary activity to split with
+ * {@link ActivityEmbeddingMainActivity}.
+ */
+public class ActivityEmbeddingSecondaryActivity extends ActivityEmbeddingBaseActivity {
+    @Override
+    int getBackgroundColor() {
+        return Color.YELLOW;
+    }
+}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
index 00684de..b61bc0c 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
@@ -87,6 +87,12 @@
                     FLICKER_APP_PACKAGE + ".ActivityEmbeddingMainActivity");
         }
 
+        public static class SecondaryActivity {
+            public static final String LABEL = "ActivityEmbeddingSecondaryActivity";
+            public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+                    FLICKER_APP_PACKAGE + ".ActivityEmbeddingSecondaryActivity");
+        }
+
         public static class PlaceholderPrimaryActivity {
             public static final String LABEL = "ActivityEmbeddingPlaceholderPrimaryActivity";
             public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivityAutoFocus.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivityAutoFocus.java
index bb200f1..7ee8deb 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivityAutoFocus.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ImeActivityAutoFocus.java
@@ -16,21 +16,29 @@
 
 package com.android.server.wm.flicker.testapp;
 
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
 import android.content.Intent;
 import android.widget.Button;
 import android.widget.EditText;
+import android.widget.ToggleButton;
 
 public class ImeActivityAutoFocus extends ImeActivity {
-
     @Override
     protected void onStart() {
         super.onStart();
 
-        EditText editTextField = findViewById(R.id.plain_text_input);
-        editTextField.requestFocus();
-
         Button startThemedActivityButton = findViewById(R.id.start_dialog_themed_activity_btn);
         startThemedActivityButton.setOnClickListener(
                 button -> startActivity(new Intent(this, DialogThemedActivity.class)));
+
+        ToggleButton toggleFixedPortraitButton = findViewById(R.id.toggle_fixed_portrait_btn);
+        toggleFixedPortraitButton.setOnCheckedChangeListener(
+                (button, isChecked) -> setRequestedOrientation(
+                        isChecked ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_UNSPECIFIED));
+
+        EditText editTextField = findViewById(R.id.plain_text_input);
+        editTextField.requestFocus();
     }
 }
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index fdba9a6..80c7a21 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -120,6 +120,15 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="ColorBitmapActivity"
+                  android:label="Bitmaps/BitmapColors"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="com.android.test.hwui.TEST"/>
+            </intent-filter>
+        </activity>
+
         <activity android:name="PathOffsetActivity"
              android:label="Path/Offset"
              android:exported="true">
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorBitmapActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorBitmapActivity.java
new file mode 100644
index 0000000..017de60
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorBitmapActivity.java
@@ -0,0 +1,196 @@
+/*
+ * 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.hwui;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorSpace;
+import android.graphics.HardwareBufferRenderer;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.RenderNode;
+import android.graphics.Shader;
+import android.hardware.HardwareBuffer;
+import android.media.Image;
+import android.media.ImageWriter;
+import android.os.Bundle;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+
+import java.time.Duration;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ColorBitmapActivity extends Activity implements SurfaceHolder.Callback,
+        AdapterView.OnItemSelectedListener {
+
+    private static final int WIDTH = 512;
+    private static final int HEIGHT = 512;
+
+    private ImageView mImageView;
+    private SurfaceView mSurfaceView;
+    private HardwareBuffer mGradientBuffer;
+    private ImageWriter mImageWriter;
+    private ColorSpace mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
+    private String[] mColorNames = {"sRGB", "BT2020_HLG", "BT2020_PQ"};
+    private String mCurrentColorName = "sRGB";
+
+    private FutureTask<HardwareBuffer> authorGradientBuffer(HardwareBuffer buffer) {
+        HardwareBufferRenderer renderer = new HardwareBufferRenderer(buffer);
+        RenderNode node = new RenderNode("content");
+        node.setPosition(0, 0, buffer.getWidth(), buffer.getHeight());
+
+        Canvas canvas = node.beginRecording();
+        LinearGradient gradient = new LinearGradient(
+                0, 0, buffer.getWidth(), buffer.getHeight(), 0xFF000000,
+                0xFFFFFFFF, Shader.TileMode.CLAMP);
+        Paint paint = new Paint();
+        paint.setShader(gradient);
+        canvas.drawRect(0f, 0f, buffer.getWidth(), buffer.getHeight(), paint);
+        node.endRecording();
+
+        renderer.setContentRoot(node);
+
+        ColorSpace colorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
+        FutureTask<HardwareBuffer> resolvedBuffer = new FutureTask<>(() -> buffer);
+        renderer.obtainRenderRequest()
+                .setColorSpace(colorSpace)
+                .draw(Executors.newSingleThreadExecutor(), result -> {
+                    result.getFence().await(Duration.ofSeconds(3));
+                    resolvedBuffer.run();
+                });
+        return resolvedBuffer;
+    }
+
+    private FutureTask<HardwareBuffer> getGradientBuffer() {
+        HardwareBuffer buffer = HardwareBuffer.create(
+                WIDTH, HEIGHT, PixelFormat.RGBA_8888, 1,
+                HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE
+                        | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT);
+        return authorGradientBuffer(buffer);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        try {
+
+            mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
+
+            ArrayAdapter<String> adapter = new ArrayAdapter<>(
+                    this, android.R.layout.simple_spinner_item, mColorNames);
+
+            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+            Spinner spinner = new Spinner(this);
+            spinner.setAdapter(adapter);
+            spinner.setOnItemSelectedListener(this);
+
+            mGradientBuffer = getGradientBuffer().get();
+
+            LinearLayout linearLayout = new LinearLayout(this);
+            linearLayout.setOrientation(LinearLayout.VERTICAL);
+
+            mImageView = new ImageView(this);
+
+            mSurfaceView = new SurfaceView(this);
+            mSurfaceView.getHolder().addCallback(this);
+
+            linearLayout.addView(spinner, new LinearLayout.LayoutParams(
+                    LinearLayout.LayoutParams.WRAP_CONTENT,
+                    LinearLayout.LayoutParams.WRAP_CONTENT));
+
+            linearLayout.addView(mImageView, new LinearLayout.LayoutParams(WIDTH, HEIGHT));
+            linearLayout.addView(mSurfaceView, new LinearLayout.LayoutParams(WIDTH, HEIGHT));
+
+            setContentView(linearLayout);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private ColorSpace getFromName(String name) {
+        if (name.equals("sRGB")) {
+            return ColorSpace.get(ColorSpace.Named.SRGB);
+        } else if (name.equals("BT2020_HLG")) {
+            return ColorSpace.get(ColorSpace.Named.BT2020_HLG);
+        } else if (name.equals("BT2020_PQ")) {
+            return ColorSpace.get(ColorSpace.Named.BT2020_PQ);
+        }
+
+        throw new RuntimeException("Unrecognized Colorspace!");
+    }
+
+    private void populateBuffers() {
+        Bitmap bitmap = Bitmap.wrapHardwareBuffer(
+                mGradientBuffer, ColorSpace.get(ColorSpace.Named.SRGB));
+        Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, false);
+        copy.setColorSpace(mColorSpace);
+        mImageView.setImageBitmap(copy);
+
+        try (Image image = mImageWriter.dequeueInputImage()) {
+            authorGradientBuffer(image.getHardwareBuffer()).get();
+            image.setDataSpace(mColorSpace.getDataSpace());
+            mImageWriter.queueInputImage(image);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        mImageWriter = new ImageWriter.Builder(holder.getSurface())
+                .setUsage(HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE
+                        | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT
+                        | HardwareBuffer.USAGE_COMPOSER_OVERLAY)
+                .build();
+        populateBuffers();
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        mImageWriter.close();
+        mImageWriter = null;
+    }
+
+
+    @Override
+    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        mCurrentColorName = mColorNames[position];
+        mColorSpace = getFromName(mCurrentColorName);
+        populateBuffers();
+    }
+
+    @Override
+    public void onNothingSelected(AdapterView<?> parent) {
+
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java
index d3a5885..413f92c 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java
@@ -26,7 +26,7 @@
 import android.graphics.MeshSpecification.Attribute;
 import android.graphics.MeshSpecification.Varying;
 import android.graphics.Paint;
-import android.graphics.Rect;
+import android.graphics.RectF;
 import android.os.Bundle;
 import android.view.View;
 
@@ -64,8 +64,8 @@
             vertexBuffer.put(4, 0.0f);
             vertexBuffer.put(5, 400.0f);
             vertexBuffer.rewind();
-            Mesh mesh = Mesh.make(
-                    meshSpec, Mesh.TRIANGLES, vertexBuffer, 3, new Rect(0, 0, 1000, 1000));
+            Mesh mesh = new Mesh(
+                    meshSpec, Mesh.TRIANGLES, vertexBuffer, 3, new RectF(0, 0, 1000, 1000));
 
             canvas.drawMesh(mesh, BlendMode.COLOR, new Paint());
 
@@ -98,8 +98,8 @@
             }
             iVertexBuffer.rewind();
             indexBuffer.rewind();
-            Mesh mesh2 = Mesh.makeIndexed(meshSpec, Mesh.TRIANGLES, iVertexBuffer, 102, indexBuffer,
-                    new Rect(0, 0, 1000, 1000));
+            Mesh mesh2 = new Mesh(meshSpec, Mesh.TRIANGLES, iVertexBuffer, 102, indexBuffer,
+                    new RectF(0, 0, 1000, 1000));
             Paint paint = new Paint();
             paint.setColor(Color.RED);
             canvas.drawMesh(mesh2, BlendMode.COLOR, paint);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java
index f97d942..e62db6b 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java
@@ -26,7 +26,7 @@
 import android.graphics.MeshSpecification.Attribute;
 import android.graphics.MeshSpecification.Varying;
 import android.graphics.Paint;
-import android.graphics.Rect;
+import android.graphics.RectF;
 import android.os.Bundle;
 import android.view.View;
 
@@ -109,9 +109,9 @@
             }
             vertexBuffer.rewind();
             indexBuffer.rewind();
-            Mesh mesh = Mesh.makeIndexed(
+            Mesh mesh = new Mesh(
                     meshSpec, Mesh.TRIANGLES, vertexBuffer, numTriangles + 2, indexBuffer,
-                    new Rect(0, 0, 1000, 1000)
+                    new RectF(0, 0, 1000, 1000)
             );
             mesh.setFloatUniform("test", 1.0f, 2.0f);
             Paint paint = new Paint();
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
index 9b0f952..0c7e452 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
@@ -60,12 +60,15 @@
 @RunWith(Parameterized.class)
 public final class AutoShowTest {
 
-    @Rule public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
-    @Rule public ScreenCaptureRule mScreenCaptureRule =
-            new ScreenCaptureRule("/sdcard/InputMethodStressTest");
-    @Rule public DisableLockScreenRule mDisableLockScreenRule = new DisableLockScreenRule();
-    @Rule public ScreenOrientationRule mScreenOrientationRule =
+    @Rule(order = 0) public DisableLockScreenRule mDisableLockScreenRule =
+            new DisableLockScreenRule();
+    @Rule(order = 1) public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
+    @Rule(order = 2) public ScreenOrientationRule mScreenOrientationRule =
             new ScreenOrientationRule(true /* isPortrait */);
+    @Rule(order = 3) public PressHomeBeforeTestRule mPressHomeBeforeTestRule =
+            new PressHomeBeforeTestRule();
+    @Rule(order = 4) public ScreenCaptureRule mScreenCaptureRule =
+            new ScreenCaptureRule("/sdcard/InputMethodStressTest");
 
     // TODO(b/240359838): add test case {@code Configuration.SCREENLAYOUT_SIZE_LARGE}.
     @Parameterized.Parameters(
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java
index e348184..9d4aefb 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeOpenCloseStressTest.java
@@ -68,12 +68,15 @@
     private static final String TAG = "ImeOpenCloseStressTest";
     private static final int NUM_TEST_ITERATIONS = 10;
 
-    @Rule public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
-    @Rule public ScreenCaptureRule mScreenCaptureRule =
-            new ScreenCaptureRule("/sdcard/InputMethodStressTest");
-    @Rule public DisableLockScreenRule mDisableLockScreenRule = new DisableLockScreenRule();
-    @Rule public ScreenOrientationRule mScreenOrientationRule =
+    @Rule(order = 0) public DisableLockScreenRule mDisableLockScreenRule =
+            new DisableLockScreenRule();
+    @Rule(order = 1) public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
+    @Rule(order = 2) public ScreenOrientationRule mScreenOrientationRule =
             new ScreenOrientationRule(true /* isPortrait */);
+    @Rule(order = 3) public PressHomeBeforeTestRule mPressHomeBeforeTestRule =
+            new PressHomeBeforeTestRule();
+    @Rule(order = 4) public ScreenCaptureRule mScreenCaptureRule =
+            new ScreenCaptureRule("/sdcard/InputMethodStressTest");
 
     private final Instrumentation mInstrumentation;
     private final int mSoftInputFlags;
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/PressHomeBeforeTestRule.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/PressHomeBeforeTestRule.java
new file mode 100644
index 0000000..6586f63
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/PressHomeBeforeTestRule.java
@@ -0,0 +1,34 @@
+/*
+ * 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.inputmethod.stresstest;
+
+import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+/** This rule will press home before a test case. */
+public class PressHomeBeforeTestRule extends TestWatcher {
+    private final UiDevice mUiDevice =
+            UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+    @Override
+    protected void starting(Description description) {
+        mUiDevice.pressHome();
+    }
+}
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
index 6d4ffcf..3567c08 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
@@ -92,7 +92,7 @@
         super.onCreate();
         IntentFilter filter = new IntentFilter();
         filter.addAction(INTENT_ACTION);
-        registerReceiver(mBroadcastReceiver, filter);
+        registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
 
         // Make sure the data directory exists, and we're the owner of it.
         try {
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
index b67dc380..7a8d949 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
@@ -15,7 +15,7 @@
  */
 package com.android.test
 
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
 import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertTrue
 import org.junit.Test
@@ -37,7 +37,7 @@
                     1000 /* ms */))
         }
 
-        assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
+        LayersTraceSubject(trace).hasFrameSequence("SurfaceView", 1..numFrames)
     }
 
     @Test
@@ -51,7 +51,7 @@
             assertEquals(0, activity.mSurfaceProxy.waitUntilBufferDisplayed(2, 5000 /* ms */))
         }
 
-        assertThat(trace).hasFrameSequence("SurfaceView", 1..2L)
+        LayersTraceSubject(trace).hasFrameSequence("SurfaceView", 1..2L)
     }
 
     @Test
@@ -69,7 +69,7 @@
                     5000 /* ms */))
         }
 
-        assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
+        LayersTraceSubject(trace).hasFrameSequence("SurfaceView", 1..numFrames)
     }
 
     @Test
@@ -92,7 +92,7 @@
                     5000 /* ms */))
         }
 
-        assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
+        LayersTraceSubject(trace).hasFrameSequence("SurfaceView", 1..numFrames)
     }
 
     @Test
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
index e9e0246..da53387 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
@@ -16,7 +16,7 @@
 package com.android.test
 
 import android.graphics.Point
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
 import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
 import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
 import junit.framework.Assert.assertEquals
@@ -45,10 +45,10 @@
             activity.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */)
         }
         // Verify we reject buffers since scaling mode == NATIVE_WINDOW_SCALING_MODE_FREEZE
-        assertThat(trace).layer("SurfaceView", 2).doesNotExist()
+        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
 
         // Verify the next buffer is submitted with the correct size
-        assertThat(trace).layer("SurfaceView", 3).also {
+        LayersTraceSubject(trace).layer("SurfaceView", 3).also {
             it.hasBufferSize(defaultBufferSize)
             // scaling mode is not passed down to the layer for blast
             if (useBlastAdapter) {
@@ -81,9 +81,9 @@
         }
 
         // verify buffer size is reset to default buffer size
-        assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
-        assertThat(trace).layer("SurfaceView", 2).doesNotExist()
-        assertThat(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
+        LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+        LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
     }
 
     @Test
@@ -109,10 +109,11 @@
         }
 
         // verify buffer size is reset to default buffer size
-        assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
-        assertThat(trace).layer("SurfaceView", 2).doesNotExist()
-        assertThat(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
-        assertThat(trace).layer("SurfaceView", 3).hasBufferOrientation(Transform.ROT_90.value)
+        LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+        LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
+        LayersTraceSubject(trace).layer("SurfaceView", 3)
+                .hasBufferOrientation(Transform.ROT_90.value)
     }
 
     @Test
@@ -141,11 +142,11 @@
         }
 
         for (count in 0 until 5) {
-            assertThat(trace).layer("SurfaceView", (count * 3) + 1L)
+            LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 1L)
                     .hasBufferSize(defaultBufferSize)
-            assertThat(trace).layer("SurfaceView", (count * 3) + 2L)
+            LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 2L)
                     .doesNotExist()
-            assertThat(trace).layer("SurfaceView", (count * 3) + 3L)
+            LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 3L)
                     .hasBufferSize(bufferSize)
         }
     }
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
index 0802990..2d6c664 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
@@ -19,7 +19,7 @@
 import android.graphics.Point
 import android.graphics.Rect
 import android.os.SystemClock
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
 import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
 import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
 import junit.framework.Assert.assertEquals
@@ -43,7 +43,7 @@
         }
 
         // verify buffer size is reset to default buffer size
-        assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+        LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
     }
 
     @Test
@@ -56,7 +56,7 @@
             activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
         }
 
-        assertThat(trace).layer("SurfaceView", 1).also {
+        LayersTraceSubject(trace).layer("SurfaceView", 1).also {
             it.hasBufferSize(bufferSize)
             it.hasLayerSize(defaultBufferSize)
             it.hasScalingMode(ScalingMode.SCALE_TO_WINDOW.ordinal)
@@ -73,7 +73,7 @@
             activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
         }
 
-        assertThat(trace).layer("SurfaceView", 1).also {
+        LayersTraceSubject(trace).layer("SurfaceView", 1).also {
             it.hasBufferSize(bufferSize)
             it.hasLayerSize(defaultBufferSize)
             it.hasScalingMode(ScalingMode.SCALE_TO_WINDOW.ordinal)
@@ -102,9 +102,9 @@
         }
 
         // verify buffer size is reset to default buffer size
-        assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
-        assertThat(trace).layer("SurfaceView", 2).doesNotExist()
-        assertThat(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
+        LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+        LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
     }
 
     @Test
@@ -118,7 +118,7 @@
                 activity.mSurfaceProxy.waitUntilBufferDisplayed(index + 1L, 500 /* ms */)
             }
 
-            assertThat(trace).layer("SurfaceView", index + 1L).also {
+            LayersTraceSubject(trace).layer("SurfaceView", index + 1L).also {
                 it.hasBufferSize(defaultBufferSize)
                 it.hasLayerSize(defaultBufferSize)
                 it.hasBufferOrientation(transform.value)
@@ -145,7 +145,7 @@
         }
 
         // check that the layer and buffer starts with the default size
-        assertThat(trace).layer("SurfaceView", 1).also {
+        LayersTraceSubject(trace).layer("SurfaceView", 1).also {
             it.hasBufferSize(defaultBufferSize)
             it.hasLayerSize(defaultBufferSize)
         }
@@ -169,7 +169,7 @@
             checkPixels(svBounds, Color.BLUE)
         }
 
-        assertThat(trace).layer("SurfaceView", 1).also {
+        LayersTraceSubject(trace).layer("SurfaceView", 1).also {
             it.hasLayerSize(newSize)
             it.hasBufferSize(defaultBufferSize)
         }
@@ -193,7 +193,7 @@
         }
 
         // check that the layer and buffer starts with the default size
-        assertThat(trace).layer("SurfaceView", 1).also {
+        LayersTraceSubject(trace).layer("SurfaceView", 1).also {
             it.hasBufferSize(defaultBufferSize)
             it.hasLayerSize(defaultBufferSize)
         }
@@ -216,7 +216,7 @@
             checkPixels(svBounds, Color.BLUE)
         }
 
-        assertThat(trace).layer("SurfaceView", 1).also {
+        LayersTraceSubject(trace).layer("SurfaceView", 1).also {
             it.hasLayerSize(defaultBufferSize)
             it.hasBufferSize(defaultBufferSize)
         }
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
index 69012bd..cf4186d 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
@@ -16,7 +16,7 @@
 package com.android.test
 
 import android.graphics.Point
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
 import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
 import junit.framework.Assert.assertEquals
 import org.junit.Assume.assumeFalse
@@ -69,8 +69,8 @@
         }
 
         // verify buffer size is reset to default buffer size
-        assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
-        assertThat(trace).layer("SurfaceView", 2).doesNotExist()
-        assertThat(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
+        LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+        LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
     }
 }
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
index ee41d79..61d4095 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
@@ -17,7 +17,7 @@
 
 import android.graphics.Color
 import android.graphics.Rect
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
 import junit.framework.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -39,7 +39,7 @@
             }
         }
 
-        assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
+        LayersTraceSubject(trace).hasFrameSequence("SurfaceView", 1..numFrames)
     }
 
     /** Submit buffers as fast as possible testing that we are not blocked when dequeuing the buffer
@@ -57,7 +57,7 @@
                     5000 /* ms */))
         }
 
-        assertThat(trace).hasFrameSequence("SurfaceView", numFrames..numFrames)
+        LayersTraceSubject(trace).hasFrameSequence("SurfaceView", numFrames..numFrames)
     }
 
     /** Keep overwriting the buffer without queuing buffers and check that we present the latest
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
index 03b43cc..722e671 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
@@ -23,7 +23,7 @@
 import androidx.test.runner.AndroidJUnit4
 import com.android.server.wm.flicker.monitor.LayersTraceMonitor
 import com.android.server.wm.flicker.monitor.withSFTracing
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
 import org.junit.After
 import org.junit.Before
 import org.junit.FixMethodOrder
@@ -90,13 +90,13 @@
         secondBounds.offsetTo(0, 0)
 
         // verify buffer size should be changed to expected values.
-        assertThat(trace).layer(FIRST_ACTIVITY, frame.toLong()).also {
+        LayersTraceSubject(trace).layer(FIRST_ACTIVITY, frame.toLong()).also {
             val firstTaskSize = Point(firstBounds.width(), firstBounds.height())
             it.hasLayerSize(firstTaskSize)
             it.hasBufferSize(firstTaskSize)
         }
 
-        assertThat(trace).layer(SECOND_ACTIVITY, frame.toLong()).also {
+        LayersTraceSubject(trace).layer(SECOND_ACTIVITY, frame.toLong()).also {
             val secondTaskSize = Point(secondBounds.width(), secondBounds.height())
             it.hasLayerSize(secondTaskSize)
             it.hasBufferSize(secondTaskSize)
diff --git a/tools/lint/framework/Android.bp b/tools/lint/framework/Android.bp
index b752503..30a6daa 100644
--- a/tools/lint/framework/Android.bp
+++ b/tools/lint/framework/Android.bp
@@ -37,12 +37,6 @@
 
 java_test_host {
     name: "AndroidFrameworkLintCheckerTest",
-    // TODO(b/239881504): Since this test was written, Android
-    // Lint was updated, and now includes classes that were
-    // compiled for java 15. The soong build doesn't support
-    // java 15 yet, so we can't compile against "lint". Disable
-    // the test until java 15 is supported.
-    enabled: false,
     srcs: ["checks/src/test/java/**/*.kt"],
     static_libs: [
         "AndroidFrameworkLintChecker",
@@ -52,5 +46,19 @@
     ],
     test_options: {
         unit_test: true,
+        tradefed_options: [
+            {
+                // lint bundles in some classes that were built with older versions
+                // of libraries, and no longer load. Since tradefed tries to load
+                // all classes in the jar to look for tests, it crashes loading them.
+                // Exclude these classes from tradefed's search.
+                name: "exclude-paths",
+                value: "org/apache",
+            },
+            {
+                name: "exclude-paths",
+                value: "META-INF",
+            },
+        ],
     },
 }
diff --git a/tools/lint/framework/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt
index b76342a..7c0ebca 100644
--- a/tools/lint/framework/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt
+++ b/tools/lint/framework/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt
@@ -105,37 +105,38 @@
                 .expectClean()
     }
 
-    fun testSubsequentFilterModification() {
-        lint().files(
-                java(
-                        """
-                    package test.pkg;
-                    import android.content.BroadcastReceiver;
-                    import android.content.Context;
-                    import android.content.Intent;
-                    import android.content.IntentFilter;
-                    public class TestClass1 {
-                        public void testMethod(Context context, BroadcastReceiver receiver) {
-                            IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
-                            filter.addAction(Intent.ACTION_BATTERY_LOW);
-                            filter.addAction(Intent.ACTION_BATTERY_OKAY);
-                            context.registerReceiver(receiver, filter);
-                            filter.addAction("querty");
-                            context.registerReceiver(receiver, filter);
-                        }
-                    }
-                   """
-                ).indented(),
-                *stubs
-        )
-                .run()
-                .expect("""
-                src/test/pkg/TestClass1.java:13: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
-                        context.registerReceiver(receiver, filter);
-                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
-            """.trimIndent())
-    }
+    // TODO(b/267510341): Reenable this test
+    // fun testSubsequentFilterModification() {
+    //     lint().files(
+    //             java(
+    //                     """
+    //                 package test.pkg;
+    //                 import android.content.BroadcastReceiver;
+    //                 import android.content.Context;
+    //                 import android.content.Intent;
+    //                 import android.content.IntentFilter;
+    //                 public class TestClass1 {
+    //                     public void testMethod(Context context, BroadcastReceiver receiver) {
+    //                         IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+    //                         filter.addAction(Intent.ACTION_BATTERY_LOW);
+    //                         filter.addAction(Intent.ACTION_BATTERY_OKAY);
+    //                         context.registerReceiver(receiver, filter);
+    //                         filter.addAction("querty");
+    //                         context.registerReceiver(receiver, filter);
+    //                     }
+    //                 }
+    //                """
+    //             ).indented(),
+    //             *stubs
+    //     )
+    //             .run()
+    //             .expect("""
+    //             src/test/pkg/TestClass1.java:13: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
+    //                     context.registerReceiver(receiver, filter);
+    //                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    //             0 errors, 1 warnings
+    //         """.trimIndent())
+    // }
 
     fun testNullReceiver() {
         lint().files(
@@ -207,61 +208,63 @@
                 .expectClean()
     }
 
-    fun testFlagArgumentAbsent() {
-        lint().files(
-                java(
-                        """
-                    package test.pkg;
-                    import android.content.BroadcastReceiver;
-                    import android.content.Context;
-                    import android.content.Intent;
-                    import android.content.IntentFilter;
-                    public class TestClass1 {
-                        public void testMethod(Context context, BroadcastReceiver receiver) {
-                            IntentFilter filter = new IntentFilter("qwerty");
-                            context.registerReceiver(receiver, filter);
-                        }
-                    }
-                   """
-                ).indented(),
-                *stubs
-        )
-                .run()
-                .expect("""
-                src/test/pkg/TestClass1.java:9: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
-                        context.registerReceiver(receiver, filter);
-                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
-            """.trimIndent())
-    }
+    // TODO(b/267510341): Reenable this test
+    // fun testFlagArgumentAbsent() {
+    //     lint().files(
+    //             java(
+    //                     """
+    //                 package test.pkg;
+    //                 import android.content.BroadcastReceiver;
+    //                 import android.content.Context;
+    //                 import android.content.Intent;
+    //                 import android.content.IntentFilter;
+    //                 public class TestClass1 {
+    //                     public void testMethod(Context context, BroadcastReceiver receiver) {
+    //                         IntentFilter filter = new IntentFilter("qwerty");
+    //                         context.registerReceiver(receiver, filter);
+    //                     }
+    //                 }
+    //                """
+    //             ).indented(),
+    //             *stubs
+    //     )
+    //             .run()
+    //             .expect("""
+    //             src/test/pkg/TestClass1.java:9: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
+    //                     context.registerReceiver(receiver, filter);
+    //                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    //             0 errors, 1 warnings
+    //         """.trimIndent())
+    // }
 
-    fun testExportedFlagsAbsent() {
-        lint().files(
-                java(
-                        """
-                    package test.pkg;
-                    import android.content.BroadcastReceiver;
-                    import android.content.Context;
-                    import android.content.Intent;
-                    import android.content.IntentFilter;
-                    public class TestClass1 {
-                        public void testMethod(Context context, BroadcastReceiver receiver) {
-                            IntentFilter filter = new IntentFilter("qwerty");
-                            context.registerReceiver(receiver, filter, 0);
-                        }
-                    }
-                   """
-                ).indented(),
-                *stubs
-        )
-                .run()
-                .expect("""
-                src/test/pkg/TestClass1.java:9: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
-                        context.registerReceiver(receiver, filter, 0);
-                                                                   ~
-                0 errors, 1 warnings
-            """.trimIndent())
-    }
+    // TODO(b/267510341): Reenable this test
+    // fun testExportedFlagsAbsent() {
+    //     lint().files(
+    //             java(
+    //                     """
+    //                 package test.pkg;
+    //                 import android.content.BroadcastReceiver;
+    //                 import android.content.Context;
+    //                 import android.content.Intent;
+    //                 import android.content.IntentFilter;
+    //                 public class TestClass1 {
+    //                     public void testMethod(Context context, BroadcastReceiver receiver) {
+    //                         IntentFilter filter = new IntentFilter("qwerty");
+    //                         context.registerReceiver(receiver, filter, 0);
+    //                     }
+    //                 }
+    //                """
+    //             ).indented(),
+    //             *stubs
+    //     )
+    //             .run()
+    //             .expect("""
+    //             src/test/pkg/TestClass1.java:9: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
+    //                     context.registerReceiver(receiver, filter, 0);
+    //                                                                ~
+    //             0 errors, 1 warnings
+    //         """.trimIndent())
+    // }
 
     fun testExportedFlagVariable() {
         lint().files(
@@ -287,62 +290,64 @@
                 .expectClean()
     }
 
-    fun testUnknownFilter() {
-        lint().files(
-                java(
-                        """
-                    package test.pkg;
-                    import android.content.BroadcastReceiver;
-                    import android.content.Context;
-                    import android.content.Intent;
-                    import android.content.IntentFilter;
-                    public class TestClass1 {
-                        public void testMethod(Context context, BroadcastReceiver receiver,
-                                IntentFilter filter) {
-                            context.registerReceiver(receiver, filter);
-                        }
-                    }
-                   """
-                ).indented(),
-                *stubs
-        )
-                .run()
-                .expect("""
-                src/test/pkg/TestClass1.java:9: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
-                        context.registerReceiver(receiver, filter);
-                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
-            """.trimIndent())
-    }
+    // TODO(b/267510341): Reenable this test
+    // fun testUnknownFilter() {
+    //     lint().files(
+    //             java(
+    //                     """
+    //                 package test.pkg;
+    //                 import android.content.BroadcastReceiver;
+    //                 import android.content.Context;
+    //                 import android.content.Intent;
+    //                 import android.content.IntentFilter;
+    //                 public class TestClass1 {
+    //                     public void testMethod(Context context, BroadcastReceiver receiver,
+    //                             IntentFilter filter) {
+    //                         context.registerReceiver(receiver, filter);
+    //                     }
+    //                 }
+    //                """
+    //             ).indented(),
+    //             *stubs
+    //     )
+    //             .run()
+    //             .expect("""
+    //             src/test/pkg/TestClass1.java:9: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
+    //                     context.registerReceiver(receiver, filter);
+    //                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    //             0 errors, 1 warnings
+    //         """.trimIndent())
+    // }
 
-    fun testFilterEscapes() {
-        lint().files(
-                java(
-                        """
-                    package test.pkg;
-                    import android.content.BroadcastReceiver;
-                    import android.content.Context;
-                    import android.content.Intent;
-                    import android.content.IntentFilter;
-                    public class TestClass1 {
-                        public void testMethod(Context context, BroadcastReceiver receiver) {
-                            IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
-                            updateFilter(filter);
-                            context.registerReceiver(receiver, filter);
-                        }
-                    }
-                   """
-                ).indented(),
-                *stubs
-        )
-                .run()
-                .expect("""
-                src/test/pkg/TestClass1.java:10: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
-                        context.registerReceiver(receiver, filter);
-                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
-            """.trimIndent())
-    }
+    // TODO(b/267510341): Reenable this test
+    // fun testFilterEscapes() {
+    //     lint().files(
+    //             java(
+    //                     """
+    //                 package test.pkg;
+    //                 import android.content.BroadcastReceiver;
+    //                 import android.content.Context;
+    //                 import android.content.Intent;
+    //                 import android.content.IntentFilter;
+    //                 public class TestClass1 {
+    //                     public void testMethod(Context context, BroadcastReceiver receiver) {
+    //                         IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+    //                         updateFilter(filter);
+    //                         context.registerReceiver(receiver, filter);
+    //                     }
+    //                 }
+    //                """
+    //             ).indented(),
+    //             *stubs
+    //     )
+    //             .run()
+    //             .expect("""
+    //             src/test/pkg/TestClass1.java:10: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
+    //                     context.registerReceiver(receiver, filter);
+    //                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    //             0 errors, 1 warnings
+    //         """.trimIndent())
+    // }
 
     fun testInlineFilter() {
         lint().files(
@@ -367,135 +372,139 @@
                 .expectClean()
     }
 
-    fun testInlineFilterApply() {
-        lint().files(
-                kotlin(
-                        """
-                    package test.pkg
-                    import android.content.BroadcastReceiver
-                    import android.content.Context
-                    import android.content.Intent
-                    import android.content.IntentFilter
-                    class TestClass1 {
-                        fun test(context: Context, receiver: BroadcastReceiver) {
-                            context.registerReceiver(receiver,
-                                    IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply {
-                                        addAction("qwerty")
-                                    })
-                        }
-                    }
-                   """
-                ).indented(),
-                *stubs
-        )
-                .run()
-                .expect("""
-                src/test/pkg/TestClass1.kt:8: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
-                        context.registerReceiver(receiver,
-                        ^
-                0 errors, 1 warnings
-            """.trimIndent())
-    }
+    // TODO(b/267510341): Reenable this test
+    // fun testInlineFilterApply() {
+    //     lint().files(
+    //             kotlin(
+    //                     """
+    //                 package test.pkg
+    //                 import android.content.BroadcastReceiver
+    //                 import android.content.Context
+    //                 import android.content.Intent
+    //                 import android.content.IntentFilter
+    //                 class TestClass1 {
+    //                     fun test(context: Context, receiver: BroadcastReceiver) {
+    //                         context.registerReceiver(receiver,
+    //                                 IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply {
+    //                                     addAction("qwerty")
+    //                                 })
+    //                     }
+    //                 }
+    //                """
+    //             ).indented(),
+    //             *stubs
+    //     )
+    //             .run()
+    //             .expect("""
+    //             src/test/pkg/TestClass1.kt:8: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
+    //                     context.registerReceiver(receiver,
+    //                     ^
+    //             0 errors, 1 warnings
+    //         """.trimIndent())
+    // }
 
-    fun testFilterVariableApply() {
-        lint().files(
-                kotlin(
-                        """
-                    package test.pkg
-                    import android.content.BroadcastReceiver
-                    import android.content.Context
-                    import android.content.Intent
-                    import android.content.IntentFilter
-                    class TestClass1 {
-                        fun test(context: Context, receiver: BroadcastReceiver) {
-                            val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply {
-                                addAction("qwerty")
-                            }
-                            context.registerReceiver(receiver, filter)
-                        }
-                    }
-                   """
-                ).indented(),
-                *stubs
-        )
-                .run()
-                .expect("""
-                src/test/pkg/TestClass1.kt:11: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
-                        context.registerReceiver(receiver, filter)
-                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
-            """.trimIndent())
-    }
+    // TODO(b/267510341): Reenable this test
+    // fun testFilterVariableApply() {
+    //     lint().files(
+    //             kotlin(
+    //                     """
+    //                 package test.pkg
+    //                 import android.content.BroadcastReceiver
+    //                 import android.content.Context
+    //                 import android.content.Intent
+    //                 import android.content.IntentFilter
+    //                 class TestClass1 {
+    //                     fun test(context: Context, receiver: BroadcastReceiver) {
+    //                         val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply {
+    //                             addAction("qwerty")
+    //                         }
+    //                         context.registerReceiver(receiver, filter)
+    //                     }
+    //                 }
+    //                """
+    //             ).indented(),
+    //             *stubs
+    //     )
+    //             .run()
+    //             .expect("""
+    //             src/test/pkg/TestClass1.kt:11: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
+    //                     context.registerReceiver(receiver, filter)
+    //                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    //             0 errors, 1 warnings
+    //         """.trimIndent())
+    // }
 
-    fun testFilterVariableApply2() {
-        lint().files(
-                kotlin(
-                        """
-                    package test.pkg
-                    import android.content.BroadcastReceiver
-                    import android.content.Context
-                    import android.content.Intent
-                    import android.content.IntentFilter
-                    class TestClass1 {
-                        fun test(context: Context, receiver: BroadcastReceiver) {
-                            val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply {
-                                addAction(Intent.ACTION_BATTERY_OKAY)
-                            }
-                            context.registerReceiver(receiver, filter.apply {
-                                addAction("qwerty")
-                            })
-                        }
-                    }
-                   """
-                ).indented(),
-                *stubs
-        )
-                .run()
-                .expect("""
-                src/test/pkg/TestClass1.kt:11: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
-                        context.registerReceiver(receiver, filter.apply {
-                        ^
-                0 errors, 1 warnings
-            """.trimIndent())
-    }
+    // TODO(b/267510341): Reenable this test
+    // fun testFilterVariableApply2() {
+    //     lint().files(
+    //             kotlin(
+    //                     """
+    //                 package test.pkg
+    //                 import android.content.BroadcastReceiver
+    //                 import android.content.Context
+    //                 import android.content.Intent
+    //                 import android.content.IntentFilter
+    //                 class TestClass1 {
+    //                     fun test(context: Context, receiver: BroadcastReceiver) {
+    //                         val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply {
+    //                             addAction(Intent.ACTION_BATTERY_OKAY)
+    //                         }
+    //                         context.registerReceiver(receiver, filter.apply {
+    //                             addAction("qwerty")
+    //                         })
+    //                     }
+    //                 }
+    //                """
+    //             ).indented(),
+    //             *stubs
+    //     )
+    //             .run()
+    //             .expect("""
+    //             src/test/pkg/TestClass1.kt:11: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
+    //                     context.registerReceiver(receiver, filter.apply {
+    //                     ^
+    //             0 errors, 1 warnings
+    //         """.trimIndent())
+    // }
 
-    fun testFilterComplexChain() {
-        lint().files(
-                kotlin(
-                        """
-                    package test.pkg
-                    import android.content.BroadcastReceiver
-                    import android.content.Context
-                    import android.content.Intent
-                    import android.content.IntentFilter
-                    class TestClass1 {
-                        fun test(context: Context, receiver: BroadcastReceiver) {
-                            val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply {
-                                addAction(Intent.ACTION_BATTERY_OKAY)
-                            }
-                            val filter2 = filter
-                            val filter3 = filter2.apply {
-                                addAction(Intent.ACTION_BATTERY_LOW)
-                            }
-                            context.registerReceiver(receiver, filter3)
-                            val filter4 = filter3.apply {
-                                addAction("qwerty")
-                            }
-                            context.registerReceiver(receiver, filter4)
-                        }
-                    }
-                   """
-                ).indented(),
-                *stubs
-        )
-                .run()
-                .expect("""
-                src/test/pkg/TestClass1.kt:19: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
-                        context.registerReceiver(receiver, filter4)
-                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                0 errors, 1 warnings
-            """.trimIndent())
-    }
+    // TODO(b/267510341): Reenable this test
+    // fun testFilterComplexChain() {
+    //     lint().files(
+    //             kotlin(
+    //                     """
+    //                 package test.pkg
+    //                 import android.content.BroadcastReceiver
+    //                 import android.content.Context
+    //                 import android.content.Intent
+    //                 import android.content.IntentFilter
+    //                 class TestClass1 {
+    //                     fun test(context: Context, receiver: BroadcastReceiver) {
+    //                         val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply {
+    //                             addAction(Intent.ACTION_BATTERY_OKAY)
+    //                         }
+    //                         val filter2 = filter
+    //                         val filter3 = filter2.apply {
+    //                             addAction(Intent.ACTION_BATTERY_LOW)
+    //                         }
+    //                         context.registerReceiver(receiver, filter3)
+    //                         val filter4 = filter3.apply {
+    //                             addAction("qwerty")
+    //                         }
+    //                         context.registerReceiver(receiver, filter4)
+    //                     }
+    //                 }
+    //                """
+    //             ).indented(),
+    //             *stubs
+    //     )
+    //             .run()
+    //             .expect("""
+    //             src/test/pkg/TestClass1.kt:19: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag]
+    //                     context.registerReceiver(receiver, filter4)
+    //                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    //             0 errors, 1 warnings
+    //         """.trimIndent())
+    // }
 
     private val broadcastReceiverStub: TestFile = java(
             """
diff --git a/wifi/java/Android.bp b/wifi/java/Android.bp
index 225e750..434226d 100644
--- a/wifi/java/Android.bp
+++ b/wifi/java/Android.bp
@@ -27,7 +27,10 @@
 
 filegroup {
     name: "framework-wifi-non-updatable-sources-internal",
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.aidl",
+    ],
     path: "src",
     visibility: ["//visibility:private"],
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/OWNERS b/wifi/java/src/android/net/wifi/sharedconnectivity/OWNERS
new file mode 100644
index 0000000..2a4acc1
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1216021
+
+asapperstein@google.com
+etancohen@google.com
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
index 497c272..35d5c15 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package android.net.wifi.sharedconnectivity.app;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+parcelable DeviceInfo;
\ No newline at end of file
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java
new file mode 100644
index 0000000..7874b2a
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * A data class representing a device providing connectivity.
+ * This class is used in IPC calls between the implementer of {@link SharedConnectivityService} and
+ * the consumers of {@link com.android.wifitrackerlib}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class DeviceInfo implements Parcelable {
+
+    /**
+     * Device type providing connectivity is unknown.
+     */
+    public static final int DEVICE_TYPE_UNKNOWN = 0;
+
+    /**
+     * Device providing connectivity is a mobile phone.
+     */
+    public static final int DEVICE_TYPE_PHONE = 1;
+
+    /**
+     * Device providing connectivity is a tablet.
+     */
+    public static final int DEVICE_TYPE_TABLET = 2;
+
+    /**
+     * Device providing connectivity is a laptop.
+     */
+    public static final int DEVICE_TYPE_LAPTOP = 3;
+
+    /**
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            DEVICE_TYPE_UNKNOWN,
+            DEVICE_TYPE_PHONE,
+            DEVICE_TYPE_TABLET,
+            DEVICE_TYPE_LAPTOP
+    })
+    public @interface DeviceType {}
+
+    @DeviceType private final int mDeviceType;
+    private final String mDeviceName;
+    private final String mModelName;
+    private final int mBatteryPercentage;
+    private final int mConnectionStrength;
+
+    /**
+     * Builder class for {@link DeviceInfo}.
+     */
+    public static final class Builder {
+        private int mDeviceType;
+        private String mDeviceName;
+        private String mModelName;
+        private int mBatteryPercentage;
+        private int mConnectionStrength;
+
+        public Builder() {}
+
+        /**
+         * Sets the device type that provides connectivity.
+         *
+         * @param deviceType Device type as represented by IntDef {@link DeviceType}.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setDeviceType(@DeviceType int deviceType) {
+            mDeviceType = deviceType;
+            return this;
+        }
+
+        /**
+         * Sets the device name of the remote device.
+         *
+         * @param deviceName The user configurable device name.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setDeviceName(@NonNull String deviceName) {
+            mDeviceName = deviceName;
+            return this;
+        }
+
+        /**
+         * Sets the model name of the remote device.
+         *
+         * @param modelName The OEM configured name for the device model.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setModelName(@NonNull String modelName) {
+            mModelName = modelName;
+            return this;
+        }
+
+        /**
+         * Sets the battery charge percentage of the remote device.
+         *
+         * @param batteryPercentage The battery charge percentage in the range 0 to 100.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setBatteryPercentage(@IntRange(from = 0, to = 100) int batteryPercentage) {
+            mBatteryPercentage = batteryPercentage;
+            return this;
+        }
+
+        /**
+         * Sets the displayed connection strength of the remote device to the internet.
+         *
+         * @param connectionStrength Connection strength in range 0 to 3.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setConnectionStrength(@IntRange(from = 0, to = 3) int connectionStrength) {
+            mConnectionStrength = connectionStrength;
+            return this;
+        }
+
+        /**
+         * Builds the {@link DeviceInfo} object.
+         *
+         * @return Returns the built {@link DeviceInfo} object.
+         */
+        @NonNull
+        public DeviceInfo build() {
+            return new DeviceInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
+                    mConnectionStrength);
+        }
+    }
+
+    private static void validate(int deviceType, String deviceName, String modelName,
+            int batteryPercentage, int connectionStrength) {
+        if (deviceType != DEVICE_TYPE_UNKNOWN && deviceType != DEVICE_TYPE_PHONE
+                && deviceType != DEVICE_TYPE_TABLET && deviceType != DEVICE_TYPE_LAPTOP) {
+            throw new IllegalArgumentException("Illegal device type");
+        }
+        if (Objects.isNull(deviceName)) {
+            throw new IllegalArgumentException("DeviceName must be set");
+        }
+        if (Objects.isNull(modelName)) {
+            throw new IllegalArgumentException("ModelName must be set");
+        }
+        if (batteryPercentage < 0 || batteryPercentage > 100) {
+            throw new IllegalArgumentException("BatteryPercentage must be in range 0-100");
+        }
+        if (connectionStrength < 0 || connectionStrength > 3) {
+            throw new IllegalArgumentException("ConnectionStrength must be in range 0-3");
+        }
+    }
+
+    private DeviceInfo(@DeviceType int deviceType, @NonNull String deviceName,
+            @NonNull String modelName, int batteryPercentage, int connectionStrength) {
+        validate(deviceType, deviceName, modelName, batteryPercentage, connectionStrength);
+        mDeviceType = deviceType;
+        mDeviceName = deviceName;
+        mModelName = modelName;
+        mBatteryPercentage = batteryPercentage;
+        mConnectionStrength = connectionStrength;
+    }
+
+    /**
+     * Gets the device type that provides connectivity.
+     *
+     * @return Returns the device type as represented by IntDef {@link DeviceType}.
+     */
+    @DeviceType
+    public int getDeviceType() {
+        return mDeviceType;
+    }
+
+    /**
+     * Gets the device name of the remote device.
+     *
+     * @return Returns the user configurable device name.
+     */
+    @NonNull
+    public String getDeviceName() {
+        return mDeviceName;
+    }
+
+    /**
+     * Gets the model name of the remote device.
+     *
+     * @return Returns the OEM configured name for the device model.
+     */
+    @NonNull
+    public String getModelName() {
+        return mModelName;
+    }
+
+    /**
+     * Gets the battery charge percentage of the remote device.
+     *
+     * @return Returns the battery charge percentage in the range 0 to 100.
+     */
+    @NonNull
+    @IntRange(from = 0, to = 100)
+    public int getBatteryPercentage() {
+        return mBatteryPercentage;
+    }
+
+    /**
+     * Gets the displayed connection strength of the remote device to the internet.
+     *
+     * @return Returns the connection strength in range 0 to 3.
+     */
+    @NonNull
+    @IntRange(from = 0, to = 3)
+    public int getConnectionStrength() {
+        return mConnectionStrength;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof DeviceInfo)) return false;
+        DeviceInfo other = (DeviceInfo) obj;
+        return mDeviceType == other.getDeviceType()
+                && Objects.equals(mDeviceName, other.mDeviceName)
+                && Objects.equals(mModelName, other.mModelName)
+                && mBatteryPercentage == other.mBatteryPercentage
+                && mConnectionStrength == other.mConnectionStrength;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
+                mConnectionStrength);
+    }
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mDeviceType);
+        dest.writeString(mDeviceName);
+        dest.writeString(mModelName);
+        dest.writeInt(mBatteryPercentage);
+        dest.writeInt(mConnectionStrength);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Creator<DeviceInfo> CREATOR = new Creator<DeviceInfo>() {
+        @Override
+        public DeviceInfo createFromParcel(Parcel in) {
+            return new DeviceInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
+                    in.readInt());
+        }
+
+        @Override
+        public DeviceInfo[] newArray(int size) {
+            return new DeviceInfo[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return new StringBuilder("DeviceInfo[")
+                .append("deviceType=").append(mDeviceType)
+                .append(", deviceName=").append(mDeviceName)
+                .append(", modelName=").append(mModelName)
+                .append(", batteryPercentage=").append(mBatteryPercentage)
+                .append(", connectionStrength=").append(mConnectionStrength)
+                .append("]").toString();
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.aidl
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.aidl
index 497c272..140d72a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package android.net.wifi.sharedconnectivity.app;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+parcelable KnownNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
new file mode 100644
index 0000000..34b7e94
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.WifiAnnotations.SecurityType;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * A data class representing a known Wifi network.
+ *
+ * @hide
+ */
+@SystemApi
+public final class KnownNetwork implements Parcelable {
+    /**
+     * Network is known by a nearby device with the same user account.
+     */
+    public static final int NETWORK_SOURCE_NEARBY_SELF = 0;
+
+    /**
+     * Network is known via cloud storage associated with this device's user account.
+     */
+    public static final int NETWORK_SOURCE_CLOUD_SELF = 1;
+
+    /**
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            NETWORK_SOURCE_NEARBY_SELF,
+            NETWORK_SOURCE_CLOUD_SELF
+    })
+    public @interface NetworkSource {}
+
+    @NetworkSource private final int mNetworkSource;
+    private final String mSsid;
+    @SecurityType private final int[] mSecurityTypes;
+    private final DeviceInfo mDeviceInfo;
+
+    /**
+     * Builder class for {@link KnownNetwork}.
+     */
+    public static final class Builder {
+        @NetworkSource private int mNetworkSource = -1;
+        private String mSsid;
+        @SecurityType private int[] mSecurityTypes;
+        private android.net.wifi.sharedconnectivity.app.DeviceInfo mDeviceInfo;
+
+        public Builder() {}
+
+        /**
+         * Sets the indicated source of the known network.
+         *
+         * @param networkSource The network source as defined by IntDef {@link NetworkSource}.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setNetworkSource(@NetworkSource int networkSource) {
+            mNetworkSource = networkSource;
+            return this;
+        }
+
+        /**
+         * Sets the SSID of the known network.
+         *
+         * @param ssid The SSID of the known network. Surrounded by double quotes if UTF-8.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setSsid(@NonNull String ssid) {
+            mSsid = ssid;
+            return this;
+        }
+
+        /**
+         * Sets the security types of the known network.
+         *
+         * @param securityTypes The array of security types supported by the known network.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setSecurityTypes(@NonNull @SecurityType int[] securityTypes) {
+            mSecurityTypes = securityTypes;
+            return this;
+        }
+
+        /**
+         * Sets the device information of the device providing connectivity.
+         *
+         * @param deviceInfo The array of security types supported by the known network.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
+            mDeviceInfo = deviceInfo;
+            return this;
+        }
+
+        /**
+         * Builds the {@link KnownNetwork} object.
+         *
+         * @return Returns the built {@link KnownNetwork} object.
+         */
+        @NonNull
+        public KnownNetwork build() {
+            return new KnownNetwork(
+                    mNetworkSource,
+                    mSsid,
+                    mSecurityTypes,
+                    mDeviceInfo);
+        }
+    }
+
+    private static void validate(int networkSource, String ssid, int [] securityTypes) {
+        if (networkSource != NETWORK_SOURCE_CLOUD_SELF && networkSource
+                != NETWORK_SOURCE_NEARBY_SELF) {
+            throw new IllegalArgumentException("Illegal network source");
+        }
+        if (TextUtils.isEmpty(ssid)) {
+            throw new IllegalArgumentException("SSID must be set");
+        }
+        if (securityTypes == null || securityTypes.length == 0) {
+            throw new IllegalArgumentException("SecurityTypes must be set");
+        }
+    }
+
+    private KnownNetwork(
+            @NetworkSource int networkSource,
+            @NonNull String ssid,
+            @NonNull @SecurityType int[] securityTypes,
+            @NonNull android.net.wifi.sharedconnectivity.app.DeviceInfo deviceInfo) {
+        validate(networkSource, ssid, securityTypes);
+        mNetworkSource = networkSource;
+        mSsid = ssid;
+        mSecurityTypes = securityTypes;
+        mDeviceInfo = deviceInfo;
+    }
+
+    /**
+     * Gets the indicated source of the known network.
+     *
+     * @return Returns the network source as defined by IntDef {@link NetworkSource}.
+     */
+    @NonNull
+    @NetworkSource
+    public int getNetworkSource() {
+        return mNetworkSource;
+    }
+
+    /**
+     * Gets the SSID of the known network.
+     *
+     * @return Returns the SSID of the known network. Surrounded by double quotes if UTF-8.
+     */
+    @NonNull
+    public String getSsid() {
+        return mSsid;
+    }
+
+    /**
+     * Gets the security types of the known network.
+     *
+     * @return Returns the array of security types supported by the known network.
+     */
+    @NonNull
+    @SecurityType
+    public int[] getSecurityTypes() {
+        return mSecurityTypes;
+    }
+
+    /**
+     * Gets the device information of the device providing connectivity.
+     *
+     * @return Returns the array of security types supported by the known network.
+     */
+    @NonNull
+    public DeviceInfo getDeviceInfo() {
+        return mDeviceInfo;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof KnownNetwork)) return false;
+        KnownNetwork other = (KnownNetwork) obj;
+        return mNetworkSource == other.getNetworkSource()
+                && Objects.equals(mSsid, other.getSsid())
+                && Arrays.equals(mSecurityTypes, other.getSecurityTypes())
+                && Objects.equals(mDeviceInfo, other.getDeviceInfo());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mNetworkSource, mSsid, Arrays.hashCode(mSecurityTypes),
+                mDeviceInfo.hashCode());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mNetworkSource);
+        dest.writeString(mSsid);
+        dest.writeIntArray(mSecurityTypes);
+        dest.writeTypedObject(mDeviceInfo, 0);
+    }
+
+    @NonNull
+    public static final Creator<KnownNetwork> CREATOR = new Creator<>() {
+        @Override
+        public KnownNetwork createFromParcel(Parcel in) {
+            return new KnownNetwork(in.readInt(), in.readString(), in.createIntArray(),
+                    in.readTypedObject(DeviceInfo.CREATOR));
+        }
+
+        @Override
+        public KnownNetwork[] newArray(int size) {
+            return new KnownNetwork[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return new StringBuilder("KnownNetwork[")
+                .append("NetworkSource=").append(mNetworkSource)
+                .append(", ssid=").append(mSsid)
+                .append(", securityTypes=").append(Arrays.toString(mSecurityTypes))
+                .append(", deviceInfo=").append(mDeviceInfo.toString())
+                .append("]").toString();
+    }
+}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
new file mode 100644
index 0000000..dcb5201
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
+
+import java.util.List;
+
+/**
+ * Interface for clients of {@link SharedConnectivityManager} to register for changes in network
+ * status.
+ *
+ * @hide
+ */
+@SystemApi
+public interface SharedConnectivityClientCallback {
+    /**
+     * This method is being called by {@link SharedConnectivityService} to notify of a change in the
+     * list of available Tether Networks.
+     * @param networks Updated Tether Network list.
+     */
+    void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks);
+
+    /**
+     * This method is being called by {@link SharedConnectivityService} to notify of a change in the
+     * list of available Known Networks.
+     * @param networks Updated Known Network list.
+     */
+    void onKnownNetworksUpdated(@NonNull List<KnownNetwork> networks);
+
+    /**
+     * This method is being called by {@link SharedConnectivityService} to notify of a change in the
+     * state of share connectivity settings.
+     * @param state The new state.
+     */
+    void onSharedConnectivitySettingsChanged(@NonNull SharedConnectivitySettingsState state);
+}
+
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
new file mode 100644
index 0000000..9d9d24b
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
@@ -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 android.net.wifi.sharedconnectivity.app;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.res.Resources;
+import android.net.wifi.sharedconnectivity.service.ISharedConnectivityCallback;
+import android.net.wifi.sharedconnectivity.service.ISharedConnectivityService;
+import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * This class is the library used by consumers of Shared Connectivity data to bind to the service,
+ * receive callbacks from, and send user actions to the service.
+ *
+ * @hide
+ */
+@SystemApi
+public class SharedConnectivityManager {
+    private static final String TAG = SharedConnectivityManager.class.getSimpleName();
+    private static final boolean DEBUG = true;
+    private static final String SERVICE_PACKAGE_NAME = "sharedconnectivity_service_package";
+    private static final String SERVICE_CLASS_NAME = "sharedconnectivity_service_class";
+
+    private static final class SharedConnectivityCallbackProxy extends
+            ISharedConnectivityCallback.Stub {
+        private final Executor mExecutor;
+        private final SharedConnectivityClientCallback mCallback;
+
+        SharedConnectivityCallbackProxy(
+                @NonNull @CallbackExecutor Executor executor,
+                @NonNull SharedConnectivityClientCallback callback) {
+            mExecutor = executor;
+            mCallback = callback;
+        }
+
+        @Override
+        public void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks) {
+            if (mCallback != null) {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mCallback.onTetherNetworksUpdated(networks));
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        }
+
+        @Override
+        public void onKnownNetworksUpdated(@NonNull List<KnownNetwork> networks) {
+            if (mCallback != null) {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mCallback.onKnownNetworksUpdated(networks));
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        }
+
+        @Override
+        public void onSharedConnectivitySettingsChanged(
+                @NonNull SharedConnectivitySettingsState state) {
+            if (mCallback != null) {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() -> mCallback.onSharedConnectivitySettingsChanged(state));
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        };
+    }
+
+    private ISharedConnectivityService mService;
+    private final Map<SharedConnectivityClientCallback, SharedConnectivityCallbackProxy>
+            mProxyMap = new HashMap<>();
+
+    /**
+     * Constructor for new instance of {@link SharedConnectivityManager}.
+     *
+     * Automatically binds to implementation of {@link SharedConnectivityService} specified in
+     * device overlay.
+     *
+     * @hide
+     */
+    public SharedConnectivityManager(@NonNull Context context) {
+        ServiceConnection serviceConnection = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                mService = ISharedConnectivityService.Stub.asInterface(service);
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                if (DEBUG) Log.i(TAG, "onServiceDisconnected");
+                mService = null;
+                mProxyMap.clear();
+            }
+        };
+        bind(context, serviceConnection);
+    }
+
+    /**
+     * @hide
+     */
+    @TestApi
+    public void setService(@Nullable IInterface service) {
+        mService = (ISharedConnectivityService) service;
+    }
+
+    private void bind(Context context, ServiceConnection serviceConnection) {
+        Resources resources = context.getResources();
+        int packageNameId = resources.getIdentifier(SERVICE_PACKAGE_NAME, "string",
+                context.getPackageName());
+        int classNameId = resources.getIdentifier(SERVICE_CLASS_NAME, "string",
+                context.getPackageName());
+        if (packageNameId == 0 || classNameId == 0) {
+            throw new Resources.NotFoundException("Package and class names for"
+                    + " shared connectivity service must be defined");
+        }
+
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(resources.getString(packageNameId),
+                resources.getString(classNameId)));
+        context.bindService(
+                intent,
+                serviceConnection, Context.BIND_AUTO_CREATE);
+    }
+
+    /**
+     * Registers a callback for receiving updates to the list of Tether Networks and Known Networks.
+     *
+     * @param executor The Executor used to invoke the callback.
+     * @param callback The callback of type {@link SharedConnectivityClientCallback} that is invoked
+     *                 when the service updates either the list of Tether Networks or Known
+     *                 Networks.
+     * @return Returns true if the registration was successful, false otherwise.
+     */
+    public boolean registerCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull SharedConnectivityClientCallback callback) {
+        Objects.requireNonNull(executor, "executor cannot be null");
+        Objects.requireNonNull(callback, "callback cannot be null");
+        if (mService == null || mProxyMap.containsKey(callback)) return false;
+        try {
+            SharedConnectivityCallbackProxy proxy =
+                    new SharedConnectivityCallbackProxy(executor, callback);
+            mService.registerCallback(proxy);
+            mProxyMap.put(callback, proxy);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in registerCallback", e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Unregisters a callback.
+     *
+     * @return Returns true if the callback was successfully unregistered, false otherwise.
+     */
+    public boolean unregisterCallback(
+            @NonNull SharedConnectivityClientCallback callback) {
+        Objects.requireNonNull(callback, "callback cannot be null");
+        if (mService == null || !mProxyMap.containsKey(callback)) return false;
+        try {
+            mService.unregisterCallback(mProxyMap.get(callback));
+            mProxyMap.remove(callback);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in unregisterCallback", e);
+            return false;
+        }
+        return true;
+    }
+
+     /**
+     * Send command to the implementation of {@link SharedConnectivityService} requesting connection
+     * to the specified Tether Network.
+     *
+     * @param network {@link TetherNetwork} object representing the network the user has requested
+     *                a connection to.
+     * @return Returns true if the service received the command. Does not guarantee that the
+     *         connection was successful.
+     */
+    public boolean connectTetherNetwork(@NonNull TetherNetwork network) {
+        if (mService == null) return false;
+        try {
+            mService.connectTetherNetwork(network);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in connectTetherNetwork", e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Send command to the implementation of {@link SharedConnectivityService} requesting
+     * disconnection from the active Tether Network.
+     *
+     * @return Returns true if the service received the command. Does not guarantee that the
+     *         disconnection was successful.
+     */
+    public boolean disconnectTetherNetwork() {
+        if (mService == null) return false;
+        try {
+            mService.disconnectTetherNetwork();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in disconnectTetherNetwork", e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Send command to the implementation of {@link SharedConnectivityService} requesting connection
+     * to the specified Known Network.
+     *
+     * @param network {@link KnownNetwork} object representing the network the user has requested
+     *                a connection to.
+     * @return Returns true if the service received the command. Does not guarantee that the
+     *         connection was successful.
+     */
+    public boolean connectKnownNetwork(@NonNull KnownNetwork network) {
+        if (mService == null) return false;
+        try {
+            mService.connectKnownNetwork(network);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in connectKnownNetwork", e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Send command to the implementation of {@link SharedConnectivityService} requesting removal of
+     * the specified Known Network from the list of Known Networks.
+     *
+     * @return Returns true if the service received the command. Does not guarantee that the
+     *         forget action was successful.
+     */
+    public boolean forgetKnownNetwork(@NonNull KnownNetwork network) {
+        if (mService == null) return false;
+        try {
+            mService.forgetKnownNetwork(network);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in forgetKnownNetwork", e);
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.aidl
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.aidl
index 497c272..289afac 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package android.net.wifi.sharedconnectivity.app;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+parcelable SharedConnectivitySettingsState;
\ No newline at end of file
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.java
new file mode 100644
index 0000000..dd2fa94
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+
+/**
+ * A data class representing the shared connectivity settings state.
+ *
+ * This class represents a snapshot of the settings and can be out of date if the settings changed
+ * after receiving an object of this class.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SharedConnectivitySettingsState implements Parcelable {
+
+    private final boolean mInstantTetherEnabled;
+    private final Bundle mExtras;
+
+    /**
+     * Builder class for {@link SharedConnectivitySettingsState}.
+     */
+    public static final class Builder {
+        private boolean mInstantTetherEnabled;
+        private Bundle mExtras;
+
+        public Builder() {}
+
+        /**
+         * Sets the state of Instant Tether in settings
+         *
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setInstantTetherEnabled(boolean instantTetherEnabled) {
+            mInstantTetherEnabled = instantTetherEnabled;
+            return this;
+        }
+
+        /**
+         * Sets the extras bundle
+         *
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setExtras(@NonNull Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+         * Builds the {@link SharedConnectivitySettingsState} object.
+         *
+         * @return Returns the built {@link SharedConnectivitySettingsState} object.
+         */
+        @NonNull
+        public SharedConnectivitySettingsState build() {
+            return new SharedConnectivitySettingsState(mInstantTetherEnabled, mExtras);
+        }
+    }
+
+    private SharedConnectivitySettingsState(boolean instantTetherEnabled, Bundle extras) {
+        mInstantTetherEnabled = instantTetherEnabled;
+        mExtras = extras;
+    }
+
+    /**
+     * Gets the state of Instant Tether in settings
+     *
+     * @return Returns true for enabled, false otherwise.
+     */
+    @NonNull
+    public boolean isInstantTetherEnabled() {
+        return mInstantTetherEnabled;
+    }
+
+    /**
+     * Gets the extras Bundle.
+     *
+     * @return Returns a Bundle object.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof SharedConnectivitySettingsState)) return false;
+        SharedConnectivitySettingsState other = (SharedConnectivitySettingsState) obj;
+        return mInstantTetherEnabled == other.isInstantTetherEnabled();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mInstantTetherEnabled);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeBoolean(mInstantTetherEnabled);
+        dest.writeBundle(mExtras);
+    }
+
+    @NonNull
+    public static final Creator<SharedConnectivitySettingsState> CREATOR =
+            new Creator<SharedConnectivitySettingsState>() {
+                @Override
+                public SharedConnectivitySettingsState createFromParcel(Parcel in) {
+                    return new SharedConnectivitySettingsState(in.readBoolean(),
+                            in.readBundle(getClass().getClassLoader()));
+                }
+
+                @Override
+                public SharedConnectivitySettingsState[] newArray(int size) {
+                    return new SharedConnectivitySettingsState[size];
+                }
+            };
+
+    @Override
+    public String toString() {
+        return new StringBuilder("SharedConnectivitySettingsState[")
+                .append("instantTetherEnabled=").append(mInstantTetherEnabled)
+                .append("extras=").append(mExtras.toString())
+                .append("]").toString();
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
similarity index 64%
copy from packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
index 497c272..6cc4cfe 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/FrameworkClassParsingException.kt
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.credentialmanager.jetpack.developer
+package android.net.wifi.sharedconnectivity.app;
 
-/**
- * Internal exception used to indicate a parsing error while converting from a framework type to
- * a jetpack type.
- *
- * @hide
- */
-internal class FrameworkClassParsingException : Exception()
\ No newline at end of file
+parcelable TetherNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java
new file mode 100644
index 0000000..bbdad53
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.WifiAnnotations.SecurityType;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * A data class representing an Instant Tether network.
+ * This class is used in IPC calls between the implementer of {@link SharedConnectivityService} and
+ * the consumers of {@link com.android.wifitrackerlib}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class TetherNetwork implements Parcelable {
+    /**
+     * Remote device is connected to the internet via an unknown connection.
+     */
+    public static final int NETWORK_TYPE_UNKNOWN = 0;
+
+    /**
+     * Remote device is connected to the internet via a cellular connection.
+     */
+    public static final int NETWORK_TYPE_CELLULAR = 1;
+
+    /**
+     * Remote device is connected to the internet via a Wi-Fi connection.
+     */
+    public static final int NETWORK_TYPE_WIFI = 2;
+
+    /**
+     * Remote device is connected to the internet via an ethernet connection.
+     */
+    public static final int NETWORK_TYPE_ETHERNET = 3;
+
+    /**
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            NETWORK_TYPE_UNKNOWN,
+            NETWORK_TYPE_CELLULAR,
+            NETWORK_TYPE_WIFI,
+            NETWORK_TYPE_ETHERNET
+    })
+    public @interface NetworkType {}
+
+    private final long mDeviceId;
+    private final DeviceInfo mDeviceInfo;
+    @NetworkType private final int mNetworkType;
+    private final String mNetworkName;
+    @Nullable private final String mHotspotSsid;
+    @Nullable private final String mHotspotBssid;
+    @Nullable @SecurityType private final int[] mHotspotSecurityTypes;
+
+    /**
+     * Builder class for {@link TetherNetwork}.
+     */
+    public static final class Builder {
+        private long mDeviceId = -1;
+        private DeviceInfo mDeviceInfo;
+        @NetworkType private int mNetworkType;
+        private String mNetworkName;
+        @Nullable private String mHotspotSsid;
+        @Nullable private String mHotspotBssid;
+        @Nullable @SecurityType private int[] mHotspotSecurityTypes;
+
+        public Builder() {}
+
+        /**
+         * Set the remote device ID.
+         *
+         * @param deviceId Locally unique ID for this Instant Tether network.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setDeviceId(long deviceId) {
+            mDeviceId = deviceId;
+            return this;
+        }
+
+        /**
+         * Sets information about the device providing connectivity.
+         *
+         * @param deviceInfo The user configurable device name.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
+            mDeviceInfo = deviceInfo;
+            return this;
+        }
+
+        /**
+         * Sets the network type that the remote device is connected to.
+         *
+         * @param networkType Network type as represented by IntDef {@link NetworkType}.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setNetworkType(@NetworkType int networkType) {
+            mNetworkType = networkType;
+            return this;
+        }
+
+        /**
+         * Sets the display name of the network the remote device is connected to.
+         *
+         * @param networkName Network display name. (e.g. "Google Fi", "Hotel WiFi", "Ethernet")
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setNetworkName(@NonNull String networkName) {
+            mNetworkName = networkName;
+            return this;
+        }
+
+        /**
+         * Sets the hotspot SSID being broadcast by the remote device, or null if hotspot is off.
+         *
+         * @param hotspotSsid The SSID of the hotspot. Surrounded by double quotes if UTF-8.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setHotspotSsid(@NonNull String hotspotSsid) {
+            mHotspotSsid = hotspotSsid;
+            return this;
+        }
+
+        /**
+         * Sets the hotspot BSSID being broadcast by the remote device, or null if hotspot is off.
+         *
+         * @param hotspotBssid The BSSID of the hotspot.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setHotspotBssid(@NonNull String hotspotBssid) {
+            mHotspotBssid = hotspotBssid;
+            return this;
+        }
+
+        /**
+         * Sets the hotspot security types supported by the remote device, or null if hotspot is
+         * off.
+         *
+         * @param hotspotSecurityTypes The array of security types supported by the hotspot.
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setHotspotSecurityTypes(@NonNull @SecurityType int[] hotspotSecurityTypes) {
+            mHotspotSecurityTypes = hotspotSecurityTypes;
+            return this;
+        }
+
+        /**
+         * Builds the {@link TetherNetwork} object.
+         *
+         * @return Returns the built {@link TetherNetwork} object.
+         */
+        @NonNull
+        public TetherNetwork build() {
+            return new TetherNetwork(
+                    mDeviceId,
+                    mDeviceInfo,
+                    mNetworkType,
+                    mNetworkName,
+                    mHotspotSsid,
+                    mHotspotBssid,
+                    mHotspotSecurityTypes);
+        }
+    }
+
+    private static void validate(long deviceId, int networkType, String networkName) {
+        if (deviceId < 0) {
+            throw new IllegalArgumentException("DeviceId must be set");
+        }
+        if (networkType != NETWORK_TYPE_CELLULAR && networkType != NETWORK_TYPE_WIFI
+                && networkType != NETWORK_TYPE_ETHERNET && networkType != NETWORK_TYPE_UNKNOWN) {
+            throw new IllegalArgumentException("Illegal network type");
+        }
+        if (Objects.isNull(networkName)) {
+            throw new IllegalArgumentException("NetworkName must be set");
+        }
+    }
+
+    private TetherNetwork(
+            long deviceId,
+            DeviceInfo deviceInfo,
+            @NetworkType int networkType,
+            @NonNull String networkName,
+            @Nullable String hotspotSsid,
+            @Nullable String hotspotBssid,
+            @Nullable @SecurityType int[] hotspotSecurityTypes) {
+        validate(deviceId,
+                networkType,
+                networkName);
+        mDeviceId = deviceId;
+        mDeviceInfo = deviceInfo;
+        mNetworkType = networkType;
+        mNetworkName = networkName;
+        mHotspotSsid = hotspotSsid;
+        mHotspotBssid = hotspotBssid;
+        mHotspotSecurityTypes = hotspotSecurityTypes;
+    }
+
+    /**
+     * Gets the remote device ID.
+     *
+     * @return Returns the locally unique ID for this Instant Tether network.
+     */
+    @NonNull
+    public long getDeviceId() {
+        return mDeviceId;
+    }
+
+    /**
+     * Gets information about the device providing connectivity.
+     *
+     * @return Returns the locally unique ID for this Instant Tether network.
+     */
+    @NonNull
+    public DeviceInfo getDeviceInfo() {
+        return mDeviceInfo;
+    }
+
+    /**
+     * Gets the network type that the remote device is connected to.
+     *
+     * @return Returns the network type as represented by IntDef {@link NetworkType}.
+     */
+    @NonNull
+    @NetworkType
+    public int getNetworkType() {
+        return mNetworkType;
+    }
+
+    /**
+     * Gets the display name of the network the remote device is connected to.
+     *
+     * @return Returns the network display name. (e.g. "Google Fi", "Hotel WiFi", "Ethernet")
+     */
+    @NonNull
+    public String getNetworkName() {
+        return mNetworkName;
+    }
+
+    /**
+     * Gets the hotspot SSID being broadcast by the remote device, or null if hotspot is off.
+     *
+     * @return Returns the SSID of the hotspot. Surrounded by double quotes if UTF-8.
+     */
+    @Nullable
+    public String getHotspotSsid() {
+        return mHotspotSsid;
+    }
+
+    /**
+     * Gets the hotspot BSSID being broadcast by the remote device, or null if hotspot is off.
+     *
+     * @return Returns the BSSID of the hotspot.
+     */
+    @Nullable
+    public String getHotspotBssid() {
+        return mHotspotBssid;
+    }
+
+    /**
+     * Gets the hotspot security types supported by the remote device.
+     *
+     * @return Returns the array of security types supported by the hotspot.
+     */
+    @Nullable
+    @SecurityType
+    public int[] getHotspotSecurityTypes() {
+        return mHotspotSecurityTypes;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof TetherNetwork)) return false;
+        TetherNetwork other = (TetherNetwork) obj;
+        return mDeviceId == other.getDeviceId()
+                && Objects.equals(mDeviceInfo, other.getDeviceInfo())
+                && mNetworkType == other.getNetworkType()
+                && Objects.equals(mNetworkName, other.getNetworkName())
+                && Objects.equals(mHotspotSsid, other.getHotspotSsid())
+                && Objects.equals(mHotspotBssid, other.getHotspotBssid())
+                && Arrays.equals(mHotspotSecurityTypes, other.getHotspotSecurityTypes());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mDeviceId, mDeviceInfo, mNetworkName, mHotspotSsid, mHotspotBssid,
+                Arrays.hashCode(mHotspotSecurityTypes));
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeLong(mDeviceId);
+        dest.writeTypedObject(mDeviceInfo, 0);
+        dest.writeInt(mNetworkType);
+        dest.writeString(mNetworkName);
+        dest.writeString(mHotspotSsid);
+        dest.writeString(mHotspotBssid);
+        dest.writeIntArray(mHotspotSecurityTypes);
+    }
+
+    @NonNull
+    public static final Creator<TetherNetwork> CREATOR = new Creator<>() {
+        @Override
+        public TetherNetwork createFromParcel(Parcel in) {
+            return new TetherNetwork(in.readLong(), in.readTypedObject(
+                    android.net.wifi.sharedconnectivity.app.DeviceInfo.CREATOR),
+                    in.readInt(), in.readString(), in.readString(), in.readString(),
+                    in.createIntArray());
+        }
+
+        @Override
+        public TetherNetwork[] newArray(int size) {
+            return new TetherNetwork[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return new StringBuilder("TetherNetwork[")
+                .append("deviceId=").append(mDeviceId)
+                .append(", networkType=").append(mNetworkType)
+                .append(", deviceInfo=").append(mDeviceInfo.toString())
+                .append(", networkName=").append(mNetworkName)
+                .append(", hotspotSsid=").append(mHotspotSsid)
+                .append(", hotspotBssid=").append(mHotspotBssid)
+                .append(", hotspotSecurityTypes=").append(Arrays.toString(mHotspotSecurityTypes))
+                .append("]").toString();
+    }
+}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
new file mode 100644
index 0000000..6e56138
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.service;
+
+import android.net.wifi.sharedconnectivity.app.KnownNetwork;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
+import android.net.wifi.sharedconnectivity.app.TetherNetwork;
+
+/*
+ * @hide
+ */
+interface ISharedConnectivityCallback {
+    oneway void onTetherNetworksUpdated(in List<TetherNetwork> networks);
+    oneway void onKnownNetworksUpdated(in List<KnownNetwork> networks);
+    oneway void onSharedConnectivitySettingsChanged(in SharedConnectivitySettingsState state);
+}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
new file mode 100644
index 0000000..5d79405
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
@@ -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 android.net.wifi.sharedconnectivity.service;
+
+import android.net.wifi.sharedconnectivity.app.KnownNetwork;
+import android.net.wifi.sharedconnectivity.app.TetherNetwork;
+import android.net.wifi.sharedconnectivity.service.ISharedConnectivityCallback;
+
+/*
+ * @hide
+ */
+interface ISharedConnectivityService {
+    void registerCallback(in ISharedConnectivityCallback callback);
+    void unregisterCallback(in ISharedConnectivityCallback callback);
+    void connectTetherNetwork(in TetherNetwork network);
+    void disconnectTetherNetwork();
+    void connectKnownNetwork(in KnownNetwork network);
+    void forgetKnownNetwork(in KnownNetwork network);
+}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
new file mode 100644
index 0000000..234319a
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.service;
+
+import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.NETWORK_SETUP_WIZARD;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.wifi.sharedconnectivity.app.KnownNetwork;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
+import android.net.wifi.sharedconnectivity.app.TetherNetwork;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * This class is the partly implemented service for injecting Shared Connectivity networks into the
+ * Wi-Fi Pickers and other relevant UI surfaces.
+ *
+ * Implementing application should extend this service and override the indicated methods.
+ * Callers to the service should use {@link SharedConnectivityManager} to bind to the implemented
+ * service as specified in the configuration overlay.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class SharedConnectivityService extends Service {
+    private static final String TAG = SharedConnectivityService.class.getSimpleName();
+    private static final boolean DEBUG = true;
+
+    private  final Handler mHandler;
+    private final List<ISharedConnectivityCallback> mCallbacks = new ArrayList<>();
+    // Used to find DeathRecipient when unregistering a callback to call unlinkToDeath.
+    private final Map<ISharedConnectivityCallback, DeathRecipient> mDeathRecipientMap =
+            new HashMap<>();
+
+    private List<TetherNetwork> mTetherNetworks = Collections.emptyList();
+    private List<KnownNetwork> mKnownNetworks = Collections.emptyList();
+    private SharedConnectivitySettingsState mSettingsState;
+
+    public SharedConnectivityService() {
+        mHandler = new Handler(getMainLooper());
+    }
+
+    public SharedConnectivityService(@NonNull Handler handler) {
+        mHandler = handler;
+    }
+
+    private final class DeathRecipient implements IBinder.DeathRecipient {
+        ISharedConnectivityCallback mCallback;
+
+        DeathRecipient(ISharedConnectivityCallback callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public void binderDied() {
+            mCallbacks.remove(mCallback);
+            mDeathRecipientMap.remove(mCallback);
+        }
+    }
+
+    @Override
+    @Nullable
+    public IBinder onBind(@NonNull Intent intent) {
+        if (DEBUG) Log.i(TAG, "onBind intent=" + intent);
+        return new ISharedConnectivityService.Stub() {
+            @Override
+            public void registerCallback(ISharedConnectivityCallback callback) {
+                checkPermissions();
+                mHandler.post(() -> registerCallback(callback));
+            }
+
+            @Override
+            public void unregisterCallback(ISharedConnectivityCallback callback) {
+                checkPermissions();
+                mHandler.post(() -> unregisterCallback(callback));
+            }
+
+            @Override
+            public void connectTetherNetwork(TetherNetwork network) {
+                checkPermissions();
+                mHandler.post(() -> onConnectTetherNetwork(network));
+            }
+
+            @Override
+            public void disconnectTetherNetwork() {
+                checkPermissions();
+                mHandler.post(() -> onDisconnectTetherNetwork());
+            }
+
+            @Override
+            public void connectKnownNetwork(KnownNetwork network) {
+                checkPermissions();
+                mHandler.post(() -> onConnectKnownNetwork(network));
+            }
+
+            @Override
+            public void forgetKnownNetwork(KnownNetwork network) {
+                checkPermissions();
+                mHandler.post(() -> onForgetKnownNetwork(network));
+            }
+
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
+            private void checkPermissions() {
+                if (checkCallingPermission(NETWORK_SETTINGS) != PackageManager.PERMISSION_GRANTED
+                        && checkCallingPermission(NETWORK_SETUP_WIZARD)
+                                != PackageManager.PERMISSION_GRANTED) {
+                    throw new SecurityException("Calling process must have NETWORK_SETTINGS or"
+                            + " NETWORK_SETUP_WIZARD permission");
+                }
+            }
+        };
+    }
+
+    private void registerCallback(ISharedConnectivityCallback callback) {
+        // Listener gets triggered on first register using cashed data
+        if (!notifyTetherNetworkUpdate(callback) || !notifyKnownNetworkUpdate(callback)) {
+            if (DEBUG) Log.w(TAG, "Failed to notify client");
+            return;
+        }
+
+        DeathRecipient deathRecipient = new DeathRecipient(callback);
+        try {
+            callback.asBinder().linkToDeath(deathRecipient, 0);
+            mCallbacks.add(callback);
+            mDeathRecipientMap.put(callback, deathRecipient);
+        } catch (RemoteException e) {
+            if (DEBUG) Log.w(TAG, "Exception in registerCallback", e);
+        }
+    }
+
+    private void unregisterCallback(ISharedConnectivityCallback callback) {
+        DeathRecipient deathRecipient = mDeathRecipientMap.get(callback);
+        if (deathRecipient != null) {
+            callback.asBinder().unlinkToDeath(deathRecipient, 0);
+            mDeathRecipientMap.remove(callback);
+        }
+        mCallbacks.remove(callback);
+    }
+
+    private boolean notifyTetherNetworkUpdate(ISharedConnectivityCallback callback) {
+        try {
+            callback.onTetherNetworksUpdated(mTetherNetworks);
+        } catch (RemoteException e) {
+            if (DEBUG) Log.w(TAG, "Exception in notifyTetherNetworkUpdate", e);
+            return false;
+        }
+        return true;
+    }
+
+    private boolean notifyKnownNetworkUpdate(ISharedConnectivityCallback callback) {
+        try {
+            callback.onKnownNetworksUpdated(mKnownNetworks);
+        } catch (RemoteException e) {
+            if (DEBUG) Log.w(TAG, "Exception in notifyKnownNetworkUpdate", e);
+            return false;
+        }
+        return true;
+    }
+
+    private boolean notifySettingsStateUpdate(ISharedConnectivityCallback callback) {
+        try {
+            callback.onSharedConnectivitySettingsChanged(mSettingsState);
+        } catch (RemoteException e) {
+            if (DEBUG) Log.w(TAG, "Exception in notifySettingsStateUpdate", e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Implementing application should call this method to provide an up-to-date list of Tether
+     * Networks to be displayed to the user.
+     *
+     * This method updates the cached list and notifies all registered callbacks. Any callbacks that
+     * are inaccessible will be unregistered.
+     *
+     * @param networks The updated list of {@link TetherNetwork} objects.
+     */
+    public final void setTetherNetworks(@NonNull List<TetherNetwork> networks) {
+        mTetherNetworks = networks;
+
+        for (ISharedConnectivityCallback callback:mCallbacks) {
+            notifyTetherNetworkUpdate(callback);
+        }
+    }
+
+    /**
+     * Implementing application should call this method to provide an up-to-date list of Known
+     * Networks to be displayed to the user.
+     *
+     * This method updates the cached list and notifies all registered callbacks. Any callbacks that
+     * are inaccessible will be unregistered.
+     *
+     * @param networks The updated list of {@link KnownNetwork} objects.
+     */
+    public final void setKnownNetworks(@NonNull List<KnownNetwork> networks) {
+        mKnownNetworks = networks;
+
+        for (ISharedConnectivityCallback callback:mCallbacks) {
+            notifyKnownNetworkUpdate(callback);
+        }
+    }
+
+    /**
+     * Implementing application should call this method to provide an up-to-date state of Shared
+     * connectivity settings state.
+     *
+     * This method updates the cached state and notifies all registered callbacks. Any callbacks
+     * that are inaccessible will be unregistered.
+     *
+     * @param settingsState The updated state {@link SharedConnectivitySettingsState}
+     *                 objects.
+     */
+    public final void setSettingsState(@NonNull SharedConnectivitySettingsState settingsState) {
+        mSettingsState = settingsState;
+
+        for (ISharedConnectivityCallback callback:mCallbacks) {
+            notifySettingsStateUpdate(callback);
+        }
+    }
+
+    /**
+     * Implementing application should implement this method.
+     *
+     * Implementation should initiate a connection to the Tether Network indicated.
+     *
+     * @param network Object identifying the Tether Network the user has requested a connection to.
+     */
+    public abstract void onConnectTetherNetwork(@NonNull TetherNetwork network);
+
+    /**
+     * Implementing application should implement this method.
+     *
+     * Implementation should initiate a disconnection from the active Tether Network.
+     */
+    public abstract void onDisconnectTetherNetwork();
+
+    /**
+     * Implementing application should implement this method.
+     *
+     * Implementation should initiate a connection to the Known Network indicated.
+     *
+     * @param network Object identifying the Known Network the user has requested a connection to.
+     */
+    public abstract void onConnectKnownNetwork(@NonNull KnownNetwork network);
+
+    /**
+     * Implementing application should implement this method.
+     *
+     * Implementation should remove the Known Network indicated from the synced list of networks.
+     *
+     * @param network Object identifying the Known Network the user has requested to forget.
+     */
+    public abstract void onForgetKnownNetwork(@NonNull KnownNetwork network);
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/OWNERS b/wifi/tests/src/android/net/wifi/sharedconnectivity/OWNERS
new file mode 100644
index 0000000..8873d07
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/OWNERS
@@ -0,0 +1 @@
+file:/wifi/java/src/android/net/wifi/sharedconnectivity/OWNERS
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
new file mode 100644
index 0000000..f8f0700
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
@@ -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 android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_LAPTOP;
+import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.app.sharedconnectivity.DeviceInfo}.
+ */
+@SmallTest
+public class DeviceInfoTest {
+
+    private static final int DEVICE_TYPE = DEVICE_TYPE_PHONE;
+    private static final String DEVICE_NAME = "TEST_NAME";
+    private static final String DEVICE_MODEL = "TEST_MODEL";
+    private static final int BATTERY_PERCENTAGE = 50;
+    private static final int CONNECTION_STRENGTH = 2;
+
+    private static final int DEVICE_TYPE_1 = DEVICE_TYPE_LAPTOP;
+    private static final String DEVICE_NAME_1 = "TEST_NAME1";
+    private static final String DEVICE_MODEL_1 = "TEST_MODEL1";
+    private static final int BATTERY_PERCENTAGE_1 = 30;
+    private static final int CONNECTION_STRENGTH_1 = 1;
+
+    /**
+     * Verifies parcel serialization/deserialization.
+     */
+    @Test
+    public void testParcelOperation() {
+        DeviceInfo info = buildDeviceInfoBuilder().build();
+
+        Parcel parcelW = Parcel.obtain();
+        info.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        DeviceInfo fromParcel = DeviceInfo.CREATOR.createFromParcel(parcelR);
+
+        assertEquals(info, fromParcel);
+        assertEquals(info.hashCode(), fromParcel.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        DeviceInfo info1 = buildDeviceInfoBuilder().build();
+        DeviceInfo info2 = buildDeviceInfoBuilder().build();
+        assertEquals(info1, info2);
+
+        DeviceInfo.Builder builder = buildDeviceInfoBuilder().setDeviceType(DEVICE_TYPE_1);
+        assertNotEquals(info1, builder.build());
+
+        builder = buildDeviceInfoBuilder().setDeviceName(DEVICE_NAME_1);
+        assertNotEquals(info1, builder.build());
+
+        builder = buildDeviceInfoBuilder().setModelName(DEVICE_MODEL_1);
+        assertNotEquals(info1, builder.build());
+
+        builder = buildDeviceInfoBuilder()
+                .setBatteryPercentage(BATTERY_PERCENTAGE_1);
+        assertNotEquals(info1, builder.build());
+
+        builder = buildDeviceInfoBuilder()
+                .setConnectionStrength(CONNECTION_STRENGTH_1);
+        assertNotEquals(info1, builder.build());
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        DeviceInfo info = buildDeviceInfoBuilder().build();
+        assertEquals(info.getDeviceType(), DEVICE_TYPE);
+        assertEquals(info.getDeviceName(), DEVICE_NAME);
+        assertEquals(info.getModelName(), DEVICE_MODEL);
+        assertEquals(info.getBatteryPercentage(), BATTERY_PERCENTAGE);
+        assertEquals(info.getConnectionStrength(), CONNECTION_STRENGTH);
+        assertEquals(info.getConnectionStrength(), CONNECTION_STRENGTH);
+    }
+
+    private DeviceInfo.Builder buildDeviceInfoBuilder() {
+        return new DeviceInfo.Builder().setDeviceType(DEVICE_TYPE).setDeviceName(DEVICE_NAME)
+                .setModelName(DEVICE_MODEL).setBatteryPercentage(BATTERY_PERCENTAGE)
+                .setConnectionStrength(CONNECTION_STRENGTH);
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
new file mode 100644
index 0000000..266afcc
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
+import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
+import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_CLOUD_SELF;
+import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.app.sharedconnectivity.KnownNetwork}.
+ */
+@SmallTest
+public class KnownNetworkTest {
+
+    private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
+    private static final String SSID = "TEST_SSID";
+    private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
+    private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
+            .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
+            .setConnectionStrength(2).setBatteryPercentage(50).build();
+    private static final int NETWORK_SOURCE_1 = NETWORK_SOURCE_CLOUD_SELF;
+    private static final String SSID_1 = "TEST_SSID1";
+    private static final int[] SECURITY_TYPES_1 = {SECURITY_TYPE_PSK};
+    private static final DeviceInfo DEVICE_INFO_1 = new DeviceInfo.Builder()
+            .setDeviceType(DEVICE_TYPE_PHONE).setDeviceName("TEST_NAME_1")
+            .setModelName("TEST_MODEL_1").setConnectionStrength(3).setBatteryPercentage(33).build();
+
+    /**
+     * Verifies parcel serialization/deserialization.
+     */
+    @Test
+    public void testParcelOperation() {
+        KnownNetwork network = buildKnownNetworkBuilder().build();
+
+        Parcel parcelW = Parcel.obtain();
+        network.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        KnownNetwork fromParcel = KnownNetwork.CREATOR.createFromParcel(parcelR);
+
+        assertEquals(network, fromParcel);
+        assertEquals(network.hashCode(), fromParcel.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        KnownNetwork network1 = buildKnownNetworkBuilder().build();
+        KnownNetwork network2 = buildKnownNetworkBuilder().build();
+        assertEquals(network1, network2);
+
+        KnownNetwork.Builder builder = buildKnownNetworkBuilder()
+                .setNetworkSource(NETWORK_SOURCE_1);
+        assertNotEquals(network1, builder.build());
+
+        builder = buildKnownNetworkBuilder().setSsid(SSID_1);
+        assertNotEquals(network1, builder.build());
+
+        builder = buildKnownNetworkBuilder().setSecurityTypes(SECURITY_TYPES_1);
+        assertNotEquals(network1, builder.build());
+
+        builder = buildKnownNetworkBuilder().setDeviceInfo(DEVICE_INFO_1);
+        assertNotEquals(network1, builder.build());
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        KnownNetwork network = buildKnownNetworkBuilder().build();
+        assertEquals(network.getNetworkSource(), NETWORK_SOURCE);
+        assertEquals(network.getSsid(), SSID);
+        assertArrayEquals(network.getSecurityTypes(), SECURITY_TYPES);
+        assertEquals(network.getDeviceInfo(), DEVICE_INFO);
+    }
+
+    private KnownNetwork.Builder buildKnownNetworkBuilder() {
+        return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
+                .setSecurityTypes(SECURITY_TYPES).setDeviceInfo(DEVICE_INFO);
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
new file mode 100644
index 0000000..9aeccac
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
+import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
+import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
+import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.wifi.sharedconnectivity.service.ISharedConnectivityService;
+import android.os.RemoteException;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Unit tests for {@link SharedConnectivityManager}.
+ */
+@SmallTest
+public class SharedConnectivityManagerTest {
+    private static final long DEVICE_ID = 11L;
+    private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
+            .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
+            .setConnectionStrength(2).setBatteryPercentage(50).build();
+    private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
+    private static final String NETWORK_NAME = "TEST_NETWORK";
+    private static final String HOTSPOT_SSID = "TEST_SSID";
+    private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
+
+    private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
+    private static final String SSID = "TEST_SSID";
+    private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
+
+    private static final int SERVICE_PACKAGE_ID = 1;
+    private static final int SERVICE_CLASS_ID = 2;
+
+    private static final String SERVICE_PACKAGE_NAME = "TEST_PACKAGE";
+    private static final String SERVICE_CLASS_NAME = "TEST_CLASS";
+    private static final String PACKAGE_NAME = "TEST_PACKAGE";
+
+    @Mock Context mContext;
+    @Mock
+    ISharedConnectivityService mService;
+    @Mock Executor mExecutor;
+    @Mock
+    SharedConnectivityClientCallback mClientCallback;
+    @Mock Resources mResources;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        setResources(mContext);
+    }
+
+    /**
+     * Verifies constructor is binding to service.
+     */
+    @Test
+    public void testBindingToService() {
+        new SharedConnectivityManager(mContext);
+        verify(mContext).bindService(any(), any(), anyInt());
+    }
+
+    /**
+     * Verifies callback is registered in the service only once and only when service is not null.
+     */
+    @Test
+    public void testRegisterCallback() throws Exception {
+        SharedConnectivityManager manager = new SharedConnectivityManager(mContext);
+        manager.setService(null);
+        assertFalse(manager.registerCallback(mExecutor, mClientCallback));
+
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        assertTrue(manager.registerCallback(mExecutor, mClientCallback));
+        verify(mService).registerCallback(any());
+
+        // Registering the same callback twice should fail.
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        manager.registerCallback(mExecutor, mClientCallback);
+        assertFalse(manager.registerCallback(mExecutor, mClientCallback));
+
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        doThrow(new RemoteException()).when(mService).registerCallback(any());
+        assertFalse(manager.registerCallback(mExecutor, mClientCallback));
+    }
+
+    /**
+     * Verifies callback is unregistered from the service if it was registered before and only when
+     * service is not null.
+     */
+    @Test
+    public void testUnregisterCallback() throws Exception {
+        SharedConnectivityManager manager = new SharedConnectivityManager(mContext);
+        manager.setService(null);
+        assertFalse(manager.unregisterCallback(mClientCallback));
+
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        manager.registerCallback(mExecutor, mClientCallback);
+        assertTrue(manager.unregisterCallback(mClientCallback));
+        verify(mService).unregisterCallback(any());
+
+
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        manager.registerCallback(mExecutor, mClientCallback);
+        manager.unregisterCallback(mClientCallback);
+        assertFalse(manager.unregisterCallback(mClientCallback));
+
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        doThrow(new RemoteException()).when(mService).unregisterCallback(any());
+        assertFalse(manager.unregisterCallback(mClientCallback));
+    }
+
+    /**
+     * Verifies service is called when not null and exceptions are handles when calling
+     * connectTetherNetwork.
+     */
+    @Test
+    public void testConnectTetherNetwork() throws RemoteException {
+        TetherNetwork network = buildTetherNetwork();
+
+        SharedConnectivityManager manager = new SharedConnectivityManager(mContext);
+        manager.setService(null);
+        assertFalse(manager.connectTetherNetwork(network));
+
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        manager.connectTetherNetwork(network);
+        verify(mService).connectTetherNetwork(network);
+
+        doThrow(new RemoteException()).when(mService).connectTetherNetwork(network);
+        assertFalse(manager.connectTetherNetwork(network));
+    }
+
+    /**
+     * Verifies service is called when not null and exceptions are handles when calling
+     * disconnectTetherNetwork.
+     */
+    @Test
+    public void testDisconnectTetherNetwork() throws RemoteException {
+        SharedConnectivityManager manager = new SharedConnectivityManager(mContext);
+        manager.setService(null);
+        assertFalse(manager.disconnectTetherNetwork());
+
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        manager.disconnectTetherNetwork();
+        verify(mService).disconnectTetherNetwork();
+
+        doThrow(new RemoteException()).when(mService).disconnectTetherNetwork();
+        assertFalse(manager.disconnectTetherNetwork());
+    }
+
+    /**
+     * Verifies service is called when not null and exceptions are handles when calling
+     * connectKnownNetwork.
+     */
+    @Test
+    public void testConnectKnownNetwork() throws RemoteException {
+        KnownNetwork network = buildKnownNetwork();
+
+        SharedConnectivityManager manager = new SharedConnectivityManager(mContext);
+        manager.setService(null);
+        assertFalse(manager.connectKnownNetwork(network));
+
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        manager.connectKnownNetwork(network);
+        verify(mService).connectKnownNetwork(network);
+
+        doThrow(new RemoteException()).when(mService).connectKnownNetwork(network);
+        assertFalse(manager.connectKnownNetwork(network));
+    }
+
+    /**
+     * Verifies service is called when not null and exceptions are handles when calling
+     * forgetKnownNetwork.
+     */
+    @Test
+    public void testForgetKnownNetwork() throws RemoteException {
+        KnownNetwork network = buildKnownNetwork();
+
+        SharedConnectivityManager manager = new SharedConnectivityManager(mContext);
+        manager.setService(null);
+        assertFalse(manager.forgetKnownNetwork(network));
+
+        manager = new SharedConnectivityManager(mContext);
+        manager.setService(mService);
+        manager.forgetKnownNetwork(network);
+        verify(mService).forgetKnownNetwork(network);
+
+        doThrow(new RemoteException()).when(mService).forgetKnownNetwork(network);
+        assertFalse(manager.forgetKnownNetwork(network));
+    }
+
+    private void setResources(@Mock Context context) {
+        when(context.getResources()).thenReturn(mResources);
+        when(context.getPackageName()).thenReturn(PACKAGE_NAME);
+        when(mResources.getIdentifier(anyString(), anyString(), anyString()))
+                .thenReturn(SERVICE_PACKAGE_ID, SERVICE_CLASS_ID);
+        when(mResources.getString(SERVICE_PACKAGE_ID)).thenReturn(SERVICE_PACKAGE_NAME);
+        when(mResources.getString(SERVICE_CLASS_ID)).thenReturn(SERVICE_CLASS_NAME);
+    }
+
+    private TetherNetwork buildTetherNetwork() {
+        return new TetherNetwork.Builder()
+                .setDeviceId(DEVICE_ID)
+                .setDeviceInfo(DEVICE_INFO)
+                .setNetworkType(NETWORK_TYPE)
+                .setNetworkName(NETWORK_NAME)
+                .setHotspotSsid(HOTSPOT_SSID)
+                .setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES)
+                .build();
+    }
+
+    private KnownNetwork buildKnownNetwork() {
+        return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
+                .setSecurityTypes(SECURITY_TYPES).build();
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
new file mode 100644
index 0000000..3137c72
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState}.
+ */
+@SmallTest
+public class SharedConnectivitySettingsStateTest {
+    private static final boolean INSTANT_TETHER_STATE = true;
+
+    private static final boolean INSTANT_TETHER_STATE_1 = false;
+    /**
+     * Verifies parcel serialization/deserialization.
+     */
+    @Test
+    public void testParcelOperation() {
+        SharedConnectivitySettingsState state = buildSettingsStateBuilder().build();
+
+        Parcel parcelW = Parcel.obtain();
+        state.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        SharedConnectivitySettingsState fromParcel =
+                SharedConnectivitySettingsState.CREATOR.createFromParcel(parcelR);
+
+        assertEquals(state, fromParcel);
+        assertEquals(state.hashCode(), fromParcel.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        SharedConnectivitySettingsState state1 = buildSettingsStateBuilder().build();
+        SharedConnectivitySettingsState state2 = buildSettingsStateBuilder().build();
+        assertEquals(state1, state2);
+
+        SharedConnectivitySettingsState.Builder builder = buildSettingsStateBuilder()
+                .setInstantTetherEnabled(INSTANT_TETHER_STATE_1);
+        assertNotEquals(state1, builder.build());
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        SharedConnectivitySettingsState state = buildSettingsStateBuilder().build();
+        assertEquals(state.isInstantTetherEnabled(), INSTANT_TETHER_STATE);
+    }
+
+    private SharedConnectivitySettingsState.Builder buildSettingsStateBuilder() {
+        return new SharedConnectivitySettingsState.Builder()
+                .setInstantTetherEnabled(INSTANT_TETHER_STATE);
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
new file mode 100644
index 0000000..b01aec4
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
+import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
+import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_WIFI;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.sharedconnectivity.app.TetherNetwork}.
+ */
+@SmallTest
+public class TetherNetworkTest {
+    private static final long DEVICE_ID = 11L;
+    private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
+            .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
+            .setConnectionStrength(2).setBatteryPercentage(50).build();
+    private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
+    private static final String NETWORK_NAME = "TEST_NETWORK";
+    private static final String HOTSPOT_SSID = "TEST_SSID";
+    private static final String HOTSPOT_BSSID = "TEST _BSSID";
+    private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
+
+    private static final long DEVICE_ID_1 = 111L;
+    private static final DeviceInfo DEVICE_INFO_1 = new DeviceInfo.Builder()
+            .setDeviceType(DEVICE_TYPE_PHONE).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
+            .setConnectionStrength(2).setBatteryPercentage(50).build();
+    private static final int NETWORK_TYPE_1 = NETWORK_TYPE_WIFI;
+    private static final String NETWORK_NAME_1 = "TEST_NETWORK1";
+    private static final String HOTSPOT_SSID_1 = "TEST_SSID1";
+    private static final String HOTSPOT_BSSID_1 = "TEST _BSSID1";
+    private static final int[] HOTSPOT_SECURITY_TYPES_1 = {SECURITY_TYPE_PSK, SECURITY_TYPE_EAP};
+
+    /**
+     * Verifies parcel serialization/deserialization.
+     */
+    @Test
+    public void testParcelOperation() {
+        TetherNetwork network = buildTetherNetworkBuilder().build();
+
+        Parcel parcelW = Parcel.obtain();
+        network.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        TetherNetwork fromParcel = TetherNetwork.CREATOR.createFromParcel(parcelR);
+
+        assertEquals(network, fromParcel);
+        assertEquals(network.hashCode(), fromParcel.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        TetherNetwork network1 = buildTetherNetworkBuilder().build();
+        TetherNetwork network2 = buildTetherNetworkBuilder().build();
+        assertEquals(network1, network2);
+
+        TetherNetwork.Builder builder = buildTetherNetworkBuilder().setDeviceId(DEVICE_ID_1);
+        assertNotEquals(network1, builder.build());
+
+        builder = buildTetherNetworkBuilder().setDeviceInfo(DEVICE_INFO_1);
+        assertNotEquals(network1, builder.build());
+
+        builder = buildTetherNetworkBuilder().setNetworkType(NETWORK_TYPE_1);
+        assertNotEquals(network1, builder.build());
+
+        builder = buildTetherNetworkBuilder().setNetworkName(NETWORK_NAME_1);
+        assertNotEquals(network1, builder.build());
+
+        builder = buildTetherNetworkBuilder().setHotspotSsid(HOTSPOT_SSID_1);
+        assertNotEquals(network1, builder.build());
+
+        builder = buildTetherNetworkBuilder().setHotspotBssid(HOTSPOT_BSSID_1);
+        assertNotEquals(network1, builder.build());
+
+        builder = buildTetherNetworkBuilder().setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES_1);
+        assertNotEquals(network1, builder.build());
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        TetherNetwork network = buildTetherNetworkBuilder().build();
+        assertEquals(network.getDeviceId(), DEVICE_ID);
+        assertEquals(network.getDeviceInfo(), DEVICE_INFO);
+        assertEquals(network.getNetworkType(), NETWORK_TYPE);
+        assertEquals(network.getNetworkName(), NETWORK_NAME);
+        assertEquals(network.getHotspotSsid(), HOTSPOT_SSID);
+        assertEquals(network.getHotspotBssid(), HOTSPOT_BSSID);
+        assertArrayEquals(network.getHotspotSecurityTypes(), HOTSPOT_SECURITY_TYPES);
+    }
+
+    private TetherNetwork.Builder buildTetherNetworkBuilder() {
+        return new TetherNetwork.Builder()
+                .setDeviceId(DEVICE_ID)
+                .setDeviceInfo(DEVICE_INFO)
+                .setNetworkType(NETWORK_TYPE)
+                .setNetworkName(NETWORK_NAME)
+                .setHotspotSsid(HOTSPOT_SSID)
+                .setHotspotBssid(HOTSPOT_BSSID)
+                .setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES);
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
new file mode 100644
index 0000000..e15be8b
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.service;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Intent;
+import android.net.wifi.sharedconnectivity.app.KnownNetwork;
+import android.net.wifi.sharedconnectivity.app.TetherNetwork;
+import android.os.Handler;
+import android.os.test.TestLooper;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.sharedconnectivity.service.SharedConnectivityService}.
+ */
+@SmallTest
+public class SharedConnectivityServiceTest {
+
+    /**
+     * Verifies service returns
+     */
+    @Test
+    public void testOnBind() {
+        SharedConnectivityService service = createService();
+        assertNotNull(service.onBind(new Intent()));
+    }
+
+    @Test
+    public void testCallbacks() {
+        SharedConnectivityService service = createService();
+        ISharedConnectivityService.Stub binder =
+                (ISharedConnectivityService.Stub) service.onBind(new Intent());
+    }
+
+    private SharedConnectivityService createService() {
+        return new SharedConnectivityService(new Handler(new TestLooper().getLooper())) {
+            @Override
+            public void onConnectTetherNetwork(TetherNetwork network) {}
+
+            @Override
+            public void onDisconnectTetherNetwork() {}
+
+            @Override
+            public void onConnectKnownNetwork(KnownNetwork network) {}
+
+            @Override
+            public void onForgetKnownNetwork(KnownNetwork network) {}
+        };
+    }
+}